1169695Skan/* Copyright (C) 1992, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. 2169695Skan This file based on setenv.c in the GNU C Library. 3169695Skan 4169695Skan The GNU C Library is free software; you can redistribute it and/or 5169695Skan modify it under the terms of the GNU Library General Public License as 6169695Skan published by the Free Software Foundation; either version 2 of the 7169695Skan License, or (at your option) any later version. 8169695Skan 9169695Skan The GNU C Library is distributed in the hope that it will be useful, 10169695Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 11169695Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12169695Skan Library General Public License for more details. 13169695Skan 14169695Skan You should have received a copy of the GNU Library General Public 15169695Skan License along with the GNU C Library; see the file COPYING.LIB. If not, 16169695Skan write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 17169695Skan Boston, MA 02110-1301, USA. */ 18169695Skan 19169695Skan 20169695Skan/* 21169695Skan 22169695Skan@deftypefn Supplemental int setenv (const char *@var{name}, const char *@var{value}, int @var{overwrite}) 23169695Skan@deftypefnx Supplemental void unsetenv (const char *@var{name}) 24169695Skan 25169695Skan@code{setenv} adds @var{name} to the environment with value 26169695Skan@var{value}. If the name was already present in the environment, 27169695Skanthe new value will be stored only if @var{overwrite} is nonzero. 28169695SkanThe companion @code{unsetenv} function removes @var{name} from the 29169695Skanenvironment. This implementation is not safe for multithreaded code. 30169695Skan 31169695Skan@end deftypefn 32169695Skan 33169695Skan*/ 34169695Skan 35169695Skan#if HAVE_CONFIG_H 36169695Skan# include <config.h> 37169695Skan#endif 38169695Skan 39169695Skan#define setenv libiberty_setenv 40169695Skan#define unsetenv libiberty_unsetenv 41169695Skan 42169695Skan#include "ansidecl.h" 43169695Skan#include <sys/types.h> /* For `size_t' */ 44169695Skan#include <stdio.h> /* For `NULL' */ 45169695Skan 46169695Skan#include <errno.h> 47169695Skan#if !defined(errno) && !defined(HAVE_ERRNO_DECL) 48169695Skanextern int errno; 49169695Skan#endif 50169695Skan#define __set_errno(ev) ((errno) = (ev)) 51169695Skan 52169695Skan#if HAVE_STDLIB_H 53169695Skan# include <stdlib.h> 54169695Skan#endif 55169695Skan#if HAVE_STRING_H 56169695Skan# include <string.h> 57169695Skan#endif 58169695Skan#if HAVE_UNISTD_H 59169695Skan# include <unistd.h> 60169695Skan#endif 61169695Skan 62169695Skan#define __environ environ 63169695Skan#ifndef HAVE_ENVIRON_DECL 64169695Skanextern char **environ; 65169695Skan#endif 66169695Skan 67169695Skan#undef setenv 68169695Skan#undef unsetenv 69169695Skan 70169695Skan/* LOCK and UNLOCK are defined as no-ops. This makes the libiberty 71169695Skan * implementation MT-Unsafe. */ 72169695Skan#define LOCK 73169695Skan#define UNLOCK 74169695Skan 75169695Skan/* Below this point, it's verbatim code from the glibc-2.0 implementation */ 76169695Skan 77169695Skan/* If this variable is not a null pointer we allocated the current 78169695Skan environment. */ 79169695Skanstatic char **last_environ; 80169695Skan 81169695Skan 82169695Skanint 83169695Skansetenv (const char *name, const char *value, int replace) 84169695Skan{ 85169695Skan register char **ep = 0; 86169695Skan register size_t size; 87169695Skan const size_t namelen = strlen (name); 88169695Skan const size_t vallen = strlen (value) + 1; 89169695Skan 90169695Skan LOCK; 91169695Skan 92169695Skan size = 0; 93169695Skan if (__environ != NULL) 94169695Skan { 95169695Skan for (ep = __environ; *ep != NULL; ++ep) 96169695Skan if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') 97169695Skan break; 98169695Skan else 99169695Skan ++size; 100169695Skan } 101169695Skan 102169695Skan if (__environ == NULL || *ep == NULL) 103169695Skan { 104169695Skan char **new_environ; 105169695Skan if (__environ == last_environ && __environ != NULL) 106169695Skan /* We allocated this space; we can extend it. */ 107169695Skan new_environ = (char **) realloc (last_environ, 108169695Skan (size + 2) * sizeof (char *)); 109169695Skan else 110169695Skan new_environ = (char **) malloc ((size + 2) * sizeof (char *)); 111169695Skan 112169695Skan if (new_environ == NULL) 113169695Skan { 114169695Skan UNLOCK; 115169695Skan return -1; 116169695Skan } 117169695Skan 118169695Skan new_environ[size] = (char *) malloc (namelen + 1 + vallen); 119169695Skan if (new_environ[size] == NULL) 120169695Skan { 121169695Skan free ((char *) new_environ); 122169695Skan __set_errno (ENOMEM); 123169695Skan UNLOCK; 124169695Skan return -1; 125169695Skan } 126169695Skan 127169695Skan if (__environ != last_environ) 128169695Skan memcpy ((char *) new_environ, (char *) __environ, 129169695Skan size * sizeof (char *)); 130169695Skan 131169695Skan memcpy (new_environ[size], name, namelen); 132169695Skan new_environ[size][namelen] = '='; 133169695Skan memcpy (&new_environ[size][namelen + 1], value, vallen); 134169695Skan 135169695Skan new_environ[size + 1] = NULL; 136169695Skan 137169695Skan last_environ = __environ = new_environ; 138169695Skan } 139169695Skan else if (replace) 140169695Skan { 141169695Skan size_t len = strlen (*ep); 142169695Skan if (len + 1 < namelen + 1 + vallen) 143169695Skan { 144169695Skan /* The existing string is too short; malloc a new one. */ 145169695Skan char *new_string = (char *) malloc (namelen + 1 + vallen); 146169695Skan if (new_string == NULL) 147169695Skan { 148169695Skan UNLOCK; 149169695Skan return -1; 150169695Skan } 151169695Skan *ep = new_string; 152169695Skan } 153169695Skan memcpy (*ep, name, namelen); 154169695Skan (*ep)[namelen] = '='; 155169695Skan memcpy (&(*ep)[namelen + 1], value, vallen); 156169695Skan } 157169695Skan 158169695Skan UNLOCK; 159169695Skan 160169695Skan return 0; 161169695Skan} 162169695Skan 163169695Skanvoid 164169695Skanunsetenv (const char *name) 165169695Skan{ 166169695Skan const size_t len = strlen (name); 167169695Skan char **ep; 168169695Skan 169169695Skan LOCK; 170169695Skan 171169695Skan for (ep = __environ; *ep; ++ep) 172169695Skan if (!strncmp (*ep, name, len) && (*ep)[len] == '=') 173169695Skan { 174169695Skan /* Found it. Remove this pointer by moving later ones back. */ 175169695Skan char **dp = ep; 176169695Skan do 177169695Skan dp[0] = dp[1]; 178169695Skan while (*dp++); 179169695Skan /* Continue the loop in case NAME appears again. */ 180169695Skan } 181169695Skan 182169695Skan UNLOCK; 183169695Skan} 184