Branch data Line data Source code
1 : : /*
2 : : * libdpkg - Debian packaging suite library routines
3 : : * i18n.c - i18n support
4 : : *
5 : : * Copyright © 2013 Guillem Jover <guillem@debian.org>
6 : : *
7 : : * This is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU General Public License as published by
9 : : * the Free Software Foundation; either version 2 of the License, or
10 : : * (at your option) any later version.
11 : : *
12 : : * This is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <config.h>
22 : : #include <compat.h>
23 : :
24 : : #include <stdbool.h>
25 : : #include <stdlib.h>
26 : : #include <string.h>
27 : :
28 : : #include <dpkg/i18n.h>
29 : :
30 : : #ifdef HAVE_USELOCALE
31 : : #ifdef HAVE_XLOCALE_H
32 : : #include <xlocale.h>
33 : : #endif
34 : : static locale_t dpkg_C_locale;
35 : : #endif
36 : :
37 : : static bool
38 : 417 : dpkg_use_nls(void)
39 : : {
40 : : const char *env;
41 : :
42 : : /* We mimic the behavior of the Dpkg::Gettext perl module. */
43 : 417 : env = getenv("DPKG_NLS");
44 [ + - ]: 417 : if (env == NULL)
45 : 417 : return true;
46 : :
47 [ # # # # ]: 0 : if (strcmp(env, "0") == 0 || env[0] == '\0')
48 : 0 : return false;
49 : :
50 : 0 : return true;
51 : : }
52 : :
53 : : void
54 : 417 : dpkg_locales_init(const char *package)
55 : : {
56 [ + - ]: 417 : if (dpkg_use_nls())
57 : 417 : setlocale(LC_ALL, "");
58 : 417 : bindtextdomain(package, LOCALEDIR);
59 : 417 : textdomain(package);
60 : :
61 : : #ifdef HAVE_USELOCALE
62 : 417 : dpkg_C_locale = newlocale(LC_ALL_MASK, "C", (locale_t)0);
63 : : #endif
64 : :
65 : : #if defined(__APPLE__) && defined(__MACH__)
66 : : /*
67 : : * On macOS, the libintl code needs to call into the CoreFoundation
68 : : * framework, which is internally threaded, to initialize some caches.
69 : : * This is a problem when that first call is done after a fork(3),
70 : : * because per POSIX, only one thread will survive, leaving the
71 : : * process in a very inconsistent state, leading to crashes.
72 : : *
73 : : * XXX: To workaround this, we try to force the caches initialization
74 : : * at program startup time, by performing a dummy gettext() call.
75 : : */
76 : : gettext("");
77 : : #endif
78 : 417 : }
79 : :
80 : : void
81 : 349 : dpkg_locales_done(void)
82 : : {
83 : : #ifdef HAVE_USELOCALE
84 : 349 : freelocale(dpkg_C_locale);
85 : 349 : dpkg_C_locale = (locale_t)0;
86 : : #endif
87 : 349 : }
88 : :
89 : : struct dpkg_locale
90 : 0 : dpkg_locale_switch_C(void)
91 : : {
92 : : struct dpkg_locale loc;
93 : :
94 : : #ifdef HAVE_USELOCALE
95 : 0 : loc.oldloc = uselocale(dpkg_C_locale);
96 : : #else
97 : : loc.oldloc = setlocale(LC_ALL, NULL);
98 : : setlocale(LC_ALL, "C");
99 : : #endif
100 : :
101 : 0 : return loc;
102 : : }
103 : :
104 : : void
105 : 0 : dpkg_locale_switch_back(struct dpkg_locale loc)
106 : : {
107 : : #ifdef HAVE_USELOCALE
108 : 0 : uselocale(loc.oldloc);
109 : : #else
110 : : setlocale(LC_ALL, loc.oldloc);
111 : : #endif
112 : 0 : }
|