简体   繁体   中英

How to pipe different processes? (C)

I'm trying to pipe two different processes to implement the terminal's functionality " | ".

I need the new child to execute a command itself, and fork another process to execute a different command using the first process's output, then output the final process's results on the terminal.

Here's my code, I keep the original parent untouched because I need to continue executing the other parts of my program afterwards.

int exec_pipe(char **args, int index, int *i, char**** jobs){

int fd1[2];
pid_t pid, wpid;
int status;
int savedStdOut = dup(1);
int savedStdIn = dup(fileno(stdin));

if (pipe(fd1)==-1)
{
    fprintf(stderr, "Pipe Failed" );
    return 1;
}

pid = fork();

if (pid < 0)
{
    fprintf(stderr, "fork Failed" );
    return 1;
}else if (pid == 0)
{
    // Child process
    close(fd1[0]);
    dup2(fd1[1], 1);

    printf("%s\n", args[index - 1]);

    if (execvp(args[0], args) == -1)
    {
        printf("command not found\n");
    }

    int childId = fork();

    if(childId < 0){
        fprintf(stderr, "fork Failed" );
        return 1;
    }else if(childId == 0){
        // child of child of parent

        fdopen(fd1[1], "r");
        dup2(fd1[1], savedStdOut);


        if (execvp(args[index + 1], args) == -1)
        {
            printf("command not found\n");
        }
        exit(EXIT_FAILURE);

    }else {
        // parent of child of child of parent
        do
        {
            wpid = waitpid(pid, &status, WUNTRACED);
        } while (!WIFEXITED(status) && !WIFSIGNALED(status)); // wait for child until it's exited or been killed
        fdopen(savedStdIn, "r");
        close(fd1[0]);
        close(fd1[1]);
    }
}else{
    // Parent process
    do
    {
        wpid = waitpid(pid, &status, WUNTRACED);
    } while (!WIFEXITED(status) && !WIFSIGNALED(status)); // wait for child until it's exited or been killed
}
return 1;

}

I'm getting a " No such file or directory " error with the program ending with exit code 9 .

Solved it based on some comments, thanks all!

int fd1[2];
pid_t pid;

// allocate two pipe sets
if (pipe(fd1) < 0)
{
    perror("Failed to create pipe.");
    return EXIT_FAILURE;
}

// launch first child process.
if ((pid = fork()) < 0)
{
    perror("Failed to fork child(1)");
    return EXIT_FAILURE;
}

if (pid == 0)
{
    // child
    //  stdout  = fd1(write)
    if(strcmp(args[0], args[index - 1]) == 0)
    {
        dup2(fd1[WRITE], STDOUT_FILENO);
        close(fd1[READ]);
        close(fd1[WRITE]);
        execlp(args[0], args[0], (char*) NULL);
        fprintf(stderr, "failed to execute '%s'\n", args[0]);
        exit(1);
    }else{
        dup2(fd1[WRITE], STDOUT_FILENO);
        close(fd1[READ]);
        close(fd1[WRITE]);
        execlp(args[0], args[0], args[index - 1], (char*) NULL);
        fprintf(stderr, "failed to execute '%s'\n", args[0]);
        exit(1);
    }
}else
{
    // parent
    //  fork once more.
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork child(2)");
        return EXIT_FAILURE;
    }

    if (pid == 0)
    {
        // child of child
        //  stdin = fd1(read)
        dup2(fd1[READ], STDIN_FILENO);
        close(fd1[WRITE]);
        close(fd1[READ]);
        execlp(args[index + 1], args[index + 1], (char*) NULL);
        fprintf(stderr, "failed to execute '%s'\n", args[index + 1]);
        exit(1);
    }else{
        int status;
        close(fd1[READ]);
        close(fd1[WRITE]);
        waitpid(pid, &status, 0);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM