This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch applied for environ


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]