X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Flocalcharset.c;h=932473c5b342ed4ddfc1a80eacd68ecc7ace0e3f;hb=115741fa52092c59e33d75428b776513caa88f87;hp=0005910b2c9f3e347a1a844c54a0bcd208113db3;hpb=7f69123abb161efe4940eae05ee962d8983759ad;p=gnulib.git diff --git a/lib/localcharset.c b/lib/localcharset.c index 0005910b2..932473c5b 100644 --- a/lib/localcharset.c +++ b/lib/localcharset.c @@ -23,9 +23,16 @@ # include #endif -#include +#if HAVE_STDDEF_H +# include +#endif + #include -#include +#if HAVE_STRING_H +# include +#else +# include +#endif #if HAVE_STDLIB_H # include #endif @@ -38,9 +45,20 @@ # endif #endif -char *xmalloc (); -char *xrealloc (); +#ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +#endif +#ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +#endif + +/* The following static variable is declared 'volatile' to avoid a + possible multithread problem in the function get_charset_aliases. If we + are running in a threaded environment, and if two threads initialize + 'charset_aliases' simultaneously, both will produce the same value, + and everything will be ok if the two assignments to 'charset_aliases' + are atomic. But I don't know what will happen if the two assignments mix. */ /* Pointer to the contents of the charset.alias file, if it has already been read, else NULL. Its format is: ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ @@ -56,10 +74,27 @@ get_charset_aliases () if (cp == NULL) { FILE *fp; + const char *dir = LIBDIR; + const char *base = "charset.alias"; + char *file_name; + + /* Concatenate dir and base into freshly allocated file_name. */ + { + size_t dir_len = strlen (dir); + size_t base_len = strlen (base); + int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); + file_name = (char *) malloc (dir_len + add_slash + base_len + 1); + if (file_name != NULL) + { + memcpy (file_name, dir, dir_len); + if (add_slash) + file_name[dir_len] = DIRECTORY_SEPARATOR; + memcpy (file_name + dir_len + add_slash, base, base_len + 1); + } + } - fp = fopen (LIBDIR "/" "charset.alias", "r"); - if (fp == NULL) - /* File not found, treat it as empty. */ + if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) + /* Out of memory or file not found, treat it as empty. */ cp = ""; else { @@ -96,12 +131,18 @@ get_charset_aliases () if (res_size == 0) { res_size = l1 + 1 + l2 + 1; - res_ptr = xmalloc (res_size + 1); + res_ptr = malloc (res_size + 1); } else { res_size += l1 + 1 + l2 + 1; - res_ptr = xrealloc (res_ptr, res_size + 1); + res_ptr = realloc (res_ptr, res_size + 1); + } + if (res_ptr == NULL) + { + /* Out of memory. */ + res_size = 0; + break; } strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); strcpy (res_ptr + res_size - (l2 + 1), buf2); @@ -117,6 +158,8 @@ get_charset_aliases () } charset_aliases = cp; + if (file_name != NULL) + free (file_name); } return cp; @@ -150,13 +193,13 @@ locale_charset () # if HAVE_SETLOCALE locale = setlocale (LC_CTYPE, NULL); # endif - if (locale == NULL) + if (locale == NULL || locale[0] == '\0') { locale = getenv ("LC_ALL"); - if (locale == NULL) + if (locale == NULL || locale[0] == '\0') { locale = getenv ("LC_CTYPE"); - if (locale == NULL) + if (locale == NULL || locale[0] == '\0') locale = getenv ("LANG"); } } @@ -168,7 +211,7 @@ locale_charset () #endif - if (codeset != NULL) + if (codeset != NULL && codeset[0] != '\0') { /* Resolve alias. */ for (aliases = get_charset_aliases ();