146445Storek /* 246445Storek * Copyright (c) 1991 The Regents of the University of California. 346445Storek * All rights reserved. 446445Storek * 560469Sbostic * This code is derived from software contributed to Berkeley by 660469Sbostic * Paul Borman at Krystal Technologies. 760469Sbostic * 846445Storek * %sccs.include.redist.c% 946445Storek */ 1046445Storek 1146445Storek #if defined(LIBC_SCCS) && !defined(lint) 12*63710Sbostic static char sccsid[] = "@(#)setlocale.c 5.4 (Berkeley) 07/04/93"; 1346445Storek #endif /* LIBC_SCCS and not lint */ 1446445Storek 1560469Sbostic #include <limits.h> 1646445Storek #include <locale.h> 1760469Sbostic #include <rune.h> 1860469Sbostic #include <stdlib.h> 1946603Sbostic #include <string.h> 2046445Storek 2160469Sbostic /* 2260469Sbostic * Category names for getenv() 2360469Sbostic */ 2460469Sbostic static char *categories[_LC_LAST] = { 2560469Sbostic "LC_ALL", 2660469Sbostic "LC_COLLATE", 2760469Sbostic "LC_CTYPE", 2860469Sbostic "LC_MONETARY", 2960469Sbostic "LC_NUMERIC", 3060469Sbostic "LC_TIME", 3160469Sbostic }; 3246445Storek 3346445Storek /* 3460469Sbostic * Current locales for each category 3546445Storek */ 3660469Sbostic static char current_categories[_LC_LAST][32] = { 3760469Sbostic "C", 3860469Sbostic "C", 3960469Sbostic "C", 4060469Sbostic "C", 4160469Sbostic "C", 4260469Sbostic "C", 4360469Sbostic }; 4460469Sbostic 4560469Sbostic /* 4660469Sbostic * The locales we are going to try and load 4760469Sbostic */ 4860469Sbostic static char new_categories[_LC_LAST][32]; 4960469Sbostic 5060469Sbostic static char current_locale_string[_LC_LAST * 33]; 5160469Sbostic static char *PathLocale; 5260469Sbostic 5360469Sbostic static char *currentlocale __P((void)); 5460469Sbostic static char *loadlocale __P((int)); 5560469Sbostic 5646445Storek char * 5746445Storek setlocale(category, locale) 5846445Storek int category; 5946603Sbostic const char *locale; 6046445Storek { 6160469Sbostic int found, i, len; 6260469Sbostic char *env, *r; 6360469Sbostic 6460469Sbostic if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE"))) 6560469Sbostic PathLocale = _PATH_LOCALE; 6660469Sbostic 6760469Sbostic if (category < 0 || category >= _LC_LAST) 6846445Storek return (NULL); 6960469Sbostic 7060469Sbostic if (!locale) 7160469Sbostic return (category ? 7260469Sbostic current_categories[category] : currentlocale()); 7360469Sbostic 7460469Sbostic /* 7560469Sbostic * Default to the current locale for everything. 7660469Sbostic */ 7760469Sbostic for (i = 1; i < _LC_LAST; ++i) 7860469Sbostic (void)strcpy(new_categories[i], current_categories[i]); 7960469Sbostic 8060469Sbostic /* 8160469Sbostic * Now go fill up new_categories from the locale argument 8260469Sbostic */ 8360469Sbostic if (!*locale) { 8460469Sbostic env = getenv(categories[category]); 8560469Sbostic 8660469Sbostic if (!env) 8760469Sbostic env = getenv(categories[0]); 8860469Sbostic 8960469Sbostic if (!env) 9060469Sbostic env = getenv("LANG"); 9160469Sbostic 9260469Sbostic if (!env) 9360469Sbostic env = "C"; 9460469Sbostic 9560469Sbostic (void) strncpy(new_categories[category], env, 31); 9660469Sbostic new_categories[category][31] = 0; 9760469Sbostic if (!category) { 9860469Sbostic for (i = 1; i < _LC_LAST; ++i) { 9960469Sbostic if (!(env = getenv(categories[i]))) 10060469Sbostic env = new_categories[0]; 10160469Sbostic (void)strncpy(new_categories[i], env, 31); 10260469Sbostic new_categories[i][31] = 0; 10360469Sbostic } 10460469Sbostic } 10560469Sbostic } else if (category) { 10660469Sbostic (void)strncpy(new_categories[category], locale, 31); 10760469Sbostic new_categories[category][31] = 0; 10860469Sbostic } else { 10960469Sbostic if ((r = strchr(locale, '/')) == 0) { 11060469Sbostic for (i = 1; i < _LC_LAST; ++i) { 11160469Sbostic (void)strncpy(new_categories[i], locale, 31); 11260469Sbostic new_categories[i][31] = 0; 11360469Sbostic } 11460469Sbostic } else { 11560469Sbostic for (i = 1; r[1] == '/'; ++r); 11660469Sbostic if (!r[1]) 11760469Sbostic return (NULL); /* Hmm, just slashes... */ 11860469Sbostic do { 11960469Sbostic len = r - locale > 31 ? 31 : r - locale; 12060469Sbostic (void)strncpy(new_categories[i++], locale, len); 12160469Sbostic new_categories[i++][len] = 0; 12260469Sbostic locale = r; 12360469Sbostic while (*locale == '/') 12460469Sbostic ++locale; 12560469Sbostic while (*++r && *r != '/'); 12660469Sbostic } while (*locale); 12760469Sbostic while (i < _LC_LAST) 12860469Sbostic (void)strcpy(new_categories[i], 12960469Sbostic new_categories[i-1]); 13060469Sbostic } 13160469Sbostic } 13260469Sbostic 13360469Sbostic if (category) 13460469Sbostic return (loadlocale(category)); 13560469Sbostic 13660469Sbostic found = 0; 13760469Sbostic for (i = 1; i < _LC_LAST; ++i) 13860469Sbostic if (loadlocale(i) != NULL) 13960469Sbostic found = 1; 14060469Sbostic if (found) 14160469Sbostic return (currentlocale()); 14260469Sbostic return (NULL); 14346445Storek } 14460469Sbostic 14560469Sbostic static char * 14660469Sbostic currentlocale() 14760469Sbostic { 14860469Sbostic int i; 14960469Sbostic 15060469Sbostic (void)strcpy(current_locale_string, current_categories[1]); 15160469Sbostic 15260469Sbostic for (i = 2; i < _LC_LAST; ++i) 15360469Sbostic if (strcmp(current_categories[1], current_categories[i])) { 15460469Sbostic (void)snprintf(current_locale_string, 15560469Sbostic sizeof(current_locale_string), "%s/%s/%s/%s/%s", 15660469Sbostic current_categories[1], current_categories[2], 15760469Sbostic current_categories[3], current_categories[4], 15860469Sbostic current_categories[5]); 15960469Sbostic break; 16060469Sbostic } 16160469Sbostic return (current_locale_string); 16260469Sbostic } 16360469Sbostic 16460469Sbostic static char * 16560469Sbostic loadlocale(category) 16660469Sbostic int category; 16760469Sbostic { 16860469Sbostic char name[PATH_MAX]; 16960469Sbostic 17060469Sbostic if (strcmp(new_categories[category], 17160469Sbostic current_categories[category]) == 0) 17260469Sbostic return (current_categories[category]); 17360469Sbostic 17460469Sbostic if (category == LC_CTYPE) { 17560469Sbostic if (setrunelocale(new_categories[LC_CTYPE])) 17660469Sbostic return (NULL); 17760469Sbostic (void)strcpy(current_categories[LC_CTYPE], 17860469Sbostic new_categories[LC_CTYPE]); 17960469Sbostic return (current_categories[LC_CTYPE]); 18060469Sbostic } 18160469Sbostic 18260469Sbostic if (!strcmp(new_categories[category], "C") || 18360469Sbostic !strcmp(new_categories[category], "POSIX")) { 18460469Sbostic 18560469Sbostic /* 18660469Sbostic * Some day this will need to reset the locale to the default 18760469Sbostic * C locale. Since we have no way to change them as of yet, 18860469Sbostic * there is no need to reset them. 18960469Sbostic */ 19060469Sbostic (void)strcpy(current_categories[category], 19160469Sbostic new_categories[category]); 19260469Sbostic return (current_categories[category]); 19360469Sbostic } 19460469Sbostic 19560469Sbostic /* 19660469Sbostic * Some day we will actually look at this file. 19760469Sbostic */ 198*63710Sbostic (void)snprintf(name, sizeof(name), "%s/%s/%s", 19960469Sbostic PathLocale, new_categories[category], categories[category]); 20060469Sbostic 20160469Sbostic switch (category) { 20260469Sbostic case LC_COLLATE: 20360469Sbostic case LC_MONETARY: 20460469Sbostic case LC_NUMERIC: 20560469Sbostic case LC_TIME: 20660469Sbostic return (NULL); 20760469Sbostic } 20860469Sbostic } 209