草庐IT

c - *几乎*完美的 C shell 管道

coder 2023-06-17 原文

我正在用 C 语言编写一个小型 linux shell,并且非常接近完成。我接收来自用户的命令并将其存储在 args 中,以空格分隔。在下面的示例中,假设 args 包含以下内容:

args[] = {"ls", "-l", "|", "wc"};

我的函数接受args 并且还接受有多少个管道。我已经尽可能多地评论了我的代码。在这里:

int do_command(char **args, int pipes) {
    // The number of commands to run
    const int commands = pipes + 1;
    int i = 0;

    int pipefds[2*pipes];

    for(i = 0; i < pipes; i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("Couldn't Pipe");
            exit(EXIT_FAILURE);
        }
    }

    int pid;
    int status;

    int j = 0;
    int k = 0;
    int s = 1;
    int place;
    int commandStarts[10];
    commandStarts[0] = 0;

    // This loop sets all of the pipes to NULL
    // And creates an array of where the next
    // Command starts

    while (args[k] != NULL){
        if(!strcmp(args[k], "|")){
            args[k] = NULL;
            // printf("args[%d] is now NULL", k);
            commandStarts[s] = k+1;
            s++;
        }
        k++;
    }



    for (i = 0; i < commands; ++i) {
        // place is where in args the program should
        // start running when it gets to the execution
        // command
        place = commandStarts[i];

        pid = fork();
        if(pid == 0) {
            //if not last command
            if(i < pipes){
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command&& j!= 2*pipes
            if(j != 0 ){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            int q;
            for(q = 0; q < 2*pipes; q++){
                    close(pipefds[q]);
            }

            // The commands are executed here, 
            // but it must be doing it a bit wrong          
            if( execvp(args[place], args) < 0 ){
                    perror(*args);
                    exit(EXIT_FAILURE);
            }
        }
        else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        j+=2;
    }

    for(i = 0; i < 2 * pipes; i++){
        close(pipefds[i]);
    }

    for(i = 0; i < pipes + 1; i++){
        wait(&status);
    }
}

我的问题是,虽然程序有点正确执行,但它的行为很奇怪,我希望你能帮助我。

例如,当我运行 ls | wc,输出是ls | wc,但随后它还在其正下方打印一个简单的 ls 的输出,即使它应该只是输出的 wc

另一个例子,当我尝试ls -l | wcwc 的第一个数字出现,但随后 ls -l 的输出显示在其下方,即使它应该只是 >wc 输出。

提前致谢! :)

最佳答案

