7

From several websites I read that getenv is a system call. However I cannot find any reference to sys_getenv.

I am trying to understand what "environment variables" are, exactly. Are they part of the kernel or a mechanism of the shell? Digging a little bit deeper I found that getenv is part of standard C library. Unfortunately this doesn't help me to answer my original question.

MariusMatutiae
  • 46,990
  • 12
  • 80
  • 129
nowox
  • 2,687
  • 13
  • 43
  • 58

3 Answers3

11

Do you understand the argument list?  For example, if you type ls -l foo bar, the shell executes /bin/ls with an argument list consisting of four strings:

    ls -l foo bar

whereas, if you type ls -l "foo bar" (or ls -l 'foo bar' or ls -l foo\ bar), the shell executes /bin/ls with an argument list consisting of three strings:

    ls -l foo bar

and ls -l * might get you something like:

    ls -l ant bat cat dog etc

i.e., whatever files are in the current directory.

Well,

the environment is basically just a second argument list.

Perhaps it would be better to say “the environment is a second list of strings, structured exactly like the argument list, but treated differently.”  If you look at execve(2), you’ll see that the execve system call takes three arguments:

  • char *filename,                                (the program to execute; e.g., /bin/ls)
  • char *argv[],
  • char *envp[]

Whenever any program executes any other program, it is basically using execve (possibly via some higher-level function, such as execl), so it is passing an argument list and an environment list.  The environment list looks a lot like the output from env; e.g.,

    HOME=/home/fred USERNAME=fred PATH=/bin:/usr/bin:… TERM=xterm SHELL=/bin/bash PWD=/home/fred/Super_User_files
    etc…

The executed program can do whatever it wants with the environment list — look at it (e.g., with getenv), modify it, or ignore it — the same things it can do with the argument list.  When a program executes another program with one of the higher-level execute functions, like execl, it automatically calls execve with the same environment list that was passed in to the program.  And that’s what happens in 90% of the programs that execute other programs.  But shells let you modify the environment, and then they use execve directly to pass the most up-to-date user-specified environment to every program that it runs.

TL;DR

