Skip to main content
added 12 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

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.

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variables. 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.

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variable 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.

added 781 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variables. 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.

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variables. 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.

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variables. 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.

Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

Most shells don't use the getenv()/setenv()/putenv() API.

Upon start-up, they create shell variables for each environment variables. 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.