首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于执行外壳管道和重定向的C程序

用于执行外壳管道和重定向的C程序
EN

Stack Overflow用户
提问于 2016-02-22 12:22:03
回答 1查看 2.3K关注 0票数 0

对此有些陌生。我正在编写一个C程序,它允许用户输入UNIX命令,例如

代码语言:javascript
运行
复制
ls –la | wc -l  and ls | head > file.txt

我已经实现了管道,并且完成了少量的重定向代码。目前,我只能执行像cat file1.txt > file2.txt这样的命令,或者其他以重定向结尾的命令。

如果我注释掉这段-所有的管道链都工作得很好。

代码语言:javascript
运行
复制
  char * srch;
  srch = strchr(cmd, '>');
  *srch++ = '\0';
  while(*srch == ' ')
  {
      ++srch;
  }

  if(srch)
  {
    dup2(open(srch, O_RDWR|O_CREAT), STDOUT_FILENO);
  }

当我尝试将管道和重定向合并到同一命令中时,例如cmd1 p1 p2 p3 < file1 | cmd2 > file2,就会出现问题。或者甚至更简单的命令,如ls | head > file.txt

是否有人可以帮助我实现在同一命令中添加重定向和管道的功能。我试了很久,但还是弄不明白。

这是我到目前为止所知道的:

代码语言:javascript
运行
复制
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

/*get args function*/

#define MAXARGS 256
char ** getargs(char * cmd) {
    // assumes that cmd ends with NULL
    char** argsarray;
    int nargs = 0;
    int nlen = strlen(cmd);
    int i = 0;
    argsarray = (char**) malloc(sizeof(char*) * MAXARGS);
    argsarray[0] = strtok(cmd," ");
    i = 0;
    while (argsarray[i] != NULL){
        i++;
        argsarray[i] = strtok(NULL," ");
    }
    return argsarray;
}


int main(void){

  pid_t childpid;
  int fd[256][2];
  char cmd[256];
  char * sepCmd[256];
  char * pch;

  printf("Please enter a command sequence: \n");
  gets(cmd);
  //scanf("%s", cmd);
  printf("You have entered: %s \n", cmd);


  printf("Attempting to split up command: \n");
  pch = strtok (cmd, "|");


  //problems here...
  char * srch;
  srch = strchr(cmd, '>');
  *srch++ = '\0';
  while(*srch == ' ')
  {
      ++srch;
  }

  if(srch)
  {
    dup2(open(srch, O_RDWR|O_CREAT), STDOUT_FILENO);
  }




  int count = 0;  
    while (pch != NULL && count < 256) {
      printf("%s\n", pch);
      sepCmd[count] = pch;
      printf("The value in this array value is: %s\n", sepCmd[count]);
      pch = strtok (NULL, "|");
      count++;
  }

  char ** argue;
  int k;

  /* Block that deals with the first command given by the user */
  k = 0;
  pipe(fd[k]);
  if(!fork()) {
        dup2(fd[k][1], STDOUT_FILENO);
        close(fd[k][0]);
        argue = getargs(sepCmd[k]);
        execvp(argue[0], argue);
        perror(argue[0]);
        exit(0);
  }

  /*Loop that will control all other comands except the last*/
  for(k = 1; k <= count - 2; k++) {
      close(fd[k-1][1]);
      pipe(fd[k]);

      if(!fork()) {
          close(fd[k][0]);
          dup2(fd[k-1][0], STDIN_FILENO);
          dup2(fd[k][1], STDOUT_FILENO);
          argue = getargs(sepCmd[k]);
          execvp(argue[0], argue);
          perror(argue[0]);
          exit(0);
      }
  }


  /*Block that will take care of the last command in the sequence*/
  k = count - 1;

  //  if(reDir){
  //argue = getargs(sepCmd[k]);
  //open(argue[count], O_RDWR);

  //if(!fork()){
  //  close(fd[0]);
  //  close(fd[1]);
  //  dup2(fd[k-1][0], STDOUT_FILENO);
  //  execl("/bin/>", argue[count]);}
  //}
  //else{

  close(fd[k-1][1]);
  if(!fork()) {
      dup2(fd[k-1][0], STDIN_FILENO);
      argue = getargs(sepCmd[k]);
      execvp(argue[0], argue);
      perror(argue[0]);
      exit(0);
  }
  // }
  while(waitpid(-1, NULL, 0) != -1);
}
EN

Stack Overflow用户

发布于 2016-02-22 14:55:23

注释代码错误。您正在查找'>‘( srch = strchr(cmd, '>') ),但没有检查结果,正在使用'\0’终止预期结果。因此,当没有重定向时,用户会暂时得到分段故障,并且当也没有什么好的事情发生时。顺便说一句,我建议去掉gets,因为它已经非常过时了。当你使用--std=gnu11编译时,你会得到implicit declaration of function ‘gets’。至于实现的技巧,在谷歌中可以看到许多很好的结果,比如:https://github.com/dan-f/my_shell或者https://github.com/jmreyes/simple-c-shell,这样你就可以检查他们是如何做到的。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35545785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档