Mail Archives: djgpp-workers/1996/10/03/04:16:10
It seems that other implementations of `putenv' tolerate setting
`environ' to something else, e.g. to start with a clean environment. At
least two programs in the GNU Sh-utils have something like this:
char *dummy_environ[1];
environ = dummy_environ;
environ[0] = NULL;
Our `putenv' of course gets totally confused by this. So here are some
changes to make it more defensive, and also support ``putenv("foobar")''
(meaning delete "foobar") which some Sh-utils need.
*** src/libc/compat/stdlib/putenv.c~2 Sat Aug 10 16:08:36 1996
--- src/libc/compat/stdlib/putenv.c Tue Oct 1 21:15:54 1996
***************
*** 15,20 ****
--- 15,21 ----
*/
extern char **environ;
+ static char **prev_environ = NULL; /* to know when it's safe to call `free' */
static int ecount = -1;
static int emax = -1;
static int putenv_bss_count = -1;
***************
*** 37,60 ****
{
int vlen = strlen(val);
char *epos = strchr(val, '=');
! int nlen = epos - val + 1;
int eindex;
! if (putenv_bss_count != __bss_count)
{
- putenv_bss_count = __bss_count;
for (ecount=0; environ[ecount]; ecount++);
emax = ecount;
/* Bump the count to a value no function has yet seen,
even if they were dumped with us. */
__environ_changed++;
}
- if (epos == 0)
- return -1;
-
for (eindex=0; environ[eindex]; eindex++)
! if (strncmp(environ[eindex], val, nlen) == 0)
{
char *oval = environ[eindex];
--- 38,73 ----
{
int vlen = strlen(val);
char *epos = strchr(val, '=');
! /* Feature: VAL without a `=' means delete the entry. GNU `putenv'
! works that way, and `env' from GNU Sh-utils counts on this behavior. */
! int nlen = epos ? epos - val + 1 : vlen;
int eindex;
! /* Force recomputation of the static counters.
!
! The second condition of the next if clause covers the case that
! somebody pointed environ to another array, which invalidates
! `ecount' and `emax'. This can be used to change the environment
! to something entirely different, or to effectively discard it
! altogether. GNU `env' from Sh-utils does just that. */
! if (putenv_bss_count != __bss_count
! || environ != prev_environ)
{
for (ecount=0; environ[ecount]; ecount++);
emax = ecount;
/* Bump the count to a value no function has yet seen,
even if they were dumped with us. */
__environ_changed++;
+ if (putenv_bss_count != __bss_count)
+ {
+ putenv_bss_count = __bss_count;
+ prev_environ = environ; /* it's malloced by crt1.c */
+ }
}
for (eindex=0; environ[eindex]; eindex++)
! if (strncmp(environ[eindex], val, nlen) == 0
! && (epos || environ[eindex][nlen] == '='))
{
char *oval = environ[eindex];
***************
*** 92,103 ****
{
char **enew;
emax += 10;
! enew = (char **)malloc(emax * sizeof(char **));
if (enew == 0)
return -1;
memcpy(enew, environ, ecount * sizeof(char *));
! free(environ);
environ = enew;
}
environ[ecount] = (char *)malloc(vlen+1);
--- 105,120 ----
{
char **enew;
emax += 10;
! enew = (char **)malloc(emax * sizeof(char *));
if (enew == 0)
return -1;
memcpy(enew, environ, ecount * sizeof(char *));
! /* If somebody set environ to another array, we can't
! safely free it. Better leak memory than crash. */
! if (environ == prev_environ)
! free(environ);
environ = enew;
+ prev_environ = environ;
}
environ[ecount] = (char *)malloc(vlen+1);
- Raw text -