getenv in FreeBSD 7

Jeremy Chadwick koitsu at freebsd.org
Mon Apr 7 05:38:50 UTC 2008


On Sun, Apr 06, 2008 at 08:18:20PM -0700, Doug Hardie wrote:
> On Apr 6, 2008, at 17:54, Jeremy Chadwick wrote:
>> On Sun, Apr 06, 2008 at 03:05:18PM -0700, Doug Hardie wrote:
>>>
>>> On Apr 6, 2008, at 14:52, Jeremy Chadwick wrote:
>>>> On Sun, Apr 06, 2008 at 02:45:24PM -0700, Jeremy Chadwick wrote:
>>>>> On Sun, Apr 06, 2008 at 02:37:06PM -0700, Doug Hardie wrote:
>>>>>> Somewhere between FreeBSD 6.2 and 7.0 getenv has been changed to 
>>>>>> return
>>>>>> a
>>>>>> null if an environment variable is set but has no value.  I don't find
>>>>>> anything anywhere in the documentation/man pages on this.  As a 
>>>>>> result,
>>>>>> you
>>>>>> cannot distinguish between a variable that is not set and one that is
>>>>>> set
>>>>>> to a value of "".  Is this a bug or a feature change?
>>>>>
>>>>> I'd begin peeking here:
>>>>>
>>>>> http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdlib/getenv.c
>>>>
>>>> Follow-up: the manpages between 6.3-PRERELEASE and 7.0-STABLE do
>>>> document said change:
>>>>
>>>> http://www.freebsd.org/cgi/man.cgi?query=getenv&apropos=0&sektion=3&manpath=FreeBSD+6.3-RELEASE&format=html
>>>
>>> Says that if the environment variable is NOT IN THE ENVIRONMENT then null
>>> is returned.  Setting the variable to "" does put it in the environment.
>>> env returns it properly.
>>>
>>>>
>>>>
>>>> http://www.freebsd.org/cgi/man.cgi?query=getenv&apropos=0&sektion=3&manpath=FreeBSD+7.0-stable&format=html
>>>
>>> Same thing.  I find nothing documented about this change.
>>
>> I'm not sure where you're going with this.  I see it clearly in the
>> ERRORS section.
>
> I didn't think that having a defined variable with the value "" would be an 
> error.  getenv does not return EINVAL but returns a zero.  I would have 
> expected some notification in the description of getenv.

My apologies: I misread the manpage.  The ERRORS section applies to
setenv(), putenv(), and unsetenv() -- not getenv().  So ignore my
earlier claims about EINVAL being relevant to getenv().

getenv() will either return a pointer to what the environment variable
contains (and if empty (e.g. ""), it should stil return a pointer to a
buffer that consists of nothing but NULL), or if getenv() returns NULL
then it means the variable isn't set.

>> But besides that, just like Bakul Shah, I cannot reproduce this problem:
>>
>> $ uname -mr
>> 7.0-STABLE amd64
>> $ gcc -o z z.c
>> $ ./z
>> getenv(FOO) = (null)
>> $ export FOO=yep
>> $ ./z
>> getenv(FOO) = yep
>> export FOO=
>> $ ./z
>> getenv(FOO) =
>> $ cat z.c
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int main(void)
>> {
>>  char *e = getenv("FOO");
>>
>>  printf("getenv(FOO) = %s\n", e);
>>  return 0;
>> }
>
> At this time, it does return a pointer to "".  However, earlier today it 
> did not.  It returned a zero.  It was quite consistent for several hours.  
> I wonder if this is another issue with gdb.  It seems to be quite flakey on 
> 7.0.

I'd expect there to be an immense amount of "random breakage" in all
sorts of scripts on a system, ditto with Apache spawning CGIs which rely
on environment variables (REMOTE_ADDR comes to mind), if getenv() was
unreliable.  The ports system, for example, relies heavily upon
environment variables.

As I was writing this, I was thinking if a local resource starvation
issue could cause this (libc being unable to malloc some memory without
a proper failure check, or stack space running out), but after looking
at getenv() and related functions, I don't see how this could be
possible.

The next time it happens, post here with some more details.  Definitely
a mysterious one...

-- 
| Jeremy Chadwick                                    jdc at parodius.com |
| Parodius Networking                           http://www.parodius.com/ |
| UNIX Systems Administrator                      Mountain View, CA, USA |
| Making life hard for others since 1977.                  PGP: 4BD6C0CB |



More information about the freebsd-stable mailing list