* sysdeps/m68k/dl-machine.h (RTLD_START): Call pre-init funtions.
[glibc.git] / locale / setlocale.c
blob1482465f43b9fddc964f3cb5e1519eb33b11c415
1 /* Copyright (C) 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <alloca.h>
20 #include <argz.h>
21 #include <errno.h>
22 #include <bits/libc-lock.h>
23 #include <locale.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
28 #include "localeinfo.h"
30 /* For each category declare two external variables (with weak references):
31 extern const struct locale_data *_nl_current_CATEGORY;
32 This points to the current locale's in-core data for CATEGORY.
33 extern const struct locale_data _nl_C_CATEGORY;
34 This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
35 Both are weak references; if &_nl_current_CATEGORY is zero,
36 then nothing is using the locale data. */
37 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
38 extern struct locale_data *_nl_current_##category; \
39 extern struct locale_data _nl_C_##category;
40 #include "categories.def"
41 #undef DEFINE_CATEGORY
43 /* Array indexed by category of pointers to _nl_current_CATEGORY slots. */
44 struct locale_data * *const _nl_current[] =
46 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
47 [category] = &_nl_current_##category,
48 #include "categories.def"
49 #undef DEFINE_CATEGORY
50 /* We need this additional element to simplify the code. It must
51 simply be != NULL. */
52 [LC_ALL] = (struct locale_data **) ~0ul
55 /* Array indexed by category of pointers to _nl_C_CATEGORY slots.
56 Elements are zero for categories whose data is never used. */
57 struct locale_data *const _nl_C[] =
59 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
60 [category] = &_nl_C_##category,
61 #include "categories.def"
62 #undef DEFINE_CATEGORY
66 /* Define an array of category names (also the environment variable names),
67 indexed by integral category.
69 We have entries of fixed width (16 for now) do avoid an array of
70 pointers. Update the size of the outer array if new, longer locale
71 names are introduced. */
72 const char _nl_category_names[][16] =
74 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
75 [category] = category_name,
76 #include "categories.def"
77 #undef DEFINE_CATEGORY
78 [LC_ALL] = "LC_ALL"
80 /* An array of their lengths, for convenience. */
81 const size_t _nl_category_name_sizes[] =
83 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
84 [category] = sizeof (category_name) - 1,
85 #include "categories.def"
86 #undef DEFINE_CATEGORY
87 [LC_ALL] = sizeof ("LC_ALL") - 1
91 /* Declare the postload functions used below. */
92 #undef NO_POSTLOAD
93 #define NO_POSTLOAD _nl_postload_ctype /* Harmless thing known to exist. */
94 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
95 extern void postload (void);
96 #include "categories.def"
97 #undef DEFINE_CATEGORY
98 #undef NO_POSTLOAD
100 /* Define an array indexed by category of postload functions to call after
101 loading and installing that category's data. */
102 static void (*const _nl_category_postload[]) (void) =
104 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
105 [category] = postload,
106 #include "categories.def"
107 #undef DEFINE_CATEGORY
111 /* Name of current locale for each individual category.
112 Each is malloc'd unless it is nl_C_name. */
113 static const char *_nl_current_names[] =
115 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
116 [category] = _nl_C_name,
117 #include "categories.def"
118 #undef DEFINE_CATEGORY
119 [LC_ALL] = _nl_C_name /* For LC_ALL. */
123 /* Lock for protecting global data. */
124 __libc_lock_define_initialized (, __libc_setlocale_lock)
127 /* Use this when we come along an error. */
128 #define ERROR_RETURN \
129 do { \
130 __set_errno (EINVAL); \
131 return NULL; \
132 } while (0)
135 /* Construct a new composite name. */
136 static inline char *
137 new_composite_name (int category, const char *newnames[LC_ALL])
139 size_t last_len = 0;
140 size_t cumlen = 0;
141 int i;
142 char *new, *p;
143 int same = 1;
145 for (i = 0; i < LC_ALL; ++i)
147 const char *name = (category == LC_ALL ? newnames[i] :
148 category == i ? newnames[0] :
149 _nl_current_names[i]);
150 last_len = strlen (name);
151 cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
152 if (same && strcmp (name, newnames[0]) != 0)
153 same = 0;
156 if (same)
158 /* All the categories use the same name. */
159 if (strcmp (newnames[0], _nl_C_name) == 0
160 || strcmp (newnames[0], _nl_POSIX_name) == 0)
161 return (char *) _nl_C_name;
163 new = malloc (last_len + 1);
165 return new == NULL ? NULL : memcpy (new, newnames[0], last_len + 1);
168 new = malloc (cumlen);
169 if (new == NULL)
170 return NULL;
171 p = new;
172 for (i = 0; i < LC_ALL; ++i)
174 /* Add "CATEGORY=NAME;" to the string. */
175 const char *name = (category == LC_ALL ? newnames[i] :
176 category == i ? newnames[0] :
177 _nl_current_names[i]);
178 p = __stpcpy (p, _nl_category_names[i]);
179 *p++ = '=';
180 p = __stpcpy (p, name);
181 *p++ = ';';
183 p[-1] = '\0'; /* Clobber the last ';'. */
184 return new;
188 /* Put NAME in _nl_current_names. */
189 static inline void
190 setname (int category, const char *name)
192 if (_nl_current_names[category] == name)
193 return;
195 if (category == LC_ALL && _nl_current_names[category] != _nl_C_name)
196 free ((char *) _nl_current_names[category]);
198 _nl_current_names[category] = name;
202 /* Put DATA in *_nl_current[CATEGORY]. */
203 static inline void
204 setdata (int category, struct locale_data *data)
206 if (_nl_current[category] != NULL)
208 *_nl_current[category] = data;
209 if (_nl_category_postload[category])
210 (*_nl_category_postload[category]) ();
215 char *
216 setlocale (int category, const char *locale)
218 char *locale_path;
219 size_t locale_path_len;
220 const char *locpath_var;
221 char *composite;
223 /* Sanity check for CATEGORY argument. */
224 if (category < 0 || category > LC_ALL)
225 ERROR_RETURN;
227 /* Does user want name of current locale? */
228 if (locale == NULL)
229 return (char *) _nl_current_names[category];
231 if (strcmp (locale, _nl_current_names[category]) == 0)
232 /* Changing to the same thing. */
233 return (char *) _nl_current_names[category];
235 /* We perhaps really have to load some data. So we determine the
236 path in which to look for the data now. The environment variable
237 `LOCPATH' must only be used when the binary has no SUID or SGID
238 bit set. */
239 locale_path = NULL;
240 locale_path_len = 0;
242 locpath_var = __secure_getenv ("LOCPATH");
243 if (locpath_var != NULL && locpath_var[0] != '\0')
244 if (__argz_create_sep (locpath_var, ':',
245 &locale_path, &locale_path_len) != 0)
246 return NULL;
248 if (__argz_add_sep (&locale_path, &locale_path_len, LOCALE_PATH, ':') != 0)
249 return NULL;
251 if (category == LC_ALL)
253 /* The user wants to set all categories. The desired locales
254 for the individual categories can be selected by using a
255 composite locale name. This is a semi-colon separated list
256 of entries of the form `CATEGORY=VALUE'. */
257 const char *newnames[LC_ALL];
258 struct locale_data *newdata[LC_ALL];
260 /* Set all name pointers to the argument name. */
261 for (category = 0; category < LC_ALL; ++category)
262 newnames[category] = (char *) locale;
264 if (strchr (locale, ';') != NULL)
266 /* This is a composite name. Make a copy and split it up. */
267 char *np = strdupa (locale);
268 char *cp;
269 int cnt;
271 while ((cp = strchr (np, '=')) != NULL)
273 for (cnt = 0; cnt < LC_ALL; ++cnt)
274 if ((size_t) (cp - np) == _nl_category_name_sizes[cnt]
275 && memcmp (np, _nl_category_names[cnt], cp - np) == 0)
276 break;
278 if (cnt == LC_ALL)
279 /* Bogus category name. */
280 ERROR_RETURN;
282 /* Found the category this clause sets. */
283 newnames[cnt] = ++cp;
284 cp = strchr (cp, ';');
285 if (cp != NULL)
287 /* Examine the next clause. */
288 *cp = '\0';
289 np = cp + 1;
291 else
292 /* This was the last clause. We are done. */
293 break;
296 for (cnt = 0; cnt < LC_ALL; ++cnt)
297 if (newnames[cnt] == locale)
298 /* The composite name did not specify all categories. */
299 ERROR_RETURN;
302 /* Protect global data. */
303 __libc_lock_lock (__libc_setlocale_lock);
305 /* Load the new data for each category. */
306 while (category-- > 0)
308 newdata[category] = _nl_find_locale (locale_path, locale_path_len,
309 category,
310 &newnames[category]);
312 if (newdata[category] == NULL)
313 break;
315 /* We must not simply free a global locale since we have no
316 control over the usage. So we mark it as un-deletable. */
317 if (newdata[category]->usage_count != UNDELETABLE)
318 newdata[category]->usage_count = UNDELETABLE;
321 /* Create new composite name. */
322 if (category >= 0
323 || (composite = new_composite_name (LC_ALL, newnames)) == NULL)
324 /* Loading this part of the locale failed. Abort the
325 composite load. */
326 composite = NULL;
327 else
329 /* Now we have loaded all the new data. Put it in place. */
330 for (category = 0; category < LC_ALL; ++category)
332 setdata (category, newdata[category]);
333 setname (category, newnames[category]);
335 setname (LC_ALL, composite);
338 /* Critical section left. */
339 __libc_lock_unlock (__libc_setlocale_lock);
341 /* Free the resources (the locale path variable. */
342 free (locale_path);
344 return composite;
346 else
348 struct locale_data *newdata = NULL;
349 const char *newname[1] = { locale };
351 /* Protect global data. */
352 __libc_lock_lock (__libc_setlocale_lock);
354 if (_nl_current[category] != NULL)
356 /* Only actually load the data if anything will use it. */
357 newdata = _nl_find_locale (locale_path, locale_path_len, category,
358 &newname[0]);
359 if (newdata == NULL)
360 goto abort_single;
362 /* We must not simply free a global locale since we have no
363 control over the usage. So we mark it as un-deletable.
365 Note: do not remove the `if', it's necessary to copy with
366 the builtin locale data. */
367 if (newdata->usage_count != UNDELETABLE)
368 newdata->usage_count = UNDELETABLE;
371 /* Create new composite name. */
372 composite = new_composite_name (category, newname);
373 if (composite == NULL)
375 /* Say that we don't have any data loaded. */
376 abort_single:
377 newname[0] = NULL;
379 else
381 if (_nl_current[category] != NULL)
382 setdata (category, newdata);
384 setname (category, newname[0]);
385 setname (LC_ALL, composite);
388 /* Critical section left. */
389 __libc_lock_unlock (__libc_setlocale_lock);
391 /* Free the resources (the locale path variable. */
392 free (locale_path);
394 return (char *) newname[0];
399 static void __attribute__ ((unused))
400 free_mem (void)
402 int category;
404 for (category = 0; category < LC_ALL; ++category)
406 struct locale_data *here = *_nl_current[category];
408 /* If this category is already "C" don't do anything. */
409 if (here == _nl_C[category])
410 continue;
412 /* We have to be prepared that sometime later me still might
413 need the locale information. */
414 setdata (category, _nl_C[category]);
415 setname (category, _nl_C_name);
417 _nl_unload_locale (here);
420 setname (LC_ALL, _nl_C_name);
422 text_set_element (__libc_subfreeres, free_mem);