pipe redirection issue, lost data

Viewed 37

I want to reproduce this shell behaviour with a small c program:

< file cmd1 | cmd2

So it takes three arguments and can be executed this way for exemple:

./a.out foo /bin/cat /usr/bin/wc

Here's my code, without error checking:

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

static void exe_cmd(char *cmd, char **env)
{
    int     pid;
    char    *av[] = {cmd, NULL};

    pid = fork();
    if (pid == 0)
    {
        execve(av[0], av, env);
        exit(0);
    }
    waitpid(pid, NULL, 0);
}

static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
    int file;

    file = open(path, O_RDONLY);
    dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
    dup2(file, STDIN_FILENO);
    close(fd[0]);
    close(fd[1]);
    close(file);
    exe_cmd(cmd, env);
}

static void right_pipe_side(int fd[2], char *cmd, char **env)
{
    dup2(fd[0], STDIN_FILENO);
    close(fd[1]);
    close(fd[0]);
    exe_cmd(cmd, env);
}

int main(int ac, char **av, char **env)
{
    int fd[2];
    pid_t   pid;

    pid = fork();
    pipe(fd);
    if (pid == 0)
    {
        left_pipe_side(fd, av[2], av[1], env);
        exit(0);
    }
    right_pipe_side(fd, av[3], env);
    waitpid(pid, NULL, 0);
    return (0);
}

My problem is that the output of wc as the second command will always be 0 0 0, as if the input were empty (but the given file contains text). If I comment out the line where I dup fd[1] to stdout in the left pipe side, the first command will output correctly, so I don't understand why the redirection makes this data "disappear"

2 Answers

You open pipe after fork, so each process has it's own very unrelated pipe. Open it before, so that it's shared between processes.

pipe(fd);
pid = fork();

in your code, you open the pipe after the fork so that's mean every process has its own pipe and that's not how pipes work

you have to open the pipes before the fork that's make the process linked with your pipe.

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

static void exe_cmd(char *cmd, char **env)
{
    int     pid;
    char    *av[] = {cmd, NULL};

    pid = fork();
    if (pid == 0)
    {
        execve(av[0], av, env);
        exit(0);
    }
    waitpid(pid, NULL, 0);
}

static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
    int file;

    file = open(path, O_RDONLY);
    dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
    dup2(file, STDIN_FILENO);
    close(fd[0]);
    close(fd[1]);
    close(file);
    exe_cmd(cmd, env);
}

static void right_pipe_side(int fd[2], char *cmd, char **env)
{
    dup2(fd[0], STDIN_FILENO);
    close(fd[1]);
    close(fd[0]);
    exe_cmd(cmd, env);
}

int main(int ac, char **av, char **env)
{
    int fd[2];
    pid_t   pid;
    /************************ the error part **********************/
    // pid = fork();
    // pipe(fd);
    pipe(fd);
    pid = fork();
    /**************************************************************/

    if (pid == 0)
    {
        left_pipe_side(fd, av[2], av[1], env);
        exit(0);
    }
    right_pipe_side(fd, av[3], env);
    waitpid(pid, NULL, 0);
    return (0);
}
Related