~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-runtime/intl/localcharset.c

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Determine a canonical name for the current locale's character encoding.
2
2
 
3
 
   Copyright (C) 2000-2006 Free Software Foundation, Inc.
 
3
   Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, Inc.
4
4
 
5
5
   This program is free software; you can redistribute it and/or modify it
6
6
   under the terms of the GNU Library General Public License as published
24
24
/* Specification.  */
25
25
#include "localcharset.h"
26
26
 
 
27
#include <fcntl.h>
27
28
#include <stddef.h>
28
29
#include <stdio.h>
29
30
#include <string.h>
30
31
#include <stdlib.h>
31
32
 
 
33
#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET
 
34
# define DARWIN7 /* Darwin 7 or newer, i.e. MacOS X 10.3 or newer */
 
35
#endif
 
36
 
32
37
#if defined _WIN32 || defined __WIN32__
33
38
# define WIN32_NATIVE
34
39
#endif
35
40
 
36
41
#if defined __EMX__
37
42
/* Assume EMX program runs on OS/2, even if compiled under DOS.  */
38
 
# define OS2
 
43
# ifndef OS2
 
44
#  define OS2
 
45
# endif
39
46
#endif
40
47
 
41
48
#if !defined WIN32_NATIVE
 
49
# include <unistd.h>
42
50
# if HAVE_LANGINFO_CODESET
43
51
#  include <langinfo.h>
44
52
# else
70
78
# include "configmake.h"
71
79
#endif
72
80
 
 
81
/* Define O_NOFOLLOW to 0 on platforms where it does not exist.  */
 
82
#ifndef O_NOFOLLOW
 
83
# define O_NOFOLLOW 0
 
84
#endif
 
85
 
73
86
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
74
87
  /* Win32, Cygwin, OS/2, DOS */
75
88
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
111
124
  cp = charset_aliases;
112
125
  if (cp == NULL)
