Neo
Neo

Reputation: 349

Pipe and Process management

I am working on a tiny shell(tsh) implemented in C(it's an assignment). One part of assignment belongs to PIPING. I have to pipe a command's output to another command. e.g:ls -l | sort

When I run the shell, every command that I execute on it, is processed by a child process that it spawns. After the child finishes the result is returned. For piping I wanted to implement a harcoded example first to check how it works. I wrote a method, that partially works. The problems is when I run the pipe command, after child process finishes, the whole program quits with it! Obviously I am not handling the child process signal properly(Method code below).

My Question:

EDIT: Also while running this code I get the result twice. don't know why it runs twice, there is no loop in there.

Here is my code:

pid_t pipeIt(void){
    pid_t pid;
    int pipefd[2];

    if(pipe(pipefd)){
        unix_error("pipe");
        return -1;
    }

    if((pid = fork()) <0){
        unix_error("fork");
        return -1;  
    }
    if(pid == 0){
        close(pipefd[0]);
        dup2(pipefd[1],1);
        close(pipefd[1]);
        if(execl("/bin/ls", "ls", (char *)NULL) < 0){
            unix_error("/bin/ls");
            return -1;
        }// End of if command wasn't successful

    }// End of pid == 0
    else{
        close(pipefd[1]);
        dup2(pipefd[0],0);
        close(pipefd[0]);
        if(execl("/usr/bin/tr", "tr", "e", "f", (char *)NULL) < 0){
            unix_error("/usr/bin/tr");
            return -1;
        }
    }

    return pid;

}// End of pipeIt

Upvotes: 3

Views: 221

Answers (2)

John Bollinger
John Bollinger

Reputation: 180266

Yes, the shell must fork to exec each subprocess. Remember that when you call one of the execve() family of functions, it replaces the current process image with the exec'ed one. Your shell cannot continue to process further commands if it directly execs a subprocess, because thereafter it no longer exists (except as the subprocess).

To fix it, simply fork() again in the pid == 0 branch, and exec the ls command in that child. Remember to wait() for both (all) child processes if you don't mean the pipeline to be executed asynchronously.

Upvotes: 1

Joni
Joni

Reputation: 111259

Yes, you do need to call fork at least twice, once for each program in the pipeline. Remember that exec replaces the program image of the current process, so your shell stops existing the moment you start running sort or (tr).

Upvotes: 0

Related Questions