105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Determine a canonical name for the current locale's character encoding. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2000-2006, 2008-2012 Free Software Foundation, Inc. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software; you can redistribute it and/or modify 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3, or (at your option) 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License along 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang with this program; if not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Written by Bruno Haible <bruno@clisp.org>. */ 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "localcharset.h" 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <fcntl.h> 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stddef.h> 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio.h> 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <string.h> 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined _WIN32 || defined __WIN32__ 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define WINDOWS_NATIVE 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined __EMX__ 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assume EMX program runs on OS/2, even if compiled under DOS. */ 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifndef OS2 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define OS2 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !defined WINDOWS_NATIVE 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <unistd.h> 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_LANGINFO_CODESET 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <langinfo.h> 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if 0 /* see comment below */ 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <locale.h> 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifdef __CYGWIN__ 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define WIN32_LEAN_AND_MEAN 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <windows.h> 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif defined WINDOWS_NATIVE 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define WIN32_LEAN_AND_MEAN 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <windows.h> 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined OS2 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define INCL_DOS 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <os2.h> 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if ENABLE_RELOCATABLE 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "relocatable.h" 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define relocate(pathname) (pathname) 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get LIBDIR. */ 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef LIBDIR 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "configmake.h" 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */ 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef O_NOFOLLOW 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define O_NOFOLLOW 0 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Native Windows, Cygwin, OS/2, DOS */ 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define ISSLASH(C) ((C) == '/' || (C) == '\\') 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef DIRECTORY_SEPARATOR 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define DIRECTORY_SEPARATOR '/' 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef ISSLASH 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_DECL_GETC_UNLOCKED 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef getc 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define getc getc_unlocked 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The following static variable is declared 'volatile' to avoid a 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang possible multithread problem in the function get_charset_aliases. If we 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang are running in a threaded environment, and if two threads initialize 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 'charset_aliases' simultaneously, both will produce the same value, 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang and everything will be ok if the two assignments to 'charset_aliases' 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang are atomic. But I don't know what will happen if the two assignments mix. */ 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __STDC__ != 1 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define volatile /* empty */ 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Pointer to the contents of the charset.alias file, if it has already been 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang read, else NULL. Its format is: 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic const char * volatile charset_aliases; 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Return a pointer to the contents of the charset.alias file. */ 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic const char * 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wangget_charset_aliases (void) 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *cp; 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = charset_aliases; 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (cp == NULL) 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__) 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *dir; 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *base = "charset.alias"; 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *file_name; 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Make it possible to override the charset.alias location. This is 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang necessary for running the testsuite before "make install". */ 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang dir = getenv ("CHARSETALIASDIR"); 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dir == NULL || dir[0] == '\0') 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang dir = relocate (LIBDIR); 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Concatenate dir and base into freshly allocated file_name. */ 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t dir_len = strlen (dir); 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t base_len = strlen (base); 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang file_name = (char *) malloc (dir_len + add_slash + base_len + 1); 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (file_name != NULL) 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (file_name, dir, dir_len); 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (add_slash) 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang file_name[dir_len] = DIRECTORY_SEPARATOR; 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (file_name + dir_len + add_slash, base, base_len + 1); 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (file_name == NULL) 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Out of memory. Treat the file as empty. */ 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = ""; 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd; 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Open the file. Reject symbolic links on platforms that support 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang O_NOFOLLOW. This is a security feature. Without it, an attacker 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang could retrieve parts of the contents (namely, the tail of the 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang first line that starts with "* ") of an arbitrary file by placing 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang a symbolic link to that file under the name "charset.alias" in 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang some writable directory and defining the environment variable 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang CHARSETALIASDIR to point to that directory. */ 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang fd = open (file_name, 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0)); 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fd < 0) 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* File not found. Treat it as empty. */ 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = ""; 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang FILE *fp; 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang fp = fdopen (fd, "r"); 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fp == NULL) 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Out of memory. Treat the file as empty. */ 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang close (fd); 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = ""; 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Parse the file's contents. */ 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *res_ptr = NULL; 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t res_size = 0; 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (;;) 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int c; 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang char buf1[50+1]; 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang char buf2[50+1]; 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t l1, l2; 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *old_res_ptr; 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang c = getc (fp); 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (c == EOF) 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (c == '\n' || c == ' ' || c == '\t') 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang continue; 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (c == '#') 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Skip comment, to end of line. */ 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang c = getc (fp); 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!(c == EOF || c == '\n')); 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (c == EOF) 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang continue; 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang ungetc (c, fp); 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang l1 = strlen (buf1); 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang l2 = strlen (buf2); 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang old_res_ptr = res_ptr; 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (res_size == 0) 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang res_size = l1 + 1 + l2 + 1; 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang res_ptr = (char *) malloc (res_size + 1); 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang res_size += l1 + 1 + l2 + 1; 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang res_ptr = (char *) realloc (res_ptr, res_size + 1); 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (res_ptr == NULL) 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Out of memory. */ 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang res_size = 0; 23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (old_res_ptr); 23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); 23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang strcpy (res_ptr + res_size - (l2 + 1), buf2); 23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang fclose (fp); 23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (res_size == 0) 23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = ""; 23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang *(res_ptr + res_size) = '\0'; 24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = res_ptr; 24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (file_name); 24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if defined DARWIN7 25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* To avoid the trouble of installing a file that is shared by many 25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU packages -- many packaging systems have problems with this --, 25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang simply inline the aliases here. */ 25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" 25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-2" "\0" "ISO-8859-2" "\0" 25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-4" "\0" "ISO-8859-4" "\0" 25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-5" "\0" "ISO-8859-5" "\0" 26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-7" "\0" "ISO-8859-7" "\0" 26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-9" "\0" "ISO-8859-9" "\0" 26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-13" "\0" "ISO-8859-13" "\0" 26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-15" "\0" "ISO-8859-15" "\0" 26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "KOI8-R" "\0" "KOI8-R" "\0" 26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "KOI8-U" "\0" "KOI8-U" "\0" 26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP866" "\0" "CP866" "\0" 26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP949" "\0" "CP949" "\0" 26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP1131" "\0" "CP1131" "\0" 26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP1251" "\0" "CP1251" "\0" 27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "eucCN" "\0" "GB2312" "\0" 27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang "GB2312" "\0" "GB2312" "\0" 27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "eucJP" "\0" "EUC-JP" "\0" 27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "eucKR" "\0" "EUC-KR" "\0" 27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "Big5" "\0" "BIG5" "\0" 27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" 27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "GBK" "\0" "GBK" "\0" 27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "GB18030" "\0" "GB18030" "\0" 27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "SJIS" "\0" "SHIFT_JIS" "\0" 27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ARMSCII-8" "\0" "ARMSCII-8" "\0" 28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "PT154" "\0" "PT154" "\0" 28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /*"ISCII-DEV" "\0" "?" "\0"*/ 28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "*" "\0" "UTF-8" "\0"; 28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if defined VMS 28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* To avoid the troubles of an extra file charset.alias_vms in the 28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang sources of many GNU packages, simply inline the aliases here. */ 28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The list of encodings is taken from the OpenVMS 7.3-1 documentation 28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "Compaq C Run-Time Library Reference Manual for OpenVMS systems" 29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang section 10.7 "Handling Different Character Sets". */ 29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" 29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-2" "\0" "ISO-8859-2" "\0" 29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-5" "\0" "ISO-8859-5" "\0" 29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-7" "\0" "ISO-8859-7" "\0" 29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-8" "\0" "ISO-8859-8" "\0" 29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "ISO8859-9" "\0" "ISO-8859-9" "\0" 29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Japanese */ 29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "eucJP" "\0" "EUC-JP" "\0" 29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "SJIS" "\0" "SHIFT_JIS" "\0" 30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "DECKANJI" "\0" "DEC-KANJI" "\0" 30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang "SDECKANJI" "\0" "EUC-JP" "\0" 30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Chinese */ 30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "eucTW" "\0" "EUC-TW" "\0" 30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "DECHANYU" "\0" "DEC-HANYU" "\0" 30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "DECHANZI" "\0" "GB2312" "\0" 30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Korean */ 30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "DECKOREAN" "\0" "EUC-KR" "\0"; 30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if defined WINDOWS_NATIVE || defined __CYGWIN__ 31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* To avoid the troubles of installing a separate file in the same 31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang directory as the DLL and of retrieving the DLL's directory at 31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang runtime, simply inline the aliases here. */ 31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = "CP936" "\0" "GBK" "\0" 31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP1361" "\0" "JOHAB" "\0" 31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP20127" "\0" "ASCII" "\0" 31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP20866" "\0" "KOI8-R" "\0" 31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP20936" "\0" "GB2312" "\0" 32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP21866" "\0" "KOI8-RU" "\0" 32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28591" "\0" "ISO-8859-1" "\0" 32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28592" "\0" "ISO-8859-2" "\0" 32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28593" "\0" "ISO-8859-3" "\0" 32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28594" "\0" "ISO-8859-4" "\0" 32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28595" "\0" "ISO-8859-5" "\0" 32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28596" "\0" "ISO-8859-6" "\0" 32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28597" "\0" "ISO-8859-7" "\0" 32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28598" "\0" "ISO-8859-8" "\0" 32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28599" "\0" "ISO-8859-9" "\0" 33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP28605" "\0" "ISO-8859-15" "\0" 33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP38598" "\0" "ISO-8859-8" "\0" 33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP51932" "\0" "EUC-JP" "\0" 33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP51936" "\0" "GB2312" "\0" 33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP51949" "\0" "EUC-KR" "\0" 33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP51950" "\0" "EUC-TW" "\0" 33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP54936" "\0" "GB18030" "\0" 33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "CP65001" "\0" "UTF-8" "\0"; 33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang charset_aliases = cp; 34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return cp; 34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Determine the current locale's character encoding, and canonicalize it 34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang into one of the canonical names listed in config.charset. 34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang The result must not be freed; it is statically allocated. 35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang If the canonical name cannot be determined, the result is a non-canonical 35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang name. */ 35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef STATIC 35405436638acc7c010349a69c3395f1a57c642dc62Ying WangSTATIC 35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 35605436638acc7c010349a69c3395f1a57c642dc62Ying Wangconst char * 35705436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocale_charset (void) 35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *codeset; 36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *aliases; 36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !(defined WINDOWS_NATIVE || defined OS2) 36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_LANGINFO_CODESET 36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 36605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Most systems support nl_langinfo (CODESET) nowadays. */ 36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = nl_langinfo (CODESET); 36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifdef __CYGWIN__ 37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always 37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang returns "US-ASCII". Return the suffix of the locale name from the 37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang environment variables (if present) or the codepage as a number. */ 37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) 37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *locale; 37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang static char buf[2 + 10 + 1]; 37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_ALL"); 37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_CTYPE"); 38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LANG"); 38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale != NULL && locale[0] != '\0') 38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If the locale name contains an encoding after the dot, return 38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang it. */ 38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *dot = strchr (locale, '.'); 39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dot != NULL) 39205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 39305436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *modifier; 39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang dot++; 39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Look for the possible @... trailer and remove it, if any. */ 39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang modifier = strchr (dot, '@'); 39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (modifier == NULL) 39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return dot; 40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (modifier - dot < sizeof (buf)) 40105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 40205436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (buf, dot, modifier - dot); 40305436638acc7c010349a69c3395f1a57c642dc62Ying Wang buf [modifier - dot] = '\0'; 40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return buf; 40505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 40605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The Windows API has a function returning the locale's codepage as a 41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang number: GetACP(). This encoding is used by Cygwin, unless the user 41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang has set the environment variable CYGWIN=codepage:oem (which very few 41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang people do). 41305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Output directed to console windows needs to be converted (to 41405436638acc7c010349a69c3395f1a57c642dc62Ying Wang GetOEMCP() if the console is using a raster font, or to 41505436638acc7c010349a69c3395f1a57c642dc62Ying Wang GetConsoleOutputCP() if it is using a TrueType font). Cygwin does 41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang this conversion transparently (see winsup/cygwin/fhandler_console.cc), 41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang converting to GetConsoleOutputCP(). This leads to correct results, 41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang except when SetConsoleOutputCP has been called and a raster font is 41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang in use. */ 42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang sprintf (buf, "CP%u", GetACP ()); 42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = buf; 42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 42605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 42705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* On old systems which lack it, use setlocale or getenv. */ 42805436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *locale = NULL; 42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* But most old systems don't have a complete set of locales. Some 43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't 43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang use setlocale here; it would return "C" when it doesn't support the 43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale name the user has set. */ 43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if 0 43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = setlocale (LC_CTYPE, NULL); 43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 43705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 43805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_ALL"); 44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 44205436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_CTYPE"); 44305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LANG"); 44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* On some old systems, one used to set locale = "iso8859_1". On others, 44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang you set it to "language_COUNTRY.charset". In any case, we resolve it 45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang through the charset.alias file. */ 45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = locale; 45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 45405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif defined WINDOWS_NATIVE 45605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45705436638acc7c010349a69c3395f1a57c642dc62Ying Wang static char buf[2 + 10 + 1]; 45805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The Windows API has a function returning the locale's codepage as a 46005436638acc7c010349a69c3395f1a57c642dc62Ying Wang number: GetACP(). 46105436638acc7c010349a69c3395f1a57c642dc62Ying Wang When the output goes to a console window, it needs to be provided in 46205436638acc7c010349a69c3395f1a57c642dc62Ying Wang GetOEMCP() encoding if the console is using a raster font, or in 46305436638acc7c010349a69c3395f1a57c642dc62Ying Wang GetConsoleOutputCP() encoding if it is using a TrueType font. 46405436638acc7c010349a69c3395f1a57c642dc62Ying Wang But in GUI programs and for output sent to files and pipes, GetACP() 46505436638acc7c010349a69c3395f1a57c642dc62Ying Wang encoding is the best bet. */ 46605436638acc7c010349a69c3395f1a57c642dc62Ying Wang sprintf (buf, "CP%u", GetACP ()); 46705436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = buf; 46805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 46905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif defined OS2 47005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47105436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *locale; 47205436638acc7c010349a69c3395f1a57c642dc62Ying Wang static char buf[2 + 10 + 1]; 47305436638acc7c010349a69c3395f1a57c642dc62Ying Wang ULONG cp[3]; 47405436638acc7c010349a69c3395f1a57c642dc62Ying Wang ULONG cplen; 47505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Allow user to override the codeset, as set in the operating system, 47705436638acc7c010349a69c3395f1a57c642dc62Ying Wang with standard language environment variables. */ 47805436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_ALL"); 47905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 48005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 48105436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LC_CTYPE"); 48205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale == NULL || locale[0] == '\0') 48305436638acc7c010349a69c3395f1a57c642dc62Ying Wang locale = getenv ("LANG"); 48405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 48505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (locale != NULL && locale[0] != '\0') 48605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 48705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If the locale name contains an encoding after the dot, return it. */ 48805436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *dot = strchr (locale, '.'); 48905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 49005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dot != NULL) 49105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 49205436638acc7c010349a69c3395f1a57c642dc62Ying Wang const char *modifier; 49305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 49405436638acc7c010349a69c3395f1a57c642dc62Ying Wang dot++; 49505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Look for the possible @... trailer and remove it, if any. */ 49605436638acc7c010349a69c3395f1a57c642dc62Ying Wang modifier = strchr (dot, '@'); 49705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (modifier == NULL) 49805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return dot; 49905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (modifier - dot < sizeof (buf)) 50005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 50105436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (buf, dot, modifier - dot); 50205436638acc7c010349a69c3395f1a57c642dc62Ying Wang buf [modifier - dot] = '\0'; 50305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return buf; 50405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 50505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 50605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 50705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Resolve through the charset.alias file. */ 50805436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = locale; 50905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 51005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 51105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 51205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* OS/2 has a function returning the locale's codepage as a number. */ 51305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (DosQueryCp (sizeof (cp), cp, &cplen)) 51405436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = ""; 51505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 51605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 51705436638acc7c010349a69c3395f1a57c642dc62Ying Wang sprintf (buf, "CP%u", cp[0]); 51805436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = buf; 51905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 52005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 52105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 52305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (codeset == NULL) 52505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The canonical name cannot be determined. */ 52605436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = ""; 52705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Resolve alias. */ 52905436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (aliases = get_charset_aliases (); 53005436638acc7c010349a69c3395f1a57c642dc62Ying Wang *aliases != '\0'; 53105436638acc7c010349a69c3395f1a57c642dc62Ying Wang aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) 53205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (strcmp (codeset, aliases) == 0 53305436638acc7c010349a69c3395f1a57c642dc62Ying Wang || (aliases[0] == '*' && aliases[1] == '\0')) 53405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 53505436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = aliases + strlen (aliases) + 1; 53605436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 53705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 53805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 53905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Don't return an empty string. GNU libc and GNU libiconv interpret 54005436638acc7c010349a69c3395f1a57c642dc62Ying Wang the empty string as denoting "the locale's character encoding", 54105436638acc7c010349a69c3395f1a57c642dc62Ying Wang thus GNU libiconv would call this function a second time. */ 54205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (codeset[0] == '\0') 54305436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = "ASCII"; 54405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 54505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef DARWIN7 54605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8" 54705436638acc7c010349a69c3395f1a57c642dc62Ying Wang (the default codeset) does not work when MB_CUR_MAX is 1. */ 54805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX <= 1) 54905436638acc7c010349a69c3395f1a57c642dc62Ying Wang codeset = "ASCII"; 55005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 55105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 55205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return codeset; 55305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 554