Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-04

SetEnv on Linux 64bit

22 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

fred f

Hi!

I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC is not supported and therefore I am looking for SetEnv which I can use on 64bit Linux.

SysUtils contains only GetEnvironmentVariable, but not Set...

Thx, f.

Reply by email

Unknown author
to fred f
fred f wrote 6 lines
Hi! I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC is not supported and therefore I am looking for SetEnv which I can use on 64bit Linux. SysUtils contains only GetEnvironmentVariable, but not Set...

That's not how it works on Unix/Linux.

You must always set up environment variables before a program starts. When starting a process, the environment for that process is started and is then immutable for the duration of the process.

What you can do is execute the same binary again, but with the environment variable added to the environment of the new process.

Michael.

Reply by email

Marco van de Voort
to Unknown author
Show quoted text 9 lines
> supported and therefore I am looking for SetEnv which I can use on 64bit Linux. > > SysUtils contains only GetEnvironmentVariable, but not Set... That's not how it works on Unix/Linux. You must always set up environment variables before a program starts. When starting a process, the environment for that process is started and is then immutable for the duration of the process.

(and even if you manage to change the copy of the process, the libraries startup code will have already been run before you make that change to the copy of the environment)

Reply by email

Unknown author
to Marco van de Voort
Marco van de Voort wrote 14 lines
On Tue, Apr 03, 2012 at 03:57:01PM +0200, wrote: >> supported and therefore I am looking for SetEnv which I can use on 64bit Linux. >> >> SysUtils contains only GetEnvironmentVariable, but not Set... > > That's not how it works on Unix/Linux. > > You must always set up environment variables before a program starts. > When starting a process, the environment for that process is started and is > then immutable for the duration of the process. (and even if you manage to change the copy of the process, the libraries startup code will have already been run before you make that change to the copy of the environment)

Hence the 'immutable'...

Michael.

Reply by email

fred f
to Unknown author

Hi guys,

I try to start itself again with this code, but it doesn't work:

  IF GetEnvironmentVariable('LIBOVERLAY_SCROLLBAR')  '0' THEN begin
    mProc := TProcess.Create(NIL);
    mProc.CommandLine := GetExeName;
    mProc.Environment.Add('LIBOVERLAY_SCROLLBAR=0');
    mProc.Environment.Add('UBUNTU_MENUPROXY=');
    mProc.Options := mProc.Options + [poNoConsole];
    mProc.Execute;
    mProc.Free;
    halt; //close itself
  END;

What's wrong with this code?

Tnx, f.

Show quoted text 36 lines
On Tue, 3 Apr 2012, Marco van de Voort wrote: > On Tue, Apr 03, 2012 at 03:57:01PM +0200, > wrote: >>> >>> supported and therefore I am looking for SetEnv which I can use on 64bit >>> Linux. >>> >>> SysUtils contains only GetEnvironmentVariable, but not Set... >> >> >> That's not how it works on Unix/Linux. >> >> You must always set up environment variables before a program starts. >> When starting a process, the environment for that process is started and >> is >> then immutable for the duration of the process. > > > (and even if you manage to change the copy of the process, the libraries > startup code will have already been run before you make that change to the > copy of the environment) Hence the 'immutable'... Michael. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

waldo kitty
to Unknown author: That's not how it works on Unix/Linux. You must always set up environment variables…
Show quoted text 11 lines
On Tue, 3 Apr 2012, fred f wrote: > I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC is not > supported and therefore I am looking for SetEnv which I can use on 64bit Linux. > > SysUtils contains only GetEnvironmentVariable, but not Set... That's not how it works on Unix/Linux. You must always set up environment variables before a program starts. When starting a process, the environment for that process is started and is then immutable for the duration of the process.

ewww... so no "fancy" capabilities like we could do in the old DOS days where we could change the base environment as well as cloning it with changes for child processes??? if so, that's blows several of my porting projects up :? :(

What you can do is execute the same binary again, but with the environment variable added to the environment of the new process.

so, like the cloning process i mention above? that would have two copies of the app in memory at once, right?

Reply by email

