title: How does execl deal with "/bin/sh" in Linux?
body: <p>I read about <a href="https://rads.stackoverflow.com/amzn/click/com/0321637739" rel="nofollow noreferrer" rel="nofollow noreferrer">APUE 3rd</a>, 8.13, system Function， and I saw a version of system function implementation without signal handling.Code is like below:</p>
  
  <pre><code>#include    &lt;sys/wait.h&gt;
  #include    &lt;errno.h&gt;
  #include    &lt;unistd.h&gt;
  
  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()) &lt; 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, &amp;status, 0) &lt; 0) {
              if (errno != EINTR) {
                  status = -1; /* error other than EINTR from waitpid() */
                  break;
              }
          }
      }
  
      return(status);
  }
  </code></pre>
  
  <p>And the code used to test system function of this version is like below:</p>
  
  <pre><code>int main(void)
  {
      int        status;
  
      if ((status = system("date")) &lt; 0)
          err_sys("system() error");
  
      pr_exit(status);
  
      if ((status = system("nosuchcommand")) &lt; 0)
          err_sys("system() error");
  
      pr_exit(status);
  
      if ((status = system("who; exit 44")) &lt; 0)
          err_sys("system() error");
  
      pr_exit(status);
  
      exit(0);
  }
  </code></pre>
  
  <p>And the result of the test code is shown by the picture(just ignore the Chinese in the result if you can't understand):
  <a href="https://i.stack.imgur.com/vBq8z.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vBq8z.png" alt="test code result"></a>
  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?</p>