~ubuntu-branches/ubuntu/natty/gnupg2/natty-security

« back to all changes in this revision

Viewing changes to gl/setenv.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Urlichs
  • Date: 2005-12-08 22:13:21 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208221321-4rvs2vu835iam5wv
Tags: 1.9.19-2
* Convert debian/changelog to UTF-8.
* Put gnupg-agent and gpgsm lintian overrides in the respectively
  right package.  Closes: #335066
* Added debhelper tokens to maintainer scripts.
* xsession fixes:
  o Added host name to gpg-agent PID file name.  Closes: #312717
  o Fixed xsession script to be able to run under zsh.  Closes: #308516
  o Don't run gpg-agent if one is already running.  Closes: #336480
* debian/control:
  o Fixed package description of gpgsm package.  Closes: #299842
  o Added mention of gpg-agent to description of gnupg-agent package.
    Closes: #304355
* Thanks to Peter Eisentraut <petere@debian.org> for all of the above.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1992,1995-1999,2000-2003 Free Software Foundation, Inc.
 
2
   This file is part of the GNU C Library.
 
3
 
 
4
   This program is free software; you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   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
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License along
 
15
   with this program; if not, write to the Free Software Foundation,
 
16
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
17
 
 
18
#if HAVE_CONFIG_H
 
19
# include <config.h>
 
20
#endif
 
21
#include <alloca.h>
 
22
 
 
23
#include <errno.h>
 
24
#ifndef __set_errno
 
25
# define __set_errno(ev) ((errno) = (ev))
 
26
#endif
 
27
 
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
#if _LIBC || HAVE_UNISTD_H
 
31
# include <unistd.h>
 
32
#endif
 
33
 
 
34
#if !_LIBC
 
35
# include "allocsa.h"
 
36
#endif
 
37
 
 
38
#if !_LIBC
 
39
# define __environ      environ
 
40
# ifndef HAVE_ENVIRON_DECL
 
41
extern char **environ;
 
42
# endif
 
43
#endif
 
44
 
 
45
#if _LIBC
 
46
/* This lock protects against simultaneous modifications of `environ'.  */
 
47
# include <bits/libc-lock.h>
 
48
__libc_lock_define_initialized (static, envlock)
 
49
# define LOCK   __libc_lock_lock (envlock)
 
50
# define UNLOCK __libc_lock_unlock (envlock)
 
51
#else
 
52
# define LOCK
 
53
# define UNLOCK
 
54
#endif
 
55
 
 
56
/* In the GNU C library we must keep the namespace clean.  */
 
57
#ifdef _LIBC
 
58
# define setenv __setenv
 
59
# define clearenv __clearenv
 
60
# define tfind __tfind
 
61
# define tsearch __tsearch
 
62
#endif
 
63
 
 
64
/* In the GNU C library implementation we try to be more clever and
 
65
   allow arbitrarily many changes of the environment given that the used
 
66
   values are from a small set.  Outside glibc this will eat up all
 
67
   memory after a while.  */
 
68
#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
 
69
                      && defined __GNUC__)
 
70
# define USE_TSEARCH    1
 
71
# include <search.h>
 
72
typedef int (*compar_fn_t) (const void *, const void *);
 
73
 
 
74
/* This is a pointer to the root of the search tree with the known
 
75
   values.  */
 
76
static void *known_values;
 
77
 
 
78
# define KNOWN_VALUE(Str) \
 
79
  ({                                                                          \
 
80
    void *value = tfind (Str, &known_values, (compar_fn_t) strcmp);           \
 
81
    value != NULL ? *(char **) value : NULL;                                  \
 
82
  })
 
83
# define STORE_VALUE(Str) \
 
84
  tsearch (Str, &known_values, (compar_fn_t) strcmp)
 
85
 
 
86
#else
 
87
# undef USE_TSEARCH
 
88
 
 
89
# define KNOWN_VALUE(Str) NULL
 
90
# define STORE_VALUE(Str) do { } while (0)
 
91
 
 
92
#endif
 
93
 
 
94
 
 
95
/* If this variable is not a null pointer we allocated the current
 
96
   environment.  */
 
