Question

So for a class assignment we're making our own basic shell. Among other functions, it has to be able to process absolute paths and execute external applications using fork() and execv.

The idea is the program forks a child process, calls execv which replaces said child process, and terminates it when the external execution is done.

Unfortunately I missed the class on this, and I've tried several examples I found online, none of them have worked. The problem is the parent process duplicating the execv command and terminating itself. Right now I'm just trying to get it to execute "/bin/ls" and return to the main loop of the shell.

Here's the offending code. I imagine I'm missing something simple. And yes, this would be a good question for the professor, but he doesn't keep Friday office hours and I don't want to wait hours or days for an email response. :P Likewise I know I should implement better error checking. Right now I'm going for basic functionality, I'll add the bells and whistles later.

I've confirmed that all variables below have their proper values. The question is how do I only cause the child process to close after execv and prevent the parent from doing the same?

TLDR: Teaching myself how to use fork/execv and finding that I'm absolutely clueless.

161 pid_t child = fork();
162 
163 if(child != -1) 
164   if(token[0] == '.' || token[0] == '/') 
165     if(access(token, X_OK) == 0) {
166       char** charArgs = toCharMatrix(args);
167       execv(token, charArgs);
169     } 
Was it helpful?

Solution

parent must wait for child process to finish... And in order to identify child and parent, use process id returned by fork.. see an example below:

int runcmd(char *cmd)
{
  char* argv[MAX_ARGS];
  pid_t child_pid;
  int child_status;

  parsecmd(cmd,argv);
  child_pid = fork();
  if(child_pid == 0) {
    /* This is done by the child process. */

    execv(argv[0], argv);

    /* If execv returns, it must have failed. */

    printf("Unknown command\n");
    exit(0);
  }
  else {
     /* This is run by the parent.  Wait for the child
        to terminate. */

     do {
       pid_t tpid = wait(&child_status);
       if(tpid != child_pid) process_terminated(tpid);
     } while(tpid != child_pid);

     return child_status;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top