Patch applied for environ
Michael Meissner
meissner@redhat.com
Wed Nov 22 10:31:00 GMT 2000
I think I've sent this out and gotten approval for it, but in case
this is new to people, I was working on a port with a short data
switch, and the users wanted to run a certain testsuite with the -G 0
option to indicate no short data. That test suite defines its own
environ variable, so the variable got put into the wrong section, and
the short references in the library gave a linker error. I've also
encountered shared library systems that failed in a similar manner.
2000-11-22 Michael Meissner <meissner@redhat.com>
* libc/posix/execl.c (execl): Don't reference environ directly,
reference it only via a static pointer to avoid problems with some
shared library systems and with different uses of small data where
the user specifies his own version of environ.
* libc/posix/execv.c (execv): Ditto.
* libc/stdlib/getenv_r.c (_findenv_r): Ditto.
* libc/stdlib/setenv_r.c (_setenv_r,_unsetenv_r): Ditto.
* libc/stdlib/system.c (system, !cygwin32 case): Ditto.
* libc/stdlib/getenv.c (environ): Delete unused reference to
environ.
* libc/stdlib/getenv_r.c: Make initial comment friendlier to emacs
colorization.
* libc/stdlib/system.c: Ditto.
*** libc/posix/execl.c.~1~ Thu Feb 17 14:39:47 2000
--- libc/posix/execl.c Tue Oct 3 18:05:01 2000
***************
*** 6,11 ****
--- 6,16 ----
#include <_ansi.h>
#include <unistd.h>
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
#ifdef _HAVE_STDC
#include <stdarg.h>
*************** execl (path, arg0, va_alist)
*** 38,42 ****
while (argv[i++] != NULL);
va_end (args);
! return _execve (path, (char * _CONST *) argv, environ);
}
--- 43,47 ----
while (argv[i++] != NULL);
va_end (args);
! return _execve (path, (char * _CONST *) argv, *p_environ);
}
*** libc/posix/execv.c.~1~ Thu Feb 17 14:39:47 2000
--- libc/posix/execv.c Tue Oct 3 18:05:18 2000
***************
*** 6,15 ****
#include <_ansi.h>
#include <unistd.h>
int
_DEFUN (execv, (path, argv),
const char *path _AND
char * const argv[])
{
! return _execve (path, (char * _CONST *) argv, environ);
}
--- 6,20 ----
#include <_ansi.h>
#include <unistd.h>
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
int
_DEFUN (execv, (path, argv),
const char *path _AND
char * const argv[])
{
! return _execve (path, (char * _CONST *) argv, *p_environ);
}
*** libc/stdlib/getenv_r.c.~1~ Thu Feb 17 14:39:47 2000
--- libc/stdlib/getenv_r.c Tue Oct 3 18:05:54 2000
*************** TRAD_SYNOPSIS
*** 19,25 ****
DESCRIPTION
<<_getenv_r>> searches the list of environment variable names and values
! (using the global pointer `<<char **environ>>') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<_getenv_r>> returns a pointer to the associated value.
--- 19,25 ----
DESCRIPTION
<<_getenv_r>> searches the list of environment variable names and values
! (using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<_getenv_r>> returns a pointer to the associated value.
*************** variables vary from one system to anothe
*** 65,70 ****
--- 65,75 ----
extern char **environ;
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
/*
* _findenv --
* Returns pointer to value associated with name, if any, else NULL.
*************** _DEFUN (_findenv_r, (reent_ptr, name, of
*** 89,95 ****
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
! if (!environ)
return NULL;
c = name;
--- 94,100 ----
/* In some embedded systems, this does not get set. This protects
newlib from dereferencing a bad pointer. */
! if (!*p_environ)
return NULL;
c = name;
*************** _DEFUN (_findenv_r, (reent_ptr, name, of
*** 100,110 ****
len++;
}
! for (p = environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
! *offset = p - environ;
ENV_UNLOCK;
return (char *) (++c);
}
--- 105,115 ----
len++;
}
! for (p = *p_environ; *p; ++p)
if (!strncmp (*p, name, len))
if (*(c = *p + len) == '=')
{
! *offset = p - *p_environ;
ENV_UNLOCK;
return (char *) (++c);
}
*** libc/stdlib/setenv_r.c.~1~ Mon Apr 17 13:10:17 2000
--- libc/stdlib/setenv_r.c Tue Oct 3 18:06:15 2000
***************
*** 29,34 ****
--- 29,41 ----
#include <string.h>
#include "envlock.h"
+ extern char **environ;
+
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
/* _findenv_r is defined in getenv_r.c. */
extern char *_findenv_r _PARAMS ((struct _reent *, const char *, int *));
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 45,51 ****
_CONST char *value _AND
int rewrite)
{
- extern char **environ;
static int alloced; /* if allocated space before */
register char *C;
int l_value, offset;
--- 52,57 ----
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 74,85 ****
register int cnt;
register char **P;
! for (P = environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
! environ = (char **) _realloc_r (reent_ptr, (char *) environ,
! (size_t) (sizeof (char *) * (cnt + 2)));
! if (!environ)
{
ENV_UNLOCK;
return -1;
--- 80,91 ----
register int cnt;
register char **P;
! for (P = *p_environ, cnt = 0; *P; ++P, ++cnt);
if (alloced)
{ /* just increase size */
! *p_environ = (char **) _realloc_r (reent_ptr, (char *) environ,
! (size_t) (sizeof (char *) * (cnt + 2)));
! if (!*p_environ)
{
ENV_UNLOCK;
return -1;
*************** _DEFUN (_setenv_r, (reent_ptr, name, val
*** 94,113 ****
ENV_UNLOCK;
return (-1);
}
! bcopy ((char *) environ, (char *) P, cnt * sizeof (char *));
! environ = P;
}
! environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
! if (!(environ[offset] = /* name + `=' + value */
_malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
{
ENV_UNLOCK;
return -1;
}
! for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; (*C++ = *value++) != 0;);
ENV_UNLOCK;
--- 100,119 ----
ENV_UNLOCK;
return (-1);
}
! bcopy ((char *) *p_environ, (char *) P, cnt * sizeof (char *));
! *p_environ = P;
}
! (*p_environ)[cnt + 1] = NULL;
offset = cnt;
}
for (C = (char *) name; *C && *C != '='; ++C); /* no `=' in name */
! if (!((*p_environ)[offset] = /* name + `=' + value */
_malloc_r (reent_ptr, (size_t) ((int) (C - name) + l_value + 2))))
{
ENV_UNLOCK;
return -1;
}
! for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C);
for (*C++ = '='; (*C++ = *value++) != 0;);
ENV_UNLOCK;
*************** _DEFUN (_unsetenv_r, (reent_ptr, name),
*** 124,137 ****
struct _reent *reent_ptr _AND
_CONST char *name)
{
- extern char **environ;
register char **P;
int offset;
ENV_LOCK;
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
! for (P = &environ[offset];; ++P)
if (!(*P = *(P + 1)))
break;
--- 130,142 ----
struct _reent *reent_ptr _AND
_CONST char *name)
{
register char **P;
int offset;
ENV_LOCK;
while (_findenv_r (reent_ptr, name, &offset)) /* if set multiple times */
! for (P = &(*p_environ)[offset];; ++P)
if (!(*P = *(P + 1)))
break;
*** libc/stdlib/system.c.~1~ Tue Oct 3 18:03:04 2000
--- libc/stdlib/system.c Tue Oct 3 18:06:38 2000
*************** DESCRIPTION
*** 27,33 ****
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
! Use `<<system(NULL)>>' to test whether your system has <</bin/sh>>
available.
The alternate function <<_system_r>> is a reentrant version. The
--- 27,33 ----
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
! Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
available.
The alternate function <<_system_r>> is a reentrant version. The
*************** system (s)
*** 107,112 ****
--- 107,119 ----
#endif
#if defined (unix) && !defined (__CYGWIN__)
+ extern char **environ;
+
+ /* Only deal with a pointer to environ, to work around subtle bugs with shared
+ libraries and/or small data systems where the user declares his own
+ 'environ'. */
+ static char ***p_environ = &environ;
+
static int
do_system (ptr, s)
struct _reent *ptr;
*************** do_system (ptr, s)
*** 114,120 ****
{
char *argv[4];
int pid, status;
- extern char **environ;
argv[0] = "sh";
argv[1] = "-c";
--- 121,126 ----
*************** do_system (ptr, s)
*** 123,129 ****
if ((pid = _fork_r (ptr)) == 0)
{
! _execve ("/bin/sh", argv, environ);
exit (100);
}
else if (pid == -1)
--- 129,135 ----
if ((pid = _fork_r (ptr)) == 0)
{
! _execve ("/bin/sh", argv, *p_environ);
exit (100);
}
else if (pid == -1)
*** libc/stdlib/getenv.c.~1~ Thu Feb 17 14:39:47 2000
--- libc/stdlib/getenv.c Tue Oct 3 18:05:35 2000
*************** TRAD_SYNOPSIS
*** 18,24 ****
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
! (using the global pointer `<<char **environ>>') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
--- 18,24 ----
DESCRIPTION
<<getenv>> searches the list of environment variable names and values
! (using the global pointer ``<<char **environ>>'') for a variable whose
name matches the string at <[name]>. If a variable name matches,
<<getenv>> returns a pointer to the associated value.
*************** variables vary from one system to anothe
*** 39,45 ****
*/
/*
! * Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
--- 39,45 ----
*/
/*
! * Copyright (c) 1987, 2000 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
*************** variables vary from one system to anothe
*** 62,69 ****
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-
- extern char **environ;
/*
* _findenv --
--- 62,67 ----
--
Michael Meissner, Red Hat, Inc.
PMB 198, 174 Littleton Road #3, Westford, Massachusetts 01886, USA
Work: meissner@redhat.com phone: +1 978-486-9304
Non-work: meissner@spectacle-pond.org fax: +1 978-692-4482
More information about the Newlib
mailing list