title: perror usage in this case
body: <p>Can we check that my perror usage is correct? The background is these questions
  <a href="https://stackoverflow.com/questions/29535576/how-to-handle-errors-in-execvp">How to handle errors in execvp?</a>
  <a href="https://stackoverflow.com/questions/29551485/how-to-use-perror-with-dup2">How to use perror with dup2?</a>
  and now I have this code which works but is the code correct?</p>
  
  <pre><code>/* Helper function that forks pipes */
  int fork_pipes (int n, struct command *cmd) {
      int i;
      int in, fd [2];
      for (i = 0; i &lt; n - 1; ++i) {
          pipe (fd);
          spawn_proc (in, fd [1], cmd + i);
          close (fd [1]);
          in = fd [0];
      }
      dup2 (in, 0);
      /*return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);*/
      if (execvp (cmd [i].argv [0], (char * const *)cmd [i].argv) &lt; 0) {
          perror("execvp failed");
          exit(1);
      } else {
          return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);
      }
  }
  </code></pre>
  
  <p>The full program is</p>
  
  <pre><code>#include &lt;sys/types.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  struct command
  {
      const char **argv;
  };
  /* Helper function that spawns processes */
  int spawn_proc (int in, int out, struct command *cmd) {
      pid_t pid;
      if ((pid = fork ()) == 0) {
          if (in != 0) {
              /*if (dup2(in, 0) == -1) {
                  perror("dup2 failed");
                  exit(1);
              }*/
              dup2 (in, 0);
              close (in);
          }
          if (out != 1) {
              dup2 (out, 1);
              close (out);
          }
          if (execvp(cmd-&gt;argv [0], (char * const *)cmd-&gt;argv) &lt; 0) {
              perror("execvp failed");
              exit(1);
          }
      } else if (pid &lt; 0) {
          perror("fork failed");
          exit(1);
      }
      return pid;
  }
  /* Helper function that forks pipes */
  int fork_pipes (int n, struct command *cmd) {
      int i;
      int in, fd [2];
      for (i = 0; i &lt; n - 1; ++i) {
          pipe (fd);
          spawn_proc (in, fd [1], cmd + i);
          close (fd [1]);
          in = fd [0];
      }
      dup2 (in, 0);
      /*return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);*/
      if (execvp (cmd [i].argv [0], (char * const *)cmd [i].argv) &lt; 0) {
          perror("execvp failed");
          exit(1);
      } else {
          return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);
      }
  }
  
  int main (int argc, char ** argv) {
      int i;
      if (argc == 1) { /* There were no arguments */
          const char *printenv[] = { "printenv", 0};
          const char *sort[] = { "sort", 0 };
          const char *less[] = { "less", 0 };
          struct command cmd [] = { {printenv}, {sort}, {less} };
          return fork_pipes (3, cmd);
      }
      if (argc &gt; 1) { /* I'd like an argument */
  
          if (strncmp(argv[1], "cd", 2) &amp;&amp; strncmp(argv[1], "exit", 2)) {
              char *tmp;
              int len = 1;
              for( i=1; i&lt;argc; i++)
              {
                  len += strlen(argv[i]) + 2;
              }
              tmp = (char*) malloc(len);
              tmp[0] = '\0';
              int pos = 0;
              for( i=1; i&lt;argc; i++)
              {
                  pos += sprintf(tmp+pos, "%s%s", (i==1?"":"|"), argv[i]);
              }
              const char *printenv[] = { "printenv", 0};
              const char *grep[] = { "grep", "-E", tmp, NULL};
              const char *sort[] = { "sort", 0 };
              const char *less[] = { "less", 0 };
              struct command cmd [] = { {printenv}, {grep}, {sort}, {less} };
              return fork_pipes (4, cmd);
              free(tmp);
          } else if (! strncmp(argv[1], "cd", 2)) { /* change directory */
              printf("change directory to %s\n" , argv[2]);
              chdir(argv[2]);
          } else if (! strncmp(argv[1], "exit", 2)) { /* change directory */
              printf("exit\n");
              exit(0);
          }
      }
      exit(0);
  }
  </code></pre>