Environment handling broken in /bin/sh with changes to
t,set,put}env()
Sean C. Farley
scf at FreeBSD.org
Sat Jul 14 00:08:56 UTC 2007
On Sat, 14 Jul 2007, Andrey Chernov wrote:
> On Fri, Jul 13, 2007 at 05:27:58PM -0500, Sean C. Farley wrote:
>> Does that mean that environ is untouched or that the environment is
>> unchanged? They seem to use both words (environ and environment) in
>> the documentation making me think they are not necessarily the same
>> thing. Currently, non-getenv() calls rebuilds the environ array if
>> having never been changed before, but the "environment" is
>> "unchanged" if the variable does not exist. Should that not meet
>> that requirement?
>
> IMHO by the environment they means environ contents, not pointers,
> because they say:
>
> "The setenv() function shall update the list of pointers to which
> environ points."
I want to make certain what you mean. Upon the first call to setenv()
or unsetenv(), the environ is rebuilt. The contents are the same.
Before and after execution if no data was changed, environ will look
like this. The addresses to environ and to each pointer will be
different. Are you saying that the addresses should not change for
environ, environ[0-1] or all?
environ[0] = "PATH=/bin"
environ[1] = "USER=root"
environ[2] = NULL
I found this in the "Rationale" for getenv():
Conforming applications are required not to modify environ directly,
but to use only the functions described here to manipulate the
process environment as an abstract object. Thus, the implementation
of the environment access functions has complete control over the
data structure used to represent the environment (subject to the
requirement that environ be maintained as a list of strings with
embedded equal signs for applications that wish to scan the
environment). This constraint allows the implementation to properly
manage the memory it allocates, either by using allocated storage
for all variables (copying them on the first invocation of setenv()
or unsetenv()), or keeping track of which strings are currently in
allocated space and which are not, via a separate table or some
other means. This enables the implementation to free any allocated
space used by strings (and perhaps the pointers to them) stored in
environ when unsetenv() is called. A C runtime start-up procedure
(that which invokes main() and perhaps initializes environ) can also
initialize a flag indicating that none of the environment has yet
been copied to allocated storage, or that the separate table has not
yet been initialized.
In fact, for higher performance of getenv(), the implementation
could also maintain a separate copy of the environment in a data
structure that could be searched much more quickly (such as an
indexed hash table, or a binary tree), and update both it and the
linear list at environ when setenv() or unsetenv() is invoked.
It does not distinguish between whether or not any data changed when
changing environ. It just says "first invocation of setenv() or
unsetenv()".
Sean
--
scf at FreeBSD.org
More information about the freebsd-current
mailing list