Linux exec function: what is the arg0 parameter used for?

c, c++, linux, unix

Solution

Your last call

execlp("ls", "-a" , 0);

does not have enough parameters to work as the previous ones. If you instead call

execlp("ls", "-a" , "-a", 0);

it should work just the same as your first 3 calls, unless the ls from your distro has some coded behavior to work differently if its name starts with a "-", but I doubt it has.

Normally ls just does a set_program_name(argv[0]) and that's all it uses argv[0] for. See source: http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/ls.c;h=cd5996eb979f9e9319089e8c065b1276a1fbece8;hb=refs/heads/master. That call sets variable called program_name, which then used to print the usage

printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);

That's why you get the different help output as Andrey has shown.

As Chris S says, some programs are coded to behave differently depending how they were called in terms of argv[0]. But GNU ls is not one of those programs. Frankly I wonder why not, because they use the same ls.c code to compile both ls and also "dir" and "vdir", but these are compiled as different binaries via ls-vdir.c and ls-dir.c. There's a header, ls. h that has

#define LS_LS 1

/* This is for the 'dir' program.  */
#define LS_MULTI_COL 2

/* This is for the 'vdir' program.  */
#define LS_LONG_FORMAT 3

extern int ls_mode;

Then look in ls-vdir.c for example. The entire file consists of

#include "ls.h"
int ls_mode = LS_LONG_FORMAT;

Finally go back to ls.c and now the comments at the top like

If ls_mode is LS_LONG_FORMAT, the long format is the default regardless of the type of output device. This is for the 'vdir' program.

should start to make sense.

Some people even thought that shipping 3 binaries (ls, dir and vdir) instead of one was a bug https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=16312 But it's apparently by design as the last comment in https://bugs.archlinux.org/task/2767 (quoting from http://www.gnu.org/prep/standards/html_node/User-Interfaces.html) says

Please don't make the behavior of a utility depend on the name used to invoke it. It is useful sometimes to make a link to a utility with a different name, and that should not change what it does.

So GNU is not Unix ;-) Even though they could make ls vary its behavior via argv[0], they chose not to do that for philosophical reasons (and ship you three binaries instead). Clearly other Unix coders (e.g. the buysbox guys) don't share that philosophy.

Problem

Here is the prototype of the function execlp: ``` int execlp(const char *file, const char *arg, ...); ``` The man page says that the first argument of `arg`(i.e. arg0), "by convention, should point to the filename associated with the file being executed." Then I did these experiments: ``` /*These three lines all produce the expected result: . .. a.out main.c */ execlp("ls", "ls", "-a", 0); execlp("ls", "arg0 is meaningless", "-a" , 0); execlp("ls", "", "-a" , 0); /*But this one does not work: a.out main.c */ execlp("ls", "-a" , 0); ``` So the question is, is the arg0 parameter meaningful under any circumstances? Why the interface was designed like this?

Original source

Related problems