~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-updates

« back to all changes in this revision

Viewing changes to intl/localealias.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Handle aliases for locale names.
2
 
   Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc.
3
 
 
4
 
   This program is free software; you can redistribute it and/or modify it
5
 
   under the terms of the GNU Library General Public License as published
6
 
   by the Free Software Foundation; either version 2, or (at your option)
7
 
   any later version.
8
 
 
9
 
   This program is distributed in the hope that it will be useful,
10
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
   Library General Public License for more details.
13
 
 
14
 
   You should have received a copy of the GNU Library General Public
15
 
   License along with this program; if not, write to the Free Software
16
 
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17
 
   USA.  */
18
 
 
19
 
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
20
 
   This must come before <config.h> because <config.h> may include
21
 
   <features.h>, and once <features.h> has been included, it's too late.  */
22
 
#ifndef _GNU_SOURCE
23
 
# define _GNU_SOURCE    1
24
 
#endif
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
# include <config.h>
28
 
#endif
29
 
 
30
 
#include <ctype.h>
31
 
#include <stdio.h>
32
 
#if defined _LIBC || defined HAVE___FSETLOCKING
33
 
# include <stdio_ext.h>
34
 
#endif
35
 
#include <sys/types.h>
36
 
 
37
 
#ifdef __GNUC__
38
 
# undef alloca
39
 
# define alloca __builtin_alloca
40
 
# define HAVE_ALLOCA 1
41
 
#else
42
 
# ifdef _MSC_VER
43
 
#  include <malloc.h>
44
 
#  define alloca _alloca
45
 
# else
46
 
#  if defined HAVE_ALLOCA_H || defined _LIBC
47
 
#   include <alloca.h>
48
 
#  else
49
 
#   ifdef _AIX
50
 
 #pragma alloca
51
 
#   else
52
 
#    ifndef alloca
53
 
char *alloca ();
54
 
#    endif
55
 
#   endif
56
 
#  endif
57
 
# endif
58
 
#endif
59
 
 
60
 
#include <stdlib.h>
61
 
#include <string.h>
62
 
 
63
 
#include "gettextP.h"
64
 
 
65
 
#if ENABLE_RELOCATABLE
66
 
# include "relocatable.h"
67
 
#else
68
 
# define relocate(pathname) (pathname)
69
 
#endif
70
 
 
71
 
/* @@ end of prolog @@ */
72
 
 
73
 
#ifdef _LIBC
74
 
/* Rename the non ANSI C functions.  This is required by the standard
75
 
   because some ANSI C functions will require linking with this object
76
 
   file and the name space must not be polluted.  */
77
 
# define strcasecmp __strcasecmp
78
 
 
79
 
# ifndef mempcpy
80
 
#  define mempcpy __mempcpy
81
 
# endif
82
 
# define HAVE_MEMPCPY   1
83
 
# define HAVE___FSETLOCKING     1
84
 
 
85
 
/* We need locking here since we can be called from different places.  */
86
 
# include <bits/libc-lock.h>
87
 
 
88
 
__libc_lock_define_initialized (static, lock);
89
 
#endif
90
 
 
91
 
#ifndef internal_function
92
 
# define internal_function
93
 
#endif
94
 
 
95
 
/* Some optimizations for glibc.  */
96
 
#ifdef _LIBC
97
 
# define FEOF(fp)               feof_unlocked (fp)
98
 
# define FGETS(buf, n, fp)      fgets_unlocked (buf, n, fp)
99
 
#else
100
 
# define FEOF(fp)               feof (fp)
101
 
# define FGETS(buf, n, fp)      fgets (buf, n, fp)
102
 
#endif
103
 
 
104
 
/* For those losing systems which don't have `alloca' we have to add
105
 
   some additional code emulating it.  */
106
 
#ifdef HAVE_ALLOCA
107
 
# define freea(p) /* nothing */
108
 
#else
109
 
# define alloca(n) malloc (n)
110
 
# define freea(p) free (p)
111
 
#endif
112
 
 
113
 
#if defined _LIBC_REENTRANT || HAVE_DECL_FGETS_UNLOCKED
114
 
# undef fgets
115
 
# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
116
 
#endif
117
 
#if defined _LIBC_REENTRANT || HAVE_DECL_FEOF_UNLOCKED
118
 
# undef feof
119
 
# define feof(s) feof_unlocked (s)
120
 
#endif
121
 
 
122
 
 
123
 
struct alias_map
124
 
{
125
 
  const char *alias;
126
 
  const char *value;
127
 
};
128
 
 
129
 
 
130
 
#ifndef _LIBC
131
 
# define libc_freeres_ptr(decl) decl
132
 
#endif
133
 
 
134
 
libc_freeres_ptr (static char *string_space);
135
 
static size_t string_space_act;
136
 
static size_t string_space_max;
137
 
libc_freeres_ptr (static struct alias_map *map);
138
 
static size_t nmap;
139
 
static size_t maxmap;
140
 
 
141
 
 
142
 
