1*5173eb0aSchristos /* Copyright (C) 1992-2024 Free Software Foundation, Inc. 298b9484cSchristos This file based on setenv.c in the GNU C Library. 398b9484cSchristos 498b9484cSchristos The GNU C Library is free software; you can redistribute it and/or 598b9484cSchristos modify it under the terms of the GNU Library General Public License as 698b9484cSchristos published by the Free Software Foundation; either version 2 of the 798b9484cSchristos License, or (at your option) any later version. 898b9484cSchristos 998b9484cSchristos The GNU C Library is distributed in the hope that it will be useful, 1098b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1198b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1298b9484cSchristos Library General Public License for more details. 1398b9484cSchristos 1498b9484cSchristos You should have received a copy of the GNU Library General Public 1598b9484cSchristos License along with the GNU C Library; see the file COPYING.LIB. If not, 1698b9484cSchristos write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 1798b9484cSchristos Boston, MA 02110-1301, USA. */ 1898b9484cSchristos 1998b9484cSchristos 2098b9484cSchristos /* 2198b9484cSchristos 2298b9484cSchristos @deftypefn Supplemental int setenv (const char *@var{name}, @ 2398b9484cSchristos const char *@var{value}, int @var{overwrite}) 2498b9484cSchristos @deftypefnx Supplemental void unsetenv (const char *@var{name}) 2598b9484cSchristos 2698b9484cSchristos @code{setenv} adds @var{name} to the environment with value 2798b9484cSchristos @var{value}. If the name was already present in the environment, 2898b9484cSchristos the new value will be stored only if @var{overwrite} is nonzero. 2998b9484cSchristos The companion @code{unsetenv} function removes @var{name} from the 3098b9484cSchristos environment. This implementation is not safe for multithreaded code. 3198b9484cSchristos 3298b9484cSchristos @end deftypefn 3398b9484cSchristos 3498b9484cSchristos */ 3598b9484cSchristos 3698b9484cSchristos #if HAVE_CONFIG_H 3798b9484cSchristos # include <config.h> 3898b9484cSchristos #endif 3998b9484cSchristos 4098b9484cSchristos #define setenv libiberty_setenv 4198b9484cSchristos #define unsetenv libiberty_unsetenv 4298b9484cSchristos 4398b9484cSchristos #include "ansidecl.h" 4498b9484cSchristos #include <sys/types.h> /* For `size_t' */ 4598b9484cSchristos #include <stdio.h> /* For `NULL' */ 4698b9484cSchristos 4798b9484cSchristos #include <errno.h> 4898b9484cSchristos #if !defined(errno) && !defined(HAVE_ERRNO_DECL) 4998b9484cSchristos extern int errno; 5098b9484cSchristos #endif 5198b9484cSchristos #define __set_errno(ev) ((errno) = (ev)) 5298b9484cSchristos 5398b9484cSchristos #if HAVE_STDLIB_H 5498b9484cSchristos # include <stdlib.h> 5598b9484cSchristos #endif 5698b9484cSchristos #if HAVE_STRING_H 5798b9484cSchristos # include <string.h> 5898b9484cSchristos #endif 5998b9484cSchristos #if HAVE_UNISTD_H 6098b9484cSchristos # include <unistd.h> 6198b9484cSchristos #endif 6298b9484cSchristos 6398b9484cSchristos #define __environ environ 64ba340e45Schristos #include "environ.h" 6598b9484cSchristos 6698b9484cSchristos #undef setenv 6798b9484cSchristos #undef unsetenv 6898b9484cSchristos 6998b9484cSchristos /* LOCK and UNLOCK are defined as no-ops. This makes the libiberty 7098b9484cSchristos * implementation MT-Unsafe. */ 7198b9484cSchristos #define LOCK 7298b9484cSchristos #define UNLOCK 7398b9484cSchristos 7498b9484cSchristos /* Below this point, it's verbatim code from the glibc-2.0 implementation */ 7598b9484cSchristos 7698b9484cSchristos /* If this variable is not a null pointer we allocated the current 7798b9484cSchristos environment. */ 7898b9484cSchristos static char **last_environ; 7998b9484cSchristos 8098b9484cSchristos 8198b9484cSchristos int 8298b9484cSchristos setenv (const char *name, const char *value, int replace) 8398b9484cSchristos { 8498b9484cSchristos register char **ep = 0; 8598b9484cSchristos register size_t size; 8698b9484cSchristos const size_t namelen = strlen (name); 8798b9484cSchristos const size_t vallen = strlen (value) + 1; 8898b9484cSchristos 8998b9484cSchristos LOCK; 9098b9484cSchristos 9198b9484cSchristos size = 0; 9298b9484cSchristos if (__environ != NULL) 9398b9484cSchristos { 9498b9484cSchristos for (ep = __environ; *ep != NULL; ++ep) 9598b9484cSchristos if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') 9698b9484cSchristos break; 9798b9484cSchristos else 9898b9484cSchristos ++size; 9998b9484cSchristos } 10098b9484cSchristos 10198b9484cSchristos if (__environ == NULL || *ep == NULL) 10298b9484cSchristos { 10398b9484cSchristos char **new_environ; 10498b9484cSchristos if (__environ == last_environ && __environ != NULL) 10598b9484cSchristos /* We allocated this space; we can extend it. */ 10698b9484cSchristos new_environ = (char **) realloc (last_environ, 10798b9484cSchristos (size + 2) * sizeof (char *)); 10898b9484cSchristos else 10998b9484cSchristos new_environ = (char **) malloc ((size + 2) * sizeof (char *)); 11098b9484cSchristos 11198b9484cSchristos if (new_environ == NULL) 11298b9484cSchristos { 11398b9484cSchristos UNLOCK; 11498b9484cSchristos return -1; 11598b9484cSchristos } 11698b9484cSchristos 11798b9484cSchristos new_environ[size] = (char *) malloc (namelen + 1 + vallen); 11898b9484cSchristos if (new_environ[size] == NULL) 11998b9484cSchristos { 12098b9484cSchristos free ((char *) new_environ); 12198b9484cSchristos __set_errno (ENOMEM); 12298b9484cSchristos UNLOCK; 12398b9484cSchristos return -1; 12498b9484cSchristos } 12598b9484cSchristos 12698b9484cSchristos if (__environ != last_environ) 12798b9484cSchristos memcpy ((char *) new_environ, (char *) __environ, 12898b9484cSchristos size * sizeof (char *)); 12998b9484cSchristos 13098b9484cSchristos memcpy (new_environ[size], name, namelen); 13198b9484cSchristos new_environ[size][namelen] = '='; 13298b9484cSchristos memcpy (&new_environ[size][namelen + 1], value, vallen); 13398b9484cSchristos 13498b9484cSchristos new_environ[size + 1] = NULL; 13598b9484cSchristos 13698b9484cSchristos last_environ = __environ = new_environ; 13798b9484cSchristos } 13898b9484cSchristos else if (replace) 13998b9484cSchristos { 14098b9484cSchristos size_t len = strlen (*ep); 14198b9484cSchristos if (len + 1 < namelen + 1 + vallen) 14298b9484cSchristos { 14398b9484cSchristos /* The existing string is too short; malloc a new one. */ 14498b9484cSchristos char *new_string = (char *) malloc (namelen + 1 + vallen); 14598b9484cSchristos if (new_string == NULL) 14698b9484cSchristos { 14798b9484cSchristos UNLOCK; 14898b9484cSchristos return -1; 14998b9484cSchristos } 15098b9484cSchristos *ep = new_string; 15198b9484cSchristos } 15298b9484cSchristos memcpy (*ep, name, namelen); 15398b9484cSchristos (*ep)[namelen] = '='; 15498b9484cSchristos memcpy (&(*ep)[namelen + 1], value, vallen); 15598b9484cSchristos } 15698b9484cSchristos 15798b9484cSchristos UNLOCK; 15898b9484cSchristos 15998b9484cSchristos return 0; 16098b9484cSchristos } 16198b9484cSchristos 16298b9484cSchristos void 16398b9484cSchristos unsetenv (const char *name) 16498b9484cSchristos { 16598b9484cSchristos const size_t len = strlen (name); 16698b9484cSchristos char **ep; 16798b9484cSchristos 16898b9484cSchristos LOCK; 16998b9484cSchristos 17098b9484cSchristos for (ep = __environ; *ep; ++ep) 17198b9484cSchristos if (!strncmp (*ep, name, len) && (*ep)[len] == '=') 17298b9484cSchristos { 17398b9484cSchristos /* Found it. Remove this pointer by moving later ones back. */ 17498b9484cSchristos char **dp = ep; 17598b9484cSchristos do 17698b9484cSchristos dp[0] = dp[1]; 17798b9484cSchristos while (*dp++); 17898b9484cSchristos /* Continue the loop in case NAME appears again. */ 17998b9484cSchristos } 18098b9484cSchristos 18198b9484cSchristos UNLOCK; 18298b9484cSchristos } 183