多流水线外壳中的I / O重定向

时间:2015-11-27 19:58:33

标签: c linux shell redirect pipeline

所以我在C中实现了一个多流水线的shell。就我测试而言,似乎一切正常。我是根据Github Example

构建的

现在我正在尝试在我的流水线命令中实现I / O重定向,但我不确定如何完成此任务。我正在阅读的这本书也没有深入探讨多流水线shell的C实现。

假设我想给出如下命令: ls -l | grep something_i_want_to_find | wc > output.txt

也许还附加了 ls -l | grep something_i_want_to_find | wc >> output.txt

当我遇到重定向操作符时,我的管道将在第3个命令点失败。

我也在阅读SO Link。第一个答案中的一条评论提及"重定向到文件,添加到最后一个阶段:if (file_fd != 1) { dup2(file_fd, 1); close(file_fd); }"我知道他们想要去哪里,但我不知道如何围绕我的管道代码实现这个。

这是我的代码:

保存命令令牌的结构

struct command
{
    char **argv;
};

Pipline功能

void pipeline(struct command *cmds, int numPipes)
{
    pid_t pid;
    int status;
    int fd[2];   // Each pipe has 2 file descriptors
    int i;
    int in = STDIN_FILENO;

    /* Loop for number of pipes */
    for (i = 0; i < numPipes; i++)
    {

        int fd[2];
        pid_t pid;  // Child's pid

        if (pipe(fd) == -1)
        {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
        else if ((pid = fork()) == -1)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        else if (pid == 0)   // Child
        {
            closeFD(fd[0]);
            redirect(in, STDIN_FILENO);
            redirect(fd[1], STDOUT_FILENO);

            execvp(cmds[i].argv[0], (char * const *)cmds[i].argv);
        }
        else    // Parent
        {
            assert(pid > 0);

            close(fd[1]);
            close(in);
            in = fd[0];
        }
    }

    // CODE FROM SO LINK - if (file_fd != 1) { dup2(file_fd, 1); close(file_fd); }

    redirect(in, STDIN_FILENO);
    redirect(STDOUT_FILENO,STDOUT_FILENO);

    for (i = 0; i < numPipes; i++)
    {
        wait(NULL);
    }

    /* Execute the last stage with the current process. */
    execvp (cmds[i].argv[0], (char * const *)cmds[i].argv);
}

关闭FD的功能

void closeFD(int fd)
{
    if ((close(fd)) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
}

重定向FD的功能

void redirect (int oldfd, int newfd)
{
    if (oldfd != newfd)
    {
        if (dup2(oldfd, newfd) != -1)
        {
            if ((close(oldfd)) == -1)
            {
                perror("close");
                exit(EXIT_FAILURE);
            }
        }
        else
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }
    }
}

当我输入ls -l | grep driver | wc > output.txt时,我的输出看起来像这样

ls -l | grep driver | wc > output.txt                            
Command: ls
Options: -l
Pipe
Command: grep
Arguments: driver
Pipe
Command: wc
File Redirection: >
File: output.txt

wc: >: open: No such file or directory
       1       3      25 output.txt
       1       3      25 total

正如您所看到的,我正在识别重定向符号,但这是在一个不同函数的解析器中完成的,如果需要我可以提供。重定向符号确实存储在struct command **cmds向量中。我怎样才能完成管道内的I / O重定向?

0 个答案:

没有答案