113
126
    {
114
 
#if !(defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
115
 
      FILE *fp;
 
127
#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
116
128
      const char *dir;
117
129
      const char *base = "charset.alias";
118
130
      char *file_name;
119
131
 
120
132
      /* Make it possible to override the charset.alias location.  This is
121
 
         necessary for running the testsuite before "make install".  */
 
133
         necessary for running the testsuite before "make install".  */
122
134
      dir = getenv ("CHARSETALIASDIR");
123
135
      if (dir == NULL || dir[0] == '\0')
124
 
        dir = relocate (LIBDIR);
 
136
        dir = relocate (LIBDIR);
125
137
 
126
138
      /* Concatenate dir and base into freshly allocated file_name.  */
127
139
      {
128
 
        size_t dir_len = strlen (dir);
129
 
        size_t base_len = strlen (base);
130
 
        int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
131
 
        file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
132
 
        if (file_name != NULL)
133
 
          {
134
 
            memcpy (file_name, dir, dir_len);
135
 
            if (add_slash)
136
 
              file_name[dir_len] = DIRECTORY_SEPARATOR;
137
 
            memcpy (file_name + dir_len + add_slash, base, base_len + 1);
138
 
          }
 
140
        size_t dir_len = strlen (dir);
 
141
        size_t base_len = strlen (base);
 
142
        int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
 
143
        file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
 
144
        if (file_name != NULL)
 
145
          {
 
146
            memcpy (file_name, dir, dir_len);
 
147
            if (add_slash)
 
148
              file_name[dir_len] = DIRECTORY_SEPARATOR;
 
149
            memcpy (file_name + dir_len + add_slash, base, base_len + 1);
 
150
          }
139
151
      }
140
152
 
141
 
      if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
142
 
        /* Out of memory or file not found, treat it as empty.  */
143
 
        cp = "";
 
153
      if (file_name == NULL)
 
154
        /* Out of memory.  Treat the file as empty.  */
 
155
        cp = "";
144
156
      else
145
 
        {
146
 
          /* Parse the file's contents.  */
147
 
          char *res_ptr = NULL;
148
 
          size_t res_size = 0;
149
 
 
150
 
          for (;;)
151
 
            {
152
 
              int c;
153
 
              char buf1[50+1];
154
 
              char buf2[50+1];
155
 
              size_t l1, l2;
156
 
              char *old_res_ptr;
157
 
 
158
 
              c = getc (fp);
159
 
              if (c == EOF)
160
 
                break;
161
 
              if (c == '\n' || c == ' ' || c == '\t')
162
 
                continue;
163
 
              if (c == '#')
164
 
                {
165
 
                  /* Skip comment, to end of line.  */
166
 
                  do
167
 
                    c = getc (fp);
168
 
                  while (!(c == EOF || c == '\n'));
169
 
                  if (c == EOF)
170
 
                    break;
171
 
                  continue;
172
 
                }
173
 
              ungetc (c, fp);
174
 
              if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
175
 
                break;
176
 
              l1 = strlen (buf1);
177
 
              l2 = strlen (buf2);
178
 
              old_res_ptr = res_ptr;
179
 
              if (res_size == 0)
180
 
                {
181
 
                  res_size = l1 + 1 + l2 + 1;
182
 
                  res_ptr = (char *) malloc (res_size + 1);
183
 
                }
184
 
              else
185
 
                {
186
 
                  res_size += l1 + 1 + l2 + 1;
187
 
                  res_ptr = (char *) realloc (res_ptr, res_size + 1);
188
 
                }
189
 
              if (res_ptr == NULL)
190
 
                {
191
 
                  /* Out of memory. */
192
 
                  res_size = 0;
193
 
                  if (old_res_ptr != NULL)
194
 
                    free (old_res_ptr);
195
 
                  break;
196
 
                }
197
 
              strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
198
 
              strcpy (res_ptr + res_size - (l2 + 1), buf2);
199
 
            }
200
 
          fclose (fp);
201
 
          if (res_size == 0)
202
 
            cp = "";
203
 
          else
204
 
            {
205
 
              *(res_ptr + res_size) = '\0';
206
 
              cp = res_ptr;
207
 
            }
208
 
        }
209
 
 
210
 
      if (file_name != NULL)
211
 
        free (file_name);
 
157
        {
 
158
          int fd;
 
159
 
 
160
          /* Open the file.  Reject symbolic links on platforms that support
 
161
             O_NOFOLLOW.  This is a security feature.  Without it, an attacker
 
162
             could retrieve parts of the contents (namely, the tail of the
 
163
             first line that starts with "* ") of an arbitrary file by placing
 
164
             a symbolic link to that file under the name "charset.alias" in
 
165
             some writable directory and defining the environment variable
 
166
             CHARSETALIASDIR to point to that directory.  */
 
167
          fd = open (file_name,
 
168
                     O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0));
 
169
          if (fd < 0)
 
170
            /* File not found.  Treat it as empty.  */
 
171
            cp = "";
 
172
          else
 
173
            {
 
174
              FILE *fp;
 
175
 
 
176
              fp = fdopen (fd, "r");
 
177
              if (fp == NULL)
 
178
                {
 
179
                  /* Out of memory.  Treat the file as empty.  */
 
180
                  close (fd);
 
181
                  cp = "";
 
182
                }
 
183
              else
 
184
                {
 
185
                  /* Parse the file's contents.  */
 
186
                  char *res_ptr = NULL;
 
187
                  size_t res_size = 0;
 
188
 
 
189
                  for (;;)
 
190
                    {
 
191
                      int c;
 
192
                      char buf1[50+1];
 
193
                      char buf2[50+1];
 
194
                      size_t l1, l2;
 
195
                      char *old_res_ptr;
 
196
 
 
197
                      c = getc (fp);
 
198
                      if (c == EOF)
 
199
                        break;
 
200
                      if (c == '\n' || c == ' ' || c == '\t')
 
201
                        continue;
 
202
                      if (c == '#')
 
203
                        {
 
204
                          /* Skip comment, to end of line.  */
 
205
                          do
 
206
                            c = getc (fp);
 
207
                          while (!(c == EOF || c == '\n'));
 
208
                          if (c == EOF)
 
209
                            break;
 
210
                          continue;
 
211
                        }
 
212
                      ungetc (c, fp);
 
213
                      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
 
214
                        break;
 
215
                      l1 = strlen (buf1);
 
216
                      l2 = strlen (buf2);
 
217
                      old_res_ptr = res_ptr;
 
218
                      if (res_size == 0)
 
219
                        {
 
220
                          res_size = l1 + 1 + l2 + 1;
 
221
                          res_ptr = (char *) malloc (res_size + 1);
 
222
                        }
 
223
                      else
 
224
                        {
 
225
                          res_size += l1 + 1 + l2 + 1;
 
226
                          res_ptr = (char *) realloc (res_ptr, res_size + 1);
 
227
                        }
 
228
                      if (res_ptr == NULL)
 
229
                        {
 
230
                          /* Out of memory. */
 
231
                          res_size = 0;
 
232
                          if (old_res_ptr != NULL)
 
233
                            free (old_res_ptr);
 
234
                          break;
 
235
                        }
 
236
                      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
 
237
                      strcpy (res_ptr + res_size - (l2 + 1), buf2);
 
238
                    }
 
239
                  fclose (fp);
 
240
                  if (res_size == 0)
 
241
                    cp = "";
 
242
                  else
 
243
                    {
 
244
                      *(res_ptr + res_size) = '\0';
 
245
                      cp = res_ptr;
 
246
                    }
 
247
                }
 
248
            }
 
249
 
 
250
          free (file_name);
 
251
        }
