#include <limits.h>
#include <locale.h>
#include <rune.h>
#include <stdlib.h>
#include <string.h>
static char *categories[_LC_LAST] = {
"LC_ALL",
"LC_COLLATE",
"LC_CTYPE",
"LC_MONETARY",
"LC_NUMERIC",
"LC_TIME",
};
static char current_categories[_LC_LAST][32] = {
"C",
"C",
"C",
"C",
"C",
"C",
};
static char new_categories[_LC_LAST][32];
static char current_locale_string[_LC_LAST * 33];
static char *PathLocale;
static char *currentlocale __P((void));
static char *loadlocale __P((int));
char *
setlocale(category, locale)
int category;
const char *locale;
{
int found, i, len;
char *env, *r;
if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
PathLocale = _PATH_LOCALE;
if (category < 0 || category >= _LC_LAST)
return (NULL);
if (!locale)
return (category ?
current_categories[category] : currentlocale());
for (i = 1; i < _LC_LAST; ++i)
(void)strcpy(new_categories[i], current_categories[i]);
if (!*locale) {
env = getenv(categories[category]);
if (!env)
env = getenv(categories[0]);
if (!env)
env = getenv("LANG");
if (!env)
env = "C";
(void) strncpy(new_categories[category], env, 31);
new_categories[category][31] = 0;
if (!category) {
for (i = 1; i < _LC_LAST; ++i) {
if (!(env = getenv(categories[i])))
env = new_categories[0];
(void)strncpy(new_categories[i], env, 31);
new_categories[i][31] = 0;
}
}
} else if (category) {
(void)strncpy(new_categories[category], locale, 31);
new_categories[category][31] = 0;
} else {
if ((r = strchr(locale, '/')) == 0) {
for (i = 1; i < _LC_LAST; ++i) {
(void)strncpy(new_categories[i], locale, 31);
new_categories[i][31] = 0;
}
} else {
for (i = 1; r[1] == '/'; ++r);
if (!r[1])
return (NULL);
do {
len = r - locale > 31 ? 31 : r - locale;
(void)strncpy(new_categories[i++], locale, len);
new_categories[i++][len] = 0;
locale = r;
while (*locale == '/')
++locale;
while (*++r && *r != '/');
} while (*locale);
while (i < _LC_LAST)
(void)strcpy(new_categories[i],
new_categories[i-1]);
}
}
if (category)
return (loadlocale(category));
found = 0;
for (i = 1; i < _LC_LAST; ++i)
if (loadlocale(i) != NULL)
found = 1;
if (found)
return (currentlocale());
return (NULL);
}
static char *
currentlocale()
{
int i;
(void)strcpy(current_locale_string, current_categories[1]);
for (i = 2; i < _LC_LAST; ++i)
if (strcmp(current_categories[1], current_categories[i])) {
(void)snprintf(current_locale_string,
sizeof(current_locale_string), "%s/%s/%s/%s/%s",
current_categories[1], current_categories[2],
current_categories[3], current_categories[4],
current_categories[5]);
break;
}
return (current_locale_string);
}
static char *
loadlocale(category)
int category;
{
char name[PATH_MAX];
if (strcmp(new_categories[category],
current_categories[category]) == 0)
return (current_categories[category]);
if (category == LC_CTYPE) {
if (setrunelocale(new_categories[LC_CTYPE]))
return (NULL);
(void)strcpy(current_categories[LC_CTYPE],
new_categories[LC_CTYPE]);
return (current_categories[LC_CTYPE]);
}
if (!strcmp(new_categories[category], "C") ||
!strcmp(new_categories[category], "POSIX")) {
(void)strcpy(current_categories[category],
new_categories[category]);
return (current_categories[category]);
}
(void)snprintf(name, sizeof(name), "%s/%s/%s",
PathLocale, new_categories[category], categories[category]);
switch (category) {
case LC_COLLATE:
case LC_MONETARY:
case LC_NUMERIC:
case LC_TIME:
return (NULL);
}
}