2016-04-29 12 views
-2

ich einen tokenizer in geschrieben haben, die Kommandosprache Eingabe tokenizes und wenn ich die Befehle ausführen ich die Ausgabe in „falschen Reihenfolge“ erhalten nach dem fork, wenn ich ein und exec tun dann die Ausgabe von fork und exec kommen könnte, in der Mitte einer Schleife in einer anderen Funktion. Die erwartete Ausgabe i willWie kann ich diesen C-Code synchronisieren?

$ 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 

Während der Ausgang I erhalten

$ 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 

den Code Einige, die tut dies ist

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

Es ist nicht unbedingt notwendig, dass ich fixiere es in meinem Code, aber ich möchte lernen, warum ich nicht erwarten kann, dass die Ausgabe "gerade" ist, wenn ich fork starte.

+1

Hat 'fork_pipes'' exec' aufgerufen und sich nie gedreht? – fluter

+0

@fluter Ich kann diesen Code auch posten. –

+2

Probieren Sie 'printf (" [% d] [% d]% s \ n ", i, j, pString [i] [j]);' aus, da das Stdout liniengepuffert ist. Warum "verzweigt" ihr beide in 'spaw_proc' und' fork_pipes'? – fluter

Antwort

2

Der Grund ist, Standard-Ausgabe ist in der Regel Linie gepuffert, benötigen Sie eine neue Zeile, um den Ausgang zu spülen, wie printf("p[%d][%d] %s\n", i, j, pString[i][j]);.

+1

Eine Faustregel könnte sein, 'fflush (NULL);' kurz vor * jedem * 'fork()' –

+2

zu verwenden. Das ist richtig, 'fflush (NULL)' spült alle geöffneten Streams, so dass Sie eine Menge Aufwand sparen haben viele Dateiströme geöffnet. – fluter