Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't the argv and envp arguments to execve pointers to const?

Tags:

c

posix

process

Take e.g. execve(2), which according to posix has this prototype [1]:

int execve(const char *path, char *const argv[], char *const envp[]);

To me, it seems as if

int execve(const char *path, const char *const argv[], const char *const envp[]);

would have been an obvious improvement.

So, does anyone know why this is as it is? What can explain the need to possibly manipulate the given argv/envp strings?

[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html

like image 369
Peter Rosin Avatar asked Oct 14 '14 19:10

Peter Rosin


1 Answers

The argv and envp arguments to execve() are not pointers to const in order to preserve backwards compatibility with valid C code that was written before const was added to C.

C first appeared in 1972. Later on, const was added to C in 1987.

In order to maintain compatibility with pre-const code, the updated-with-const declaration of execve() must be able to accept non-const inputs. C does not allow assignments from char *[] to const char *[]. This can be verified by trying (and failing) to compile the following program:

void  foo  ( const char * argv[] )  {  return;  }
void  main  ( int argc, char * argv[] )  {  foo ( argv );  }

Therefore, char *const[] is the strictest type that is backwards compatible with pre-const code.

The question provides a link to the POSIX documentation for execve(). The linked POSIX documentation does explain this as follows:

The statement about argv[] and envp[] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. Due to a limitation of the ISO C standard, it is not possible to state that idea in standard C. ...

Actually, to be precise: it is not possible to state that idea in a way that is backwards compatible with pre-const code.

... Specifying two levels of const- qualification for the argv[] and envp[] parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant. The table of assignment compatibility for dst= src derived from the ISO C standard summarizes the compatibility:

        dst:          char *[]   const char *[]   char *const[]   const char *const[]
src:
char *[]               VALID           -              VALID               -
const char *[]           -           VALID              -               VALID 
char * const []          -             -              VALID               - 
const char *const[]      -             -                -               VALID

Since all existing code ...

Meaning all code that existed prior to const being added to C.

... has a source type matching the first row, the column that gives the most valid combinations is the third column. The only other possibility is the fourth column, but using it would require a cast on the argv or envp arguments. It is unfortunate that the fourth column cannot be used, because the declaration a non-expert would naturally use would be that in the second row.

Sources: 2018 edition, 2004 edition.

like image 197
mpb Avatar answered Nov 14 '22 23:11

mpb