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