Home | History | Annotate | Download | only in lib
      1 /* Copyright (C) 1992, 1995-2002, 2005-2012 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 #include <config.h>
     18 
     19 /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
     20    optimizes away the name == NULL test below.  */
     21 #define _GL_ARG_NONNULL(params)
     22 
     23 /* Specification.  */
     24 #include <stdlib.h>
     25 
     26 #include <errno.h>
     27 #if !_LIBC
     28 # define __set_errno(ev) ((errno) = (ev))
     29 #endif
     30 
     31 #include <string.h>
     32 #include <unistd.h>
     33 
     34 #if !_LIBC
     35 # define __environ      environ
     36 #endif
     37 
     38 #if _LIBC
     39 /* This lock protects against simultaneous modifications of 'environ'.  */
     40 # include <bits/libc-lock.h>
     41 __libc_lock_define_initialized (static, envlock)
     42 # define LOCK   __libc_lock_lock (envlock)
     43 # define UNLOCK __libc_lock_unlock (envlock)
     44 #else
     45 # define LOCK
     46 # define UNLOCK
     47 #endif
     48 
     49 /* In the GNU C library we must keep the namespace clean.  */
     50 #ifdef _LIBC
     51 # define unsetenv __unsetenv
     52 #endif
     53 
     54 #if _LIBC || !HAVE_UNSETENV
     55 
     56 int
     57 unsetenv (const char *name)
     58 {
     59   size_t len;
     60   char **ep;
     61 
     62   if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
     63     {
     64       __set_errno (EINVAL);
     65       return -1;
     66     }
     67 
     68   len = strlen (name);
     69 
     70   LOCK;
     71 
     72   ep = __environ;
     73   while (*ep != NULL)
     74     if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
     75       {
     76         /* Found it.  Remove this pointer by moving later ones back.  */
     77         char **dp = ep;
     78 
     79         do
     80           dp[0] = dp[1];
     81         while (*dp++);
     82         /* Continue the loop in case NAME appears again.  */
     83       }
     84     else
     85       ++ep;
     86 
     87   UNLOCK;
     88 
     89   return 0;
     90 }
     91 
     92 #ifdef _LIBC
     93 # undef unsetenv
     94 weak_alias (__unsetenv, unsetenv)
     95 #endif
     96 
     97 #else /* HAVE_UNSETENV */
     98 
     99 # undef unsetenv
    100 # if !HAVE_DECL_UNSETENV
    101 #  if VOID_UNSETENV
    102 extern void unsetenv (const char *);
    103 #  else
    104 extern int unsetenv (const char *);
    105 #  endif
    106 # endif
    107 
    108 /* Call the underlying unsetenv, in case there is hidden bookkeeping
    109    that needs updating beyond just modifying environ.  */
    110 int
    111 rpl_unsetenv (const char *name)
    112 {
    113   int result = 0;
    114   if (!name || !*name || strchr (name, '='))
    115     {
    116       errno = EINVAL;
    117       return -1;
    118     }
    119   while (getenv (name))
    120 # if !VOID_UNSETENV
    121     result =
    122 # endif
    123       unsetenv (name);
    124   return result;
    125 }
    126 
    127 #endif /* HAVE_UNSETENV */
    128