dup2() and exec()

Notes on Dup2 and Exec


Dup2

Declaration:

    #include <unistd.h>

    int dup2(int filedes, int filedes2);
    /* returns new file descriptor if ok, -1 on error */

dup2() causes the file descriptor filedes2 to reference the same file as filedes. If filedes2 is already open, it is first closed. If filedes = filedes2, then dup2 returns filedes2 without closing it

The following lines of code are taken from Program 14.2 on p.432 of Stevens. They demonstrate how to redirect stdin using dup2:

    ...
    if (fd[0] != STDIN_FILENO) 
    {
        if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) 
        {
            /* error message & die */
        }
        close(fd[0]);       /* don't need this after dup2 */
    }
    ...

The check, if (fd[0] != STDIN_FILENO), is good programming practice and should be used whenever dup2 is used in combination with close. Stevens offers a good explanation: When we duplicate a descriptor onto another (fd[0] onto standard input in the child), we have to be careful that the descriptor doesn't already have the desired value. If the descriptor already had the desired value and we called dup2 and close, the single copy of the descriptor would be closed.

Exec

All varieties of exec() system call perform the same function: they transform the calling process by loading a new program into its address space. If the exec() is successful the calling program is completely overlaid (replaced) by the new program, which is then started from its beginning. The process ID does not change across an exec().

As a note of interest, the shell itself invokes commands by using one of the exec commands.

exec() is commonly used with fork(). The fork function creates a new process (the child) that then causes another program to be executed by calling one of the exec functions.

The declarations of the 6 different flavours of exec():

    #include <unistd.h>

    int execl (const char *pathname, const char *arg0, ...
                          ... /* (char *) 0 */ );

    int execv (const char *pathname, char *const argv[]);

    int execle(const char *pathname, const char *arg0, ...
                          ... /* (char *) 0, char *const envp[] */ );

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

    int execlp(const char *filename, const char *arg0, ... 
                          ... /* (char *) 0 */ );

    int execvp(const char *filename, char *const argv[]);

    /* All six return: -1 on error, no return on success */

The initial argument for these functions is the pathname of a file which is to be executed

The const char *arg and subsequent ellipses in the execl, execlp, and execle functions can be thought of as arg0, arg1, ..., argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the file name associated with the file being executed. The list of arguments must be terminated by a NULL pointer.

The execv and execvp functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the file name associated with the file being executed. The array of pointers must be terminated by a NULL pointer.

The letters in the functions names help identify the expected arguments:

The letters l and v are mutually exclusive.

References