-1

I have been given a c language code

#include <stdio.h> 
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"

int makeargv(const char *s, const char *delimiters, char ***argvp);

int main (void) {
   char **chargv;
   char inbuf[MAX_BUFFER];

   for( ; ; ) {
      gets(inbuf);
      if (strcmp(inbuf, QUIT_STRING) == 0)
         return 0;
      if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0))
         execvp(chargv[0], chargv);
      wait(NULL);
   }
}

makeargv function which makes tokens out of the string passed as 1st argument (using delimiters passed in 2nd argument) and stores these tokens in the array pointed to by the 3rd argument.

#include <errno.h>
#include <stdlib.h>
#include <string.h>

int makeargv(const char *s, const char *delimiters, char ***argvp) {
   int error;
   int i;
   int numtokens;
   const char *snew;
   char *t;

   if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
      errno = EINVAL;
      return -1;
   }
   *argvp = NULL;                           
   snew = s + strspn(s, delimiters);         /* snew is real start of string */
   if ((t = malloc(strlen(snew) + 1)) == NULL) 
      return -1; 
   strcpy(t, snew);               
   numtokens = 0;
   if (strtok(t, delimiters) != NULL)     /* count the number of tokens in s */
      for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; 

                             /* create argument array for ptrs to the tokens */
   if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
      error = errno;
      free(t);
      errno = error;
      return -1; 
   } 
                        /* insert pointers to tokens into the argument array */
   if (numtokens == 0) 
      free(t);
   else {
      strcpy(t, snew);
      **argvp = strtok(t, delimiters);
      for (i = 1; i < numtokens; i++)
          *((*argvp) + i) = strtok(NULL, delimiters);
    } 
    *((*argvp) + numtokens) = NULL;             /* put in final NULL pointer */
    return numtokens;
}    

and i need to answer 3 questions which are mentioned below

  1. How would the shell implemented in above code will behave when the user gives an invalid command (i.e. a command for which no executable exists)?

  2. What would happen if the user gives multiple invalid commands?

  3. What happens when the user tries to quit the shell after giving multiple invalid commands.

Here's what i think are the answers to these questions

  1. The execv will return an error, but I do not think it will break the code so it will result in two forks trying to read inputs

  2. More forks will be created

  3. Only one of the forks will quit

Question

Are all of the answers correct? Could any of the answers be improved?

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 2
    ***Never ever*** use `gets`. It's a [dangerous](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) function, and for that reason even have been removed from the C standard. Use e.g. [`fgets`](https://en.cppreference.com/w/c/io/fgets) instead, but be aware of the slight differences from `gets`. – Some programmer dude Mar 03 '19 at 16:51
  • 1
    As for your questions, that could actually be easily answered (or at least checked) by simply step through the code in a debugger. – Some programmer dude Mar 03 '19 at 16:53
  • Always keep the result of `fork` (you'll need to `wait` later for it) and test the three cases `<0` (failure), `==0` (child process), `>0` (parent process). – Basile Starynkevitch Mar 03 '19 at 17:35

1 Answers1

1

Never have two processes trying to read stdin at once. Race conditions make the resulting environment unusable.

 if (fork() ==0){ 
        if(...)
            execvp();
         _exit(255); /* don't fall back to parent code */
 }
Joshua
  • 40,822
  • 8
  • 72
  • 132
  • i appreciate the suggestions for improving the code but its not my code, i just have to answer the questions related to the code mentioned above. Just want to know that the answers i gave are correct or not. –  Mar 03 '19 at 17:03
  • 2
    @Nick: it invokes unspecified behavior immediately due to stdin's buffer. – Joshua Mar 03 '19 at 17:08