Print this page
2964 need POSIX 2008 locale object support
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libc/port/locale/setlocale.c
+++ new/usr/src/lib/libc/port/locale/setlocale.c
1 1 /*
2 2 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
3 3 * Copyright (c) 1996 - 2002 FreeBSD Project
4 4 * Copyright (c) 1991, 1993
5 5 * The Regents of the University of California. All rights reserved.
6 6 *
7 7 * This code is derived from software contributed to Berkeley by
8 8 * Paul Borman at Krystal Technologies.
9 9 *
10 10 * Redistribution and use in source and binary forms, with or without
11 11 * modification, are permitted provided that the following conditions
12 12 * are met:
13 13 * 1. Redistributions of source code must retain the above copyright
14 14 * notice, this list of conditions and the following disclaimer.
15 15 * 2. Redistributions in binary form must reproduce the above copyright
16 16 * notice, this list of conditions and the following disclaimer in the
17 17 * documentation and/or other materials provided with the distribution.
18 18 * 4. Neither the name of the University nor the names of its contributors
19 19 * may be used to endorse or promote products derived from this software
20 20 * without specific prior written permission.
21 21 *
22 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 32 * SUCH DAMAGE.
33 33 */
34 34
35 35 #include "lint.h"
36 36 #include <sys/types.h>
37 37 #include <sys/stat.h>
38 38 #include <errno.h>
39 39 #include <limits.h>
40 40 #include <locale.h>
41 41 #include <stdlib.h>
42 42 #include <string.h>
43 43 #include <unistd.h>
44 44 #include <alloca.h>
45 45 #include <stdio.h>
46 46 #include "collate.h"
47 47 #include "lmonetary.h" /* for __monetary_load_locale() */
48 48 #include "lnumeric.h" /* for __numeric_load_locale() */
49 49 #include "lmessages.h" /* for __messages_load_locale() */
50 50 #include "setlocale.h"
51 51 #include "ldpart.h"
52 52 #include "timelocal.h" /* for __time_load_locale() */
53 53 #include "../i18n/_loc_path.h"
54 54
55 55 /*
56 56 * Category names for getenv() Note that this was modified
57 57 * for Solaris. See <iso/locale_iso.h>.
58 58 */
59 59 #define NUM_CATS 7
60 60 static char *categories[7] = {
61 61 "LC_CTYPE",
62 62 "LC_NUMERIC",
63 63 "LC_TIME",
64 64 "LC_COLLATE",
65 65 "LC_MONETARY",
66 66 "LC_MESSAGES",
67 67 "LC_ALL",
68 68 };
69 69
70 70 /*
71 71 * Current locales for each category
72 72 */
73 73 static char current_categories[NUM_CATS][ENCODING_LEN + 1] = {
74 74 "C",
75 75 "C",
76 76 "C",
77 77 "C",
78 78 "C",
79 79 "C",
80 80 "C",
81 81 };
82 82
83 83 /*
84 84 * Path to locale storage directory. See ../i18n/_loc_path.h
85 85 */
86 86 char *_PathLocale = _DFLT_LOC_PATH;
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
87 87
88 88 /*
89 89 * The locales we are going to try and load
90 90 */
91 91 static char new_categories[NUM_CATS][ENCODING_LEN + 1];
92 92 static char saved_categories[NUM_CATS][ENCODING_LEN + 1];
93 93 static char current_locale_string[NUM_CATS * (ENCODING_LEN + 1 + 1)];
94 94
95 95 static char *currentlocale(void);
96 96 static char *loadlocale(int);
97 -static const char *__get_locale_env(int);
98 97
99 98 char *
100 99 setlocale(int category, const char *locale)
101 100 {
102 101 int i, j, saverr;
103 102 const char *env, *r;
104 103
105 104 if (category < 0 || category >= NUM_CATS) {
106 105 errno = EINVAL;
107 106 return (NULL);
108 107 }
109 108
110 109 if (locale == NULL)
111 110 return (category != LC_ALL ?
112 111 current_categories[category] : currentlocale());
113 112
114 113 /*
115 114 * Default to the current locale for everything.
116 115 */
117 116 for (i = 0; i < NUM_CATS; ++i)
118 117 (void) strcpy(new_categories[i], current_categories[i]);
119 118
120 119 /*
121 120 * Now go fill up new_categories from the locale argument
122 121 */
123 122 if (!*locale) {
124 123 if (category == LC_ALL) {
125 124 for (i = 0; i < NUM_CATS; ++i) {
126 125 if (i == LC_ALL)
127 126 continue;
128 127 env = __get_locale_env(i);
129 128 if (strlen(env) > ENCODING_LEN) {
130 129 errno = EINVAL;
131 130 return (NULL);
132 131 }
133 132 (void) strcpy(new_categories[i], env);
134 133 }
135 134 } else {
136 135 env = __get_locale_env(category);
137 136 if (strlen(env) > ENCODING_LEN) {
138 137 errno = EINVAL;
139 138 return (NULL);
140 139 }
141 140 (void) strcpy(new_categories[category], env);
142 141 }
143 142 } else if (category != LC_ALL) {
144 143 if (strlen(locale) > ENCODING_LEN) {
145 144 errno = EINVAL;
146 145 return (NULL);
147 146 }
148 147 (void) strcpy(new_categories[category], locale);
149 148 } else {
150 149 if ((r = strchr(locale, '/')) == NULL) {
151 150 if (strlen(locale) > ENCODING_LEN) {
152 151 errno = EINVAL;
153 152 return (NULL);
154 153 }
155 154 for (i = 0; i < NUM_CATS; ++i)
156 155 (void) strcpy(new_categories[i], locale);
157 156 } else {
158 157 char *buf;
159 158 char *save;
160 159
161 160 buf = alloca(strlen(locale) + 1);
162 161 (void) strcpy(buf, locale);
163 162
164 163 save = NULL;
165 164 r = strtok_r(buf, "/", &save);
166 165 for (i = 0; i < NUM_CATS; i++) {
167 166 if (i == LC_ALL)
168 167 continue;
169 168 if (r == NULL) {
170 169 /*
171 170 * Composite Locale is inadequately
172 171 * specified! (Or with empty fields.)
173 172 * The old code would fill fields
174 173 * out from the last one, but I think
175 174 * this is suboptimal.
176 175 */
177 176 errno = EINVAL;
178 177 return (NULL);
179 178 }
180 179 (void) strlcpy(new_categories[i], r,
181 180 ENCODING_LEN);
182 181 r = strtok_r(NULL, "/", &save);
183 182 }
184 183 if (r != NULL) {
185 184 /*
186 185 * Too many components - we had left over
187 186 * data in the LC_ALL. It is malformed.
188 187 */
189 188 errno = EINVAL;
190 189 return (NULL);
191 190 }
192 191 }
193 192 }
194 193
195 194 if (category != LC_ALL)
196 195 return (loadlocale(category));
197 196
198 197 for (i = 0; i < NUM_CATS; ++i) {
199 198 (void) strcpy(saved_categories[i], current_categories[i]);
200 199 if (i == LC_ALL)
201 200 continue;
202 201 if (loadlocale(i) == NULL) {
203 202 saverr = errno;
204 203 for (j = 0; j < i; j++) {
205 204 (void) strcpy(new_categories[j],
206 205 saved_categories[j]);
207 206 if (i == LC_ALL)
208 207 continue;
209 208 if (loadlocale(j) == NULL) {
210 209 (void) strcpy(new_categories[j], "C");
211 210 (void) loadlocale(j);
212 211 }
213 212 }
214 213 errno = saverr;
215 214 return (NULL);
216 215 }
217 216 }
218 217 return (currentlocale());
219 218 }
220 219
221 220 static char *
222 221 currentlocale(void)
223 222 {
224 223 int i;
225 224 int composite = 0;
226 225
227 226 /* Look to see if any category is different */
228 227 for (i = 1; i < NUM_CATS; ++i) {
229 228 if (i == LC_ALL)
230 229 continue;
231 230 if (strcmp(current_categories[0], current_categories[i])) {
232 231 composite = 1;
233 232 break;
234 233 }
235 234 }
236 235
237 236 if (composite) {
238 237 /*
239 238 * Note ordering of these follows the numeric order,
240 239 * if the order is changed, then setlocale() will need
241 240 * to be changed as well.
242 241 */
243 242 (void) snprintf(current_locale_string,
244 243 sizeof (current_locale_string),
245 244 "%s/%s/%s/%s/%s/%s",
246 245 current_categories[LC_CTYPE],
247 246 current_categories[LC_NUMERIC],
248 247 current_categories[LC_TIME],
249 248 current_categories[LC_COLLATE],
250 249 current_categories[LC_MONETARY],
251 250 current_categories[LC_MESSAGES]);
252 251 } else {
253 252 (void) strlcpy(current_locale_string, current_categories[0],
254 253 sizeof (current_locale_string));
255 254 }
256 255 return (current_locale_string);
257 256 }
258 257
259 258 static char *
260 259 loadlocale(int category)
261 260 {
262 261 char *new = new_categories[category];
263 262 char *old = current_categories[category];
264 263 int (*func)(const char *);
265 264
266 265 if ((new[0] == '.' &&
267 266 (new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
268 267 strchr(new, '/') != NULL) {
269 268 errno = EINVAL;
270 269 return (NULL);
271 270 }
272 271
273 272 switch (category) {
274 273 case LC_CTYPE:
275 274 func = __wrap_setrunelocale;
276 275 break;
277 276 case LC_COLLATE:
278 277 func = _collate_load_tables;
279 278 break;
280 279 case LC_TIME:
281 280 func = __time_load_locale;
282 281 break;
283 282 case LC_NUMERIC:
284 283 func = __numeric_load_locale;
285 284 break;
286 285 case LC_MONETARY:
287 286 func = __monetary_load_locale;
288 287 break;
289 288 case LC_MESSAGES:
290 289 func = __messages_load_locale;
291 290 break;
292 291 default:
293 292 errno = EINVAL;
294 293 return (NULL);
295 294 }
296 295
297 296 if (strcmp(new, old) == 0)
↓ open down ↓ |
190 lines elided |
↑ open up ↑ |
298 297 return (old);
299 298
300 299 if (func(new) != _LDP_ERROR) {
301 300 (void) strcpy(old, new);
302 301 return (old);
303 302 }
304 303
305 304 return (NULL);
306 305 }
307 306
308 -static const char *
307 +const char *
309 308 __get_locale_env(int category)
310 309 {
311 310 const char *env;
312 311
313 312 /* 1. check LC_ALL. */
314 313 env = getenv(categories[LC_ALL]);
315 314
316 315 /* 2. check LC_* */
317 316 if (env == NULL || !*env)
318 317 env = getenv(categories[category]);
319 318
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
320 319 /* 3. check LANG */
321 320 if (env == NULL || !*env)
322 321 env = getenv("LANG");
323 322
324 323 /* 4. if none is set, fall to "C" */
325 324 if (env == NULL || !*env)
326 325 env = "C";
327 326
328 327 return (env);
329 328 }
329 +
330 +/*
331 + * Detect locale storage location and store its value to _PathLocale variable
332 + */
333 +int
334 +__detect_path_locale(void)
335 +{
336 + /* XXX */
337 +
338 + return (0);
339 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX