Back to index

cell-binutils  2.17cvs20070401
setenv.c
Go to the documentation of this file.
00001 /* Copyright (C) 1992, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
00002    This file based on setenv.c in the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public License as
00006    published by the Free Software Foundation; either version 2 of the
00007    License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public
00015    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00016    write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00017    Boston, MA 02110-1301, USA.  */
00018 
00019 
00020 /*
00021 
00022 @deftypefn Supplemental int setenv (const char *@var{name}, const char *@var{value}, int @var{overwrite})
00023 @deftypefnx Supplemental void unsetenv (const char *@var{name})
00024 
00025 @code{setenv} adds @var{name} to the environment with value
00026 @var{value}.  If the name was already present in the environment,
00027 the new value will be stored only if @var{overwrite} is nonzero.
00028 The companion @code{unsetenv} function removes @var{name} from the
00029 environment.  This implementation is not safe for multithreaded code.
00030 
00031 @end deftypefn
00032 
00033 */
00034 
00035 #if HAVE_CONFIG_H
00036 # include <config.h>
00037 #endif
00038 
00039 #define setenv libiberty_setenv
00040 #define unsetenv libiberty_unsetenv
00041 
00042 #include "ansidecl.h"
00043 #include <sys/types.h> /* For `size_t' */
00044 #include <stdio.h>     /* For `NULL' */
00045 
00046 #include <errno.h>
00047 #if !defined(errno) && !defined(HAVE_ERRNO_DECL)
00048 extern int errno;
00049 #endif
00050 #define __set_errno(ev) ((errno) = (ev))
00051 
00052 #if HAVE_STDLIB_H
00053 # include <stdlib.h>
00054 #endif
00055 #if HAVE_STRING_H
00056 # include <string.h>
00057 #endif
00058 #if HAVE_UNISTD_H
00059 # include <unistd.h>
00060 #endif
00061 
00062 #define __environ    environ
00063 #ifndef HAVE_ENVIRON_DECL
00064 extern char **environ;
00065 #endif
00066 
00067 #undef setenv
00068 #undef unsetenv
00069 
00070 /* LOCK and UNLOCK are defined as no-ops.  This makes the libiberty
00071  * implementation MT-Unsafe. */
00072 #define LOCK
00073 #define UNLOCK
00074 
00075 /* Below this point, it's verbatim code from the glibc-2.0 implementation */
00076 
00077 /* If this variable is not a null pointer we allocated the current
00078    environment.  */
00079 static char **last_environ;
00080 
00081 
00082 int
00083 setenv (const char *name, const char *value, int replace)
00084 {
00085   register char **ep = 0;
00086   register size_t size;
00087   const size_t namelen = strlen (name);
00088   const size_t vallen = strlen (value) + 1;
00089 
00090   LOCK;
00091 
00092   size = 0;
00093   if (__environ != NULL)
00094     {
00095       for (ep = __environ; *ep != NULL; ++ep)
00096        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
00097          break;
00098        else
00099          ++size;
00100     }
00101 
00102   if (__environ == NULL || *ep == NULL)
00103     {
00104       char **new_environ;
00105       if (__environ == last_environ && __environ != NULL)
00106        /* We allocated this space; we can extend it.  */
00107        new_environ = (char **) realloc (last_environ,
00108                                     (size + 2) * sizeof (char *));
00109       else
00110        new_environ = (char **) malloc ((size + 2) * sizeof (char *));
00111 
00112       if (new_environ == NULL)
00113        {
00114          UNLOCK;
00115          return -1;
00116        }
00117 
00118       new_environ[size] = (char *) malloc (namelen + 1 + vallen);
00119       if (new_environ[size] == NULL)
00120        {
00121          free ((char *) new_environ);
00122          __set_errno (ENOMEM);
00123          UNLOCK;
00124          return -1;
00125        }
00126 
00127       if (__environ != last_environ)
00128        memcpy ((char *) new_environ, (char *) __environ,
00129               size * sizeof (char *));
00130 
00131       memcpy (new_environ[size], name, namelen);
00132       new_environ[size][namelen] = '=';
00133       memcpy (&new_environ[size][namelen + 1], value, vallen);
00134 
00135       new_environ[size + 1] = NULL;
00136 
00137       last_environ = __environ = new_environ;
00138     }
00139   else if (replace)
00140     {
00141       size_t len = strlen (*ep);
00142       if (len + 1 < namelen + 1 + vallen)
00143        {
00144          /* The existing string is too short; malloc a new one.  */
00145          char *new_string = (char *) malloc (namelen + 1 + vallen);
00146          if (new_string == NULL)
00147            {
00148              UNLOCK;
00149              return -1;
00150            }
00151          *ep = new_string;
00152        }
00153       memcpy (*ep, name, namelen);
00154       (*ep)[namelen] = '=';
00155       memcpy (&(*ep)[namelen + 1], value, vallen);
00156     }
00157 
00158   UNLOCK;
00159 
00160   return 0;
00161 }
00162 
00163 void
00164 unsetenv (const char *name)
00165 {
00166   const size_t len = strlen (name);
00167   char **ep;
00168 
00169   LOCK;
00170 
00171   for (ep = __environ; *ep; ++ep)
00172     if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
00173       {
00174        /* Found it.  Remove this pointer by moving later ones back.  */
00175        char **dp = ep;
00176        do
00177          dp[0] = dp[1];
00178        while (*dp++);
00179        /* Continue the loop in case NAME appears again.  */
00180       }
00181 
00182   UNLOCK;
00183 }