97
static char **last_environ;
 
98
 
 
99
 
 
100
/* This function is used by `setenv' and `putenv'.  The difference between
 
101
   the two functions is that for the former must create a new string which
 
102
   is then placed in the environment, while the argument of `putenv'
 
103
   must be used directly.  This is all complicated by the fact that we try
 
104
   to reuse values once generated for a `setenv' call since we can never
 
105
   free the strings.  */
 
106
int
 
107
__add_to_environ (const char *name, const char *value, const char *combined,
 
108
                  int replace)
 
109
{
 
110
  register char **ep;
 
111
  register size_t size;
 
112
  const size_t namelen = strlen (name);
 
113
  const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
 
114
 
 
115
  LOCK;
 
116
 
 
117
  /* We have to get the pointer now that we have the lock and not earlier
 
118
     since another thread might have created a new environment.  */
 
119
  ep = __environ;
 
120
 
 
121
  size = 0;
 
122
  if (ep != NULL)
 
123
    {
 
124
      for (; *ep != NULL; ++ep)
 
125
        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
 
126
          break;
 
127
        else
 
128
          ++size;
 
129
    }
 
130
 
 
131
  if (ep == NULL || *ep == NULL)
 
132
    {
 
133
      char **new_environ;
 
134
#ifdef USE_TSEARCH
 
135
      char *new_value;
 
136
#endif
 
137
 
 
138
      /* We allocated this space; we can extend it.  */
 
139
      new_environ =
 
140
        (char **) (last_environ == NULL
 
141
                   ? malloc ((size + 2) * sizeof (char *))
 
142
                   : realloc (last_environ, (size + 2) * sizeof (char *)));
 
143
      if (new_environ == NULL)
 
144
        {
 
145
          UNLOCK;
 
146
          return -1;
 
147
        }
 
148
 
 
149
      /* If the whole entry is given add it.  */
 
150
      if (combined != NULL)
 
151
        /* We must not add the string to the search tree since it belongs
 
152
           to the user.  */
 
153
        new_environ[size] = (char *) combined;
 
154
      else
 
155
        {
 
156
          /* See whether the value is already known.  */
 
157
#ifdef USE_TSEARCH
 
158
# ifdef _LIBC
 
159
          new_value = (char *) alloca (namelen + 1 + vallen);
 
160
          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
 
161
                     value, vallen);
 
162
# else
 
163
          new_value = (char *) allocsa (namelen + 1 + vallen);
 
164
          if (new_value == NULL)
 
165
            {
 
166
              __set_errno (ENOMEM);
 
167
              UNLOCK;
 
168
              return -1;
 
169
            }
 
170
          memcpy (new_value, name, namelen);
 
171
          new_value[namelen] = '=';
 
172
          memcpy (&new_value[namelen + 1], value, vallen);
 
173
# endif
 
174
 
 
175
          new_environ[size] = KNOWN_VALUE (new_value);
 
176
          if (new_environ[size] == NULL)
 
177
#endif
 
178
            {
 
179
              new_environ[size] = (char *) malloc (namelen + 1 + vallen);
 
180
              if (new_environ[size] == NULL)
 
181
                {
 
182
#if defined USE_TSEARCH && !defined _LIBC
 
183
                  freesa (new_value);
 
184
#endif
 
185
                  __set_errno (ENOMEM);
 
186
                  UNLOCK;
 
187
                  return -1;
 
188
                }
 
189
 
 
190
#ifdef USE_TSEARCH
 
191
              memcpy (new_environ[size], new_value, namelen + 1 + vallen);
 
192
#else
 
193
              memcpy (new_environ[size], name, namelen);
 
194
              new_environ[size][namelen] = '=';
 
195
              memcpy (&new_environ[size][namelen + 1], value, vallen);
 
196
#endif
 
197
              /* And save the value now.  We cannot do this when we remove
 
198
                 the string since then we cannot decide whether it is a
 
199
                 user string or not.  */
 
200
              STORE_VALUE (new_environ[size]);
 
201
            }
 
202
#if defined USE_TSEARCH && !defined _LIBC
 
203
          freesa (new_value);
 
204
#endif
 
205
        }
 
206
 
 
207
      if (__environ != last_environ)
 
208
        memcpy ((char *) new_environ, (char *) __environ,
 
209
                size * sizeof (char *));
 
210
 
 
211
      new_environ[size + 1] = NULL;
 
212
 
 
213
      last_environ = __environ = new_environ;
 
214
    }
 
