Diff for /embedaddon/libiconv/srclib/setenv.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 22:57:48 version 1.1.1.2, 2012/05/29 09:29:43
Line 1 Line 1
/* Copyright (C) 1992,1995-1999,2000-2003,2005-2008 Free Software Foundation, Inc./* Copyright (C) 1992, 1995-2003, 2005-2011 Free Software Foundation, Inc.
    This file is part of the GNU C Library.     This file is part of the GNU C Library.
   
    This program is free software: you can redistribute it and/or modify     This program is free software: you can redistribute it and/or modify
Line 15 Line 15
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   
 #if !_LIBC  #if !_LIBC
   # define _GL_USE_STDLIB_ALLOC 1
 # include <config.h>  # include <config.h>
 #endif  #endif
   
   /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
      optimizes away the name == NULL test below.  */
   #define _GL_ARG_NONNULL(params)
   
 #include <alloca.h>  #include <alloca.h>
   
 /* Specification.  */  /* Specification.  */
Line 32 Line 38
 # include <unistd.h>  # include <unistd.h>
 #endif  #endif
   
 #if _LIBC || !HAVE_SETENV  
   
 #if !_LIBC  #if !_LIBC
 # include "malloca.h"  # include "malloca.h"
 #endif  #endif
   
   #if _LIBC || !HAVE_SETENV
   
 #if !_LIBC  #if !_LIBC
# define __environ      environ# define __environ      environ
 #endif  #endif
   
 #if _LIBC  #if _LIBC
 /* This lock protects against simultaneous modifications of `environ'.  */  /* This lock protects against simultaneous modifications of `environ'.  */
 # include <bits/libc-lock.h>  # include <bits/libc-lock.h>
 __libc_lock_define_initialized (static, envlock)  __libc_lock_define_initialized (static, envlock)
# define LOCK   __libc_lock_lock (envlock)# define LOCK   __libc_lock_lock (envlock)
# define UNLOCK __libc_lock_unlock (envlock)# define UNLOCK __libc_lock_unlock (envlock)
 #else  #else
 # define LOCK  # define LOCK
 # define UNLOCK  # define UNLOCK
Line 66  __libc_lock_define_initialized (static, envlock) Line 72  __libc_lock_define_initialized (static, envlock)
    values are from a small set.  Outside glibc this will eat up all     values are from a small set.  Outside glibc this will eat up all
    memory after a while.  */     memory after a while.  */
 #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \  #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
                      && defined __GNUC__)                      && defined __GNUC__)
# define USE_TSEARCH    1# define USE_TSEARCH    1
 # include <search.h>  # include <search.h>
 typedef int (*compar_fn_t) (const void *, const void *);  typedef int (*compar_fn_t) (const void *, const void *);
   
Line 76  typedef int (*compar_fn_t) (const void *, const void * Line 82  typedef int (*compar_fn_t) (const void *, const void *
 static void *known_values;  static void *known_values;
   
 # define KNOWN_VALUE(Str) \  # define KNOWN_VALUE(Str) \
  ({                                                                          \  ({                                                                          \
    void *value = tfind (Str, &known_values, (compar_fn_t) strcmp);           \    void *value = tfind (Str, &known_values, (compar_fn_t) strcmp);           \
    value != NULL ? *(char **) value : NULL;                                  \    value != NULL ? *(char **) value : NULL;                                  \
   })    })
 # define STORE_VALUE(Str) \  # define STORE_VALUE(Str) \
   tsearch (Str, &known_values, (compar_fn_t) strcmp)    tsearch (Str, &known_values, (compar_fn_t) strcmp)
Line 105  static char **last_environ; Line 111  static char **last_environ;
    free the strings.  */     free the strings.  */
 int  int
 __add_to_environ (const char *name, const char *value, const char *combined,  __add_to_environ (const char *name, const char *value, const char *combined,
                  int replace)                  int replace)
 {  {
  register char **ep;  char **ep;
  register size_t size;  size_t size;
   const size_t namelen = strlen (name);    const size_t namelen = strlen (name);
   const size_t vallen = value != NULL ? strlen (value) + 1 : 0;    const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
   
Line 122  __add_to_environ (const char *name, const char *value, Line 128  __add_to_environ (const char *name, const char *value,
   if (ep != NULL)    if (ep != NULL)
     {      {
       for (; *ep != NULL; ++ep)        for (; *ep != NULL; ++ep)
        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
          break;          break;
        else        else
          ++size;          ++size;
     }      }
   
   if (ep == NULL || *ep == NULL)    if (ep == NULL || *ep == NULL)
Line 137  __add_to_environ (const char *name, const char *value, Line 143  __add_to_environ (const char *name, const char *value,
   
       /* We allocated this space; we can extend it.  */        /* We allocated this space; we can extend it.  */
       new_environ =        new_environ =
        (char **) (last_environ == NULL        (char **) (last_environ == NULL
                   ? malloc ((size + 2) * sizeof (char *))                   ? malloc ((size + 2) * sizeof (char *))
                   : realloc (last_environ, (size + 2) * sizeof (char *)));                   : realloc (last_environ, (size + 2) * sizeof (char *)));
       if (new_environ == NULL)        if (new_environ == NULL)
        {        {
          UNLOCK;          /* It's easier to set errno to ENOMEM than to rely on the
          return -1;             'malloc-posix' and 'realloc-posix' gnulib modules.  */
        }          __set_errno (ENOMEM);
           UNLOCK;
           return -1;
         }
   
       /* If the whole entry is given add it.  */        /* If the whole entry is given add it.  */
       if (combined != NULL)        if (combined != NULL)
        /* We must not add the string to the search tree since it belongs        /* We must not add the string to the search tree since it belongs
           to the user.  */           to the user.  */
        new_environ[size] = (char *) combined;        new_environ[size] = (char *) combined;
       else        else
        {        {
          /* See whether the value is already known.  */          /* See whether the value is already known.  */
 #ifdef USE_TSEARCH  #ifdef USE_TSEARCH
 # ifdef _LIBC  # ifdef _LIBC
          new_value = (char *) alloca (namelen + 1 + vallen);          new_value = (char *) alloca (namelen + 1 + vallen);
          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
                     value, vallen);                     value, vallen);
 # else  # else
          new_value = (char *) malloca (namelen + 1 + vallen);          new_value = (char *) malloca (namelen + 1 + vallen);
          if (new_value == NULL)          if (new_value == NULL)
            {            {
              __set_errno (ENOMEM);              __set_errno (ENOMEM);
              UNLOCK;              UNLOCK;
              return -1;              return -1;
            }            }
          memcpy (new_value, name, namelen);          memcpy (new_value, name, namelen);
          new_value[namelen] = '=';          new_value[namelen] = '=';
          memcpy (&new_value[namelen + 1], value, vallen);          memcpy (&new_value[namelen + 1], value, vallen);
 # endif  # endif
   
          new_environ[size] = KNOWN_VALUE (new_value);          new_environ[size] = KNOWN_VALUE (new_value);
          if (new_environ[size] == NULL)          if (new_environ[size] == NULL)
 #endif  #endif
            {            {
              new_environ[size] = (char *) malloc (namelen + 1 + vallen);              new_environ[size] = (char *) malloc (namelen + 1 + vallen);
              if (new_environ[size] == NULL)              if (new_environ[size] == NULL)
                {                {
 #if defined USE_TSEARCH && !defined _LIBC  #if defined USE_TSEARCH && !defined _LIBC
                  freea (new_value);                  freea (new_value);
 #endif  #endif
                  __set_errno (ENOMEM);                  __set_errno (ENOMEM);
                  UNLOCK;                  UNLOCK;
                  return -1;                  return -1;
                }                }
   
 #ifdef USE_TSEARCH  #ifdef USE_TSEARCH
              memcpy (new_environ[size], new_value, namelen + 1 + vallen);              memcpy (new_environ[size], new_value, namelen + 1 + vallen);
 #else  #else
              memcpy (new_environ[size], name, namelen);              memcpy (new_environ[size], name, namelen);
              new_environ[size][namelen] = '=';              new_environ[size][namelen] = '=';
              memcpy (&new_environ[size][namelen + 1], value, vallen);              memcpy (&new_environ[size][namelen + 1], value, vallen);
 #endif  #endif
              /* And save the value now.  We cannot do this when we remove              /* And save the value now.  We cannot do this when we remove
                 the string since then we cannot decide whether it is a                 the string since then we cannot decide whether it is a
                 user string or not.  */                 user string or not.  */
              STORE_VALUE (new_environ[size]);              STORE_VALUE (new_environ[size]);
            }            }
 #if defined USE_TSEARCH && !defined _LIBC  #if defined USE_TSEARCH && !defined _LIBC
          freea (new_value);          freea (new_value);
 #endif  #endif
        }        }
   
       if (__environ != last_environ)        if (__environ != last_environ)
        memcpy ((char *) new_environ, (char *) __environ,        memcpy ((char *) new_environ, (char *) __environ,
                size * sizeof (char *));                size * sizeof (char *));
   
       new_environ[size + 1] = NULL;        new_environ[size + 1] = NULL;
   
Line 218  __add_to_environ (const char *name, const char *value, Line 227  __add_to_environ (const char *name, const char *value,
   
       /* Use the user string if given.  */        /* Use the user string if given.  */
       if (combined != NULL)        if (combined != NULL)
        np = (char *) combined;        np = (char *) combined;
       else        else
        {        {
 #ifdef USE_TSEARCH  #ifdef USE_TSEARCH
          char *new_value;          char *new_value;
 # ifdef _LIBC  # ifdef _LIBC
          new_value = alloca (namelen + 1 + vallen);          new_value = alloca (namelen + 1 + vallen);
          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),          __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
                     value, vallen);                     value, vallen);
 # else  # else
          new_value = malloca (namelen + 1 + vallen);          new_value = malloca (namelen + 1 + vallen);
          if (new_value == NULL)          if (new_value == NULL)
            {            {
              __set_errno (ENOMEM);              __set_errno (ENOMEM);
              UNLOCK;              UNLOCK;
              return -1;              return -1;
            }            }
          memcpy (new_value, name, namelen);          memcpy (new_value, name, namelen);
          new_value[namelen] = '=';          new_value[namelen] = '=';
          memcpy (&new_value[namelen + 1], value, vallen);          memcpy (&new_value[namelen + 1], value, vallen);
 # endif  # endif
   
          np = KNOWN_VALUE (new_value);          np = KNOWN_VALUE (new_value);
          if (np == NULL)          if (np == NULL)
 #endif  #endif
            {            {
              np = malloc (namelen + 1 + vallen);              np = (char *) malloc (namelen + 1 + vallen);
              if (np == NULL)              if (np == NULL)
                {                {
 #if defined USE_TSEARCH && !defined _LIBC  #if defined USE_TSEARCH && !defined _LIBC
                  freea (new_value);                  freea (new_value);
 #endif  #endif
                  __set_errno (ENOMEM);                  __set_errno (ENOMEM);
                  UNLOCK;                  UNLOCK;
                  return -1;                  return -1;
                }                }
   
 #ifdef USE_TSEARCH  #ifdef USE_TSEARCH
              memcpy (np, new_value, namelen + 1 + vallen);              memcpy (np, new_value, namelen + 1 + vallen);
 #else  #else
              memcpy (np, name, namelen);              memcpy (np, name, namelen);
              np[namelen] = '=';              np[namelen] = '=';
              memcpy (&np[namelen + 1], value, vallen);              memcpy (&np[namelen + 1], value, vallen);
 #endif  #endif
              /* And remember the value.  */              /* And remember the value.  */
              STORE_VALUE (np);              STORE_VALUE (np);
            }            }
 #if defined USE_TSEARCH && !defined _LIBC  #if defined USE_TSEARCH && !defined _LIBC
          freea (new_value);          freea (new_value);
 #endif  #endif
        }        }
   
       *ep = np;        *ep = np;
     }      }
Line 281  __add_to_environ (const char *name, const char *value, Line 290  __add_to_environ (const char *name, const char *value,
 int  int
 setenv (const char *name, const char *value, int replace)  setenv (const char *name, const char *value, int replace)
 {  {
     if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
       {
         __set_errno (EINVAL);
         return -1;
       }
   
   return __add_to_environ (name, value, NULL, replace);    return __add_to_environ (name, value, NULL, replace);
 }  }
   
Line 328  weak_alias (__clearenv, clearenv) Line 343  weak_alias (__clearenv, clearenv)
 #endif  #endif
   
 #endif /* _LIBC || !HAVE_SETENV */  #endif /* _LIBC || !HAVE_SETENV */
   
   /* The rest of this file is called into use when replacing an existing
      but buggy setenv.  Known bugs include failure to diagnose invalid
      name, and consuming a leading '=' from value.  */
   #if HAVE_SETENV
   
   # undef setenv
   # if !HAVE_DECL_SETENV
   extern int setenv (const char *, const char *, int);
   # endif
   # define STREQ(a, b) (strcmp (a, b) == 0)
   
   int
   rpl_setenv (const char *name, const char *value, int replace)
   {
     int result;
     if (!name || !*name || strchr (name, '='))
       {
         errno = EINVAL;
         return -1;
       }
     /* Call the real setenv even if replace is 0, in case implementation
        has underlying data to update, such as when environ changes.  */
     result = setenv (name, value, replace);
     if (result == 0 && replace && *value == '=')
       {
         char *tmp = getenv (name);
         if (!STREQ (tmp, value))
           {
             int saved_errno;
             size_t len = strlen (value);
             tmp = malloca (len + 2);
             /* Since leading '=' is eaten, double it up.  */
             *tmp = '=';
             memcpy (tmp + 1, value, len + 1);
             result = setenv (name, tmp, replace);
             saved_errno = errno;
             freea (tmp);
             errno = saved_errno;
           }
       }
     return result;
   }
   
   #endif /* HAVE_SETENV */

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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