Why do we have to pass the file name twice in exec functions

command lineexec

I read Advanced Programming in the UNIX Environment by Stevens, 8th chapter.
I read and understand all the six of exec functions.

One thing I notice is, in all the exec functions:

  • first argument is the file name / path name (depends on the exec function).
  • second argument is argv[0] that we get in main(), which is the file name itself.

So here we do have to pass the file name twice in the function.

Is there any reason for it (like we cannot get the file name from the path name from the first argument)?

Best Answer

So here we do have to pass the file name twice in the function.

They are not quite the same thing as you notice by observing that one of them is used as the argv[0] value. This doesn't have to be the same as the basename of the executable; many/most things ignore it and you can put whatever you want in there.

The first one is the actual path to the executable, for which there is an obvious necessity. The second one is passed to the process ostensibly as the name used to invoke it, but, e.g.:

execl("/bin/ls", "banana", "-l", NULL);

Will work fine, presuming /bin/ls is the correct path.

Some applications do, however, make use of argv[0]. Usually these have one or more symlinks in $PATH; this is common with compression utilities (sometimes they use shell wrappers instead). If you have xz installed, stat $(which xzcat) shows it's a link to xz, and man xzcat is the same as man xz which explains "xzcat is equivalent to xz --decompress --stdout". The way xz can tell how it was invoked is by checking argv[0], making these equivalent:

execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);
Related Question