72

In order to get an environment variable in a C program, one could use the following:

  • getenv()
  • extern char **environ;

But other than the above mentioned, is using char *envp[] as a third argument to main() to get the environment variables considered part of the standard?

#include <stdio.h>

int main(int argc, char *argv[], char *envp[])
{
    while(*envp)
        printf("%s\n",*envp++);
}

Is char *envp[] portable?

psmears
  • 21,582
  • 4
  • 37
  • 47
Sangeeth Saravanaraj
  • 14,309
  • 20
  • 66
  • 95

4 Answers4

61

The function getenv is the only one specified by the C standard. The function putenv, and the extern environ are POSIX-specific.

EDIT

The main parameter envp is not specified by POSIX but is widely supported.

An alternative method of accessing the environment list is to declare a third argument to the main() function:

int main(int argc, char *argv[], char *envp[])

This argument can then be treated in the same way as environ, with the difference that its scope is local to main(). Although this feature is widely implemented on UNIX systems, its use should be avoided since, in addition to the scope limitation, it is not specified in SUSv3.

cnicutar
  • 164,886
  • 23
  • 329
  • 361
  • 10
    Note that the C standard recognizes this as a common alternative — even C89 mentioned it in Annex G (Portability Issues); it is in Annex J (Portability Issues) in both C99 and C11. – Jonathan Leffler May 17 '14 at 20:15
  • It does not work with (at least) z/OS 2.4 and xlc/c99/c89 on the IBM Mainframe. There is a [POSIX solution](https://stackoverflow.com/questions/10649273/where-is-the-definition-of-extern-char-environ). – ben Mar 23 '21 at 07:33
18

It isn't portable. *envp[] is a traditional UNIX thing, and not all modern UNIX systems implement it.

Also as a side note you could access envp by doing a pointer traversal over *argv[], overflowing it...but i don't think that can be considered safe programming. If you take a look at the process memory map you will see that envp[] is just above argv[].

Sangeeth Saravanaraj
  • 14,309
  • 20
  • 66
  • 95
skyel
  • 613
  • 1
  • 6
  • 18
  • 3
    And you can go past the environment too and examine `auxv`... ;-) – R.. GitHub STOP HELPING ICE Apr 25 '12 at 18:35
  • What is usually stored in auxv, because i was just wondering the other days why where the fields after envp constant(between runs)? – skyel Apr 25 '12 at 20:05
  • 1
    Look in `elf.h` for the macros beginning with `AT_`. Some of the more interesting things are `AT_SECURE`, `AT_RANDOM`, `AT_EXECFN`, `AT_HWCAP`, and the uid/gid ones. Otherwise they're mostly of interest to the dynamic linker and libc init code. The format of `auxv` is pairs of system-word-size integers, the first of which is one of the `AT_` constants (a tag) and the second of which is the value associated with that tag (possibly a pointer, depending on the tag). – R.. GitHub STOP HELPING ICE Apr 26 '12 at 03:14
  • 1
    What about using a pointer to find the end of argv, and going one step further? `char **find = argv, **envp; while(*find) find++; envp = find + 1;` Probably undefined behavior since an OS isn't guaranteed to put environment stuff after argv's last arg... – Braden Best Nov 27 '15 at 20:47
16

The Standard describes two formats for main (see 5.1.2.2.1 in the C99 Standard (pdf))

a) int main(void)

and

b) int main(int argc, char **argv) or equivalent

and it allows implementations to define other formats (which can allow a 3rd argument)

c) or in some other implementation-defined manner.

pmg
  • 98,431
  • 10
  • 118
  • 189
  • 6
    An implementation _may_ provide further formats for `main`, but these two are the only ones guaranteed to be present in any hosted implementation. – Daniel Fischer Apr 25 '12 at 18:22
9

The 3rd argument is valid in Microsoft C and GNU GCC:

Visual Studio 2015: Arguments to main

GNU C Programming Tutorial: Environment variables

chux - Reinstate Monica
  • 113,725
  • 11
  • 107
  • 213
user3683366
  • 91
  • 1
  • 1