I think this is POSIX portable:
. <<ENV /dev/stdin
$(sed -n 'H;${x;s/\(^\|\x00\)\([^=]*.\)\([^\x00]*\)/\2\x27\3\x27\n/gp}' \
/proc/$pid/environ)
ENV
But @Gilles makes a good point - sed
will probably handle nulls, but maybe not. So there's this (I Really think so this time) actually POSIX portable method, too:
s=$$SED$$
sed 's/'\''/'$s'/;1s/^./'\''&/' </proc/"$$"/environ |
tr '\0' "'" |
sed 's/'\''/&\n&/g' |
sed '1d;$d;s/^\('\''\)\([^=]*.\)/\2\1/;s/'$s'/'\\\''/g'
Still, if you've got GNU sed
you need only do:
sed -z 's/^[^=]*./&'\''/;s/$/'\''\n/' </proc/"$$"/environ
#BOTH METHODS OUTPUT:

Well, POSIX portable that is except for the /dev/...
which is not specified but you can pretty much expect that syntax to behave same on most Unices.
Now if this has anything to do with your other question, you might like to use it like this:
nsenter -m -u -i -n -p -t $PID /bin/bash 5<<ENV --rcfile=/dev/fd/5
$(sed -z 's/^[^=]*./&'\''/;s/$/'\''\n/' </proc/"$$"/environ)
ENV
The here-doc is extremely helpful in that it keeps the shell from screwing with any of the quoting we work so hard to handle in the subshell and also provides us a reliable path to a .dot
sourceable file rather than, again, a subshell or a shell variable. Others here use the <(process substitution)
bashism which works in much the same way - only it's definitely an anonymous |pipe
whereas POSIX only specifies an iohere
for here-docs and so it can be any type of file, though, in practice, it's usually a temp
file. (dash,
on the other hand, does use anonymous |pipes
for here-docs). The unfortunate thing about process substitution though, is it's also shell dependent - which might be an especially annoying issue if you're working with init
.
This also works with |pipes
of course, but then you lose the environment again in the end when the |pipe's
state evaporates with its subshell. Then again, this works:
sed '...;a\exec <>/dev/tty' /proc/$pid/environ | sh -i
The sed
statement itself works by holding every line in memory until it reaches the last, at which time it performs a global replace handling quoting and inserting newlines where appropriate by anchoring on the nulls. Fairly simple really.
In the dash
picture you'll see I opted to eschew the \ mess and added the GNU
specific -r
option to sed
. But that's just cause it was less to type. It works either way, as you can see in the zsh
image.
Here's zsh
:

And here's dash
doing the vary same thing:

Even terminal escapes come through unscathed:
