'Redirecting stdin in C

I am have written a function in C that emulates command line piping. Now i am trying to handle redirection using '<' and '>'. I have managed to implement redirecting stdout correctly, however I am having problems wit stdin.

The function takes 3 arguments, the list of commands, and an input and output location. These can be NULL if there is no '<' or '>' used.

I am not sure why the input is not working. When I run "wc < input_file" it just executes wc.

The code looks like this:

void pipe_function(char *** cmd, char * input, char * output)
{
    int p[2];
    pid_t pid;
    int fd_in = 0;
    int count = 0;

    /* If there are no input or output destinations specified */
    if ((input == NULL) && (output == NULL))
    {
        while (* cmd != NULL)
        {
            pipe(p);
            if ((pid = fork()) == -1)
            {
                exit(EXIT_FAILURE);
            }
            else if (pid == 0)
            {
                dup2(fd_in, 0);
                if (* (cmd + 1) != NULL)
                {
                    dup2(p[1], 1);
                }
                close(p[0]);
                execvp((* cmd)[0], * cmd);
                exit(EXIT_FAILURE);
            }
            else
            {
                wait(NULL);
                close(p[1]);
                fd_in = p[0];
                cmd++;
            }
        }
    }
    /* If there is no input destination specified but an output destination specified */
    else if ((input == NULL) && (output != NULL))
    {
        while (* cmd != NULL)
        {
            pipe(p);
            if ((pid = fork()) == -1)
            {
                exit(EXIT_FAILURE);
            }
            else if (pid == 0)
            {
                dup2(fd_in, 0);
                if (* (cmd + 1) != NULL)
                {
                    dup2(p[1], 1);
                }
                else
                {
                    int file = open(output, O_WRONLY | O_CREAT, 0777);
                    dup2(file, 1);
                    close(file);
                }
                close(p[0]);
                execvp((* cmd)[0], * cmd);
                exit(EXIT_FAILURE);
            }
            else
            {
                wait(NULL);
                close(p[1]);
                fd_in = p[0];
                cmd++;
            }
        }
    }
    /* If there is an input destination and no output destination */

/* THIS IS WHERE TROUBLE IS OCCOURING*/

    else if ((input != NULL) && (output == NULL))
    {
        while (* cmd != NULL)
        {
            pipe(p);
            if ((pid = fork()) == -1)
            {
                exit(EXIT_FAILURE);
            }
            else if (pid == 0)
            {
                if (count != 0)
                {
                    dup2(fd_in, 0);
                }
                else
                {
                    int file = open(input, O_RDONLY);
                    dup2(file, 0);
                    close(file);
                }

                if (* (cmd + 1) != NULL)
                {
                    dup2(p[1], 1);
                }
                close(p[0]);
                execvp((* cmd)[0], * cmd);
                exit(EXIT_FAILURE);
            }
            else
            {
                wait(NULL);
                close(p[1]);
                fd_in = p[0];
                cmd++;
            }
            count++;
        }
        
    }
    /* If there is both an input and an output destination */
    else 
    {

    }
}

Any help would be greatly appreciated :)



Solution 1:[1]

It doesn't completely fix your program, but I think the main bug here is that you don't close STDIN_FILENO before calling dup2. Thus dup2 fails, and you remain with STDIN at the 0 fd.

This is actually incorrect, dup2() closes newfd for you!

Generally, the code looks pretty good, but it's best practice to always check the return value of library functions - this would obviously have caught the bug here.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1