212
252
 
213
253
#else
214
254
 
 
255
# if defined DARWIN7
 
256
      /* To avoid the trouble of installing a file that is shared by many
 
257
         GNU packages -- many packaging systems have problems with this --,
 
258
         simply inline the aliases here.  */
 
259
      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
 
260
           "ISO8859-2" "\0" "ISO-8859-2" "\0"
 
261
           "ISO8859-4" "\0" "ISO-8859-4" "\0"
 
262
           "ISO8859-5" "\0" "ISO-8859-5" "\0"
 
263
           "ISO8859-7" "\0" "ISO-8859-7" "\0"
 
264
           "ISO8859-9" "\0" "ISO-8859-9" "\0"
 
265
           "ISO8859-13" "\0" "ISO-8859-13" "\0"
 
266
           "ISO8859-15" "\0" "ISO-8859-15" "\0"
 
267
           "KOI8-R" "\0" "KOI8-R" "\0"
 
268
           "KOI8-U" "\0" "KOI8-U" "\0"
 
269
           "CP866" "\0" "CP866" "\0"
 
270
           "CP949" "\0" "CP949" "\0"
 
271
           "CP1131" "\0" "CP1131" "\0"
 
272
           "CP1251" "\0" "CP1251" "\0"
 
273
           "eucCN" "\0" "GB2312" "\0"
 
274
           "GB2312" "\0" "GB2312" "\0"
 
275
           "eucJP" "\0" "EUC-JP" "\0"
 
276
           "eucKR" "\0" "EUC-KR" "\0"
 
277
           "Big5" "\0" "BIG5" "\0"
 
278
           "Big5HKSCS" "\0" "BIG5-HKSCS" "\0"
 
279
           "GBK" "\0" "GBK" "\0"
 
280
           "GB18030" "\0" "GB18030" "\0"
 
281
           "SJIS" "\0" "SHIFT_JIS" "\0"
 
282
           "ARMSCII-8" "\0" "ARMSCII-8" "\0"
 
283
           "PT154" "\0" "PT154" "\0"
 
284
         /*"ISCII-DEV" "\0" "?" "\0"*/
 
285
           "*" "\0" "UTF-8" "\0";
 
286
# endif
 
287
 
215
288
# if defined VMS
216
289
      /* To avoid the troubles of an extra file charset.alias_vms in the
217
 
         sources of many GNU packages, simply inline the aliases here.  */
 
290
         sources of many GNU packages, simply inline the aliases here.  */
218
291
      /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
219
 
         "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
220
 
         section 10.7 "Handling Different Character Sets".  */
 
292
         "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
 
293
         section 10.7 "Handling Different Character Sets".  */
221
294
      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
222
 
           "ISO8859-2" "\0" "ISO-8859-2" "\0"
223
 
           "ISO8859-5" "\0" "ISO-8859-5" "\0"
224
 
           "ISO8859-7" "\0" "ISO-8859-7" "\0"
225
 
           "ISO8859-8" "\0" "ISO-8859-8" "\0"
226
 
           "ISO8859-9" "\0" "ISO-8859-9" "\0"
227
 
           /* Japanese */
228
 
           "eucJP" "\0" "EUC-JP" "\0"
229
 
           "SJIS" "\0" "SHIFT_JIS" "\0"
230
 
           "DECKANJI" "\0" "DEC-KANJI" "\0"
231
 
           "SDECKANJI" "\0" "EUC-JP" "\0"
