views:

94

answers:

1

What I am implementing is a (simpler) version of bash. One of the tasks is to accept the command :

$ bg <command> <arguments>

This will then fork a new process and then run execvp() in the new process using <command> and <arguments> as parameters. The problem is that when I capture the output from the child process, I use pipe(), and after getting the output from the child process and outputting it when I want, I can't seem to switch back to STDIN for my parent (shell) process, which results in a segfault the next time I need to accept input.

Here is part of my "bg" function.

ChildPID = fork();
if (ChildPID < 0) {
 /* There is an error */
 printf("Error forking the process.\n");
 exit(1);
}
if (ChildPID >= 0) {
 if (ChildPID == 0) {  /* Child Process */
  close(m_pipefd[0]);
  dup2(m_pipefd[1], STDOUT_FILENO);
  close(m_pipefd[1]);
  //sleep(5);
         err = execvp(optionsPTR[0], optionsPTR);
  switch (errno) {
   case ENOENT:
    printf("RSI: %s: command not found\n", optionsPTR[0]);
    break;
   case EACCES:
    printf("RSI: %s: Permission denied\n", optionsPTR[0]);
    break;
  }
  exit(1);
 }
 else {  /* Parent Process */
  WaitErr = waitpid(ChildPID, &status, WNOHANG | WUNTRACED);
                return(0); /* to main */
        }
}
return 0;

And the code for when I get the output from the pipe after the process finishes.

close(m_pipefd[1]);     
dup2(m_pipefd[0], STDIN_FILENO);
while(fgets(buffer, sizeof(buffer), stdin)) {
 buf = buffer;
 printf("%s\n", buf);
}
close(m_pipefd[0]);

So the tl;dr version is that I need to reset back to stdin for the parent process after capturing the child processes output.

Thanks,

Braden

+2  A: 

There is usually no need to mess with stdin and stdout in your parent. After you connect your pipes in the child to stdin and stdout, the other ends of the pipes should be able to send data or get data from the child.

Just read from m_pipefd[1] in your parent.

KFro
Thanks, I don't know what I was thinking. That fixed it.
Braden