好的,我发现了一个小错误。这个

       if( execvp(args[place], args) < 0 ){

应该是

       if( execvp(args[place], args+place) < 0 ){

您的版本将 args 用于所有其他命令的第一个命令。除此之外,它对我有用。

关于c - *几乎*完美的 C shell 管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12679075/

有关c - *几乎*完美的 C shell 管道的更多相关文章

  1. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

  2. ruby - 为什么我会看到这两个几乎相同的 Ruby 正则表达式模式的不同结果,为什么一个匹配我认为不应该匹配的内容? - 2

    使用Ruby1.9.2,我在IRB中有以下Ruby代码:>r1=/^(?=.*[\d])(?=.*[\W]).{8,20}$/i>r2=/^(?=.*\d)(?=.*\W).{8,20}$/i>a=["password","1password","password1","pass1word","password1"]>a.each{|p|puts"r1:#{r1.match(p)?"+":"-"}\"#{p}\"".ljust(25)+"r2:#{r2.match(p)?"+":"-"}\"#{p}\""}这会产生以下输出:r1:-"password"r2:-"password"r1:

  3. ruby-on-rails - 如何通过 Assets 管道加载css.erb文件 - 2

    我希望我的样式表保持纯css,但我想使用嵌入式ruby​​来包含一些图像的动态路径:.home{background:#FFFurl()no-repeat;}如果我将样式表从.css更改为.css.erb,image_path会得到正确解释,但当我部署到生产环境时,它不会被Assets管道处理。如果我硬编码路径,无论是在生产还是开发中都会出错,因为它们以不同的方式加载Assets。我该如何解决? 最佳答案 这是有效的:将.erb添加到.css文件并使用ruby/rails代码就可以了。所以我上面的问题中的片段很好。你必须在/conf

  4. Ruby gem 几乎每个命令都显示 "Invalid argument"错误 - 2

    我正在OSXElCapitan上完成NativeScript的设置,我被困在我应该安装xcodeproj和cocoapods。我尝试用gem做的几乎所有事情都显示相同的错误:$sudogeminstallxcodeprojERROR:Whileexecutinggem...(Errno::EINVAL)Invalidargument以下命令显示相同的错误,无论我是否使用sudo运行它:$gemupdate--system$gemupdate$geminstallwhatever$geminstallcocoapods我有以下版本:$ruby--versionruby2.3.1p112(

  5. ruby-on-rails - 在 Assets 管道中需要树 - 2

    我的Assets管道中有一个名为typefaces的文件夹。它无需向application.rb添加任何内容即可工作。在目录中,我有不同的字体类型,例如文件夹中的.eof、.ttf等AssetsTypefacesEof...filesTtf...files除非字体在Assets/字体中,否则它们不会成为Assets管道的一部分。Assets管道不会进入子目录。我如何让Assets管道超越Assets/字体,进入Assets/字体/eof、Assets/字体/ttf等? 最佳答案 在您的app/assets/javascripts/a

  6. ruby-on-rails - Rails Assets 管道和摘要值 - 2

    有谁知道Assets摘要值是怎么计算出来的?如果我有两个JS文件,其中包含各种其他包含的JS脚本,那么如果没有更改任何内部脚本,每个文件是否会保持相同的摘要哈希?还是每次运行assets:precompile操作时都会计算一个新的摘要值? 最佳答案 公认的答案并不完全正确。我们为暂存、演示和生产服务器构建静态Assets,并且在每种情况下为同一Assets赋予不同的摘要值。原来Rails环境也在考虑之列。Sprockets按如下方式创建摘要:#Sprockets::Environment::initialize@digest_cla

  7. ruby - 执行 ruby​​ 作为 logstash 的管道输入 - 2

    Logstash允许executingarbitrarycommands作为管道的输入。这是我的示例管道:input{exec{command=>'/usr/bin/ruby-e"putsRUBY_VERSION"'interval=>10}}output{stdout{codec=>rubydebug}}有了这个我得到了以下错误:/opt/logstash/vendor/bundle/jruby/1.9/gems/bundler-1.9.10/lib/bundler/resolver.rb:328:in`blockinverify_gemfile_dependencies_are_f

  8. ruby-on-rails - 获取 Assets 管道路径中的 Gem 供应商文件 - 2

    我创建了一个带有供应商目录的gem,其中包含来自bootstrap-sass的样式表和javascripts并自行引导。目录结构为bootstrap-sass-gem/vendor/assets/javascripts和bootstrap-sass-gem/供应商/Assets/样式表我在测试项目中需要gem,但每当我尝试从该gem中请求某些东西时,我都会收到Sprockets::FileNotFound错误。例如,我在application.css中添加了*=requirebootstrap。bootstrap位于bootstrap-sass-gem/vendor/assets/st

  9. ruby-on-rails - Rails Assets 管道中的动态 CSS,即时编译 - 2

    我正在使用Rails3.2构建站点。我接触Rails或Ruby已经3年了,所以我对两者都生疏了,加上我最后一次使用Rails是Rails2.3。不用说,请原谅下面的任何“简单”问题。这是规范MultiTennantCMS/商店网站http://company1.mywebsite.comhttp://company2.mywebsite.com等等每个“商店”(又名子域)都可以通过CSS定制拥有自己的外观、感觉等自定义可以在应用程序的UI中执行,允许用户更改Bootstrap的基本变量(即@textColor、@bodyBackground等)我将less-rails-bootstra

  10. ruby-on-rails - Node/NPM 依赖于 Ruby on Rails 引擎 gem Assets 管道 - 2

    我正在构建一个打包在gem中的RubyonRails引擎,但无法弄清楚如何确保加载NPM依赖项。在常规Rails应用程序中,您可以安装NPM,然后使用npminstall命令将包放入node_modules基本目录中。然后在您的application.rb中使用以下行将node_modules添加到Assets管道:config.assets.paths但是,就我而言,我正在构建一个Rails引擎以作为gem加载。.gemspec文件允许您的gem将其他Ruby依赖项加载到主机应用程序中,但我不知道如何对Node依赖项执行相同的操作。在我的引擎中注意它需要某些NPM模块才能工作以便它们

随机推荐