xref: /illumos-gate/usr/src/lib/libc/port/i18n/gettext.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright 2015 Joyent, Inc.
28  */
29 
30 #pragma weak _bindtextdomain = bindtextdomain
31 #pragma weak _textdomain = textdomain
32 #pragma weak _gettext = gettext
33 #pragma weak _dgettext = dgettext
34 #pragma weak _dcgettext = dcgettext
35 #pragma weak _ngettext = ngettext
36 #pragma weak _dngettext = dngettext
37 #pragma weak _dcngettext = dcngettext
38 #pragma weak _bind_textdomain_codeset = bind_textdomain_codeset
39 
40 #include "lint.h"
41 #include "mtlib.h"
42 #include <errno.h>
43 #include <ctype.h>
44 #include <locale.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <sys/param.h>
49 #include <libintl.h>
50 #include <thread.h>
51 #include <synch.h>
52 #include "libc.h"
53 #include "_loc_path.h"
54 #include "msgfmt.h"
55 #include "gettext.h"
56 
57 #define	INIT_GT(def) \
58 	if (!global_gt) { \
59 		global_gt = (Gettext_t *)calloc(1, sizeof (Gettext_t)); \
60 		if (global_gt) \
61 			global_gt->cur_domain = (char *)default_domain; \
62 		else { \
63 			callout_lock_exit(); \
64 			return ((def)); \
65 		} \
66 	}
67 
68 const char	*defaultbind = DEFAULT_BINDING;
69 const char	default_domain[] = DEFAULT_DOMAIN;
70 Gettext_t	*global_gt = NULL;
71 
72 char *
73 bindtextdomain(const char *domain, const char *binding)
74 {
75 	char	*res;
76 
77 	callout_lock_enter();
78 	INIT_GT(NULL);
79 	res = _real_bindtextdomain_u(domain, binding, TP_BINDING);
80 	callout_lock_exit();
81 	return (res);
82 }
83 
84 char *
85 bind_textdomain_codeset(const char *domain, const char *codeset)
86 {
87 	char	*res;
88 
89 	callout_lock_enter();
90 	INIT_GT(NULL);
91 	res = _real_bindtextdomain_u(domain, codeset, TP_CODESET);
92 	callout_lock_exit();
93 	return (res);
94 }
95 
96 /*
97  * textdomain() sets or queries the name of the current domain of
98  * the active LC_MESSAGES locale category.
99  */
100 char *
101 textdomain(const char *domain)
102 {
103 	char	*res;
104 	char	tmp_domain[TEXTDOMAINMAX + 1];
105 
106 	callout_lock_enter();
107 	INIT_GT(NULL);
108 	res = _textdomain_u(domain, tmp_domain);
109 	if (res == NULL) {
110 		callout_lock_exit();
111 		return (NULL);
112 	}
113 	callout_lock_exit();
114 	return (CURRENT_DOMAIN(global_gt));
115 }
116 
117 /*
118  * gettext() is a pass-thru to _real_gettext_u() with a NULL pointer passed
119  * for domain and LC_MESSAGES passed for category.
120  */
121 char *
122 gettext(const char *msg_id)
123 {
124 	char	*res;
125 	int	errno_save = errno;
126 
127 	callout_lock_enter();
128 	INIT_GT((char *)msg_id);
129 	res = _real_gettext_u(NULL, msg_id, NULL, 0, LC_MESSAGES, 0, NULL);
130 	callout_lock_exit();
131 	errno = errno_save;
132 	return (res);
133 }
134 
135 
136 /*
137  * In dcgettext() call, domain is valid only for this call.
138  */
139 char *
140 dgettext(const char *domain, const char *msg_id)
141 {
142 	char	*res;
143 	int	errno_save = errno;
144 
145 	callout_lock_enter();
146 	INIT_GT((char *)msg_id);
147 	res = _real_gettext_u(domain, msg_id, NULL, 0, LC_MESSAGES, 0, NULL);
148 	callout_lock_exit();
149 	errno = errno_save;
150 	return (res);
151 }
152 
153 char *
154 dgettext_l(const char *domain, const char *msg_id, locale_t loc)
155 {
156 	char	*res;
157 	int	errno_save = errno;
158 
159 	callout_lock_enter();
160 	INIT_GT((char *)msg_id);
161 	res = _real_gettext_u(domain, msg_id, NULL, 0, LC_MESSAGES, 0, loc);
162 	callout_lock_exit();
163 	errno = errno_save;
164 	return (res);
165 }
166 
167 char *
168 dcgettext(const char *domain, const char *msg_id, const int category)
169 {
170 	char	*res;
171 	int	errno_save = errno;
172 
173 	callout_lock_enter();
174 	INIT_GT((char *)msg_id);
175 	res = _real_gettext_u(domain, msg_id, NULL, 0, category, 0, NULL);
176 	callout_lock_exit();
177 	errno = errno_save;
178 	return (res);
179 }
180 
181 char *
182 ngettext(const char *msgid1, const char *msgid2, unsigned long int n)
183 {
184 	char	*res;
185 	int	errno_save = errno;
186 
187 	callout_lock_enter();
188 	INIT_GT((char *)msgid1);
189 	res = _real_gettext_u(NULL, msgid1, msgid2, n, LC_MESSAGES, 1, NULL);
190 	callout_lock_exit();
191 	errno = errno_save;
192 	return (res);
193 }
194 
195 char *
196 dngettext(const char *domain, const char *msgid1, const char *msgid2,
197 	unsigned long int n)
198 {
199 	char	*res;
200 	int	errno_save = errno;
201 
202 	callout_lock_enter();
203 	INIT_GT((char *)msgid1);
204 	res = _real_gettext_u(domain, msgid1, msgid2, n, LC_MESSAGES, 1, NULL);
205 	callout_lock_exit();
206 	errno = errno_save;
207 	return (res);
208 }
209 
210 char *
211 dcngettext(const char *domain, const char *msgid1, const char *msgid2,
212 	unsigned long int n, int category)
213 {
214 	char	*res;
215 	int	errno_save = errno;
216 
217 	callout_lock_enter();
218 	INIT_GT((char *)msgid1);
219 	res = _real_gettext_u(domain, msgid1, msgid2, n, category, 1, NULL);
220 	callout_lock_exit();
221 	errno = errno_save;
222 	return (res);
223 }
224