From: MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 18-JAN-1993 02:23:08.69 To: INFO-VAX@kl.sri.com CC: Subj: re: Re: Where is the putenv()??? [Someone asked:] Hi, I am porting a make to VMS. and it needs putenv(). while the [I answered:] There isn't any. The Unix "environment" doesn't really exist on VMS... You're going to have to look at the code that uses putenv() and determine what it does, then figure out how to get the equivalent effect on VMS. [Don Stokes writes:] That's not a very imaginative response, Jerry! 8-) The following is a putenv() that will do most things. Chaining using exec*() won't work, but it will work across a spawn (ie system() or vfork()/exec*() combination). The unix environment is not propagated back to the parent process, hence the use of user-mode logicals which are destroyed at image run-down to emulate this behaviour.... Besides not working in the case of "chaining" with exec*() - a fairly rare thing for Unix programs to do - it fails in a much more prosaic case: If you use system() to run a command file, the first image to run down in the command file will destroy all the user-mode logicals. Then the rest of the command file will run without the "environment" that you tried to set up. It is fairly common for Unix programs to use system() to start a subsidiary shell directly, or (since the equivalent of command files on Unix can be run as programs, with the effect that a shell is started to interpret them) to apply system() to a command that will start a command file. In fact, I would expect that kind of thing to be done in a make program in response to multi- line build specifications. A putenv() based on user-mode logicals is likely to work in small test cases, then fail in ways that a Unix programmer (and many VMS programmers!) will have a great deal of trouble understanding. Such a putenv() implementation is a trap for the unwary, and I would never recommend it. You could come close to Unix functionality by implementing putenv("xxx") as: - If this is the first call to putenv, establish an exit handler. - If this is the first time xxx is being added to the environment, check if xxx is defined as a supervisor-mode logical and if so save its old value; else flag it as checked but don't save a value. - Define xxx as a supervisor-mode logical (LIB$SET_LOGICAL). - In the exit handler, walk through the list of saved environment values (saved logical names) and put them back. This assumes the exit handler always gets executed. Of course, if the user blocks it by typing STOP, or so badly damages the stack that proper rundown is impossible (not unheard of with C programs), the "environment changes" become permanent. (Also, any method based on defining logical names could break file accesses; but that's another story. It's too bad getenv() looks for logicals before it looks for DCL symbols - it's much safer to make up arbitrary new DCL symbols than arbitrary new logical names.) Ultimately, I'll have to stand by my original comment: The only way to port a Unix program using putenv() with any assurance that it will work as you expect is to "determine what it does, then figure out how to get the equivalent effect on VMS". -- Jerry