215
  else if (replace)
 
216
    {
 
217
      char *np;
 
218
 
 
219
      /* Use the user string if given.  */
 
220
      if (combined != NULL)
 
221
        np = (char *) combined;
 
222
      else
 
223
        {
 
224
#ifdef USE_TSEARCH
 
225
          char *new_value;
 
226
# ifdef _LIBC
 
227
          new_value = alloca (namelen + 1 + vallen);
 
228
          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
 
229
                     value, vallen);
 
230
# else
 
231
          new_value = allocsa (namelen + 1 + vallen);
 
232
          if (new_value == NULL)
 
233
            {
 
234
              __set_errno (ENOMEM);
 
235
              UNLOCK;
 
236
              return -1;
 
237
            }
 
238
          memcpy (new_value, name, namelen);
 
239
          new_value[namelen] = '=';
 
240
          memcpy (&new_value[namelen + 1], value, vallen);
 
241
# endif
 
242
 
 
243
          np = KNOWN_VALUE (new_value);
 
244
          if (np == NULL)
 
245
#endif
 
246
            {
 
247
              np = malloc (namelen + 1 + vallen);
 
248
              if (np == NULL)
 
249
                {
 
250
#if defined USE_TSEARCH && !defined _LIBC
 
251
                  freesa (new_value);
 
252
#endif
 
253
                  __set_errno (ENOMEM);
 
254
                  UNLOCK;
 
255
                  return -1;
 
256
                }
 
257
 
 
258
#ifdef USE_TSEARCH
 
259
              memcpy (np, new_value, namelen + 1 + vallen);
 
260
#else
 
261
              memcpy (np, name, namelen);
 
262
              np[namelen] = '=';
 
263
              memcpy (&np[namelen + 1], value, vallen);
 
264
#endif
 
265
              /* And remember the value.  */
 
266
              STORE_VALUE (np);
 
267
            }
 
268
#if defined USE_TSEARCH && !defined _LIBC
 
269
          freesa (new_value);
 
270
#endif
 
271
        }
 
272
 
 
273
      *ep = np;
 
274
    }
 
275
 
 
276
  UNLOCK;
 
277
 
 
278
  return 0;
 
279
}
 
280
 
 
281
int
 
282
setenv (const char *name, const char *value, int replace)
 
283
{
 
284
  return __add_to_environ (name, value, NULL, replace);
 
285
}
 
286
 
 
287
/* The `clearenv' was planned to be added to POSIX.1 but probably
 
288
   never made it.  Nevertheless the POSIX.9 standard (POSIX bindings
 
289
   for Fortran 77) requires this function.  */
 
290
int
 
291
clearenv (void)
 
292
{
 
293
  LOCK;
 
294
 
 
295
  if (__environ == last_environ && __environ != NULL)
 
296
    {
 
297
      /* We allocated this environment so we can free it.  */
 
298
      free (__environ);
 
299
      last_environ = NULL;
 
300
    }
 
301
 
 
302
  /* Clear the environment pointer removes the whole environment.  */
 
303
  __environ = NULL;
 
304
 
 
305
  UNLOCK;
 
306
 
 
307
  return 0;
 
308
}
 
309
 
 
310
#ifdef _LIBC
 
311
static void
 
312
free_mem (void)
 
313
{
 
314
  /* Remove all traces.  */
 
315
  clearenv ();
 
316
 
 
317
  /* Now remove the search tree.  */
 
318
  __tdestroy (known_values, free);
 
319
  known_values = NULL;
 
320
}
 
321
text_set_element (__libc_subfreeres, free_mem);
 
322
 
 
323
 
 
324
# undef setenv
 
325
# undef clearenv
 
326
weak_alias (__setenv, setenv)
 
327
weak_alias (__clearenv, clearenv)
 
328
#endif