The reason is that `getenv()` hands out raw pointers to the variables, so overwriting a variable using `setenv()` is impossible to guard against. Treat with extreme caution.
The reason is that `getenv()` hands out raw pointers to the variables, so overwriting a variable using `setenv()` is impossible to guard against. Treat with extreme caution.
I think that would still be better than env vars, which are more likely to leak somewhere you didn't intend them to.
ps wwwex | grep [w]wwex
31109 pts/0 R+ 0:00 ps wwwex GDM_LANG=en_GB.utf8 STARSHIP_SHELL=fish GDMSESSION=xfce STARSHIP_SESSION_KEY=2904922223926273 XDG_CURRENT_DESKTOP=XFCE LC_NUMERIC=en_GB.UTF-8 TERMINFO=/usr/share/terminfo LC_MONETARY=en_GB.UTF-8 SHELL=/bin/fish LC_ADDRESS=en_GB.UTF-8 ... many, many more ...edit: submitted before I saw your edit. :-)
In contrast, arguments are an ordered sequence of strings, so are more suited for present/not-present flags (e.g. --dry-run) , or listing a variable number of values (e.g. filenames). Using arguments for name=value data either requires individual strings to be parsed into components, or requires a pair of name and value strings to appear sequentially (without overlapping another pair, etc.). Arguments also tend to require disambiguation, e.g. prepending names with `--`, to account for optional arguments not being present, or for allowing options to be given in any order, etc. That may also require escape hatches, like a standalone `--` argument, in case user data conflicts with such reserved patterns, etc.
Sure, there are libraries for parsing this stuff; and conventions that we can get used to (except when a tool doesn't follow them...), but it's still a complicated mess compared to `NAME1=val1 NAME2=val2 my-command --flag1 --flag2 file1 file2 file3`
FreeBSD does the same. See here for discussion: https://freebsd-current.freebsd.narkive.com/NwqZQDWm/fix-for...
For a lot of applications that's the right call given the rest of the posix semantics you're constrained to and the kinds and frequency of data you pass via env vars.
execve seems like the preferable choice on a lot of grounds.
Getenv in a program without setenv is fine in both implementations. Setenv is unusable with all conforming implementations.
To pass environments to children, use execve.
The Linux behavior allows a careful single threaded program to use setenv correctly. The BSD/Solaris behavior makes all usage incorrect, but the incorrectness comes in the form of a memory leak, which is preferable to a security issue, usually.
There's no correct, portable use of setenv. If you call it, it's a bug.
> frequency of data
Practically, if you're moving enough data through setenv that the memory leaked versus the steady state fluctuation of the program is at all visible, you've got much bigger problems.
But it I were implementing POSIX and had to implement it, I would almost certainly make Sun's choice thinking of it as the least evil given the expected use cases.
Arguably that's less harmful than the thread-safety issues on Linux, but there's no perfect solution here as long as POSIX stays what it is.
[0] https://man.netbsd.org/getenv_r.3
[1] https://github.com/freebsd/freebsd-src/commit/873420ca1e6e8a...
Well, you can know, if you check their imported symbols. (I suppose they could be getting it via dlsym, but what are the odds of that...)
So if getenv_r() is added to the C library, and over time third party libraries started adopting it, you could get to the point that you could know no code in your process is calling getenv(), because none of the libraries your process loads import that symbol.
They could even add a glibc tunable to make getenv() call abort()... then you could be very sure nobody is calling getenv(), because if anyone ever did, boom