c - 我正在 build 一个小 shell 。如何将两个进程的标准输入和输出设置为管道,以便它们可以通信?

标签 c shell unix fork pipe

我正在尝试实现一个自己的非常小的 shell 。我必须能够处理管道,例如

ls -l | wc -l

但一次只能用于两个程序。现在,我有这个:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define BUFFER_SIZE 256
#define NO_PARAMS 32

void split_string(char **params, char *string){ 
  char *arg;
  int i;

  arg = strtok(string, " ");
  params[0] = arg;
  i = 1;
  while(arg != NULL){
    arg = strtok(NULL, " ");
    params[i] = arg;
    i++;
  }
}

int main(int argc, char **argv){
  char string[BUFFER_SIZE];
  char *prog1, *prog2;
  int i, err; 
  int fd[2];
  pid_t pid1, pid2;
  size_t buffer = BUFFER_SIZE;
  char *params1[NO_PARAMS], *params2[NO_PARAMS];
  int pipe_exists = 0;

  memset(string,0,buffer); 

  while(1){
    /*Read command*/ 
    fgets(string, BUFFER_SIZE-1, stdin);
    if(string == NULL){
      perror("Error reading input:\n");
      exit(1);
    }


    /*replace linefeed character with end of line character*/
    for(i=0;i<BUFFER_SIZE;i++){
      if(string[i] == 10){
        string[i] = 0;
      }
    }       

    /*check if command is "exit"*/
    if(strcmp(string,"exit") == 0){
      return 0;
    }

    /*split command into different program calls*/
    prog1 = strtok(string, "|");
    prog2 = strtok(NULL,"\0");
    if(prog2 != NULL){
      pipe_exists = 1;
      printf("PIPE!\n");
      err =  pipe(fd);
      if(err<0){
        perror("Error creating pipe:\n");
        exit(1);
      }

    }


    /*split string into arguments*/
    split_string(params1, prog1);
    if(pipe_exists){
      split_string(params2, prog2);
    }



    /*fork child process*/
    pid1 = fork(); 

    if(pid1==0){ /*child 1*/
      if(pipe_exists){
        close(fd[0]); /*close read-end*/
        err = dup2(fd[1], 1);
        if(err<0){
          perror("Error with dup in child 1!\n");
          exit(1);
        }
      }
      execvp(params1[0],params1);
      perror("Error calling exec()!\n");
      exit(1);

    }else{ /*parent*/
      if(pipe_exists){

        pid2 = fork();

        if(pid2==0){ /*child 2*/
          close(fd[1]); /*close pipe write-end*/
          err = dup2(fd[0], 0);

          if(err<0){
            perror("Error with dup in child 2!\n");
            exit(1);
          }
          execvp(params2[0],params2);
          perror("Error calling exec()!\n");
          exit(1);

        }else{ /*parent with 2 children*/
          waitpid(pid1,0,0);
          waitpid(pid2,0,0);
        }
      }else{ /*parent with 1 child*/
       waitpid(pid1,0,0); 
      }
    }
  }
}

现在,它可以很好地处理单个命令,但是当我输入类似上面的命令时,什么也没有发生!

谢谢!

最佳答案

哦!我已经想通了。我还必须关闭父程序中的管道:)

关于c - 我正在 build 一个小 shell 。如何将两个进程的标准输入和输出设置为管道,以便它们可以通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12408799/

相关文章:

java - cat Unix命令直接来自java,不应该调用shell脚本

c - c中指向堆栈位置的指针

c - 指向 C 函数的指针

linux - shell 脚本 : Hexadecimal Loop

linux - 进程 grep 给出不明确的输出

linux - Linux 配置 bash 脚本示例

linux - 是什么导致在 find 中执行 -type f 的时间增加

可以创建函数返回零,它的含义是什么?

c - 在 C 中没有匹配项时在字符串中插入一个字符

shell - 如何在shell脚本中保留$@中的双引号?