469,647 Members | 1,778 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,647 developers. It's quick & easy.

Odd behavior of getenv and putenv

Hi,

Recently I have observed some odd behavior of getenv and putenv function. I
am developing some code that integrates with several other libraries. This
program is not using MFC. It is plain C and C++ code.

Some login and initialization function from one dll is setting an
environment variable “MANUAL_LOGIN” to value “TRUE”. I tried three different
cases and here is what I found:

Case 1: If I write following code in my function:

char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = []
MANUAL_LOGIN = [TRUE]

Case 2: If I use same code as in case 1, but define following environment
variable on the command line prior to running the program:
set MANUAL_LOGIN=SOME_JUNK

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [TRUE]

Case 3: Now if I write following code in my function:

putenv (“MANUAL_LOGIN=SOME_JUNK”) ;
char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [SOME_JUNK]

So it seems that getenv() and system() look at different environment. Can
somebody please explain me what is happening here? My goal is to get original
value of environment variable. Change it to different value and then do some
processing and reset it back to its original value. Any idea how I can
achieve that?

Here is another odd behavior that I saw, this time with putenv. Following
code does not unset the environment variable, even though there is nothing
after = sign:

putenv (“MANUAL_LOGIN=”) ;

This may or may not be related to what I have described above.

Any explanations?
May 2 '06 #1
4 2126
On Tue, 2 May 2006 15:29:02 -0700, Yogi Watcher
<Yo*********@discussions.microsoft.com> wrote:
Hi,

Recently I have observed some odd behavior of getenv and putenv function. I
am developing some code that integrates with several other libraries. This
program is not using MFC. It is plain C and C++ code.

Some login and initialization function from one dll is setting an
environment variable MANUAL_LOGIN to value TRUE. I tried three different
cases and here is what I found:

Case 1: If I write following code in my function:

char *val = getenv (MANUAL_LOGIN) ;
printf (MANUAL_LOGIN = [%s]\n, val == NULL ? : val) ;
system (echo MANUAL_LOGIN = [%MANUAL_LOGIN%]) ;

then I get following output on screen:

MANUAL_LOGIN = []
MANUAL_LOGIN = [TRUE]
This sounds like the modules (EXE, DLL) are using different CRTs and thus
have distinct C-level environments. Sticking to the Windows functions
GetEnvironmentVariable and SetEnvironmentVariable should work for you, or
you could link everyone to the same CRT DLL so they would share CRT state.
Case 2: If I use same code as in case 1, but define following environment
variable on the command line prior to running the program:
set MANUAL_LOGIN=SOME_JUNK

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [TRUE]
Right, the new process inherits the environment of the process that started
it, so this is expected.
Case 3: Now if I write following code in my function:

putenv (MANUAL_LOGIN=SOME_JUNK) ;
char *val = getenv (MANUAL_LOGIN) ;
printf (MANUAL_LOGIN = [%s]\n, val == NULL ? : val) ;
system (echo MANUAL_LOGIN = [%MANUAL_LOGIN%]) ;

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [SOME_JUNK]

So it seems that getenv() and system() look at different environment. Can
somebody please explain me what is happening here?
If DLL X links to a different CRT than DLL Y, they will have separate
C-level environments, heap, errno, etc.
My goal is to get original
value of environment variable. Change it to different value and then do some
processing and reset it back to its original value. Any idea how I can
achieve that?
Link everyone to the same CRT DLL or use the Windows functions.
Here is another odd behavior that I saw, this time with putenv. Following
code does not unset the environment variable, even though there is nothing
after = sign:

putenv (MANUAL_LOGIN=) ;

This may or may not be related to what I have described above.

Any explanations?


Depending on where you're doing your getenv, it may well be related.

--
Doug Harrison
Visual C++ MVP
May 3 '06 #2
Thanks Doug.

That's exactly what was causing this. Once I fixed this, the issue that I
saw with putenv went away too.

Thanks a lot.

"Doug Harrison [MVP]" wrote:
On Tue, 2 May 2006 15:29:02 -0700, Yogi Watcher
<Yo*********@discussions.microsoft.com> wrote:
Hi,

Recently I have observed some odd behavior of getenv and putenv function. I
am developing some code that integrates with several other libraries. This
program is not using MFC. It is plain C and C++ code.

Some login and initialization function from one dll is setting an
environment variable “MANUAL_LOGIN” to value “TRUE”. I tried three different
cases and here is what I found:

Case 1: If I write following code in my function:

char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = []
MANUAL_LOGIN = [TRUE]


This sounds like the modules (EXE, DLL) are using different CRTs and thus
have distinct C-level environments. Sticking to the Windows functions
GetEnvironmentVariable and SetEnvironmentVariable should work for you, or
you could link everyone to the same CRT DLL so they would share CRT state.
Case 2: If I use same code as in case 1, but define following environment
variable on the command line prior to running the program:
set MANUAL_LOGIN=SOME_JUNK

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [TRUE]


