Annotation of embedaddon/libiconv/srclib/setenv.c, revision 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>