xref: /csrg-svn/lib/libc/locale/setlocale.c (revision 60469)
146445Storek /*
246445Storek  * Copyright (c) 1991 The Regents of the University of California.
346445Storek  * All rights reserved.
446445Storek  *
5*60469Sbostic  * This code is derived from software contributed to Berkeley by
6*60469Sbostic  * Paul Borman at Krystal Technologies.
7*60469Sbostic  *
846445Storek  * %sccs.include.redist.c%
946445Storek  */
1046445Storek 
1146445Storek #if defined(LIBC_SCCS) && !defined(lint)
12*60469Sbostic static char sccsid[] = "@(#)setlocale.c	5.3 (Berkeley) 05/26/93";
1346445Storek #endif /* LIBC_SCCS and not lint */
1446445Storek 
15*60469Sbostic #include <limits.h>
1646445Storek #include <locale.h>
17*60469Sbostic #include <rune.h>
18*60469Sbostic #include <stdlib.h>
1946603Sbostic #include <string.h>
2046445Storek 
21*60469Sbostic /*
22*60469Sbostic  * Category names for getenv()
23*60469Sbostic  */
24*60469Sbostic static char *categories[_LC_LAST] = {
25*60469Sbostic     "LC_ALL",
26*60469Sbostic     "LC_COLLATE",
27*60469Sbostic     "LC_CTYPE",
28*60469Sbostic     "LC_MONETARY",
29*60469Sbostic     "LC_NUMERIC",
30*60469Sbostic     "LC_TIME",
31*60469Sbostic };
3246445Storek 
3346445Storek /*
34*60469Sbostic  * Current locales for each category
3546445Storek  */
36*60469Sbostic static char current_categories[_LC_LAST][32] = {
37*60469Sbostic     "C",
38*60469Sbostic     "C",
39*60469Sbostic     "C",
40*60469Sbostic     "C",
41*60469Sbostic     "C",
42*60469Sbostic     "C",
43*60469Sbostic };
44*60469Sbostic 
45*60469Sbostic /*
46*60469Sbostic  * The locales we are going to try and load
47*60469Sbostic  */
48*60469Sbostic static char new_categories[_LC_LAST][32];
49*60469Sbostic 
50*60469Sbostic static char current_locale_string[_LC_LAST * 33];
51*60469Sbostic static char *PathLocale;
52*60469Sbostic 
53*60469Sbostic static char	*currentlocale __P((void));
54*60469Sbostic static char	*loadlocale __P((int));
55*60469Sbostic 
5646445Storek char *
5746445Storek setlocale(category, locale)
5846445Storek 	int category;
5946603Sbostic 	const char *locale;
6046445Storek {
61*60469Sbostic 	int found, i, len;
62*60469Sbostic 	char *env, *r;
63*60469Sbostic 
64*60469Sbostic 	if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
65*60469Sbostic 		PathLocale = _PATH_LOCALE;
66*60469Sbostic 
67*60469Sbostic 	if (category < 0 || category >= _LC_LAST)
6846445Storek 		return (NULL);
69*60469Sbostic 
70*60469Sbostic 	if (!locale)
71*60469Sbostic 		return (category ?
72*60469Sbostic 		    current_categories[category] : currentlocale());
73*60469Sbostic 
74*60469Sbostic 	/*
75*60469Sbostic 	 * Default to the current locale for everything.
76*60469Sbostic 	 */
77*60469Sbostic 	for (i = 1; i < _LC_LAST; ++i)
78*60469Sbostic 		(void)strcpy(new_categories[i], current_categories[i]);
79*60469Sbostic 
80*60469Sbostic 	/*
81*60469Sbostic 	 * Now go fill up new_categories from the locale argument
82*60469Sbostic 	 */
83*60469Sbostic 	if (!*locale) {
84*60469Sbostic 		env = getenv(categories[category]);
85*60469Sbostic 
86*60469Sbostic 		if (!env)
87*60469Sbostic 			env = getenv(categories[0]);
88*60469Sbostic 
89*60469Sbostic 		if (!env)
90*60469Sbostic 			env = getenv("LANG");
91*60469Sbostic 
92*60469Sbostic 		if (!env)
93*60469Sbostic 			env = "C";
94*60469Sbostic 
95*60469Sbostic 		(void) strncpy(new_categories[category], env, 31);
96*60469Sbostic 		new_categories[category][31] = 0;
97*60469Sbostic 		if (!category) {
98*60469Sbostic 			for (i = 1; i < _LC_LAST; ++i) {
99*60469Sbostic 				if (!(env = getenv(categories[i])))
100*60469Sbostic 					env = new_categories[0];
101*60469Sbostic 				(void)strncpy(new_categories[i], env, 31);
102*60469Sbostic 				new_categories[i][31] = 0;
103*60469Sbostic 			}
104*60469Sbostic 		}
105*60469Sbostic 	} else if (category)  {
106*60469Sbostic 		(void)strncpy(new_categories[category], locale, 31);
107*60469Sbostic 		new_categories[category][31] = 0;
108*60469Sbostic 	} else {
109*60469Sbostic 		if ((r = strchr(locale, '/')) == 0) {
110*60469Sbostic 			for (i = 1; i < _LC_LAST; ++i) {
111*60469Sbostic 				(void)strncpy(new_categories[i], locale, 31);
112*60469Sbostic 				new_categories[i][31] = 0;
113*60469Sbostic 			}
114*60469Sbostic 		} else {
115*60469Sbostic 			for (i = 1; r[1] == '/'; ++r);
116*60469Sbostic 			if (!r[1])
117*60469Sbostic 				return (NULL);	/* Hmm, just slashes... */
118*60469Sbostic 			do {
119*60469Sbostic 				len = r - locale > 31 ? 31 : r - locale;
120*60469Sbostic 				(void)strncpy(new_categories[i++], locale, len);
121*60469Sbostic 				new_categories[i++][len] = 0;
122*60469Sbostic 				locale = r;
123*60469Sbostic 				while (*locale == '/')
124*60469Sbostic 				    ++locale;
125*60469Sbostic 				while (*++r && *r != '/');
126*60469Sbostic 			} while (*locale);
127*60469Sbostic 			while (i < _LC_LAST)
128*60469Sbostic 				(void)strcpy(new_categories[i],
129*60469Sbostic 				    new_categories[i-1]);
130*60469Sbostic 		}
131*60469Sbostic 	}
132*60469Sbostic 
133*60469Sbostic 	if (category)
134*60469Sbostic 		return (loadlocale(category));
135*60469Sbostic 
136*60469Sbostic 	found = 0;
137*60469Sbostic 	for (i = 1; i < _LC_LAST; ++i)
138*60469Sbostic 		if (loadlocale(i) != NULL)
139*60469Sbostic 			found = 1;
140*60469Sbostic 	if (found)
141*60469Sbostic 	    return (currentlocale());
142*60469Sbostic 	return (NULL);
14346445Storek }
144*60469Sbostic 
145*60469Sbostic static char *
146*60469Sbostic currentlocale()
147*60469Sbostic {
148*60469Sbostic 	int i;
149*60469Sbostic 
150*60469Sbostic 	(void)strcpy(current_locale_string, current_categories[1]);
151*60469Sbostic 
152*60469Sbostic 	for (i = 2; i < _LC_LAST; ++i)
153*60469Sbostic 		if (strcmp(current_categories[1], current_categories[i])) {
154*60469Sbostic 			(void)snprintf(current_locale_string,
155*60469Sbostic 			    sizeof(current_locale_string), "%s/%s/%s/%s/%s",
156*60469Sbostic 			    current_categories[1], current_categories[2],
157*60469Sbostic 			    current_categories[3], current_categories[4],
158*60469Sbostic 			    current_categories[5]);
159*60469Sbostic 			break;
160*60469Sbostic 		}
161*60469Sbostic 	return (current_locale_string);
162*60469Sbostic }
163*60469Sbostic 
164*60469Sbostic static char *
165*60469Sbostic loadlocale(category)
166*60469Sbostic 	int category;
167*60469Sbostic {
168*60469Sbostic 	char name[PATH_MAX];
169*60469Sbostic 
170*60469Sbostic 	if (strcmp(new_categories[category],
171*60469Sbostic 	    current_categories[category]) == 0)
172*60469Sbostic 		return (current_categories[category]);
173*60469Sbostic 
174*60469Sbostic 	if (category == LC_CTYPE) {
175*60469Sbostic 		if (setrunelocale(new_categories[LC_CTYPE]))
176*60469Sbostic 			return (NULL);
177*60469Sbostic 		(void)strcpy(current_categories[LC_CTYPE],
178*60469Sbostic 		    new_categories[LC_CTYPE]);
179*60469Sbostic 		return (current_categories[LC_CTYPE]);
180*60469Sbostic 	}
181*60469Sbostic 
182*60469Sbostic 	if (!strcmp(new_categories[category], "C") ||
183*60469Sbostic 		!strcmp(new_categories[category], "POSIX")) {
184*60469Sbostic 
185*60469Sbostic 		/*
186*60469Sbostic 		 * Some day this will need to reset the locale to the default
187*60469Sbostic 		 * C locale.  Since we have no way to change them as of yet,
188*60469Sbostic 		 * there is no need to reset them.
189*60469Sbostic 		 */
190*60469Sbostic 		(void)strcpy(current_categories[category],
191*60469Sbostic 		    new_categories[category]);
192*60469Sbostic 		return (current_categories[category]);
193*60469Sbostic 	}
194*60469Sbostic 
195*60469Sbostic 	/*
196*60469Sbostic 	 * Some day we will actually look at this file.
197*60469Sbostic 	 */
198*60469Sbostic 	(void)sprintf(name, sizeof(name), "%s/%s/%s",
199*60469Sbostic 	    PathLocale, new_categories[category], categories[category]);
200*60469Sbostic 
201*60469Sbostic 	switch (category) {
202*60469Sbostic 		case LC_COLLATE:
203*60469Sbostic 		case LC_MONETARY:
204*60469Sbostic 		case LC_NUMERIC:
205*60469Sbostic 		case LC_TIME:
206*60469Sbostic 			return (NULL);
207*60469Sbostic 	}
208*60469Sbostic }
209