获取bash命令的输出并将其作为命令行参数传递给c可执行文件(管道)

时间:2018-12-04 18:09:54

标签: c shell redirect pipe output

我正在尝试在c中以及运行时创建自定义外壳程序

pwd | ./show

它将获取pwd输出并将其作为./show的命令行参数传递,并且必须使用管道。

我已阅读我可以找到的任何相关问题,但我无法使其正常工作。

到目前为止,我认为我已将输出成功定向到管道中,但是我不知道如何将其传递到./show。我一直在打印它,只是为了验证它是否通过管道。

        if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);
        pid = fork();

        if(!pid){
            dup2(fd[1],STDOUT_FILENO); //output into pipe
            close(fd[0]);
            close(fd[1]);

            com=args[0];
            for(i=1;i<(size-2);i++){
              com=concat(com," ");
              com=concat(com,args[i]);
            }

            readCommand(args,directory,com,(size-1));
            return 1;
        }

        close(fd[1]);

        int nbytes = read(fd[0], foo, sizeof(foo));
        printf("Output: (%.*s)\n", nbytes, foo);

    }

exec发生在readCommand内部,所以在这里

      void readCommand(char *args[10],char *directory,char *com, int i){

    if(execl(directory, args[i],args[i+1], NULL)==-1){
        execl("/bin/sh", "/bin/sh", "-c", com, NULL);
        perror("execlp");
    }
    else{
        execl(directory, args[0],args[1],args[2],args[3],args[4], NULL); //max number of args=4
        perror("execlp");
    }
  }

我以前曾尝试使它与两个fork一起工作,但是后来我不确定我是否正确重定向了输出,并且似乎更难了。如果有帮助,我也可以包含该代码。

感谢您的帮助,我的截止日期为几个小时...

更新:阅读答案后,我更新了代码

if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);

        if (!fork()) {
            pipe(fd);

            if(!fork()) {

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

                execlp(args[0], args[0], NULL);
            }
            else {

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

                execlp(args[size-1], args[size-1], NULL);
            }
        }
        wait(NULL);
    }

现在我打印出一个空行,然后提示输入新命令。

1 个答案:

答案 0 :(得分:0)

您需要派生两个进程,并在它们之间使用管道。您的外壳程序不应尝试读取或写入管道。

这是一个完整的示例,该示例对管道​​进行了硬编码以演示如何进行设置:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
  char* producer="pwd";
  char* consumer="./show";
  int fds[2];

  printf("Going to run the equivalent of '%s | %s'\n", producer, consumer);
  // Create a child that will become the consumer
  if (!fork()) {
    pipe(fds);
    // Create another child to be the producer
    if(!fork()) {
      // Set up stdout to be the pipe
      dup2(fds[1], 1);
      close(fds[0]);
      close(fds[1]);
      // Execute the producer
      execlp(producer, producer, NULL);
    } else {
      // Set up stdin to be the pipe
      dup2(fds[0], 0);
      close(fds[0]);
      close(fds[1]);
      // Execute the consumer
      execlp(consumer, consumer, NULL);
    }
  }
  // Wait for the consumer to finish
  wait(NULL);
  printf("The pipeline is done, the \"shell\" is exiting\n");
}

这是show的实现:

#!/bin/sh
echo "Here's the data $0 read: $(cat)"

这是来自真实外壳的结果:

$ pwd
/tmp

$ pwd | ./show
Here's the data ./show read: /tmp

这是运行此示例时的结果:

$ gcc foo.c -o foo && ./foo
Going to run the equivalent of 'pwd | ./show'
Here's the data ./show read: /tmp
The pipeline is done, the "shell" is exiting