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