Most shells don't use the getenv()
/setenv()
/putenv()
API.
Upon start-up, they create shell variables for each environment variablesvariable they received. Those will be stored in internal structures that need to carry other information like whether the variable is exported, read-only... They can't use the libc's environ
for that.
Similarly, and for that reason, they won't use execlp()
, execvp()
to execute commands but call the execve()
system call directly, computing the envp[]
array based on the list of their exported variables.
So in your gdb
, you'd need to add an entry to that shells internal table of variables, or possibly call the right function that would make it interpret a export VAR=value
code for it to update that table by itself.
As to why you see a difference between bash
and zsh
when you call setenv()
in gdb
, I suspect that's because you're calling setenv()
before the shell initialises, for instance upon entering main()
.
You'll notice bash
's main()
is int main(int argc, char* argv[], char* envp[])
(and bash
maps variables from those env vars in envp[]
) while zsh
's is int main(int argc, char* argv[])
and zsh
gets the variables from environ
instead. setenv()
does modify environ
but cannot modify envp[]
in-place (read-only on several systems as well as the strings those pointers point to).
In any case, after the shell has read environ
upon startup, using setenv()
would be ineffective as the shell no longer uses environ
(or getenv()
) afterwards.