1 #include <locale.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "locale_impl.h"
5 #include "libc.h"
6 #include "lock.h"
7
8 static char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
9
Fresh(struct __locale_map * lm)10 static inline int Fresh(struct __locale_map *lm)
11 {
12 if (lm != NULL) {
13 return lm->flag;
14 }
15 return VALID;
16 }
17
setlocale(int cat,const char * name)18 char *setlocale(int cat, const char *name)
19 {
20 const struct __locale_map *lm;
21 char flag = VALID;
22 if ((unsigned)cat > LC_ALL) return 0;
23
24 LOCK(__locale_lock);
25
26 /* For LC_ALL, setlocale is required to return a string which
27 * encodes the current setting for all categories. The format of
28 * this string is unspecified, and only the following code, which
29 * performs both the serialization and deserialization, depends
30 * on the format, so it can easily be changed if needed. */
31 if (cat == LC_ALL) {
32 int i;
33 if (name) {
34 struct __locale_struct tmp_locale;
35 char part[LOCALE_NAME_MAX+1] = "C.UTF-8";
36 const char *p = name;
37 for (i=0; i<LC_ALL; i++) {
38 const char *z = __strchrnul(p, ';');
39 if (z-p <= LOCALE_NAME_MAX) {
40 memcpy(part, p, z-p);
41 part[z-p] = 0;
42 if (*z) p = z+1;
43 }
44 lm = __get_locale(i, part);
45 if (lm == LOC_MAP_FAILED) {
46 UNLOCK(__locale_lock);
47 return 0;
48 }
49 if(Fresh(lm) == INVALID) {
50 flag = INVALID;
51 }
52 tmp_locale.cat[i] = lm;
53 }
54 libc.global_locale = tmp_locale;
55 }
56 char *s = buf;
57 const char *part;
58 int same = 0;
59 for (i=0; i<LC_ALL; i++) {
60 const struct __locale_map *lm =
61 libc.global_locale.cat[i];
62 if (lm == libc.global_locale.cat[0]) same++;
63 part = lm ? lm->name : "C";
64 size_t l = strlen(part);
65 memcpy(s, part, l);
66 s[l] = ';';
67 s += l+1;
68 }
69 *--s = 0;
70 UNLOCK(__locale_lock);
71 if (flag == INVALID) {
72 return 0;
73 }
74 return same==LC_ALL ? (char *)part : buf;
75 }
76
77 if (name) {
78 lm = __get_locale(cat, name);
79 if (lm == LOC_MAP_FAILED) {
80 UNLOCK(__locale_lock);
81 return 0;
82 }
83 flag = Fresh(lm);
84 libc.global_locale.cat[cat] = lm;
85 } else {
86 lm = libc.global_locale.cat[cat];
87 }
88 char *ret = lm ? (char *)lm->name : "C";
89
90 UNLOCK(__locale_lock);
91 if (flag == INVALID) {
92 return 0;
93 }
94 return ret;
95 }
96