2013-02-08 24 views
0

当我简单地管道ls -l |按照这个排序,该程序只是从ls -l无限地吐出结果。任何人都可以看到有什么不对? 假设您只需查看主要功能。虽然这会编译。导致无限输出的管道

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


#define COMMAND_LINE_LENGTH 256 
#define HISTORY_LENGTH 10 
#define TOKEN_MAX 50 
#define DIRECTORY_LENGTH 5 
#define DIRECTORY_PREFIX "/bin/" 

struct prog_def 
{ 
    //Binary location 
    char *bin; 

    //Is this program expecting a pipe? 
    int expecting_pipe; 

    //Arguments 
    char *args[TOKEN_MAX + 1]; 

    pid_t pid; 

} prog_def; 

int get_prog_defs(const char* buf, struct prog_def prog_defs[]) 
{ 
    char *line = malloc(strlen(buf) + 1); 

    int prog_count = 0; 
    char* token; 

    strcpy(line, buf); 
    line[strlen(buf)] = 0; 

    while(1) 
    { 
     int arg_count = 0; 

     //The first time through we have to pass the line 
     token = strtok(line, " "); 

     //Each subsequent call we have to pass NULL 
     //http://www.cplusplus.com/reference/cstring/strtok/ 
     line = NULL; 

     //Start building the binary location string 
     prog_defs[prog_count].bin = (char*)malloc(strlen(token) + DIRECTORY_LENGTH + 1); 

     //Concatenate the directory prefix and command name 
     strcat(prog_defs[prog_count].bin, DIRECTORY_PREFIX); 
     strcat(prog_defs[prog_count].bin, token); 

     //The first argument execvp will expect is the binary location itself 
     //Redundant but if I wasn't too lazy to read the doc then I'd know why 
     prog_defs[prog_count].args[arg_count++] = prog_defs[prog_count].bin; 

     while(1) 
     { 
      prog_defs[prog_count].expecting_pipe = 0; 

      //Check next token for end, pipe, IO redirection, or argument 
      token = strtok(NULL, " "); 

      //If we've consumed all tokens 
      if (token == NULL) 
       break; 

      //Pipe 
      if (strcmp(token, "|") == 0) 
      { 
       prog_defs[prog_count - 1].expecting_pipe = 1; 
       break; 
      } 

      //Regular argument 
      prog_defs[prog_count].args[arg_count++] = token; 
     } 

     ++prog_count; 

     if (token == NULL) break; 
    } 

    return prog_count; 
} 


int main(int argc, char** argv) 
{ 

    char command[COMMAND_LINE_LENGTH] = {0}; 

    //Generic loop counter 
    int x = 0; 

    while(1) 
    { 
     printf(">"); 

     //Get the command 
     gets(command); 

     struct prog_def prog_defs[TOKEN_MAX]; 
     int prog_count = get_prog_defs(command, prog_defs); 

     //Keep the previous out fd for the in of the subsequent process 
     int prev_out_fd = open("/dev/null", O_RDONLY); 

     for (x = 0; x < prog_count; ++x) 
     { 
      //Create a pipe for both processes to share 
      int pipefd[2]; 

      if (x != prog_count -1) 
      { 
       pipe(pipefd); 
      } 

      prog_defs[x].pid = fork(); 

      if(prog_defs[x].pid == 0) 
      { 
       dup2(prev_out_fd, STDIN_FILENO); 
       close(pipefd[1]); 

       if(x != prog_count - 1) 
       { 
        dup2(pipefd[1], STDOUT_FILENO); 
        close(pipefd[0]); 
        close(pipefd[1]); 
       } 


       execvp(prog_defs[x].bin, prog_defs[x].args); 
      prev_out_fd = pipefd[0]; 
      close(pipefd[1]); 
      } 

     close(prev_out_fd); 

      prev_out_fd = pipefd[0]; 
      close(pipefd[1]); 

     } 

     printf("\n"); 

     for (x = 0; x < prog_count; ++x) 
     { 
      waitpid(prog_defs[x].pid, NULL, 0); 
     } 

    } 
} 
+0

这是不同于[你的早期问题“无限管道疯狂”与巨大的代码转储](http://stackoverflow.com/q/14780894/2509)? – dmckee 2013-02-08 22:41:20

+0

“execvp”后面两行的含义是什么?除非'execvp'失败,否则不会触及它们,在这种情况下,您应该处理错误。 – musiphil 2013-11-07 18:41:17

回答

1

你叫malloc得到的字符串,这将是未初始化的一些内存,所以包含随机的垃圾。然后你调用strcat,它会试图将另一个字符串附加到随机垃圾上,几乎可以肯定会在malloc'd空间的末尾运行,导致随机混淆行为和崩溃。

您还可以使用prog_defs[prog_count - 1]不断递增prog_count之前,所以第一次循环,(当prog_count == 0),这将数组,这也导致随机行为混乱和崩溃开始前写的。