title: Implementing a simple shell in c - wc command not working
body: <p>I am implementing a simple shell in c for a class. There are a number of requirements but the one thing that I am concerned about is this sequence of commands:</p>
  
  <p>ls > test</p>
  
  <p>wc &lt; test</p>
  
  <p>which will output the results of the ls command to the file test and the wc
  command will then count the number of words, bytes, characters (or something
  like that) in that file. </p>
  
  <p>Anyway, the first command works and the test file is successfully created with
  the expected content. The wc command doesn't work however. It triggers the error associated with the execv statement "Command can't be executed. My input redirection works as a command like: 
  grep test &lt; test   works perfectly. My question is, Why doesn't my shell recognize the wc command? </p>
  
  <pre><code>#include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;fcntl.h&gt;
  
  void parse(char buffer[2048], char *arguments[512]){
      //these characters(space, tab, new line, return)represent white space
      //that separate words
      char * delim = " \t\r\n\f";
      char * token;
      int count = 0;
      //Finds the first word in buffer
      token = strtok (buffer, delim);
      //While a token still exists
      while (token != NULL){
          //if token is not empty it is added to arguments
          if (strlen (token) &gt; 0){
              arguments[count]=token;
              count++;
          }
          //Find the next token.
          token = strtok (NULL, delim);
  
          arguments[count+1]=NULL;
      }
  
  int checkInput(char *arguments[512]){
      int loc = 0;
      int count = 0;
      while (arguments[count]!=NULL){
          if (strcmp(arguments[count],"&lt;")==0){
              loc = count;
          }
          count++;
      }
      return loc;
  }
  
  void redirectInput(int input,char *arguments[512]){
      int in;
      int in2;
      char*inFile = arguments[input+1];
  
      in = open(inFile, O_RDONLY);
      if (in &lt; 0){
          perror("Error Opening File");
          exit(1);
      }
      in2 = dup2(in, 0);
      if (in2 &lt; 0){
          perror("Error redirecting stdin");
          exit(1);
      }
      close(in);
  }
  
  int checkOutput(char *arguments[512]){
      int loc = 0;
      int count = 0;
      while (arguments[count]!=NULL){
          if (strcmp(arguments[count],"&gt;")==0){
              loc = count;
          }
          count++;
      }
      return loc;
  }
  
  void redirectOutput(int output,char *arguments[512]){
      int out;
      int out2;
      char*outFile=arguments[output+1];
  
      out = open(outFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
      if (out &lt; 0){
          perror("Error Opening File");
          exit(1);
      }
      out2 = dup2(out, 1);
      if (out2 &lt; 0){
          perror("Error redirecting stdout");
          exit(1);
      }
      close(out);
  }
  
  int main(int argc, char **argv){
      //buffer is to hold the commands that the user will type in
      char buffer[512];
      char buffer2[512];
      //bin/program_name is the arguments to pass to execv
      //if we want to run ls, "/bin/ls" is required to be passed to execv()
      char* path = "/bin/";
      char * arguments[512];
      char * args_copy[512];
      //This will be the final path to the program is passed to execv
      char prog[512];
      char directory[512];
      pid_t pid,w;
      int status;
      int isValid;
      int input;
      int output;
  
      getcwd(directory,sizeof(directory));
  
      while(1){
          isValid = 0;
          while(!isValid){
              //print the prompt
              printf(":");
              fflush(stdout);
              //get input
              fgets(buffer, 512, stdin);
              if(buffer[0]!='\n' &amp;&amp; buffer[0] != '#'){
                  isValid=1;
              }
          }
  
          strcpy(buffer2, buffer);
          parse(buffer2, args_copy);
          //Handle the builtin functions without before forking
          if (strcmp(args_copy[0],"exit")==0){
              exit(0);
          }
          else if (strcmp(args_copy[0],"status")==0){
              printf("exit value %d\n",WEXITSTATUS(status));
          }else if( strcmp(args_copy[0],"cd") == 0 ){
              if(args_copy[1]==NULL){
                  chdir(directory);
              }
              else{
                  chdir(args_copy[1]);
              }
          }
          else{
              //fork!
              pid = fork();
              //Error checking to see if fork works
              if (pid &lt; 0) {
                  perror("fork");
                  exit(EXIT_FAILURE);
              }
              //If pid !=0 then it's the parent
              if(pid!=0){
                  do {
                      w = waitpid(pid, &amp;status, WUNTRACED | WCONTINUED);
                      if (w == -1) {
                          perror("waitpid");
                          exit(EXIT_FAILURE);
                     }
                     if (WIFEXITED(status)) {
                     }
                     else if (WIFSIGNALED(status)) {
                         printf("killed by signal %d\n", WTERMSIG(status));
                     }
                     else if (WIFSTOPPED(status)) {
                         printf("stopped by signal %d\n", WSTOPSIG(status));
                     }
                     else if (WIFCONTINUED(status)) {
                         printf("continued\n");
                     }
                  }while (!WIFEXITED(status) &amp;&amp; !WIFSIGNALED(status));
              }
              else{
                  //parse the user input into an array of strings(arguments)
                  parse(buffer, arguments);
                  input = checkInput(arguments);
  
                  if (input){
                      redirectInput(input,arguments);
                      arguments[input]=NULL;
                  }
  
                  output = checkOutput(arguments);
  
                  if (output){
                      redirectOutput(output,arguments);
                      arguments[output]=NULL;
                  }
                  //First we copy a /bin/ to prog
                  strcpy(prog, path);
                  //Then we concancate the program name to /bin/
                  //If the program name is ls, then it'll be /bin/ls
                  strcat(prog, arguments[0]);
                  //pass the prepared arguments to execv and we're done!
                  int rv=execv(prog, arguments);
                  if (rv == -1) {
                      perror("Command can't execute");
                      exit(EXIT_FAILURE);
                  }
              }
          }
      }
      return 0;
  }
  </code></pre>