summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1996-11-26 02:49:53 +0000
committerache <ache@FreeBSD.org>1996-11-26 02:49:53 +0000
commitde0f02e3b7cd27d981f14b6dea4859953e240390 (patch)
treea6517b924f385d091b11e9ff009dfec8cd705f08 /lib
parentdcd629b514014b18a3c683df3e53ece7f0b6e4d7 (diff)
downloadFreeBSD-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')
-rw-r--r--lib/libc/locale/collate.c10
-rw-r--r--lib/libc/locale/setlocale.c153
-rw-r--r--lib/libc/locale/setrunelocale.c7
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);
OpenPOWER on IntegriCloud