Is char *envp[] as a third argument to main() portable [duplicate]
Asked Answered
U

4

86

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?

Unsavory answered 25/4, 2012 at 18:17 Comment(0)
P
73

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.

Proffitt answered 25/4, 2012 at 18:20 Comment(2)
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.Fagoting
It does not work with (at least) z/OS 2.4 and xlc/c99/c89 on the IBM Mainframe. There is a POSIX solution.Indelicate
V
24

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[].

Villon answered 25/4, 2012 at 18:22 Comment(5)
And you can go past the environment too and examine auxv... ;-)Jounce
What is usually stored in auxv, because i was just wondering the other days why where the fields after envp constant(between runs)?Villon
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).Jounce
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...Caelum
More traditional/idiomatic and concise version of the last comment's way: char **envp = argv; while(*envp++);Tuberose
A
19

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.

Antietam answered 25/4, 2012 at 18:20 Comment(1)
An implementation may provide further formats for main, but these two are the only ones guaranteed to be present in any hosted implementation.Josiah
C
12

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

Visual Studio 2015: Arguments to main

GNU C Programming Tutorial: Environment variables

Channel answered 30/7, 2015 at 11:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.