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 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. Usually these have one or more symlinks in
$PATH; this is common with compression utilities (sometimes they use shell wrappers instead). If you have
stat $(which xzcat) shows it's a link to
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, making these equivalent:
execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);