Discussion:
clearing the environment
Jorge Almeida
2012-06-02 20:51:33 UTC
Permalink
What would be the proper way of clearing the environment before setting some
variable and then execve()'ing?

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

extern char** environ;

int main(){
environ=NULL;
// clearenv();
printf("here\n");
if(-1 == setenv("FOO", "bar", 1)) printf("%s", strerror(errno));
char* foobar=getenv("FOO");
printf("FOO=%s\n", foobar);
exit(0);
}
$ ./test
here
Segmentation fault

Setting "environ=NULL" is what the source for clearenv() says. Segfault
doesn't occur when this line is commented out.
On the other hand:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

extern char** environ;

int main(){
// environ=NULL;
clearenv();
printf("here\n");
if(-1 == setenv("FOO", "bar", 1)) printf("%s", strerror(errno));
char* foobar=getenv("FOO");
printf("FOO=%s\n", foobar);
exit(0);
}
$ make test
/opt/bin/diet gcc -O2 -march=atom -mfpmath=sse -mssse3
-fomit-frame-pointer -pipe -Wall -o test test.c
test.c: In function ‘main’:
test.c:17:3: warning: implicit declaration of function ‘clearenv’
[-Wimplicit-function-declaration]
/tmp/ccXEu0zU.o: In function `main':
test.c:(.text.startup+0x33): warning: setenv calls malloc. Avoid it
in small programs.
/extra/dietlibc/dietlibc-cvs/bin-i386/dietlibc.a(vprintf.o): In
function `vprintf':
vprintf.c:(.text+0x58): warning: warning: the printf functions add
several kilobytes of bloat.
/tmp/ccXEu0zU.o: In function `main':
test.c:(.text.startup+0xb): undefined reference to `clearenv'
collect2: error: ld returned 1 exit status
make: *** [test] Error 1


TIA

Jorge Almeida
Felix von Leitner
2012-06-03 04:27:41 UTC
Permalink
Post by Jorge Almeida
What would be the proper way of clearing the environment before setting some
variable and then execve()'ing?
execve takes the new environment as an argument.
The proper way is to pass a pointer to an empty environment to execve.

Note there is a difference between NULL and a pointer to NULL. :)

Felix
Jorge Almeida
2012-06-03 06:55:50 UTC
Permalink
On Sun, Jun 3, 2012 at 5:27 AM, Felix von Leitner
Post by Felix von Leitner
Post by Jorge Almeida
What would be the proper way of clearing the environment before setting some
variable and then execve()'ing?
execve takes the new environment as an argument.
The proper way is to pass a pointer to an empty environment to execve.
Note there is a difference between NULL and a pointer to NULL. :)
So, if I understood right, we shouldn't use clearenv() or equivalent and then
setup a few variables, but rather build from scratch an array an pass it to
execve. Is there some issue with clearenv, e.g. related with memory leaking?

Thanks

Jorge
Laurent Bercot
2012-06-03 09:24:18 UTC
Permalink
Post by Jorge Almeida
So, if I understood right, we shouldn't use clearenv() or equivalent and then
setup a few variables, but rather build from scratch an array an pass it to
execve. Is there some issue with clearenv, e.g. related with memory leaking?
putenv() and friends were made to modify the environment within the same
process, without execve'ing. It requires some hidden memory allocations,
it's inefficient, and unless you're coding a shell, it's mostly useless.

Since you can afford to execve(), it's much simpler to just setup a new
environment array and pass it to execve(). You *can* use putenv(), or
heap memory allocation, and just not care about memory leaks, since
execve() will clean up everything anyway; but you don't need to - and you
certainly don't need to if all you want is clear the environment.

Btw, don't pass NULL to execve(). Pass char const *envp[1] = { NULL }.
--
Laurent
Jorge Almeida
2012-06-03 12:44:07 UTC
Permalink
On Sun, Jun 3, 2012 at 10:24 AM, Laurent Bercot
Post by Jorge Almeida
So, if I understood right, we shouldn't use clearenv() or equivalent and then
setup a few variables, but rather build from scratch an array an pass it to
execve. Is there some issue with clearenv, e.g. related with memory leaking?
 putenv() and friends were made to modify the environment within the same
process, without execve'ing. It requires some hidden memory allocations,
it's inefficient, and unless you're coding a shell, it's mostly useless.
Thanks for the explanation, it's hard to find this kind of stuff in the net.
 Since you can afford to execve(), it's much simpler to just setup a new
environment array and pass it to execve(). You *can* use putenv(), or
heap memory allocation, and just not care about memory leaks, since
execve() will clean up everything anyway; but you don't need to - and you
certainly don't need to if all you want is clear the environment.
 Btw, don't pass NULL to execve(). Pass char const *envp[1] = { NULL }.
Actually, I want to clear the environment and then set two variables, so I
have a 3 elements array.

Cheers

Jorge

Loading...