--- bash-2.05b/locale.c.mitr 2002-10-10 03:03:16.000000000 +0200 +++ bash-2.05b/locale.c 2002-10-10 03:16:32.000000000 +0200 @@ -47,6 +47,16 @@ categories */ static char *lc_all; +/* tracks the value of LANG; used to provide default value for locale + categories */ +static char *lang; + +static int reload_all_locales __P((void)); + +/* As a general rule, never EVER call setlocale (foo, ""). libc doesn't + know about shell variables and uses values from environment at time + of shell startup. */ + /* Set the value of default_locale and make the current locale the system default locale. This should be called very early in main(). */ void @@ -137,15 +147,16 @@ FREE (lc_all); if (value) lc_all = savestring (value); - else if (default_locale) - lc_all = savestring (default_locale); else { lc_all = (char *)xmalloc (1); lc_all[0] = '\0'; } #if defined (HAVE_SETLOCALE) - return (setlocale (LC_ALL, lc_all) != 0); + if (*lc_all != '\0') + return (setlocale (LC_ALL, lc_all) != 0); + else + return reload_all_locales (); #else return (1); #endif @@ -155,27 +166,27 @@ else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */ { if (lc_all == 0 || *lc_all == '\0') - return (setlocale (LC_CTYPE, value ? value : "") != 0); + return (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0); } else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */ { # if defined (LC_COLLATE) if (lc_all == 0 || *lc_all == '\0') - return (setlocale (LC_COLLATE, value ? value : "") != 0); + return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0); # endif /* LC_COLLATE */ } else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */ { # if defined (LC_MESSAGES) if (lc_all == 0 || *lc_all == '\0') - return (setlocale (LC_MESSAGES, value ? value : "") != 0); + return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0); # endif /* LC_MESSAGES */ } else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */ { # if defined (LC_NUMERIC) if (lc_all == 0 || *lc_all == '\0') - return (setlocale (LC_NUMERIC, value ? value : "") != 0); + return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0); # endif /* LC_NUMERIC */ } #endif /* HAVE_SETLOCALE */ @@ -190,7 +201,46 @@ set_lang (var, value) char *var, *value; { - return ((lc_all == 0 || *lc_all == 0) ? setlocale (LC_ALL, value?value:"") != NULL : 0); + FREE (lang); + if (value) + lang = savestring (value); + else + { + lang = (char *)xmalloc (1); + lang[0] = '\0'; + } + return ((lc_all == 0 || *lc_all == 0) ? reload_all_locales () : 0); +} + +/* LC_ALL is unset or empty and a variable affecting all locales (even those + we don't know about) has chaged. Rebuild the whole mess. + Returns 1 on success, 0 on failure. */ +static int +reload_all_locales () +{ +#if defined (HAVE_SETLOCALE) + char *locale; + + locale = lang; + if (locale == 0 || *locale == '\0') + locale = default_locale; + if (setlocale (LC_ALL, locale) == 0) + return (0); + + /* It doesn't matter whether we return success or failure when one of the + following fails, because return value of our callers is ignored ;-). */ + setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")); +# if defined (LC_COLLATE) + setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")); +# endif /* LC_COLLATE */ +# if defined (LC_MESSAGES) + setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")); +# endif /* LC_MESSAGES */ +# if defined (LC_NUMERIC) + setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")); +# endif /* LC_NUMERIC */ +#endif /* HAVE_SETLOCALE */ + return (1); } /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE) */ @@ -202,9 +252,16 @@ locale = lc_all; - if (locale == 0) + if (locale == 0 || *locale == '\0') locale = get_string_value (var); - if (locale == 0) + if (locale == 0 || *locale == '\0') + locale = lang; + if (locale == 0 || *locale == '\0') + /* FIXME: This is not really portable. Valid values of the 2nd parameter + to setlocale () are implementation defined, which doesn't even + guarantee that what is a valid locale name in one category is a valid + name in other category. In fact, glibc may from setlocale (LC_ALL, "") + return LC_CTYPE=cs_CZ.UTF-8;LC_NUMERIC=C;... */ locale = default_locale; return (locale);