189857Sobrien/* Copyright (C) 1992, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. 260484Sobrien This file based on setenv.c in the GNU C Library. 360484Sobrien 460484Sobrien The GNU C Library is free software; you can redistribute it and/or 560484Sobrien modify it under the terms of the GNU Library General Public License as 660484Sobrien published by the Free Software Foundation; either version 2 of the 760484Sobrien License, or (at your option) any later version. 860484Sobrien 960484Sobrien The GNU C Library is distributed in the hope that it will be useful, 1060484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1160484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1260484Sobrien Library General Public License for more details. 1360484Sobrien 1460484Sobrien You should have received a copy of the GNU Library General Public 1560484Sobrien License along with the GNU C Library; see the file COPYING.LIB. If not, 16218822Sdim write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 17218822Sdim Boston, MA 02110-1301, USA. */ 1860484Sobrien 1989857Sobrien 2089857Sobrien/* 2189857Sobrien 2289857Sobrien@deftypefn Supplemental int setenv (const char *@var{name}, const char *@var{value}, int @var{overwrite}) 2389857Sobrien@deftypefnx Supplemental void unsetenv (const char *@var{name}) 2489857Sobrien 2589857Sobrien@code{setenv} adds @var{name} to the environment with value 2689857Sobrien@var{value}. If the name was already present in the environment, 2789857Sobrienthe new value will be stored only if @var{overwrite} is nonzero. 2889857SobrienThe companion @code{unsetenv} function removes @var{name} from the 2989857Sobrienenvironment. This implementation is not safe for multithreaded code. 3089857Sobrien 3189857Sobrien@end deftypefn 3289857Sobrien 3389857Sobrien*/ 3489857Sobrien 3560484Sobrien#if HAVE_CONFIG_H 3660484Sobrien# include <config.h> 3760484Sobrien#endif 3860484Sobrien 3989857Sobrien#define setenv libiberty_setenv 4089857Sobrien#define unsetenv libiberty_unsetenv 4189857Sobrien 4260484Sobrien#include "ansidecl.h" 4360484Sobrien#include <sys/types.h> /* For `size_t' */ 4460484Sobrien#include <stdio.h> /* For `NULL' */ 4560484Sobrien 4660484Sobrien#include <errno.h> 4760484Sobrien#if !defined(errno) && !defined(HAVE_ERRNO_DECL) 4860484Sobrienextern int errno; 4960484Sobrien#endif 5060484Sobrien#define __set_errno(ev) ((errno) = (ev)) 5160484Sobrien 5260484Sobrien#if HAVE_STDLIB_H 5360484Sobrien# include <stdlib.h> 5460484Sobrien#endif 5560484Sobrien#if HAVE_STRING_H 5660484Sobrien# include <string.h> 5760484Sobrien#endif 5860484Sobrien#if HAVE_UNISTD_H 5960484Sobrien# include <unistd.h> 6060484Sobrien#endif 6160484Sobrien 6260484Sobrien#define __environ environ 6360484Sobrien#ifndef HAVE_ENVIRON_DECL 6460484Sobrienextern char **environ; 6560484Sobrien#endif 6660484Sobrien 6789857Sobrien#undef setenv 6889857Sobrien#undef unsetenv 6989857Sobrien 7060484Sobrien/* LOCK and UNLOCK are defined as no-ops. This makes the libiberty 7160484Sobrien * implementation MT-Unsafe. */ 7260484Sobrien#define LOCK 7360484Sobrien#define UNLOCK 7460484Sobrien 7560484Sobrien/* Below this point, it's verbatim code from the glibc-2.0 implementation */ 7660484Sobrien 7760484Sobrien/* If this variable is not a null pointer we allocated the current 7860484Sobrien environment. */ 7960484Sobrienstatic char **last_environ; 8060484Sobrien 8160484Sobrien 8260484Sobrienint 83218822Sdimsetenv (const char *name, const char *value, int replace) 8460484Sobrien{ 8577298Sobrien register char **ep = 0; 8660484Sobrien register size_t size; 8760484Sobrien const size_t namelen = strlen (name); 8860484Sobrien const size_t vallen = strlen (value) + 1; 8960484Sobrien 9060484Sobrien LOCK; 9160484Sobrien 9260484Sobrien size = 0; 9360484Sobrien if (__environ != NULL) 9477298Sobrien { 9577298Sobrien for (ep = __environ; *ep != NULL; ++ep) 9677298Sobrien if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') 9777298Sobrien break; 9877298Sobrien else 9977298Sobrien ++size; 10077298Sobrien } 10160484Sobrien 10260484Sobrien if (__environ == NULL || *ep == NULL) 10360484Sobrien { 10460484Sobrien char **new_environ; 10560484Sobrien if (__environ == last_environ && __environ != NULL) 10660484Sobrien /* We allocated this space; we can extend it. */ 10760484Sobrien new_environ = (char **) realloc (last_environ, 10860484Sobrien (size + 2) * sizeof (char *)); 10960484Sobrien else 11060484Sobrien new_environ = (char **) malloc ((size + 2) * sizeof (char *)); 11160484Sobrien 11260484Sobrien if (new_environ == NULL) 11360484Sobrien { 11460484Sobrien UNLOCK; 11560484Sobrien return -1; 11660484Sobrien } 11760484Sobrien 118218822Sdim new_environ[size] = (char *) malloc (namelen + 1 + vallen); 11960484Sobrien if (new_environ[size] == NULL) 12060484Sobrien { 12160484Sobrien free ((char *) new_environ); 12260484Sobrien __set_errno (ENOMEM); 12360484Sobrien UNLOCK; 12460484Sobrien return -1; 12560484Sobrien } 12660484Sobrien 12760484Sobrien if (__environ != last_environ) 12860484Sobrien memcpy ((char *) new_environ, (char *) __environ, 12960484Sobrien size * sizeof (char *)); 13060484Sobrien 13160484Sobrien memcpy (new_environ[size], name, namelen); 13260484Sobrien new_environ[size][namelen] = '='; 13360484Sobrien memcpy (&new_environ[size][namelen + 1], value, vallen); 13460484Sobrien 13560484Sobrien new_environ[size + 1] = NULL; 13660484Sobrien 13760484Sobrien last_environ = __environ = new_environ; 13860484Sobrien } 13960484Sobrien else if (replace) 14060484Sobrien { 14160484Sobrien size_t len = strlen (*ep); 14260484Sobrien if (len + 1 < namelen + 1 + vallen) 14360484Sobrien { 14460484Sobrien /* The existing string is too short; malloc a new one. */ 145218822Sdim char *new_string = (char *) malloc (namelen + 1 + vallen); 146218822Sdim if (new_string == NULL) 14760484Sobrien { 14860484Sobrien UNLOCK; 14960484Sobrien return -1; 15060484Sobrien } 151218822Sdim *ep = new_string; 15260484Sobrien } 15360484Sobrien memcpy (*ep, name, namelen); 15460484Sobrien (*ep)[namelen] = '='; 15560484Sobrien memcpy (&(*ep)[namelen + 1], value, vallen); 15660484Sobrien } 15760484Sobrien 15860484Sobrien UNLOCK; 15960484Sobrien 16060484Sobrien return 0; 16160484Sobrien} 16260484Sobrien 16360484Sobrienvoid 164218822Sdimunsetenv (const char *name) 16560484Sobrien{ 16660484Sobrien const size_t len = strlen (name); 16760484Sobrien char **ep; 16860484Sobrien 16960484Sobrien LOCK; 17060484Sobrien 17160484Sobrien for (ep = __environ; *ep; ++ep) 17260484Sobrien if (!strncmp (*ep, name, len) && (*ep)[len] == '=') 17360484Sobrien { 17460484Sobrien /* Found it. Remove this pointer by moving later ones back. */ 17560484Sobrien char **dp = ep; 17660484Sobrien do 17760484Sobrien dp[0] = dp[1]; 17860484Sobrien while (*dp++); 17960484Sobrien /* Continue the loop in case NAME appears again. */ 18060484Sobrien } 18160484Sobrien 18260484Sobrien UNLOCK; 18360484Sobrien} 184