0

I want to make a simple shell with pipe. I think I almost did it but it does not return to main. I think exec is not finishing. Below is part of my code. I parsed the command to blocks of struct defined as below. symbol type 5 means that it has | . when I run this program, this is result image. when I don't use pipe, it returns and prints > again but when I use pipe it doesn't.

typedef struct Command {
    char *file;             // file to execute 
    char **arglist;         // argument list to executable
    SymbolType symbolType;  // command seperator 

    int status;             // exit code of the commnad

    struct Command *next, *prev;
} Command;


void GetPipe(Command *command, int *fd){
  SymbolType symbol = command->symbolType;
    if(symbol==5){
      close(1);
      close(fd[0]);
      dup2(fd[1],1);
}

  if((command->prev)!=NULL) symbol=command->prev->symbolType;
  if(symbol==5){
    close(0);
    close(fd[1]);
    dup2(fd[0],0);
  }
}

void ExecuteCommand(Command *command){
  int fd[2];
  pipe(fd);
  for(;command!=NULL;command=command->next){
    pid_t pid = fork();
    if(pid<0) exit(1);
    else if(pid==0){
      GetPipe(command, fd);
      if (execvp(command->file, command->arglist)==-1){
      command->status=status_failure; exit(1);}}
    else {
      int status;
      //waitpid(pid, &status, 0);
      wait(&status);
    }
  }

  close(fd[0]);
  close(fd[1]);

}

int main(void){

Command *head = NULL;
int should_run = 1;

  while (should_run){
    printf("> ");
    fflush(stdout);
    GetCommandChain(&head);
    ExecuteCommand(head);
    DeleteCommandChain(head);
  }
}
  • Why do you think `exec` is not finishing? Have you stepped through your code with a debugger? If not, please do so, and post what you find out. – Ben Steffan Apr 24 '17 at 15:55

1 Answers1

2

. I think exec is not finishing.

The exec family of system calls replaces the entire address space of the process with a new address space for the command being exec'd. It won't return. Having said that, your child code looks sort of OK.

One potential issue is that the parent process doesn't do anything with the read end of the pipe. So the command will write its output to the pipe and then, when the buffer is full, it will block on a write waiting for something to read some data.

Another potential problem is that, you never write anything to the command's stdin. If it is expecting input, it'll block forever on a read.

What I think you need to do is pipe stdout of each command in the chain to stdin of the next command in the chain (and also probably put some input into the first command depending on what it is).

JeremyP
  • 84,577
  • 15
  • 123
  • 161