Michael Van Canneyt
to waldo kitty
waldo kitty wrote 19 lines
On 4/3/2012 09:57, wrote: > On Tue, 3 Apr 2012, fred f wrote: >> I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC is >> not >> supported and therefore I am looking for SetEnv which I can use on 64bit >> Linux. >> >> SysUtils contains only GetEnvironmentVariable, but not Set... > > That's not how it works on Unix/Linux. > > You must always set up environment variables before a program starts. > When starting a process, the environment for that process is started and is > then immutable for the duration of the process. ewww... so no "fancy" capabilities like we could do in the old DOS days where we could change the base environment as well as cloning it with changes for child processes??? if so, that's blows several of my porting projects up :? :(

Not possible on Posix platforms.

Show quoted text 5 lines
> What you can do is execute the same binary again, but with the environment > variable added to the environment of the new process. so, like the cloning process i mention above? that would have two copies of the app in memory at once, right?

If you do an fpExec() without first a fpFork() you'll have only 1 copy in memory. fpExec replaces the current process with a new process, and a new environment can be specified for the new process.

Michael.

Reply by email

Andrew Haines
to fred f: I try to start itself again with this code, but it doesn't work: IF…
fred f wrote 20 lines
Hi guys, I try to start itself again with this code, but it doesn't work: IF GetEnvironmentVariable('LIBOVERLAY_SCROLLBAR') '0' THEN begin mProc := TProcess.Create(NIL); mProc.CommandLine := GetExeName; mProc.Environment.Add('LIBOVERLAY_SCROLLBAR=0'); mProc.Environment.Add('UBUNTU_MENUPROXY='); mProc.Options := mProc.Options + [poNoConsole]; mProc.Execute; mProc.Free; halt; //close itself END; What's wrong with this code? Tnx, f.

I'm can't say for sure that this is your problem but in the past I have observed that TProcess dumps all the inherited environment vairables as soon as you add something to it. On linux this means that the DISPLAY environment variable is not set.

You'll need something like this:

for i := 0 to GetEnvironmentVariableCount-1 do
begin
   EnvVarName := GetEnvironmentString(i);
   EnvVarValue := GetEnvironmentVariable(EnvVarName);
   mProc.Environment.Add(EnvVarName+'='+EnvVarValue);
end;
mProc.Environment.Add('LIBOVERLAY_SCROLLBAR=0');

Regards,

Andrew Haines

Reply by email

Andrew Haines
to Unknown author: That's not how it works on Unix/Linux. You must always set up environment variables…
Show quoted text 13 lines
You must always set up environment variables before a program starts. When starting a process, the environment for that process is started and is then immutable for the duration of the process. What you can do is execute the same binary again, but with the environment variable added to the environment of the new process. Michael. --

How does setenv work in libc? For instance you need to use that at runtime to embed a SDL window into your application. (only one sdl window per application works)

Regards,

Andrew Haines

Reply by email

waldo kitty
to Michael Van Canneyt: Not possible on Posix platforms. If you do an fpExec() without first a fpFork() you'll…
Michael Van Canneyt wrote 13 lines
On Tue, 3 Apr 2012, waldo kitty wrote: > On 4/3/2012 09:57, wrote: >> That's not how it works on Unix/Linux. >> >> You must always set up environment variables before a program starts. >> When starting a process, the environment for that process is started and is >> then immutable for the duration of the process. > > ewww... so no "fancy" capabilities like we could do in the old DOS days where > we could change the base environment as well as cloning it with changes for > child processes??? if so, that's blows several of my porting projects up :? :( Not possible on Posix platforms.

so i've been hearing over the years :( but i've kept on searching for a solution :P

Show quoted text 9 lines
>> What you can do is execute the same binary again, but with the environment >> variable added to the environment of the new process. > > so, like the cloning process i mention above? that would have two copies of > the app in memory at once, right? If you do an fpExec() without first a fpFork() you'll have only 1 copy in memory. fpExec replaces the current process with a new process, and a new environment can be specified for the new process.

that is seemingly like the clone of the initial environment plus modifications... yes... maybe my historical project ports are not all blown up :)

Reply by email

Honza
to Michael Van Canneyt: Not possible on Posix platforms. If you do an fpExec() without first a fpFork() you'll…

2012/4/3 Michael Van Canneyt :

Show quoted text 31 lines
On Tue, 3 Apr 2012, waldo kitty wrote: > On 4/3/2012 09:57, wrote: >> >> On Tue, 3 Apr 2012, fred f wrote: >>> >>> I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC >>> is not >>> supported and therefore I am looking for SetEnv which I can use on 64bit >>> Linux. >>> >>> SysUtils contains only GetEnvironmentVariable, but not Set... >> >> >> That's not how it works on Unix/Linux. >> >> You must always set up environment variables before a program starts. >> When starting a process, the environment for that process is started and >> is >> then immutable for the duration of the process. > > > ewww... so no "fancy" capabilities like we could do in the old DOS days > where we could change the base environment as well as cloning it with > changes for child processes??? if so, that's blows several of my porting > projects up :? :( Not possible on Posix platforms.

Now I'm confused. AFAICS
(http://pubs.opengroup.org/onlinepubs/007904975/functions/setenv.html) Posix setenv() allows a process to mutate its environment variables.

I probably misunderstood something, can someone enlighten me please?

-- jan

Reply by email

Unknown author
to Honza
Honza wrote 38 lines
2012/4/3 Michael Van Canneyt : > > > On Tue, 3 Apr 2012, waldo kitty wrote: > >> On 4/3/2012 09:57, wrote: >>> >>> On Tue, 3 Apr 2012, fred f wrote: >>>> >>>> I need to set up LIBOVERLAY_SCROLLBAR=0 on Ubuntu 64bit, but there LIBC >>>> is not >>>> supported and therefore I am looking for SetEnv which I can use on 64bit >>>> Linux. >>>> >>>> SysUtils contains only GetEnvironmentVariable, but not Set... >>> >>> >>> That's not how it works on Unix/Linux. >>> >>> You must always set up environment variables before a program starts. >>> When starting a process, the environment for that process is started and >>> is >>> then immutable for the duration of the process. >> >> >> ewww... so no "fancy" capabilities like we could do in the old DOS days >> where we could change the base environment as well as cloning it with >> changes for child processes??? if so, that's blows several of my porting >> projects up :? :( > > > Not possible on Posix platforms. Now I'm confused. AFAICS (http://pubs.opengroup.org/onlinepubs/007904975/functions/setenv.html) Posix setenv() allows a process to mutate its environment variables. I probably misunderstood something, can someone enlighten me please?

You can always modify them (it's just data in memory), but modifying them will only change your private view of the variables. The changes you make will not propagate to libraries or newly started processes.

Therefor it makes no sense to change them, and the FPC runtime does not allow it. If we did allow it, people would expect DOS/Windows like behaviour, which we simply cannot provide.

If you read the second part of the provided URL, you'll see that the POSIX group recognises that the behaviour of setenv() is problematical.

The URL points - for restrictions - to the exec function

http://pubs.opengroup.org/onlinepubs/007904975/functions/exec.html

Where it says:

"For those forms not containing an envp pointer ( execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process."

Etc etc etc.

Michael.

Reply by email

Honza
to Unknown author

2012/4/4 :

Thank you for the help. Unfortunately I'm now confused even more. I believe it's my fault, not yours.

You can always modify them (it's just data in memory), but modifying them will only change your private view of the variables. The changes you make will not propagate to libraries or newly started processes.

If "library" means a .so (or .dll, but Windows are not that much of a Posix system), then it is in in-process space, so I would think the change *does* propagate, i.e. the change is observable by a call to getenv() from inside a library function. About started processes see below.

Show quoted text 20 lines
Therefor it makes no sense to change them, and the FPC runtime does not allow it. If we did allow it, people would expect DOS/Windows like behaviour, which we simply cannot provide. If you read the second part of the provided URL, you'll see that the POSIX group recognises that the behaviour of setenv() is problematical. The URL points - for restrictions - to the exec function http://pubs.opengroup.org/onlinepubs/007904975/functions/exec.html Where it says: "For those forms not containing an envp pointer ( execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process."

The extrn char **environ (just environ from now on) points to the environment variables of the executing process. Setenv may mutates this environment. The various forms of exec do have either explicit envp, so one can create any required environment vars set, or pass the current environ, effectively enabling the inheritance of the (posibly mutated) environment as an option.

The other forms, w/o envp, are defined to do exactly that, i.e. they will use the current environ as their environment vars pointer, effectively forcing the inheritance of the (possibly mutated) environment. ("the environment for the new process image shall be taken from the external variable environ in the calling process")

I honestly presume I'm extra dumb today, anyway it still seems to me like the opposite of what was said in this thread is true:

Environment variables can be mutated, the changes are visible in a library (.so or and maybe in a .dll too) and with exec() one can choose if to pass a new environment or if the current one is to be inherited.

Apologies, I don't want to sound like a troll, I just want to figure out why the same Posix specs can be seen/interpreted in two mutually exclusive ways and naturally - which one is the correct interpretation.

PS: I've just cross-checked with some other language (Go if you are curious) and its std library and there seems to work all like I think the Posix specs says (http://golang.org/pkg/os/#Setenv and http://golang.org/pkg/os/exec/#Cmd) and I think the high level (and cross platform, Go programs should behave identically on Linux and Windows) wrapper of the Go 'os' package just reiterates the standard Posix behavior in a libc independent way.

-- jan

Reply by email

Unknown author
to Honza
Honza wrote 14 lines
2012/4/4 : Thank you for the help. Unfortunately I'm now confused even more. I believe it's my fault, not yours. > You can always modify them (it's just data in memory), but modifying them > will only change your private view of the variables. The changes you make > will not propagate to libraries or newly started processes. If "library" means a .so (or .dll, but Windows are not that much of a Posix system), then it is in in-process space, so I would think the change *does* propagate, i.e. the change is observable by a call to getenv() from inside a library function. About started processes see below.

Typically, libraries will read the environment subsequent change to the environment will not have any effect.

Show quoted text 29 lines
> Therefor it makes no sense to change them, and the FPC runtime does not > allow > it. If we did allow it, people would expect DOS/Windows like behaviour, > which > we simply cannot provide. > > If you read the second part of the provided URL, you'll see that the POSIX > group recognises that the behaviour of setenv() is problematical. > > The URL points - for restrictions - to the exec function > > http://pubs.opengroup.org/onlinepubs/007904975/functions/exec.html > > Where it says: > > "For those forms not containing an envp pointer ( execl(), execv(), > execlp(), > and execvp()), the environment for the new process image shall be taken from > the external variable environ in the calling process." The extrn char **environ (just environ from now on) points to the environment variables of the executing process. Setenv may mutates this environment. The various forms of exec do have either explicit envp, so one can create any required environment vars set, or pass the current environ, effectively enabling the inheritance of the (posibly mutated) environment as an option. The other forms, w/o envp, are defined to do exactly that, i.e. they will use the current environ as their environment vars pointer,

Not the current.

The EXTERNAL variable environ, i.e. the one that the kernel passed on, which cannot be modified. You can only modify your local copy.

Michael.

Reply by email

Honza
to Unknown author

2012/4/4 :

Not the current. The EXTERNAL variable environ, i.e. the one that the kernel passed on, which cannot be modified. You can only modify your local copy.
14:00 myname at tux64:~/tmp/c$ ls
a.c  b.c
14:00 myname at tux64:~/tmp/c$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
main() {
	char *e = getenv("MYVAR");
	printf("a1: %s\n", e);
	setenv("MYVAR", "MYVALUE", 1);
	e = getenv("MYVAR");
	printf("a2: %s\n", e);
	execv("./b.out", NULL);
}
14:00 myname at tux64:~/tmp/c$ cat b.c
#include <stdlib.h>
#include <stdio.h>
main() {
	char *e = getenv("MYVAR");
	printf("b: %s\n", e);
}

14:00 myname at tux64:~/tmp/c$ gcc -o a.out a.c && gcc -o b.out b.c && ls a.c a.out b.c b.out
14:00 myname at tux64:~/tmp/c$ ./a.out
a1: (null)
a2: MYVALUE
b: MYVALUE
14:00 myname at tux64:~/tmp/c$

-- jan

Reply by email

Unknown author
to Honza
Honza wrote 37 lines
2012/4/4 : > Not the current. > > The EXTERNAL variable environ, i.e. the one that the kernel passed on, > which cannot be modified. You can only modify your local copy. 14:00 myname at tux64:~/tmp/c$ ls a.c b.c 14:00 myname at tux64:~/tmp/c$ cat a.c #include <stdlib.h> #include <stdio.h> #include <unistd.h> main() { char *e = getenv("MYVAR"); printf("a1: %s\n", e); setenv("MYVAR", "MYVALUE", 1); e = getenv("MYVAR"); printf("a2: %s\n", e); execv("./b.out", NULL); } 14:00 myname at tux64:~/tmp/c$ cat b.c #include <stdlib.h> #include <stdio.h> main() { char *e = getenv("MYVAR"); printf("b: %s\n", e); } 14:00 myname at tux64:~/tmp/c$ gcc -o a.out a.c && gcc -o b.out b.c && ls a.c a.out b.c b.out 14:00 myname at tux64:~/tmp/c$ ./a.out a1: (null) a2: MYVALUE b: MYVALUE 14:00 myname at tux64:~/tmp/c$

Output of strace:

brk(0) = 0x21a5000 brk(0x21c6000) = 0x21c6000 write(1, "a2: MYVALUE\n", 12a2: MYVALUE
) = 12
execve("./b.out", [0], [/* 57 vars */]) = 0
brk(0) = 0x189e000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)

As you can see, it uses execve() behind the scenes to be able to pass the modified local environment.

This is libc-specific behaviour.

Michael.

Reply by email

Honza
to Unknown author

2012/4/4 :

Show quoted text 14 lines
Output of strace: brk(0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x21a5000 brk(0x21c6000) ? ? ? ? ? ? ? ?= 0x21c6000 write(1, "a2: MYVALUE\n", 12a2: MYVALUE ) ? = 12 execve("./b.out", [0], [/* 57 vars */]) = 0 brk(0) ? ? ? ? ? ? ? ?= 0x189e000 access("/etc/ld.so.nohwcap", F_OK) ? ? ?= -1 ENOENT (No such file or directory) As you can see, it uses execve() behind the scenes to be able to pass the modified local environment. This is libc-specific behaviour.

I think I cannot agree. IMO its a POSIX specified behavior. libc, at least in this case, just implements the POSIX specs: http://pubs.opengroup.org/onlinepubs/007904975/functions/exec.html

And as the ouptut of executing a.out shows, libc implements it correctly: "For those forms not containing an envp pointer ( execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process.", which libc achieves by calling execve() with the current environ, effectively just filling the prescribed default.

'extern **char environ' is no [kernel] magic*, it's just an ordinary pointer variable sitting in the process address space, it's only special in that it gets set (by means which are not important to this discussion) before main() starts executing.

-- jan

(*) One can e.g. happily set it directly to any other value:
14:41 myname at tux64:~/tmp/c$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
extern char **environ;
main() {
	char *e = getenv("MYVAR");
	printf("a1: %s\n", e);
	setenv("MYVAR", "MYVALUE", 1);
	e = getenv("MYVAR");
	printf("a2: %s\n", e);
	environ = NULL;
	e = getenv("MYVAR");
	printf("a3: %s\n", e);
}
14:41 myname at tux64:~/tmp/c$ gcc a.c && ./a.out
a1: (null)
a2: MYVALUE
a3: (null)
14:41 myname at tux64:~/tmp/c$

Reply by email

Unknown author
to Honza
Honza wrote 26 lines
2012/4/4 : > Output of strace: > > brk(0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= 0x21a5000 brk(0x21c6000) > ? ? ? ? ? ? ? ?= 0x21c6000 write(1, "a2: MYVALUE\n", 12a2: MYVALUE ) > ? = 12 execve("./b.out", [0], [/* 57 vars */]) = 0 brk(0) > ? ? ? ? ? ? ? ?= 0x189e000 access("/etc/ld.so.nohwcap", F_OK) ? ? ?= -1 > ENOENT (No such file or > directory) > > As you can see, it uses execve() behind the scenes to be able to pass the > modified > local environment. > > This is libc-specific behaviour. I think I cannot agree. IMO its a POSIX specified behavior. libc, at least in this case, just implements the POSIX specs: http://pubs.opengroup.org/onlinepubs/007904975/functions/exec.html And as the ouptut of executing a.out shows, libc implements it correctly: "For those forms not containing an envp pointer ( execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process.", which libc achieves by calling execve() with the current environ, effectively just filling the prescribed default.

I do not agree with this interpretation.

First of all, you are calling execv() in your code, not execve(). That libc changes this to execve() is IMHO not permissible. So all bets and conclusions are off from that point onwards.

Secondly, we interpret differently 'external variable environ'. (note the 'external'). For me this clearly means the original environment as passed on to the current process. Which probably is what happens if you'd call the execv() kernel function, although that would need testing.

Thirdly, the 2 referenced pages clearly indicate that the whole environment handling is hairy at best in corner cases like this.

And lastly: We on purpose do not follow Libc;
Otherwise we'd simply have built the whole RTL on top of it. So we are not under any obligation to mimic its behaviour.

Michael.

Reply by email

waldo kitty
to Honza: 2012/4/4 : 14:00 myname at tux64:~/tmp/c$ ls a.c b.c 14:00 myname at tux64:~/tmp/c$ cat…
Honza wrote 8 lines
2012/4/4: > Not the current. > > The EXTERNAL variable environ, i.e. the one that the kernel passed on, > which cannot be modified. You can only modify your local copy. 14:00 myname at tux64:~/tmp/c$ ls a.c b.c

[trim]

Show quoted text 5 lines
14:00 myname at tux64:~/tmp/c$ ./a.out a1: (null) a2: MYVALUE b: MYVALUE 14:00 myname at tux64:~/tmp/c$

your example shows a shell... i may have added to the confusion because a trick i recall us doing in the DOS days was to change the master environment... after running ./a.out, do you see your MYVAR in the environment via "set | more" or "export | more" or whatever?? most likely you will not see your MYVAR at that point after a.out finishes execution... i believe this is what was being pointed to as not supported...

my apologies if i added confusion...

Reply by email

Honza
to Unknown author: I do not agree with this interpretation. First of all, you are calling execv() in your…

2012/4/4 :

Show quoted text 5 lines
I do not agree with this interpretation. First of all, you are calling execv() in your code, not execve(). That libc changes this to execve() is IMHO not permissible. So all bets and conclusions are off from that point onwards.

Why not permissible? The POSIX specs describe what the semantics and/or effects of executing a defined function are. The semantics and effects of libc's execv() are what is said about it in POSIX. I don't see any 'off' conclusion derivable ;-)

Show quoted text 5 lines
Secondly, we interpret differently 'external variable environ'. (note the 'external'). For me this clearly means the original environment as passed on to the current process. From the moment main() starts executing, environ is the process

current environment. Initially, as it was passed, after any mutation well, that mutated state. No copy of the original environment of a process exists anywhere in the process nor in the kernel. A copy might still exists, though not necessarily, in the originating process, but that is anyway not accessible by the new/now executing process (modulo shmem etc.).

Also the 'external variable' is just a reference to the C specification, i.e. that's the way C says to the linker to find the variable defined elsewhere, not in this compilation unit/produced object code.

Which probably is what happens if you'd call the execv() kernel function, although that would need testing.

I can perhaps save someone's time, as there's no execv() kernel call. There's only execve() and that's why a POSIX compliant libc calls execve() with the current value of environ.

Thirdly, the 2 referenced pages clearly indicate that the whole environment handling is hairy at best in corner cases like this.

Perhaps, not relevant to us, IMO.

And lastly: We on purpose do not follow Libc; Otherwise we'd simply have built the whole RTL on top of it. So we are not under any obligation to mimic its behaviour.

No one said so. Actually that's just fine. The discussion went about various claims from various people that in POSIX the environment is either immutable at all, or the mutations are not visible in libraries, or not inherited on exec() - we (you and me) were not discussing FPC at all, IMO.

AFAICS, all the above claims were not true. Actually it's the first time ever I saw such claims, as mutating environment in a POSIX program, because of child process inherits that by default, is so common, that I have never even thought before of a possibility it could be otherwise, so I wanted to verify, to my own benefit, "how that stuff I never really looked into actually works" ;-)

-- jnml

PS: I think there's no reason why a SetEnv should not by available in sysutils (or system, or ...) on POSIX systems, and as other languages demonstrate, such call can work seamlessly on Windows too. And as FPC is a cross platform compiler.... Actually I think if there is GetEnv somewhere and its natural counterpart SetEnv is nowhere, then it's quite surprising - don't know about a similar example with some other language.

Reply by email

Unknown author
to Honza
Honza wrote 21 lines
2012/4/4 : > I do not agree with this interpretation. > > First of all, you are calling execv() in your code, not execve(). That libc > changes this to execve() is IMHO not permissible. > So all bets and conclusions are off from that point onwards. Why not permissible? The POSIX specs describe what the semantics and/or effects of executing a defined function are. The semantics and effects of libc's execv() are what is said about it in POSIX. I don't see any 'off' conclusion derivable ;-) > Secondly, we interpret differently 'external variable environ'. (note the > 'external'). For me this clearly means the original environment as passed on > to the current process. > From the moment main() starts executing, environ is the process current environment. Initially, as it was passed, after any mutation well, that mutated state. No copy of the original environment of a process exists anywhere in the process nor in the kernel.

I think you'll find that the environment block is copied as soon as you add a new environment variable.

Since the original environment as passed by the kernel is not in the heap, so how could you add something to it, except by copying the array of pointers and enlarging it ?

What happens to it in a library, is currently open for speculation.

Show quoted text 9 lines
A copy might still exists, though not necessarily, in the originating process, but that is anyway not accessible by the new/now executing process (modulo shmem etc.). Also the 'external variable' is just a reference to the C specification, i.e. that's the way C says to the linker to find the variable defined elsewhere, not in this compilation unit/produced object code.

I agree a C person might interpret it like that.

Show quoted text 7 lines
> Which probably is what happens if you'd call the > execv() kernel function, although that would need testing. I can perhaps save someone's time, as there's no execv() kernel call. There's only execve() and that's why a POSIX compliant libc calls execve() with the current value of environ.

I stand corrected on this front.

Show quoted text 15 lines
> Thirdly, the 2 referenced pages clearly indicate that the whole environment > handling is hairy at best in corner cases like this. Perhaps, not relevant to us, IMO. > And lastly: We on purpose do not follow Libc; Otherwise we'd simply have > built the whole RTL on top of it. So we are not under any obligation to > mimic its behaviour. No one said so. Actually that's just fine. The discussion went about various claims from various people that in POSIX the environment is either immutable at all, or the mutations are not visible in libraries, or not inherited on exec() - we (you and me) were not discussing FPC at all, IMO.

Yes. I was sloppy in my terminology.

Show quoted text 7 lines
AFAICS, all the above claims were not true. Actually it's the first time ever I saw such claims, as mutating environment in a POSIX program, because of child process inherits that by default, is so common, that I have never even thought before of a possibility it could be otherwise, so I wanted to verify, to my own benefit, "how that stuff I never really looked into actually works" ;-)

I think the confusion came from the original posters request to modify the 'global environment', which - I hope you'll agree - is not possible on Posix, as the environment is passed on from process to process using execve.

So, my conclusions:

* The SetEnvironment() call on windows will do something totally different than what happens under Posix, and the Windows behaviour cannot be mimicked. Which is why it isn't in sysutils.

* A posixy SetEnv() could be implemented for the Unix layer, to mimic Libc. But I think it would not be usable for libraries, since the environment copy of the RTL would not be shareable with the library without pulling in the C memory manager.
At best it could be used to be passed on to a new process.

Michael.

Reply by email