Deleted Added
full compact
1/*
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Paul Borman at Krystal Technologies.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 29 unchanged lines hidden (view full) ---

38static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
39#endif /* LIBC_SCCS and not lint */
40
41#include <limits.h>
42#include <locale.h>
43#include <rune.h>
44#include <stdlib.h>
45#include <string.h>
46#include <sys/stat.h>
47#include "collate.h"
48
49/*
50 * Category names for getenv()
51 */
52static char *categories[_LC_LAST] = {
53 "LC_ALL",
54 "LC_COLLATE",

--- 14 unchanged lines hidden (view full) ---

69 "C",
70 "C",
71};
72
73/*
74 * The locales we are going to try and load
75 */
76static char new_categories[_LC_LAST][32];
77static char saved_categories[_LC_LAST][32];
78
79static char current_locale_string[_LC_LAST * 33];
80char *_PathLocale;
81
82static char *currentlocale __P((void));
83static char *loadlocale __P((int));
84static int stub_load_locale __P((const char *));
85
86extern int __time_load_locale __P((const char *)); /* strftime.c */
87
88#ifdef XPG4
89extern int _xpg4_setrunelocale __P((char *));
90#endif
91
92char *
93setlocale(category, locale)
94 int category;
95 const char *locale;
96{
94 int found, i, len;
97 int i, j, len;
98 char *env, *r;
99
97 if (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE")))
98 _PathLocale = _PATH_LOCALE;
99
100 if (category < 0 || category >= _LC_LAST)
100 if (category < LC_ALL || category >= _LC_LAST)
101 return (NULL);
102
103 if (!locale)
104 return (category ?
104 return (category != LC_ALL ?
105 current_categories[category] : currentlocale());
106
107 /*
108 * Default to the current locale for everything.
109 */
110 for (i = 1; i < _LC_LAST; ++i)
110 for (i = 1; i < _LC_LAST; ++i) {
111 (void)strcpy(new_categories[i], current_categories[i]);
112 (void)strcpy(saved_categories[i], current_categories[i]);
113 }
114
115 /*
116 * Now go fill up new_categories from the locale argument
117 */
118 if (!*locale) {
119 env = getenv(categories[category]);
120
119 if (!env)
120 env = getenv(categories[0]);
121 if (category != LC_ALL && (!env || !*env))
122 env = getenv(categories[LC_ALL]);
123
122 if (!env)
124 if (!env || !*env)
125 env = getenv("LANG");
126
125 if (!env)
127 if (!env || !*env)
128 env = "C";
129
130 (void) strncpy(new_categories[category], env, 31);
131 new_categories[category][31] = 0;
130 if (!category) {
132 if (category == LC_ALL) {
133 for (i = 1; i < _LC_LAST; ++i) {
132 if (!(env = getenv(categories[i])))
133 env = new_categories[0];
134 if (!(env = getenv(categories[i])) || !*env)
135 env = new_categories[LC_ALL];
136 (void)strncpy(new_categories[i], env, 31);
137 new_categories[i][31] = 0;
138 }
139 }
138 } else if (category) {
140 } else if (category != LC_ALL) {
141 (void)strncpy(new_categories[category], locale, 31);
142 new_categories[category][31] = 0;
143 } else {
144 if ((r = strchr(locale, '/')) == 0) {
145 for (i = 1; i < _LC_LAST; ++i) {
146 (void)strncpy(new_categories[i], locale, 31);
147 new_categories[i][31] = 0;
148 }

--- 11 unchanged lines hidden (view full) ---

160 while (*++r && *r != '/');
161 } while (*locale);
162 while (i < _LC_LAST)
163 (void)strcpy(new_categories[i],
164 new_categories[i-1]);
165 }
166 }
167
166 if (category)
167 return (loadlocale(category));
168 if (category) {
169 if ((r = loadlocale(category)) == NULL) {
170 (void)strcpy(new_categories[category],
171 saved_categories[category]);
172 /* XXX can fail too */
173 (void)loadlocale(category);
174 }
175 return (r);
176 }
177
169 found = 0;
178 for (i = 1; i < _LC_LAST; ++i)
171 if (loadlocale(i) != NULL)
172 found = 1;
173 if (found)
174 return (currentlocale());
175 return (NULL);
179 if (loadlocale(i) == NULL) {
180 for (j = 1; j < i; j++) {
181 (void)strcpy(new_categories[j],
182 saved_categories[j]);
183 /* XXX can fail too */
184 (void)loadlocale(j);
185 }
186 return (NULL);
187 }
188 return (currentlocale());
189}
190
191/* To be compatible with crt0 hack */
192void
193_startup_setlocale(category, locale)
194 int category;
195 const char *locale;
196{
197#ifndef XPG4
198 (void) setlocale(category, locale);
199#endif
200}
201
202static char *
203currentlocale()
204{
192 int i, len;
205 int i;
206
207 (void)strcpy(current_locale_string, current_categories[1]);
208
209 for (i = 2; i < _LC_LAST; ++i)
210 if (strcmp(current_categories[1], current_categories[i])) {
198 len = strlen(current_categories[1]) + 1 +
199 strlen(current_categories[2]) + 1 +
200 strlen(current_categories[3]) + 1 +
201 strlen(current_categories[4]) + 1 +
202 strlen(current_categories[5]) + 1;
203 if (len > sizeof(current_locale_string))
204 return NULL;
211 (void) strcpy(current_locale_string, current_categories[1]);
212 (void) strcat(current_locale_string, "/");
213 (void) strcat(current_locale_string, current_categories[2]);
214 (void) strcat(current_locale_string, "/");
215 (void) strcat(current_locale_string, current_categories[3]);
216 (void) strcat(current_locale_string, "/");
217 (void) strcat(current_locale_string, current_categories[4]);
218 (void) strcat(current_locale_string, "/");
219 (void) strcat(current_locale_string, current_categories[5]);
220 break;
221 }
222 return (current_locale_string);
223}
224
225static char *
226loadlocale(category)
227 int category;
228{
223#if 0
224 char name[PATH_MAX];
225#endif
226 if (strcmp(new_categories[category],
229 char *encoding = new_categories[category];
230
231 if (strcmp(encoding,
232 current_categories[category]) == 0)
233 return (current_categories[category]);
234
235 if ( !_PathLocale
236 && strcmp(encoding, "C") && strcmp(encoding, "POSIX")
237 ) {
238 char *pl = getenv("PATH_LOCALE");
239
240 if (!pl)
241 _PathLocale = _PATH_LOCALE;
242 else if ( strlen(pl) + 45 > PATH_MAX
243 || !(_PathLocale = strdup(pl))
244 )
245 return (NULL);
246 }
247
248 if (category == LC_CTYPE) {
249#ifdef XPG4
232 if (_xpg4_setrunelocale(new_categories[LC_CTYPE]))
250 if (_xpg4_setrunelocale(encoding))
251#else
234 if (setrunelocale(new_categories[LC_CTYPE]))
252 if (setrunelocale(encoding))
253#endif
254 return (NULL);
237 (void)strcpy(current_categories[LC_CTYPE],
238 new_categories[LC_CTYPE]);
255 (void)strcpy(current_categories[LC_CTYPE], encoding);
256 return (current_categories[LC_CTYPE]);
257 }
258
259 if (category == LC_COLLATE) {
243 if (__collate_load_tables(new_categories[LC_COLLATE]) < 0)
260 if (__collate_load_tables(encoding) < 0)
261 return (NULL);
245 (void)strcpy(current_categories[LC_COLLATE],
246 new_categories[LC_COLLATE]);
262 (void)strcpy(current_categories[LC_COLLATE], encoding);
263 return (current_categories[LC_COLLATE]);
264 }
265
266 if (category == LC_TIME) {
251 if (__time_load_locale(new_categories[LC_TIME]) < 0)
267 if (__time_load_locale(encoding) < 0)
268 return (NULL);
253 (void)strcpy(current_categories[LC_TIME],
254 new_categories[LC_TIME]);
269 (void)strcpy(current_categories[LC_TIME], encoding);
270 return (current_categories[LC_TIME]);
271 }
272
258 if (!strcmp(new_categories[category], "C") ||
259 !strcmp(new_categories[category], "POSIX")) {
260
261 /*
262 * Some day this will need to reset the locale to the default
263 * C locale. Since we have no way to change them as of yet,
264 * there is no need to reset them.
265 */
266 (void)strcpy(current_categories[category],
267 new_categories[category]);
273 if (category == LC_MONETARY || category == LC_NUMERIC) {
274 if (stub_load_locale(encoding))
275 return (NULL);
276 (void)strcpy(current_categories[category], encoding);
277 return (current_categories[category]);
278 }
279
280 /* Just in case...*/
281 return (NULL);
282}
283
284static int
285stub_load_locale(encoding)
286const char *encoding;
287{
288 char name[PATH_MAX];
289 struct stat st;
290
291 if (!encoding)
292 return(1);
293 /*
294 * The "C" and "POSIX" locale are always here.
295 */
296 if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
297 return(0);
298 if (!_PathLocale)
299 return(1);
300 strcpy(name, _PathLocale);
301 strcat(name, "/");
302 strcat(name, encoding);
303#if 0
304 /*
305 * Some day we will actually look at this file.
306 */
274 (void)snprintf(name, sizeof(name), "%s/%s/%s",
275 _PathLocale, new_categories[category], categories[category]);
307#endif
277 switch (category) {
278 case LC_MONETARY:
279 case LC_NUMERIC:
280 return (NULL);
281 }
282 /* Just in case...*/
283 return (NULL);
308 return (stat(name, &st) != 0 || !S_ISDIR(st.st_mode));
309}