232
 
           /* Chinese */
233
 
           "eucTW" "\0" "EUC-TW" "\0"
234
 
           "DECHANYU" "\0" "DEC-HANYU" "\0"
235
 
           "DECHANZI" "\0" "GB2312" "\0"
236
 
           /* Korean */
237
 
           "DECKOREAN" "\0" "EUC-KR" "\0";
 
295
           "ISO8859-2" "\0" "ISO-8859-2" "\0"
 
296
           "ISO8859-5" "\0" "ISO-8859-5" "\0"
 
297
           "ISO8859-7" "\0" "ISO-8859-7" "\0"
 
298
           "ISO8859-8" "\0" "ISO-8859-8" "\0"
 
299
           "ISO8859-9" "\0" "ISO-8859-9" "\0"
 
300
           /* Japanese */
 
301
           "eucJP" "\0" "EUC-JP" "\0"
 
302
           "SJIS" "\0" "SHIFT_JIS" "\0"
 
303
           "DECKANJI" "\0" "DEC-KANJI" "\0"
 
304
           "SDECKANJI" "\0" "EUC-JP" "\0"
 
305
           /* Chinese */
 
306
           "eucTW" "\0" "EUC-TW" "\0"
 
307
           "DECHANYU" "\0" "DEC-HANYU" "\0"
 
308
           "DECHANZI" "\0" "GB2312" "\0"
 
309
           /* Korean */
 
310
           "DECKOREAN" "\0" "EUC-KR" "\0";
238
311
# endif
239
312
 
240
313
# if defined WIN32_NATIVE || defined __CYGWIN__
241
314
      /* To avoid the troubles of installing a separate file in the same
242
 
         directory as the DLL and of retrieving the DLL's directory at
243
 
         runtime, simply inline the aliases here.  */
 
315
         directory as the DLL and of retrieving the DLL's directory at
 
316
         runtime, simply inline the aliases here.  */
244
317
 
245
318
      cp = "CP936" "\0" "GBK" "\0"
246
 
           "CP1361" "\0" "JOHAB" "\0"
247
 
           "CP20127" "\0" "ASCII" "\0"
248
 
           "CP20866" "\0" "KOI8-R" "\0"
249
 
           "CP20936" "\0" "GB2312" "\0"
250
 
           "CP21866" "\0" "KOI8-RU" "\0"
251
 
           "CP28591" "\0" "ISO-8859-1" "\0"
252
 
           "CP28592" "\0" "ISO-8859-2" "\0"
253
 
           "CP28593" "\0" "ISO-8859-3" "\0"
254
 
           "CP28594" "\0" "ISO-8859-4" "\0"
255
 
           "CP28595" "\0" "ISO-8859-5" "\0"
256
 
           "CP28596" "\0" "ISO-8859-6" "\0"
257
 
           "CP28597" "\0" "ISO-8859-7" "\0"
258
 
           "CP28598" "\0" "ISO-8859-8" "\0"
259
 
           "CP28599" "\0" "ISO-8859-9" "\0"
260
 
           "CP28605" "\0" "ISO-8859-15" "\0"
261
 
           "CP38598" "\0" "ISO-8859-8" "\0"
262
 
           "CP51932" "\0" "EUC-JP" "\0"
263
 
           "CP51936" "\0" "GB2312" "\0"
264
 
           "CP51949" "\0" "EUC-KR" "\0"
265
 
           "CP51950" "\0" "EUC-TW" "\0"
266
 
           "CP54936" "\0" "GB18030" "\0"
267
 
           "CP65001" "\0" "UTF-8" "\0";
 
319
           "CP1361" "\0" "JOHAB" "\0"
 
320
           "CP20127" "\0" "ASCII" "\0"
 
321
           "CP20866" "\0" "KOI8-R" "\0"
 
322
           "CP20936" "\0" "GB2312" "\0"
 
323
           "CP21866" "\0" "KOI8-RU" "\0"
 
324
           "CP28591" "\0" "ISO-8859-1" "\0"
 
325
           "CP28592" "\0" "ISO-8859-2" "\0"
 
326
           "CP28593" "\0" "ISO-8859-3" "\0"
 
327
           "CP28594" "\0" "ISO-8859-4" "\0"
 
328
           "CP28595" "\0" "ISO-8859-5" "\0"
 
329
           "CP28596" "\0" "ISO-8859-6" "\0"
 
