Xref: utzoo comp.unix.microport:2871 comp.unix.wizards:14803 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uflorida!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.microport,comp.unix.wizards Subject: Re: bug in putenv()! Keywords: bug putenv Message-ID: <16066@mimsy.UUCP> Date: 21 Feb 89 23:50:06 GMT References: <204@tree.UUCP> <1046@auspex.UUCP> <233@tree.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 88 In article <233@tree.UUCP> asmodeus@tree.UUCP (Jonathan Ballard) writes: >From what you people have been saying is that I can't pass in a automatic >varible because putenv uses that space, right? No, not right; see below. >... Why doesn't putenv just alloc a new spot for the enviroment >varible to go? It expects *you* to do that, if it is necessary (often it is not). >But if I do understand this right - I have to make several global or >static varible just to handle space for the enviroment. Not so. A real treatment of the issue belongs in comp.lang.c. The important part, however, is the storage for the *characters* to which the thing you hand to putenv() will point must remain undisturbed. Thus, the following is wrong (but may work, if you are unlucky, depending on how much stack junk you might have:) main() { set(); ... refer to environment ... } set() { char env[30]; strcpy(env, "FOO=bar"); putenv(env); } But if main() does not return to its caller (if it ends with exit(0)), or if its caller (the C library startup code) does not look at the environment, the following is correct: main() { char env[30]; strcpy(env, "FOO=bar"); putenv(env); } In both examples, `env' provides space for 30 characters. The environment will retain a pointer to the first of those thirty characters (the `F' in FOO=bar). This space-for-30-chars is `alive' (guaranteed to remain undisturbed) for the duration of main() and any functions called by main()---in other words, for the entire program. If `env' is declared in `set()', the space is alive only for the duration of the call to set(). When set() returns to main(), the space becomes dead and is free to be reused. Whether it *is* reused is compiler- and system-dependent (and may even vary from one run to another). As another example, putenv("FOO=bar"); would be correct whether it were in set() or in main(). This is because a double-quoted string has static storage duration: that is, there is one copy of the characters making up that string, and it sits somewhere in text or data space, never moving and (unless you do something technically illegal) never changing. You can make set() work by changing it from set() { char env[30]; to set() { static char env[30]; Finally, at any time, you can always call p = strdup(pointer); if (p == NULL) ... error ... putenv(p); (you may need to write strdup() first if you have an old support library). strdup() calls malloc() to allocate space for the string at which `pointer' is assumed to point. The space allocated by malloc() will not be reused unless you allow it. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris