2016-04-29 57 views
-2

我在该标记化命令语言输入,当我执行命令我得到的fork后在“错误的顺序”的输出,如果我写的一个标记一个exec然后从fork和exec输出可能出现在一些其他功能的循环中。预期的输出我要的是如何同步此C代码?

$ ls openshell.*|grep o 
{ls} {openshell.cbp} {|} {grep} {o} {|} 
p[0][0] ls 
p[0][1] openshell.cbp  
p[1][0] grep 
p[1][1] o 
17109: executing ls 
17108: executing grep 
openshell.cbp 

,而输出我得到的是

$ ls openshell.*|grep o 
{ls} {openshell.cbp} {|} {grep} {o} {|} 
p[0][0] ls 
p[0][1] openshell.cbp 
17108: executing grep 
p[1][0] grep 
openshell.cbp 
17109: executing ls 
p[1][1] o 

一些,这是否是

static int runCmd(const char *cmd) { 
    const char *cp; 
    pid_t pid; 
    int status; 
    struct command shellcommand[4]; 
    char **argv = 0; 
    int argc = 1; 
    bool pipe = false; 
    char *pString[75][75]; 
    char *command[40]; 
    char *command2[40]; 
    int i1 = 0; 
    char **tokens; 
    char tokenscopy[75]; 
    bool keep = false; 
    char *conc[75]; 
    char *conc2[75]; 
    *conc = "\0"; 
    *conc2 = "\0"; 
    char temp[75] = {'\0'}; 
    int w = 0; 
    bool quoted = false; 
    int j = 0; 
    int i; 
    int p = 0; 
    char **ptr; 
    char *tmpchar; 
    char *cmdtmp; 
    bool change = false; 
    int f = 0; 
    char *char2; 
int y = 0; 

    for (int i = 0; i < 75; i++) { /* for each pipeline */ 
     for (int j = 0; j < 75; j++) { /* for each pipeline */ 
      pString[i][j] = '\0'; 
     } 

    } 
    for (cp = cmd; *cp; cp++) { 
     if ((*cp >= 'a') && (*cp <= 'z')) { 
      continue; 
     } 
     if ((*cp >= 'A') && (*cp <= 'Z')) { 
      continue; 
     } 
     if (isDecimal(*cp)) { 
      continue; 
     } 
     if (isBlank(*cp)) { 
      continue; 
     } 
     if ((*cp == '.') || (*cp == '/') || (*cp == '-') || 
      (*cp == '+') || (*cp == '=') || (*cp == '_') || 
      (*cp == ':') || (*cp == ',') || (*cp == '\'') || 
      (*cp == '"')) { 
      continue; 
     } 
    } 
    char a[20] = {0}; 
    cmdtmp = malloc(sizeof(cmd)); 
    strcpy(cmdtmp, cmd); 
    tmpchar = malloc(sizeof(cmd)); 
    strcpy(tmpchar, cmd); 
    tokens = str_split(command, cmdtmp, '|'); 
    if (strstr(cmd, "|") == NULL) { 
     /* not a pipeline */ 
     makeArgs(cmd, &argc, (const char ***) &argv, pipe, 0, 0); 
     /*dump_argv((const char *) "d", argc, argv);*/ 
     for (j = 0; j < argc; j++) { 
      pString[0][j] = argv[j]; 
      shellcommand[i].argv = pString[0]; /*command;*/ 
     } 
    } 
    else { 
     i1 = 1; 
     for (i = 0; *(tokens + i); i++) { /* for each pipeline*/ 
      i1++; 
      int e = 0; 
      *conc2 = "\0"; 
      strcpy(tokenscopy, *(tokens + i)); 
      if ((tokenscopy[0] != '\0') && !isspace(tokenscopy[0])) { 

       ptr = str_split(command2, *(&tokenscopy), ' '); 
       f = 0; 
       int j2 = 0; 



        for (j = 0; *(ptr + j); j++) { 
         if (ptr + j && !quoted && strstr(*(ptr + j), "'")) { 
          quoted = true; 
          strcpy(temp, *(ptr + j)); 
          if(y<1) { 
          /* pString[i][j] = temp;*/ 
           y++; 
          } 
         } 
         while (quoted) { 
          if (*(ptr + j) && strstr(*(ptr + j), "'")) { /* end of quote */ 
           quoted = false; 
           if(y<1) { 
            pString[i][j] = strcpy(temp, *(ptr + j)); 
           } 
           y=0; 

          } 
          else if (*(ptr + j)) { /* read until end of quote */ 
           pString[i][j] = temp; 
           continue; 

          } else { 
           quoted = false; 
           break; 
          } 

         } 
         if (ptr + j) { 
          if (*(ptr + j)[0] == '{') { 
           keep = true; 
          } 
          if (testFn(*(ptr + j))) { /* test for last char */ 
           pString[i][j - p] = concat(*conc, *(ptr + j)); 
           keep = false; 
           free(*conc); 
           goto mylabel; 
          } 
          if (keep) { 
           *conc = concat(*conc, *(ptr + j)); 
           *conc = concat(*conc, " "); 
           p++; 
          } else { 
           if (*(ptr + j + f + 1) == NULL) 
            break; 
           strcpy(temp, *(ptr + j)); 
           change = false; 
           for (e = 0; *(ptr + j + e); e++) { 
            change = true; 
            if (*(ptr + e + j)) { 
             *conc2 = concat(*conc2, *(ptr + e + j)); 
             *conc2 = concat(*conc2, " "); 
            } 
           } 
           if (change) j++; 
           if (makeArgs(*conc2, &argc, (const char ***) &argv, pipe, i, j2)) { 
            for (int r = 0; argv[r] != NULL; r++) { 
             char2 = malloc(sizeof(char *)); 
             *char2 = '0'; 
             strcpy(char2, argv[r]); 
             pString[w][r] = char2; 
            } 
            w++; 
            dump_argv((const char *) "d", argc, argv); 
           } else { 
            if (!change) { 
             for (int r = 0; argv[r] != NULL; r++) { 
              pString[i][r] = argv[r]; 
             } 

            } 
           } 

          } 
         } 

       } 
       mylabel: 
       free(ptr); 
      } 
     } 
     free(tokens); 
     free(cmdtmp); 
     free(tmpchar); 
     for (i = 0; i < i1 - 1; i++) { 
      for (j = 0; pString[i][j] != 0; j++) { 
       printf("\np[%d][%d] %s", i, j, pString[i][j]); 
      } 
      shellcommand[i].argv = pString[i]; 
     } 
    } 



    pid = fork(); 
    if (pid < 0) { 
     perror("fork failed"); 
     return -1; 
    } 
    /* If we are the child process, then go execute the pString.*/ 
    if (pid == 0) { 
     /* spawn(cmd);*/ 
     fork_pipes(i1 - 1, shellcommand); 
    } 
    /* 
    * We are the parent process. 
    * Wait for the child to complete. 
    */ 
    status = 0; 
    while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR)); 
    if (pid < 0) { 
     fprintf(stderr, "Error from waitpid: %s", strerror(errno)); 
     return -1; 
    } 
    if (WIFSIGNALED(status)) { 
     fprintf(stderr, "pid %ld: killed by signal %d\n", 
       (long) pid, WTERMSIG(status)); 

     return -1; 
    } 
    return WEXITSTATUS(status); 
} 

fork_pipes

/* Helper function that forks pipes */ 
void fork_pipes(int n, struct command *cmd) { 
    int i; 
    int in = 0; 
    int fd[2]; 

    for (i = 0; i < n - 1; ++i) { 

     if (pipe(fd) == -1) { 
      err_syserr("Failed creating pipe"); 
     } 

     spawn_proc(in, fd[1], cmd + i); 
     close(fd[1]); 
     in = fd[0]; 
    } 
    if (dup2(in, 0) < 0) { 
     err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]); 
    } 
    fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd[i].argv[0]); 
    execvp(cmd[i].argv[0], cmd[i].argv); 
    err_syserr("failed to execute %s: ", cmd[i].argv[0]); 
} 


    /* Helper function that spawns processes */ 
    int spawn_proc(int in, int out, struct command *cmd) { 
     pid_t pid; 
     pid = fork(); 
     if (pid == 0) { 
      if (in != 0) { 
       if (dup2(in, 0) < 0) 
        err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]); 
       close(in); 
      } 
      if (out != 1) { 
       if (dup2(out, 1) < 0) 
        err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]); 
       close(out); 
      } 
      fprintf(stderr, "%d: executing %s\n", (int) getpid(), cmd->argv[0]); 
      execvp(cmd->argv[0], cmd->argv); 
      err_syserr("failed to execute %s: ", cmd->argv[0]); 
     } 
     else if (pid < 0) { 
      err_syserr("fork failed: "); 
     } else { 
      /* printf("** we are the parent ***"); */ 
     } 
     return pid; 
    } 

它的代码我不是绝对必要的修复它在我的代码中,但我想知道为什么我不能期望当我运行fork时输出是“直线”的。

+1

'fork_pipes'是否调用'exec'并且永远不会转向? – fluter

+0

@fluter我也可以发布该代码。 –

+2

尝试'printf(“p [%d] [%d]%s \ n”,i,j,pString [i] [j]);',因为stdout是行缓冲的。为什么'fork'在'spaw_proc'和'fork_pipes'? – fluter

回答

2

原因是标准输出通常是行缓冲的,您将需要一个新行来刷新输出,如printf("p[%d][%d] %s\n", i, j, pString[i][j]);

+1

经验法则可能是在所有* fork()之前调用'fflush(NULL);'' –

+2

这是正确的,'fflush(NULL)'冲洗所有打开的流,所以当你节省很多努力时打开大量文件流。 – fluter