330
           "CP28597" "\0" "ISO-8859-7" "\0"
 
331
           "CP28598" "\0" "ISO-8859-8" "\0"
 
332
           "CP28599" "\0" "ISO-8859-9" "\0"
 
333
           "CP28605" "\0" "ISO-8859-15" "\0"
 
334
           "CP38598" "\0" "ISO-8859-8" "\0"
 
335
           "CP51932" "\0" "EUC-JP" "\0"
 
336
           "CP51936" "\0" "GB2312" "\0"
 
337
           "CP51949" "\0" "EUC-KR" "\0"
 
338
           "CP51950" "\0" "EUC-TW" "\0"
 
339
           "CP54936" "\0" "GB18030" "\0"
 
340
           "CP65001" "\0" "UTF-8" "\0";
268
341
# endif
269
342
#endif
270
343
 
297
370
  codeset = nl_langinfo (CODESET);
298
371
 
299
372
#  ifdef __CYGWIN__
300
 
  /* Cygwin 2006 does not have locales.  nl_langinfo (CODESET) always
301
 
     returns "US-ASCII".  As long as this is not fixed, return the suffix
302
 
     of the locale name from the environment variables (if present) or
303
 
     the codepage as a number.  */
 
373
  /* Cygwin < 1.7 does not have locales.  nl_langinfo (CODESET) always
 
374
     returns "US-ASCII".  Return the suffix of the locale name from the
 
375
     environment variables (if present) or the codepage as a number.  */
304
376
  if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
305
377
    {
306
378
      const char *locale;
308
380
 
309
381
      locale = getenv ("LC_ALL");
310
382
      if (locale == NULL || locale[0] == '\0')
311
 
        {
312
 
          locale = getenv ("LC_CTYPE");
313
 
          if (locale == NULL || locale[0] == '\0')
314
 
            locale = getenv ("LANG");
315
 
        }
 
383
        {
 
384
          locale = getenv ("LC_CTYPE");
 
385
          if (locale == NULL || locale[0] == '\0')
 
386
            locale = getenv ("LANG");
 
387
        }
316
388
      if (locale != NULL && locale[0] != '\0')
317
 
        {
318
 
          /* If the locale name contains an encoding after the dot, return
319
 
             it.  */
320
 
          const char *dot = strchr (locale, '.');
321
 
 
322
 
          if (dot != NULL)
323
 
            {
324
 
              const char *modifier;
325
 
 
326
 
              dot++;
327
 
              /* Look for the possible @... trailer and remove it, if any.  */
328
 
              modifier = strchr (dot, '@');
329
 
              if (modifier == NULL)
330
 
                return dot;
331
 
              if (modifier - dot < sizeof (buf))
332
 
                {
333
 
                  memcpy (buf, dot, modifier - dot);
334
 
                  buf [modifier - dot] = '\0';
335
 
                  return buf;
336
 
                }
337
 
            }
338
 
        }
339
 
 
340
 
      /* Woe32 has a function returning the locale's codepage as a number.  */
 
389
        {
 
390
          /* If the locale name contains an encoding after the dot, return
 
391
             it.  */
 
392
          const char *dot = strchr (locale, '.');
 
393
 
 
394
          if (dot != NULL)
 
395
            {
 
396
              const char *modifier;
 
397
 
 
398
              dot++;
 
399
              /* Look for the possible @... trailer and remove it, if any.  */
 
400
              modifier = strchr (dot, '@');
 
401
              if (modifier == NULL)
 
402
                return dot;
 
403
              if (modifier - dot < sizeof (buf))
 
404
                {
 
405
                  memcpy (buf, dot, modifier - dot);
 
406
                  buf [modifier - dot] = '\0';
 
407
                  return buf;
 
408
                }
 
409
            }
 
410
        }
 
411
 
 
412
      /* Woe32 has a function returning the locale's codepage as a number:
 
413
         GetACP().  This encoding is used by Cygwin, unless the user has set
 
414
         the environment variable CYGWIN=codepage:oem (which very few people
 
415
         do).
 
416
         Output directed to console windows needs to be converted (to
 
417
         GetOEMCP() if the console is using a raster font, or to
 
418
         GetConsoleOutputCP() if it is using a TrueType font).  Cygwin does
 
419
         this conversion transparently (see winsup/cygwin/fhandler_console.cc),
 
420
         converting to GetConsoleOutputCP().  This leads to correct results,
 
421
         except when SetConsoleOutputCP has been called and a raster font is
 
422
         in use.  */
341
423
      sprintf (buf, "CP%u", GetACP ());
342
424
      codeset = buf;
343
425
    }
