clinuxforkargvexecve

Why do we pass the command name twice to execve, as a path and in the argument list?


I have a program written by my professor that prints the working directory (pwd) by using execve(), but I don't understand the parameters.

pid_t pid = fork();

if(pid <0)
   perror(NULL);
else if(pid == 0)
{
   char*argv[] = {"pwd",NULL};
   execve("/bin/pwd",argv,NULL);
   perror(NULL);
}
else
    printf("Im the parent!");
return 0;
}

"/bin/pwd" gives the path to the executable that will be executed.

This means that it will call the pwd function, doesn't it? Then why do I need to have the parameter pwd?

Couldn't the program run without that parameter?


Solution

  • By convention, the first argument passed to a program is the file name of the executable. However, it doesn't necessarily have to be.

    As an example, take the following program:

    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        int i;
    
        printf("number of arguments: %d\n", argc);
        printf("program name: %s\n", argv[0]);
        for (i=1; i<argc; i++) {
            printf("arg %d: %s\n", argv[i]);
        }
        return 0;
    }
    

    If you run this program from another like this:

    char*argv[] = {"myprog", "A", "B", NULL};
    execve("/home/dbush/myprog",argv,NULL);
    

    The above will output:

    number of arguments: 3
    program name: myprog
    arg 1: A
    arg 2: B
    

    But you could also run it like this

    char*argv[] = {"myotherprog", "A", "B", NULL};
    execve("/home/dbush/myprog",argv,NULL);
    

    And it will output:

    number of arguments: 3
    program name: myotherprog
    arg 1: A
    arg 2: B
    

    You can use the value of argv[0] as a way to know how your program was called and perhaps expose different functionality based on that.

    The popular busybox tool does just this. A single executable is linked with different file names. Depending on which link a user used to run the executable, it can read argv[0] to know whether it was called as ls, ps, pwd, etc.