【问题标题】:How to implement pipes and redirections in my shell?如何在我的 shell 中实现管道和重定向?
【发布时间】:2021-02-08 03:41:39
【问题描述】:

据我所知,有很多关于管道和文件重定向的信息。但我找不到任何关于同时进行管道和文件重定向的具体内容。如果有类似的东西我可能错过了,如果你不介意的话,请给我链接。

我想要做的是在 shell 中执行一个命令,例如 ls -l | grep total > test.txt,以便 grepls -l 获取总数并将其输入到 test.txt

按照我的程序设置方式,所有内容都被分解为 if() 逻辑以确定使用哪种符号。这是我只为一个管道工作的,而且只为一个重定向工作。当我收到|> 时,我对如何继续操作有点困惑。如何将两者结合起来?

else if(pipey && !redirect)
{
    char main_str[1024];
    char pipe_str[1024];
    char *left_args[100] = {NULL};
    char *right_args[100] = {NULL};
    strcpy(main_str, string);

    int fd[2];

    char *token = strchr(main_str, '|');
    *token = '\0';
    token++;
    while(*token == ' ')
    {
        token++;
    }

    strcpy(pipe_str, token);

    int i = 0;  
    for(token = strtok(main_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
    {
        left_args[i] = token;
    }

     i = 0;
    for(token = strtok(pipe_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
    {
        right_args[i] = token;
    }

    if(pipe(fd) == -1)
    {
        return 2;
    }

    c1_pid = fork();
    if(c1_pid < 0)
    {
        return 3;
    }

    if(c1_pid == 0)
    {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        execvp(left_args[0], left_args);
    }

    c2_pid = fork();
    if(c2_pid < 0)
    {
        return 4;
    }

    if(c2_pid == 0)
    {
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        execvp(right_args[0], right_args);

    }

    close(fd[0]);
    close(fd[1]);

    waitpid(c1_pid, NULL, 0);
    waitpid(c2_pid, NULL, 0);

}

// A single redirect given by user
else if(!pipey && redirect)
{
    char main_str[1024];
    char pipe_str[1024];
    char *left_args[100] = {NULL};
    char *middle_args[100] = {NULL};
    char *right_args[100] = {NULL};
    strcpy(main_str, string);

    char *token = strchr(main_str, '>');
    *token = '\0';
    token++;
    while(*token == ' ')
    {
        token++;
    }

    strcpy(pipe_str, token);

    int i = 0;  
    for(token = strtok(main_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
    {
        left_args[i] = token;
    }

     i = 0;
    for(token = strtok(pipe_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
    {
        right_args[i] = token;
    }


    c1_pid = fork();
    if(c1_pid < 0)
    {
        return 5;
    }

    if(c1_pid == 0)
    {
        int file = open(right_args[0], O_WRONLY | O_CREAT, 0777);
        if(file == -1)
        {
            return 6;
        }

        dup2(file, STDOUT_FILENO);
        execvp(left_args[0], left_args);
        close(file);

    }
    waitpid(c1_pid, NULL, 0);
}

再次,我只是想知道如何获取我目前拥有的东西,并将其应用于两个符号是否同时出现。所有解析的东西都很好,只是管道和复制的东西我有点不确定。

【问题讨论】:

    标签: c pipe io-redirection dup


    【解决方案1】:

    将两个概念分成层次结构:

    1. 首先,管道由一个或多个用管道链接在一起的命令组成:command | command | command
    2. 其次,命令由程序、其参数和任何重定向组成:program arg1 arg2 arg3 &gt;redirect1 2&gt;redirect2 &lt;redirect3

    在一个函数中处理管道,在第二个从属函数中处理命令/重定向。

    这将使您可以将这个单一的代码块分解成更小的部分。管道和重定向是正交的概念。它们属于独立、独立的功能,因此它们不必相互了解。


    您还应该将解析与执行分离。智能解耦对于将代码复杂性保持在可管理的水平至关重要。

    不要解析命令行在同一代码块中执行子进程。将它们分开。执行字符串解析,提取相关部分,然后调用单独的函数来实际 fork/open/dup2/exec/waitpid。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 2015-11-02
      • 2011-04-25
      相关资源
      最近更新 更多