Search code examples
linuxbashshellsystem-callsexecl

How does execl deal with "/bin/sh" in Linux?


I read about APUE 3rd, 8.13, system Function, and I saw a version of system function implementation without signal handling.Code is like below:

#include    <sys/wait.h>
#include    <errno.h>
#include    <unistd.h>

int system(const char *cmdstring)    /* version without signal handling */
{
    pid_t    pid;
    int        status;

    if (cmdstring == NULL)
        return(1);        /* always a command processor with UNIX */

    if ((pid = fork()) < 0) {
        status = -1;    /* probably out of processes */
    } else if (pid == 0) {                /* child */
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        _exit(127);        /* execl error */
    } else {                            /* parent */
        while (waitpid(pid, &status, 0) < 0) {
            if (errno != EINTR) {
                status = -1; /* error other than EINTR from waitpid() */
                break;
            }
        }
    }

    return(status);
}

And the code used to test system function of this version is like below:

int main(void)
{
    int        status;

    if ((status = system("date")) < 0)
        err_sys("system() error");

    pr_exit(status);

    if ((status = system("nosuchcommand")) < 0)
        err_sys("system() error");

    pr_exit(status);

    if ((status = system("who; exit 44")) < 0)
        err_sys("system() error");

    pr_exit(status);

    exit(0);
}

And the result of the test code is shown by the picture(just ignore the Chinese in the result if you can't understand): test code result I wonder why will execl return if "nosuchcommand", which is not valid for /bin/sh, is given to /bin/sh. In my point of view, execl just replace the code of current process and then run from entry point, even though "nosuchcommand" is not valid for /bin/sh, it has nothing to do with execl but /bin/sh. So, how execl know "nosuchcommand" is not valid for /bin/sh to execute and return? Does execl treat /bin/sh differently by checking the command given to /bin/sh before executing /bin/sh so that it will know the invalid argument given to /bin/sh in advance? I know execl won't treat /bin/sh differently, so, how does execl know "nosuchcommand" is not valid for /bin/sh to execute and return?


Solution

  • sh -c nosuchcommand itself returns 127. It's one of those return codes with a special meaning.

    So I don't think you're seeing execl actually returning in this case.