359
441
    {
360
442
      locale = getenv ("LC_ALL");
361
443
      if (locale == NULL || locale[0] == '\0')
362
 
        {
363
 
          locale = getenv ("LC_CTYPE");
364
 
          if (locale == NULL || locale[0] == '\0')
365
 
            locale = getenv ("LANG");
366
 
        }
 
444
        {
 
445
          locale = getenv ("LC_CTYPE");
 
446
          if (locale == NULL || locale[0] == '\0')
 
447
            locale = getenv ("LANG");
 
448
        }
367
449
    }
368
450
 
369
451
  /* On some old systems, one used to set locale = "iso8859_1". On others,
377
459
 
378
460
  static char buf[2 + 10 + 1];
379
461
 
380
 
  /* Woe32 has a function returning the locale's codepage as a number.  */
 
462
  /* Woe32 has a function returning the locale's codepage as a number:
 
463
     GetACP().
 
464
     When the output goes to a console window, it needs to be provided in
 
465
     GetOEMCP() encoding if the console is using a raster font, or in
 
466
     GetConsoleOutputCP() encoding if it is using a TrueType font.
 
467
     But in GUI programs and for output sent to files and pipes, GetACP()
 
468
     encoding is the best bet.  */
381
469
  sprintf (buf, "CP%u", GetACP ());
382
470
  codeset = buf;
383
471
 
395
483
    {
396
484
      locale = getenv ("LC_CTYPE");
397
485
      if (locale == NULL || locale[0] == '\0')
398
 
        locale = getenv ("LANG");
 
486
        locale = getenv ("LANG");
399
487
    }
400
488
  if (locale != NULL && locale[0] != '\0')
401
489
    {
403
491
      const char *dot = strchr (locale, '.');
404
492
 
405
493
      if (dot != NULL)
406
 
        {
407
 
          const char *modifier;
 
494
        {
 
495
          const char *modifier;
408
496
 
409
 
          dot++;
410
 
          /* Look for the possible @... trailer and remove it, if any.  */
411
 
          modifier = strchr (dot, '@');
412
 
          if (modifier == NULL)
413
 
            return dot;
414
 
          if (modifier - dot < sizeof (buf))
415
 
            {
416
 
              memcpy (buf, dot, modifier - dot);
417
 
              buf [modifier - dot] = '\0';
418
 
              return buf;
419
 
            }
420
 
        }
 
497
          dot++;
 
498
          /* Look for the possible @... trailer and remove it, if any.  */
 
499
          modifier = strchr (dot, '@');
 
500
          if (modifier == NULL)
 
501
            return dot;
 
502
          if (modifier - dot < sizeof (buf))
 
503
            {
 
504
              memcpy (buf, dot, modifier - dot);
 
505
              buf [modifier - dot] = '\0';
 
506
              return buf;
 
507
            }
 
508
        }
421
509
 
422
510
      /* Resolve through the charset.alias file.  */
423
511
      codeset = locale;
426
514
    {
427
515
      /* OS/2 has a function returning the locale's codepage as a number.  */
428
516
      if (DosQueryCp (sizeof (cp), cp, &cplen))
429
 
        codeset = "";
 
517
        codeset = "";
430
518
      else
431
 
        {
432
 
          sprintf (buf, "CP%u", cp[0]);
433
 
          codeset = buf;
434
 
        }
 
519
        {
 
520
          sprintf (buf, "CP%u", cp[0]);
 
521
          codeset = buf;
 
522
        }
435
523
    }
436
524
 
437
525
#endif
445
533
       *aliases != '\0';
446
534
       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
447
535
    if (strcmp (codeset, aliases) == 0
448
 
        || (aliases[0] == '*' && aliases[1] == '\0'))
 
536
        || (aliases[0] == '*' && aliases[1] == '\0'))
449
537
      {
450
 
        codeset = aliases + strlen (aliases) + 1;
451
 
        break;
 
538
        codeset = aliases + strlen (aliases) + 1;
 
539
        break;
452
540
      }
453
541
 
454
542
  /* Don't return an empty string.  GNU libc and GNU libiconv interpret