Every process contains its environment list in memory, the same way it contains its argument list and ordinary variables.  The environment is passed from program to program through the exec mechanism.  Library functions make it easy for a program to pass its own environment to any other program that it runs.  (Naturally, environment is preserved (copied) across a fork, just as all other local memory is.)  The kernel doesn’t really know anything about the environment except for the fact that it provides a means for the environment to be passed through execve.

  • So, I understood that `execve` is part of the libc. Inside this function I will found a real system call which should be `fork()`, is it right? – nowox Jun 25 '15 at 06:01
  • 1
    No, no, no.  `fork()` and `exec()` (by which I mean the `exec` family of functions) are related somewhat like a left glove and a right glove; they often go together, and they are conceptually related, but they are *not* the same thing.  `execl()` is in libc, but `execve()` is a system call.  `execl()` *calls* `execve()`, not unlike the way the libc function `fprintf()` calls the `write()` system call, and the libc function `sleep()` calls the `alarm()` system call.  You can check by typing `man ` *`foo`*  —  if the man page comes up as `foo(2)`, it's a syscall; `foo(3)` is a library function. – Scott - Слава Україні Jun 25 '15 at 06:47
  • 1
    @fixer1234 — Thanks, but −1: unclear what you're asking; −1: too broad.  Seriously; I said, “Every process contains its environment list in memory, the same way it contains … ordinary variables.”  Can you clarify what more than that you want?  Would it help if I said, “Every process contains its environment list in *user space* memory …” ?  Would it help if I said, “Processes ‘own’ their local memory, and can access it directly, without kernel intervention.  An appropriately privileged process may be able to access another process’s local memory via system calls.” ? – Scott - Слава Україні Jul 11 '15 at 19:15
  • I reread your answer. What I was asking is sort of in there, implied by the process you describe. No fair making me think. :-) – fixer1234 Jul 12 '15 at 00:36
  • @fixer1234: I’m glad if you found what you were looking for.  I presume you’ve read [What are PATH and other environment variables, and how can I set or use them?](http://superuser.com/q/284342/150988); and, if you believe that there’s nothing there that answers the question “What are environment variables?”, I don’t entirely disagree.  [user945389’s answer](http://superuser.com/a/787949/150988) perhaps comes closest: “Environment Variables … store various values to allow programs to get necessary OS information, or ‘Environment’ information.  For example, USERPROFILE and MAIL ….”  … (Cont’d) – Scott - Слава Україні Jul 13 '15 at 03:34
  • (Cont’d) …  I would paraphrase it as: “Environment variables are the containers in which processes (programs) receive information about their environment.”  Some of these (e.g., USERNAME, HOME, and PWD) are things that a process could find out by other means.  Some (e.g., PRINTER, TERM, and TZ) are things that cannot be learned so easily.  And some (e.g., LANG, PATH, and TEMP) represent not just information, but directives.  (These categories are necessarily mutually exclusive, exhaustive, or entirely objective.)  But perhaps the question “To whom do environment variables belong?”  … (Cont’d) – Scott - Слава Україні Jul 13 '15 at 03:35
  • (Cont’d) …  is best answered by an analogy: Environment variables are like family traditions (e.g., “We open one present after dinner on the 24th, and the rest after 7:00 AM on the 25th.”)  You get yours from your parents.  You can change yours, and what you pass on to your children.  You can’t change anybody else’s but your own — not your parents’, and not even your children’s (after they have moved out).  In fact, you generally can’t even *see* anybody else’s but your own (you can’t even tell whether your parents have changed theirs after you got your start).  … … … … …  Any other questions? – Scott - Слава Україні Jul 13 '15 at 03:35
  • My question was tied to the title of the thread, which didn't seem to be explicitly addressed in the answer. Rather than directly addressing it (no heading, "Who Owns the Variables"), your answer describes how the process works. Ownership is implied by the process. I now understand more about the process, but you made me work for the answer. ;-) – fixer1234 Jul 13 '15 at 03:56
  • Nice analogy, BTW. Consider using it as an intro or closing in the answer for readers attracted by the title. – fixer1234 Jul 13 '15 at 04:00
4

To whom do environment variables belong?

Each process owns its own environment variables.

Notes:

  • Every process has an environment block that contains a set of environment variables and their values.

  • The environment variables are inherited from the parent process and is a copy of the parent block.

  • By default, a child process inherits the environment variables of its parent process.

  • A process may choose to pass a different environment to a child process by creating a new environment block and passing this to the child process when it is created.

  • It's not possible for any process to alter any other process's environment variables.


What is getenv

getenv is function in the Standard C Library.

Name

getenv, secure_getenv - get an environment variable Synopsis

#include <stdlib.h>

char *getenv(const char *name);

char *secure_getenv(const char *name);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

secure_getenv(): _GNU_SOURCE

Description

The getenv() function searches the environment list to find the environment variable name, and returns a pointer to the corresponding value string.

The GNU-specific secure_getenv() function is just like getenv() except that it returns NULL in cases where "secure execution" is required.

...

Source getenv(3) - Linux man page


Further reading

getenv() source code


"I am trying to understand what "environment variables" are, exactly."

See the answer https://superuser.com/a/932191/337631 by Scott for a detailed explanation from a coding perspective.

DavidPostill
  • 153,128
  • 77
  • 353
  • 394
  • I am cloning glibc to browse the codebase. I want to know what's behind `getenv`. `man` won't help me here. – nowox Jun 24 '15 at 18:24
  • I've already linked to the source in my answer, as well as giving you a link explaining environment variables. If you don't yet understand what they are then reading the c source code probably won't help you. – DavidPostill Jun 24 '15 at 18:31
  • Ok I see that I got confused again and felt into X-Y issue. `getenv.c` is referring to `__environ` which is declared in `posix/environ.c` and then local to the current process. I don't understand how a process can inherit environment variables from its parent. – nowox Jun 24 '15 at 18:42
  • @nowox The man page helps very well here. You can detect a link to `man 5 environ` and there `extern char **environ;` in it, a table that a process inherits from it's parent, and which you can modify too. – ott-- Jun 24 '15 at 18:49
  • @David, Environment variables are **nothing to do** with shells, other than in that they provide a means to manipulate theirs. Environment variables are a part of **every process**, copied on `fork()`, and passed to successor with `exec()`. See Scott's answer. – Toby Speight Jul 01 '15 at 12:28
  • @TobySpeight Yes, mine was a simplified answer in that respect. I will correct my answer and point to Scott's for the detailed answer. – DavidPostill Jul 01 '15 at 12:41
  • An answer even a non-programmer can understand. Thanks. +1 – fixer1234 Jul 11 '15 at 17:22
2

getenv is part of the Standard C Library. So, in C you would need to include stdlib.h.

Excellll
  • 12,627
  • 11
  • 51
  • 78