2016-04-29 10 views
-2

私はコマンド言語入力をトークン化でトークナイザを書かれていると私はコマンドを実行したときに、私はfork後に「間違った順序」の出力を取得し、私はexecを行うならば、フォークとexecからの出力が来るかもしれません他の機能のループの途中で。私が手出力がこのCコードをどのように同期できますか?

$ 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; 
    } 

イッツであるのに対し、私が欲しい予想される出力は

$ 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 

です絶対に必要なわけではない私のコードでそれを修正しますが、フォークを実行すると出力が "まっすぐ"であるとは思えません。

+1

'fork_pipes'は' exec'を呼び出していませんでしたか? – fluter

+0

@fluter私もそのコードを投稿することができます。 –

+2

stdoutはラインバッファーであるため、 'printf(" p [%d] [%d]%s \ n "、i、j、pString [i] [j]);'を試してください。 'spaw_proc'と' fork_pipes'の両方でforkしているのはなぜですか? – fluter

答えて

2

標準出力は通常、ラインバッファであるため、出力をフラッシュするための新しい行が必要です(printf("p[%d][%d] %s\n", i, j, pString[i][j]);など)。

+1

経験豊富な人は、すべての 'fork() 'の直前で' fflush(NULL); 'を呼び出すことがあるかもしれません。 –

+2

' fflush(NULL) 'は開いているストリームをすべてフラッシュします。たくさんのファイルストリームを開いている – fluter

関連する問題