diff options
author | ache <ache@FreeBSD.org> | 1996-11-26 02:49:53 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1996-11-26 02:49:53 +0000 |
commit | de0f02e3b7cd27d981f14b6dea4859953e240390 (patch) | |
tree | a6517b924f385d091b11e9ff009dfec8cd705f08 /lib/libc | |
parent | dcd629b514014b18a3c683df3e53ece7f0b6e4d7 (diff) | |
download | FreeBSD-src-de0f02e3b7cd27d981f14b6dea4859953e240390.zip FreeBSD-src-de0f02e3b7cd27d981f14b6dea4859953e240390.tar.gz |
PATH_LOCALE: use this non-standard env variable first time only, i.e.
strdup() it to prevent unsetenv() or setenv() effects. Check its length to
not allow user to overflow internal locale buffer. Move PATH_LOCALE
handling code into one place.
POSIX: make better stub for LC_MONETARY & LC_NUMERIC, now it check
locale directory existance instead of refusing all non-C non-POSIX
locales. POSIX treats empty locale env variable as unset variable
while our old code treats it as "C" locale, fix it. Implement previous locale
restoring, if locale setting fails. Old code assumes success if some
of LC_ALL subset is successed even other fails, POSIX treats it as
failure with previous locale restoring, fix it.
Remove unneccessary length checking in currentlocale()
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/locale/collate.c | 10 | ||||
-rw-r--r-- | lib/libc/locale/setlocale.c | 153 | ||||
-rw-r--r-- | lib/libc/locale/setrunelocale.c | 7 |
3 files changed, 98 insertions, 72 deletions
diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c index 97522192..a74a1a3 100644 --- a/lib/libc/locale/collate.c +++ b/lib/libc/locale/collate.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: collate.c,v 1.7 1996/10/15 21:53:22 ache Exp $ + * $Id: collate.c,v 1.8 1996/10/23 15:35:43 ache Exp $ */ #include <rune.h> @@ -67,10 +67,12 @@ __collate_load_tables(encoding) __collate_load_error = save_load_error; return -1; } - if (!*encoding || !strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) + if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) return 0; - if (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))) - _PathLocale = _PATH_LOCALE; + if (!_PathLocale) { + __collate_load_error = save_load_error; + return -1; + } strcpy(buf, _PathLocale); strcat(buf, "/"); strcat(buf, encoding); diff --git a/lib/libc/locale/setlocale.c b/lib/libc/locale/setlocale.c index 11f2139..9bcb88a 100644 --- a/lib/libc/locale/setlocale.c +++ b/lib/libc/locale/setlocale.c @@ -43,6 +43,7 @@ static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93"; #include <rune.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include "collate.h" /* @@ -73,12 +74,14 @@ static char current_categories[_LC_LAST][32] = { * The locales we are going to try and load */ static char new_categories[_LC_LAST][32]; +static char saved_categories[_LC_LAST][32]; static char current_locale_string[_LC_LAST * 33]; char *_PathLocale; static char *currentlocale __P((void)); static char *loadlocale __P((int)); +static int stub_load_locale __P((const char *)); extern int __time_load_locale __P((const char *)); /* strftime.c */ @@ -91,24 +94,23 @@ setlocale(category, locale) int category; const char *locale; { - int found, i, len; + int i, j, len; char *env, *r; - if (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))) - _PathLocale = _PATH_LOCALE; - - if (category < 0 || category >= _LC_LAST) + if (category < LC_ALL || category >= _LC_LAST) return (NULL); if (!locale) - return (category ? + return (category != LC_ALL ? current_categories[category] : currentlocale()); /* * Default to the current locale for everything. */ - for (i = 1; i < _LC_LAST; ++i) + for (i = 1; i < _LC_LAST; ++i) { (void)strcpy(new_categories[i], current_categories[i]); + (void)strcpy(saved_categories[i], current_categories[i]); + } /* * Now go fill up new_categories from the locale argument @@ -116,26 +118,26 @@ setlocale(category, locale) if (!*locale) { env = getenv(categories[category]); - if (!env) - env = getenv(categories[0]); + if (category != LC_ALL && (!env || !*env)) + env = getenv(categories[LC_ALL]); - if (!env) + if (!env || !*env) env = getenv("LANG"); - if (!env) + if (!env || !*env) env = "C"; (void) strncpy(new_categories[category], env, 31); new_categories[category][31] = 0; - if (!category) { + if (category == LC_ALL) { for (i = 1; i < _LC_LAST; ++i) { - if (!(env = getenv(categories[i]))) - env = new_categories[0]; + if (!(env = getenv(categories[i])) || !*env) + env = new_categories[LC_ALL]; (void)strncpy(new_categories[i], env, 31); new_categories[i][31] = 0; } } - } else if (category) { + } else if (category != LC_ALL) { (void)strncpy(new_categories[category], locale, 31); new_categories[category][31] = 0; } else { @@ -163,16 +165,27 @@ setlocale(category, locale) } } - if (category) - return (loadlocale(category)); + if (category) { + if ((r = loadlocale(category)) == NULL) { + (void)strcpy(new_categories[category], + saved_categories[category]); + /* XXX can fail too */ + (void)loadlocale(category); + } + return (r); + } - found = 0; for (i = 1; i < _LC_LAST; ++i) - if (loadlocale(i) != NULL) - found = 1; - if (found) - return (currentlocale()); - return (NULL); + if (loadlocale(i) == NULL) { + for (j = 1; j < i; j++) { + (void)strcpy(new_categories[j], + saved_categories[j]); + /* XXX can fail too */ + (void)loadlocale(j); + } + return (NULL); + } + return (currentlocale()); } /* To be compatible with crt0 hack */ @@ -189,19 +202,12 @@ _startup_setlocale(category, locale) static char * currentlocale() { - int i, len; + 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])) { - len = strlen(current_categories[1]) + 1 + - strlen(current_categories[2]) + 1 + - strlen(current_categories[3]) + 1 + - strlen(current_categories[4]) + 1 + - strlen(current_categories[5]) + 1; - if (len > sizeof(current_locale_string)) - return NULL; (void) strcpy(current_locale_string, current_categories[1]); (void) strcat(current_locale_string, "/"); (void) strcat(current_locale_string, current_categories[2]); @@ -220,65 +226,84 @@ static char * loadlocale(category) int category; { -#if 0 - char name[PATH_MAX]; -#endif - if (strcmp(new_categories[category], + char *encoding = new_categories[category]; + + if (strcmp(encoding, current_categories[category]) == 0) return (current_categories[category]); + if ( !_PathLocale + && strcmp(encoding, "C") && strcmp(encoding, "POSIX") + ) { + char *pl = getenv("PATH_LOCALE"); + + if (!pl) + _PathLocale = _PATH_LOCALE; + else if ( strlen(pl) + 45 > PATH_MAX + || !(_PathLocale = strdup(pl)) + ) + return (NULL); + } + if (category == LC_CTYPE) { #ifdef XPG4 - if (_xpg4_setrunelocale(new_categories[LC_CTYPE])) + if (_xpg4_setrunelocale(encoding)) #else - if (setrunelocale(new_categories[LC_CTYPE])) + if (setrunelocale(encoding)) #endif return (NULL); - (void)strcpy(current_categories[LC_CTYPE], - new_categories[LC_CTYPE]); + (void)strcpy(current_categories[LC_CTYPE], encoding); return (current_categories[LC_CTYPE]); } if (category == LC_COLLATE) { - if (__collate_load_tables(new_categories[LC_COLLATE]) < 0) + if (__collate_load_tables(encoding) < 0) return (NULL); - (void)strcpy(current_categories[LC_COLLATE], - new_categories[LC_COLLATE]); + (void)strcpy(current_categories[LC_COLLATE], encoding); return (current_categories[LC_COLLATE]); } if (category == LC_TIME) { - if (__time_load_locale(new_categories[LC_TIME]) < 0) + if (__time_load_locale(encoding) < 0) return (NULL); - (void)strcpy(current_categories[LC_TIME], - new_categories[LC_TIME]); + (void)strcpy(current_categories[LC_TIME], encoding); return (current_categories[LC_TIME]); } - if (!strcmp(new_categories[category], "C") || - !strcmp(new_categories[category], "POSIX")) { - - /* - * Some day this will need to reset the locale to the default - * C locale. Since we have no way to change them as of yet, - * there is no need to reset them. - */ - (void)strcpy(current_categories[category], - new_categories[category]); + if (category == LC_MONETARY || category == LC_NUMERIC) { + if (stub_load_locale(encoding)) + return (NULL); + (void)strcpy(current_categories[category], encoding); return (current_categories[category]); } + + /* Just in case...*/ + return (NULL); +} + +static int +stub_load_locale(encoding) +const char *encoding; +{ + char name[PATH_MAX]; + struct stat st; + + if (!encoding) + return(1); + /* + * The "C" and "POSIX" locale are always here. + */ + if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) + return(0); + if (!_PathLocale) + return(1); + strcpy(name, _PathLocale); + strcat(name, "/"); + strcat(name, encoding); #if 0 /* * Some day we will actually look at this file. */ - (void)snprintf(name, sizeof(name), "%s/%s/%s", - _PathLocale, new_categories[category], categories[category]); #endif - switch (category) { - case LC_MONETARY: - case LC_NUMERIC: - return (NULL); - } - /* Just in case...*/ - return (NULL); + return (stat(name, &st) != 0 || !S_ISDIR(st.st_mode)); } diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c index 4889667..228efe29 100644 --- a/lib/libc/locale/setrunelocale.c +++ b/lib/libc/locale/setrunelocale.c @@ -78,14 +78,13 @@ _xpg4_setrunelocale(encoding) /* * The "C" and "POSIX" locale are always here. */ - if (!*encoding || !strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) { + if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) { _CurrentRuneLocale = &_DefaultRuneLocale; return(0); } - if (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))) - _PathLocale = _PATH_LOCALE; - + if (!_PathLocale) + return(EFAULT); (void) strcpy(name, _PathLocale); (void) strcat(name, "/"); (void) strcat(name, encoding); |