Annotation of embedaddon/libiconv/srclib/setenv.c, revision 1.1.1.1

1.1       misho       1: /* Copyright (C) 1992,1995-1999,2000-2003,2005-2008 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 3 of the License, or
                      7:    (at your option) 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
                     15:    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
                     16: 
                     17: #if !_LIBC
                     18: # include <config.h>
                     19: #endif
                     20: #include <alloca.h>
                     21: 
                     22: /* Specification.  */
                     23: #include <stdlib.h>
                     24: 
                     25: #include <errno.h>
                     26: #ifndef __set_errno
                     27: # define __set_errno(ev) ((errno) = (ev))
                     28: #endif
                     29: 
                     30: #include <string.h>
                     31: #if _LIBC || HAVE_UNISTD_H
                     32: # include <unistd.h>
                     33: #endif
                     34: 
                     35: #if _LIBC || !HAVE_SETENV
                     36: 
                     37: #if !_LIBC
                     38: # include "malloca.h"
                     39: #endif
                     40: 
                     41: #if !_LIBC
                     42: # define __environ     environ
                     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 *) malloca (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:                  freea (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:          freea (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 = malloca (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:                  freea (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:          freea (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
                    329: 
                    330: #endif /* _LIBC || !HAVE_SETENV */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>