1/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2010 Free Software 2 Foundation, Inc. 3 4 NOTE: The canonical source of this file is maintained with the GNU C 5 Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. 6 7 This program is free software: you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by the 9 Free Software Foundation; either version 3 of the License, or any 10 later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include <config.h> 21 22/* Specification. */ 23#include <stdlib.h> 24 25#include <stddef.h> 26 27/* Include errno.h *after* sys/types.h to work around header problems 28 on AIX 3.2.5. */ 29#include <errno.h> 30#ifndef __set_errno 31# define __set_errno(ev) ((errno) = (ev)) 32#endif 33 34#include <string.h> 35#include <unistd.h> 36 37#if HAVE_GNU_LD 38# define environ __environ 39#else 40extern char **environ; 41#endif 42 43#if _LIBC 44/* This lock protects against simultaneous modifications of `environ'. */ 45# include <bits/libc-lock.h> 46__libc_lock_define_initialized (static, envlock) 47# define LOCK __libc_lock_lock (envlock) 48# define UNLOCK __libc_lock_unlock (envlock) 49#else 50# define LOCK 51# define UNLOCK 52#endif 53 54static int 55_unsetenv (const char *name) 56{ 57 size_t len; 58 char **ep; 59 60 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) 61 { 62 __set_errno (EINVAL); 63 return -1; 64 } 65 66 len = strlen (name); 67 68 LOCK; 69 70 ep = environ; 71 while (*ep != NULL) 72 if (!strncmp (*ep, name, len) && (*ep)[len] == '=') 73 { 74 /* Found it. Remove this pointer by moving later ones back. */ 75 char **dp = ep; 76 77 do 78 dp[0] = dp[1]; 79 while (*dp++); 80 /* Continue the loop in case NAME appears again. */ 81 } 82 else 83 ++ep; 84 85 UNLOCK; 86 87 return 0; 88} 89 90 91/* Put STRING, which is of the form "NAME=VALUE", in the environment. 92 If STRING contains no `=', then remove STRING from the environment. */ 93int 94putenv (char *string) 95{ 96 const char *const name_end = strchr (string, '='); 97 register size_t size; 98 register char **ep; 99 100 if (name_end == NULL) 101 { 102 /* Remove the variable from the environment. */ 103 return _unsetenv (string); 104 } 105 106 size = 0; 107 for (ep = environ; *ep != NULL; ++ep) 108 if (!strncmp (*ep, string, name_end - string) && 109 (*ep)[name_end - string] == '=') 110 break; 111 else 112 ++size; 113 114 if (*ep == NULL) 115 { 116 static char **last_environ = NULL; 117 char **new_environ = (char **) malloc ((size + 2) * sizeof (char *)); 118 if (new_environ == NULL) 119 return -1; 120 (void) memcpy ((void *) new_environ, (void *) environ, 121 size * sizeof (char *)); 122 new_environ[size] = (char *) string; 123 new_environ[size + 1] = NULL; 124 free (last_environ); 125 last_environ = new_environ; 126 environ = new_environ; 127 } 128 else 129 *ep = string; 130 131 return 0; 132} 133