The environment is a list of strings passed along the
execve system call, just like the list of arguments. Period. What the applications do with that list of strings it receives is up to the application.
Now, by convention, that list is generally used differently from the list of arguments. Programs generally remember the list of environment variables they receive and reuse the same when executing another command.
They've got C library functions to help them doing that: the environment is made available as a
environ variable, and you can retrieve and modify that list (the copy of the list of environment variables it received) with
putenv, and functions like
popen... use that
environ variable when executing commands (call
execve with the
environ they're keeping track of).
Now applications don't have to use that API. They can use their own way to manage the list of environment variables. Shells for instance, map environment variables to shell variables and are likely not to use putenv/setenv libc functions.
perl has its
%ENV associative array and so on.
You can always use
gdb to attach to a process and make it call
system("env > /tmp/some-file") (assuming they are dynamically linked to the libc), but you've got no guarantee that
env will get the same environment than another command would get if the command you're attaching to was executing it in its own way (think of shells for instance). (also note that
system() starts a shell (to interpret the command line) and shells may alter their environment on start up (try for instance
env -i sh -c env).
$ sleep 100 &
$ gdb --pid=$! /bin/sleep
(gdb) p environ
$1 = 0x7fffd722d227 "STY=7498.pts-0.hostname"
(gdb) p environ
$2 = 0x7fffd722d245 "TERM=screen-bce"
(gdb) call system("env > /tmp/some-file")
$4 = 0
Detaching from program: /bin/sleep, process 17098
$ cat /tmp/some-file