/* Prototypes for local functions.  */
143
 
static size_t read_alias_file (const char *fname, int fname_len)
144
 
     internal_function;
145
 
static int extend_alias_table (void);
146
 
static int alias_compare (const struct alias_map *map1,
147
 
                          const struct alias_map *map2);
148
 
 
149
 
 
150
 
const char *
151
 
_nl_expand_alias (const char *name)
152
 
{
153
 
  static const char *locale_alias_path;
154
 
  struct alias_map *retval;
155
 
  const char *result = NULL;
156
 
  size_t added;
157
 
 
158
 
#ifdef _LIBC
159
 
  __libc_lock_lock (lock);
160
 
#endif
161
 
 
162
 
  if (locale_alias_path == NULL)
163
 
    locale_alias_path = LOCALE_ALIAS_PATH;
164
 
 
165
 
  do
166
 
    {
167
 
      struct alias_map item;
168
 
 
169
 
      item.alias = name;
170
 
 
171
 
      if (nmap > 0)
172
 
        retval = (struct alias_map *) bsearch (&item, map, nmap,
173
 
                                               sizeof (struct alias_map),
174
 
                                               (int (*) (const void *,
175
 
                                                         const void *)
176
 
                                                ) alias_compare);
177
 
      else
178
 
        retval = NULL;
179
 
 
180
 
      /* We really found an alias.  Return the value.  */
181
 
      if (retval != NULL)
182
 
        {
183
 
          result = retval->value;
184
 
          break;
185
 
        }
186
 
 
187
 
      /* Perhaps we can find another alias file.  */
188
 
      added = 0;
189
 
      while (added == 0 && locale_alias_path[0] != '\0')
190
 
        {
191
 
          const char *start;
192
 
 
193
 
          while (locale_alias_path[0] == PATH_SEPARATOR)
194
 
            ++locale_alias_path;
195
 
          start = locale_alias_path;
196
 
 
197
 
          while (locale_alias_path[0] != '\0'
198
 
                 && locale_alias_path[0] != PATH_SEPARATOR)
199
 
            ++locale_alias_path;
200
 
 
201
 
          if (start < locale_alias_path)
202
 
            added = read_alias_file (start, locale_alias_path - start);
203
 
        }
204
 
    }
205
 
  while (added != 0);
206
 
 
207
 
#ifdef _LIBC
208
 
  __libc_lock_unlock (lock);
209
 
#endif
210
 
 
211
 
  return result;
212
 
}
213
 
 
214
 
 
215
 
static size_t
216
 
internal_function
217
 
read_alias_file (const char *fname, int fname_len)
218
 
{
219
 
  FILE *fp;
220
 
  char *full_fname;
221
 
  size_t added;
222
 
  static const char aliasfile[] = "/locale.alias";
223
 
 
224
 
  full_fname = (char *) alloca (fname_len + sizeof aliasfile);
225
 
#ifdef HAVE_MEMPCPY
226
 
  mempcpy (mempcpy (full_fname, fname, fname_len),
227
 
           aliasfile, sizeof aliasfile);
228
 
#else
229
 
  memcpy (full_fname, fname, fname_len);
230
 
  memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
231
 
#endif
232
 
 
233
 
  fp = fopen (relocate (full_fname), "r");
234
 
  freea (full_fname);
235
 
  if (fp == NULL)
236
 
    return 0;
237
 
 
238
 
#ifdef HAVE___FSETLOCKING
239
 
  /* No threads present.  */
240
 
  __fsetlocking (fp, FSETLOCKING_BYCALLER);
241
 
#endif
242
 
 
243
 
  added = 0;
244
 
  while (!FEOF (fp))
245
 
    {
246
 
      /* It is a reasonable approach to use a fix buffer here because
247
 
         a) we are only interested in the first two fields
248
 
         b) these fields must be usable as file names and so must not
249
 
            be that long
250
 
         We avoid a multi-kilobyte buffer here since this would use up
251
 
         stack space which we might not have if the program ran out of
252
 
         memory.  */
253
 
      char buf[400];
254
 
      char *alias;
255
 
      char *value;
256
 
      char *cp;
257
 
 
258
 
      if (FGETS (buf, sizeof buf, fp) == NULL)
259
 
        /* EOF reached.  */
260
 
        break;
261
 
 
262
 
      cp = buf;
263
 
      /* Ignore leading white space.  */
264
 
      while (isspace ((unsigned char) cp[0]))
265
 
        ++cp;
266
 
 
267
 
      /* A leading '#' signals a comment line.  */
268
 
      if (cp[0] != '\0' && cp[0] != '#')
269
 
        {
270
 
          alias = cp++;
271
 
          while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
272
 
            ++cp;
273
 
          /* Terminate alias name.  */
274
 
          if (cp[0] != '\0')
275
 
            *cp++ = '\0';
276
 
 
277
 
          /* Now look for the beginning of the value.  */
278
 
          while (isspace ((unsigned char) cp[0]))
279
 
            ++cp;
280
 
 
281
 
          if (cp[0] != '\0')
282
 
            {
283
 
              size_t alias_len;
284
 
              size_t value_len;
285
 
 
286
 
              value = cp++;
287
 
              while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
288
 
                ++cp;
289
 
              /* Terminate value.  */
290
 
              if (cp[0] == '\n')
291
 
                {
292
 
                  /* This has to be done to make the following test
293
 
                     for the end of line possible.  We are looking for
294
 
                     the terminating '\n' which do not overwrite here.  */
295
 
                  *cp++ = '\0';
296
 
                  *cp = '\n';
297
 
                }
298
 
              else if (cp[0] != '\0')
299
 
                *cp++ = '\0';
300
 
 
301
 
              if (nmap >= maxmap)
302
 
                if (__builtin_expect (extend_alias_table (), 0))
303
 
                  return added;
304
 
 
305
 
              alias_len = strlen (alias) + 1;
306
 
              value_len = strlen (value) + 1;
307
 
 
308
 
              if (string_space_act + alias_len + value_len > string_space_max)
309
 
                {
310
 
                  /* Increase size of memory pool.  */
311
 
                  size_t new_size = (string_space_max
312
 
                                     + (alias_len + value_len > 1024
313
 
                                        ? alias_len + value_len : 1024));
314
 
                  char *new_pool = (char *) realloc (string_space, new_size);
315
 
                  if (new_pool == NULL)
316
 
                    return added;
317
 
 
318
 
                  if (__builtin_expect (string_space != new_pool, 0))
319
 
                    {
320
 
                      size_t i;
321
 
 
322
 
                      for (i = 0; i < nmap; i++)
323
 
                        {
324
 
                          map[i].alias += new_pool - string_space;
325
 
                          map[i].value += new_pool - string_space;
326
 
                        }
327
 
                    }
328
 
 
329
 
                  string_space = new_pool;
330
 
                  string_space_max = new_size;
331
 
                }
332
 
 
333
 
              map[nmap].alias = memcpy (&string_space[string_space_act],
334
 
                                        alias, alias_len);
335
 
              string_space_act += alias_len;
336
 
 
337
 
              map[nmap].value = memcpy (&string_space[string_space_act],
338
 
                                        value, value_len);
339
 
              string_space_act += value_len;
340
 
 
341
 
              ++nmap;
342
 
              ++added;
343
 
            }
344
 
        }
345
 
 
346
 
      /* Possibly not the whole line fits into the buffer.  Ignore
347
 
         the rest of the line.  */
348
 
      while (strchr (buf, '\n') == NULL)
349
 
        if (FGETS (buf, sizeof buf, fp) == NULL)
350
 
          /* Make sure the inner loop will be left.  The outer loop
351
 
             will exit at the `feof' test.  */
352
 
          break;
353
 
    }
354
 
 
355
 
  /* Should we test for ferror()?  I think we have to silently ignore
356
 
     errors.  --drepper  */
357
 
  fclose (fp);
358
 
 
359
 
  if (added > 0)
360
 
    qsort (map, nmap, sizeof (struct alias_map),
361
 
           (int (*) (const void *, const void *)) alias_compare);
362
 
 
363
 
  return added;
364
 
}
365
 
 
366
 
 
367
 
static int
368
 
extend_alias_table ()
369
 
{
370
 
  size_t new_size;
371
 
  struct alias_map *new_map;
372
 
 
373
 
  new_size = maxmap == 0 ? 100 : 2 * maxmap;
374
 
  new_map = (struct alias_map *) realloc (map, (new_size
375
 
                                                * sizeof (struct alias_map)));
376
 
  if (new_map == NULL)
377
 
    /* Simply don't extend: we don't have any more core.  */
378
 
    return -1;
379
 
 
380
 
  map = new_map;
381
 
  maxmap = new_size;
382
 
  return 0;
383
 
}
384
 
 
385
 
 
386
 
static int
387
 
alias_compare (const struct alias_map *map1, const struct alias_map *map2)
388
 
{
389
 
#if defined _LIBC || defined HAVE_STRCASECMP
390
 
  return strcasecmp (map1->alias, map2->alias);
391
 
#else
392
 
  const unsigned char *p1 = (const unsigned char *) map1->alias;
393
 
  const unsigned char *p2 = (const unsigned char *) map2->alias;
394
 
  unsigned char c1, c2;
395
 
 
396
 
  if (p1 == p2)
397
 
    return 0;
398
 
 
399
 
  do
400
 
    {
401
 
      /* I know this seems to be odd but the tolower() function in
402
 
         some systems libc cannot handle nonalpha characters.  */
403
 
      c1 = isupper (*p1) ? tolower (*p1) : *p1;
404
 
      c2 = isupper (*p2) ? tolower (*p2) : *p2;
405
 
      if (c1 == '\0')
406
 
        break;
407
 
      ++p1;
408
 
      ++p2;
409
 
    }
410
 
  while (c1 == c2);
411
 
 
412
 
  return c1 - c2;
413
 
#endif
414
 
}