管道没有创建特定的管道描述符

问题描述:

我有一个项目在C上复制shell命令。其中一个命令是|这需要使用管道进行。我的其他命令有效,但我无法使(ls | sort)工作。它说, LS不能访问|:没有这样的文件或目录 LS不能排序访问:没有这样的文件或目录管道没有创建特定的管道描述符

我希望有人能帮助我弄清楚如何解决这个问题的管道?它开始试图做到这一点,所以我不必为每个命令做一个单独的管道,所以我通过for循环运行它。

执行大部分工作的功能是执行。 Runsource和Rundest在管道中进行信息的打开和传输。

void execute(char *cmdline) 
{ 
    int pid, async; 
    char *args[MAX_ARGS]; 
    char *pargs[MAX_ARGS]; 
    int i = 1; 
    int j; 

    int nargs = get_args(cmdline, args); 
    if (nargs <= 0) 
     return; 

    if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 
    { 
     exit(0); 
    } 

    int npargs = get_pipe(cmdline, pargs); 
    if (npargs > 1) 
    { 
     int pdes[2]; 
     pipe(pdes); 

     for (j = 0; i < npargs; j++) 
     { 
      nargs = get_args(pargs[j], pargs); 
      runsource(pdes, j, pargs, npargs); 
      rundest(pdes, j + 1, pargs, npargs); 
      close(pdes[0]); 
      close(pdes[1]); 
     } 
    } 
    else 
    { 
     while (args[i] < args[nargs]) 
     { 
      if (strcmp(args[i], ">")) 
      { 
       freopen(args[i + 1], "w", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], ">>")) 
      { 
       freopen(args[i + 1], "a", stdout); 
       args[i] = NULL; 
      } 

      if (strcmp(args[i], "<")) 
      { 
       freopen(args[i + 1], "r", stdin); 
       args[i] = NULL; 
      } 
     } 
    } 


    /* check if async call */ 
    if (!strcmp(args[nargs - 1], "&")) 
    { 
     async = 1; 
     args[--nargs] = 0; 
    } 
    else 
     async = 0; 

    pid = fork(); 
    if (pid == 0) /* child process */ 
    { 
     execvp(args[0], args); 
/* return only when exec fails */ 
     perror("exec failed"); 
     exit(-1); 
    } 
    else if (pid > 0) /* parent process */ 
    { 
     if (!async) 
      waitpid(pid, NULL, 0); 
     else 
      printf("this is an async call\n"); 
    } 
    else /* error occurred */ 
    { 
     perror("fork failed"); 
     exit(1); 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    char cmdline[BUFFSIZE]; 

    for (; ;) 
    { 
     printf("COP4338$ "); 
     if (fgets(cmdline, BUFFSIZE, stdin) == NULL) 
     { 
      perror("fgets failed"); 
      exit(1); 
     } 
     execute(cmdline); 
    } 
    return 0; 
} 
+0

确保你没有任何标签在你的代码copy'n'paste然后缩进。它弄得一团糟。 –

+0

是的,在管道之前或之后处理命令之前,您必须知道管道。你可以调用函数'get_pipe()',但不要在问题中包含该函数。还有其他的缺失功能。这不是一个MCVE([MCVE])。很难知道'get_pipe()'函数的作用。你需要它来分割'ls -l | sort -k2n -k5n | sed's/*// g'| less“分成4组独立的命令加参数,并且管道不会出现在任何参数列表中。 'sed'命令也只需要两个参数,并且没有引号(shell将它们删除)。你可以跳过引用参数的东西。 –

我看你有没有特殊的代码来处理“<”和“>”符号,但是我没有看到你的答案,处理任何代码“|”,那么,您如何甚至它期待工作?现在的问题是你传递“|”作为ls的一个参数,实际上你应该在管道后面运行这个东西,作为将标准输出ls发送到该命令的标准输入的命令。

你为什么试图通过手动解析东西和设置管道从头开始创建一个shell?难道你不能只用system()来执行一个shell命令吗?

+0

难道你不需要知道“|”在你运行ls之前,因为它会运行并发送到标准输出,而不是我想将它发送到下一个命令 –

+0

另外一个要点是将管道集成到其中。我只是在编写代码的时候遇到了麻烦,而不是手动编写管道 –

+0

不,系统()调用的重点在于它使用shell执行命令('/ bin/sh '根据我在我的回答中链接到的文档)。你的shell将解析管道角色并做适当的事情,因为这是shell应该做的主要事情之一。如果这是作业,那么老师是否明确说过你不能使用'system()'或者运行一个像sh或bash这样的外部shell? –