# include <config.h>
#endif
-#include <stddef.h>
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
#include <stdio.h>
-#include <string.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
# 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' */
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
{
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);
}
charset_aliases = cp;
+ if (file_name != NULL)
+ free (file_name);
}
return cp;
# 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");
}
}
#endif
- if (codeset != NULL)
+ if (codeset != NULL && codeset[0] != '\0')
{
/* Resolve alias. */
for (aliases = get_charset_aliases ();