Right, the new process inherits the environment of the process that started
it, so this is expected.
Case 3: Now if I write following code in my function:

putenv (“MANUAL_LOGIN=SOME_JUNK”) ;
char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [SOME_JUNK]

So it seems that getenv() and system() look at different environment. Can
somebody please explain me what is happening here?


If DLL X links to a different CRT than DLL Y, they will have separate
C-level environments, heap, errno, etc.
My goal is to get original
value of environment variable. Change it to different value and then do some
processing and reset it back to its original value. Any idea how I can
achieve that?


Link everyone to the same CRT DLL or use the Windows functions.
Here is another odd behavior that I saw, this time with putenv. Following
code does not unset the environment variable, even though there is nothing
after = sign:

putenv (“MANUAL_LOGIN=”) ;

This may or may not be related to what I have described above.

Any explanations?


Depending on where you're doing your getenv, it may well be related.

--
Doug Harrison
Visual C++ MVP

May 3 '06 #3
Now I have interesting question. If DLL X links to different CRT than DLL Y,
and If I change some environment variable in a function in DLL Y and then
spawn a process, then which environment will the spawned process get? one
(modified) from DLL Y, or one (original) from DLL X or combination of both
(???).

Thanks

"Doug Harrison [MVP]" wrote:
On Tue, 2 May 2006 15:29:02 -0700, Yogi Watcher
<Yo*********@discussions.microsoft.com> wrote:
Hi,

Recently I have observed some odd behavior of getenv and putenv function. I
am developing some code that integrates with several other libraries. This
program is not using MFC. It is plain C and C++ code.

Some login and initialization function from one dll is setting an
environment variable “MANUAL_LOGIN” to value “TRUE”. I tried three different
cases and here is what I found:

Case 1: If I write following code in my function:

char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = []
MANUAL_LOGIN = [TRUE]


This sounds like the modules (EXE, DLL) are using different CRTs and thus
have distinct C-level environments. Sticking to the Windows functions
GetEnvironmentVariable and SetEnvironmentVariable should work for you, or
you could link everyone to the same CRT DLL so they would share CRT state.
Case 2: If I use same code as in case 1, but define following environment
variable on the command line prior to running the program:
set MANUAL_LOGIN=SOME_JUNK

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [TRUE]


Right, the new process inherits the environment of the process that started
it, so this is expected.
Case 3: Now if I write following code in my function:

putenv (“MANUAL_LOGIN=SOME_JUNK”) ;
char *val = getenv (“MANUAL_LOGIN”) ;
printf (“MANUAL_LOGIN = [%s]\n”, val == NULL ? “” : val) ;
system (“echo MANUAL_LOGIN = [%MANUAL_LOGIN%]”) ;

then I get following output on screen:

MANUAL_LOGIN = [SOME_JUNK]
MANUAL_LOGIN = [SOME_JUNK]

So it seems that getenv() and system() look at different environment. Can
somebody please explain me what is happening here?


If DLL X links to a different CRT than DLL Y, they will have separate
C-level environments, heap, errno, etc.
My goal is to get original
value of environment variable. Change it to different value and then do some
processing and reset it back to its original value. Any idea how I can
achieve that?


Link everyone to the same CRT DLL or use the Windows functions.
Here is another odd behavior that I saw, this time with putenv. Following
code does not unset the environment variable, even though there is nothing
after = sign:

putenv (“MANUAL_LOGIN=”) ;

This may or may not be related to what I have described above.

Any explanations?


Depending on where you're doing your getenv, it may well be related.

--
Doug Harrison
Visual C++ MVP

May 3 '06 #4
On Wed, 3 May 2006 12:16:02 -0700, Yogi Watcher
<Yo*********@discussions.microsoft.com> wrote:
Now I have interesting question. If DLL X links to different CRT than DLL Y,
and If I change some environment variable in a function in DLL Y and then
spawn a process, then which environment will the spawned process get? one
(modified) from DLL Y, or one (original) from DLL X or combination of both
(???).


If you start the process using a CRT function, it will get the environment
from the CRT instance whose function you invoked. So if you invoke the
program from DLL X, it will get the environment from the CRT DLL X is
using. Same for DLL Y or any other module. If you want to use the
Windows-level environment, use CreateProcess directly. Note that putenv
does set both the CRT and Windows environments.

--
Doug Harrison
Visual C++ MVP
May 4 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by JDJones | last post: by
5 posts views Thread by Chad Paquette | last post: by
10 posts views Thread by Protoman | last post: by
17 posts views Thread by Protoman | last post: by
7 posts views Thread by dpugmire | last post: by
5 posts views Thread by silrandir | last post: by
8 posts views Thread by Michael B Allen | last post: by
4 posts views Thread by google | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.