【问题标题】:Redirecting I/O in a custom shell program written in C在用 C 编写的自定义 shell 程序中重定向 I/O
【发布时间】:2018-10-23 00:16:14
【问题描述】:

我一直在编写自定义 shell 脚本,并在使用下面给出的代码重定向输出时遇到了一个小错误。在其当前状态下,代码运行良好,但在传递给 execvp args 时会引发错误,例如:(ls ">" no such file or directory)。我知道这是因为它将整个 args[] 传递给不起作用的父 shell。添加 args[j] = NULL 会删除 "" 从而修复错误,但也会导致重定向不再起作用。我怎样才能让它不抛出错误但也能正常工作?我已经阅读了这个问题的多个版本,但似乎找不到答案。提前感谢您的帮助。

switch (fork()){
        case -1:
        fprintf(stderr, "error forking");

        case 0://CHILD

        for(int j = 0; j < size; j++){

            if(!strcmp(args[j], "<")){//looking for input character
            ++ext;
            if((in = open(args[j+1], O_RDONLY)) < 0){//open file for reading
                fprintf(stderr, "error opening file\n");
            }
            dup2(in, STDIN_FILENO);//duplicate stdin to input file
            close(in);//close after use
            //args[j] = NULL;
                }//end input chech


            if(!strcmp(args[j],">")){//looking for output character
            ++ext;
                out = creat(args[j+1], 0644);//create new output file           
            dup2(out, STDOUT_FILENO);//redirect stdout to file
            close(out);//close after usere  
        //  args[j] = NULL;
            }//end output check 

            if(!strcmp(args[j], ">>")){//looking for append
            ++ext;
            int append = open(args[j+1],O_CREAT | O_RDWR | O_APPEND, 0644);
                dup2(append, STDOUT_FILENO);
                close(append);
             // args[j] = NULL;
            }                

         }//end loop


        execvp(args[0],args);//execute in parent
        fprintf(stderr, "error in child execi \n");//error
        exit(0);    

         default://PARENT
        wait(&status);  //wait for child to finish  
    }//end switch

【问题讨论】:

  • 您的意思是“shell 程序”(替代标准 shell,例如 Bash),还是“shell 脚本”(由特定 shell 运行的程序)?当心;程序不一定是脚本,如果你发布 C 源代码,你就不是在发布脚本——至少,使用传统的含义。另外,请注意,有一个特定的 C shell,它的语法与 Bash 和其他从 Bourne shell 派生的 shell 不同。因此,您可能是指“在用 C 编写的自定义 shell 程序中重定向 I/O”或类似的意思。

标签: c shell url-redirection


【解决方案1】:

当您解析重定向(例如&lt;&gt;&gt;&gt;)并执行您的open/dup2 时,您必须从传递给@987654328 的参数列表中剥离它们@。

因此,鉴于您的args,您需要一个(例如args_clean)参数列表,您复制程序名称及其参数。

而且,您需要额外增加 j 才能跳过 args 中的重定向文件(即,仅执行 j + 1 并不等效)。


这是清理后的子代码[请原谅无偿的风格清理]:

char *args_clean[size];
int cleanidx = 0;

for (int j = 0; j < size; j++) {
    if (!strcmp(args[j], "<")) {        // looking for input character
        ++j;
        if ((in = open(args[j], O_RDONLY)) < 0) {   // open file for reading
            fprintf(stderr, "error opening file\n");
        }
        dup2(in, STDIN_FILENO);         // duplicate stdin to input file
        close(in);                      // close after use
        continue;
    }                                   // end input chech

    if (!strcmp(args[j], ">")) {        // looking for output character
        ++j;
        out = creat(args[j], 0644); // create new output file
        dup2(out, STDOUT_FILENO);       // redirect stdout to file
        close(out);                     // close after usere
        continue;
    }                                   // end output check

    if (!strcmp(args[j], ">>")) {       // looking for append
        ++j;
        int append = open(args[j], O_CREAT | O_RDWR | O_APPEND, 0644);

        dup2(append, STDOUT_FILENO);
        close(append);
        continue;
    }

    args_clean[cleanidx++] = args[j];
}                                       // end loop

args_clean[cleanidx] = NULL;
execvp(args_clean[0], args_clean);                  // execute in parent
fprintf(stderr, "error in child execi \n"); // error
exit(0);

另外,请在此处查看我的回答,了解与管道类似的内容:fd leak, custom Shell

而且,对于完整的外壳,请参阅我的回答:Implementing input/output redirection in a Linux shell using C 并查看嵌入式 pastebin 链接

【讨论】:

  • 现在是自我推销——干得好! (以及一个很好的答案......)
  • @DavidC.Rankin 谢谢。是的,无耻。但是,请参阅这个 SO 答案 [not mine] stackoverflow.com/a/52442453/5382650 和我对 Vittorio 的评论(即我同意他所说的话,做了 +1 并告诉他)。彼得施耐德然后插话。我[只是]链接到我在codereview上所做的一个答案,因为我在cmets中反驳彼得的所有内容都包含在链接的答案中。嗯,更多的自我推销,但这个是坚持原则 :-) 而且,我必须在 codereview 答案中坚持我的原则,因为在我做了一些之前得到了 DV'ed to -3澄清
  • 其实,没有太多个模组。我看了你open/dup2/close的代码,感觉还不错,所以没仔细检查,也没改。许多 OP 在这方面也遇到了麻烦 [尤其是 管道],所以你领先于游戏。
  • 哇,我没想到会这样做,但它可以解决所有问题,非常感谢您的帮助!
  • 证据在布丁:)
猜你喜欢
  • 2016-07-15
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多