2010-11-29 5 views
0

EDIT: Ich kann einige der Einzüge nicht funktionieren, aber der Code ist vollständig und blockiert richtig. Es tut uns leid.Problem mit Umleitung und Pipelining in meiner einfachen UNIX-Shell

Für eine Klassenzuweisung musste ich einen Teil einer einfachen UNIX-Shell implementieren. Es muss Umleitung, Rohrleitungen und Hintergründe unterstützen. Mir wurde ein Parser zur Verfügung gestellt, der eine Struktur mit dem Namen Command_line auffüllt (ich werde den folgenden Struct-Prototyp hinzufügen). Meine Aufgabe besteht darin, eine Funktion zu schreiben, die diese Befehlszeilen verarbeitet (behandelt Umleitungen, Hintergrundinformationen, Verrohrungen und führt Programme aus).

Ich habe es fast funktioniert, aber aus irgendeinem Grund behandelt es nicht ordnungsgemäß Befehle des Formulars program1 | program2 - Datei. Beispiel: cat < file1.in | Katze - Datei2.in. Das Problem scheint nicht in der Umleitung zu sein, da ich Testprogramme geschrieben habe, die vor die Pipe gestellt werden, die keine Umleitung erfordern, aber immer noch das gleiche Problem verursachen. Das Pipelining funktioniert in den meisten Fällen; Es sind nur diese Programme mit "-" als Argument, die Probleme verursachen.

Wenn ich eine dieser problematischen Befehlszeilen ausführen, wird die Ausgabe aus dem ersten Programm gedruckt und der Prozess aufgelegt (ich muss manuell anhalten und beenden). Es gibt dem Benutzer keine Eingabeaufforderung oder reagiert nicht auf Eingabe (abgesehen von Strg + Z, die ich verwende, um den Prozess zu unterbrechen).

Irgendwelche Ratschläge, wie man dieses Arbeiten erhält, würde sehr geschätzt.

Hier ist die Struktur:

/* This is the structure that holds the information about a parsed 
* command line. The argvs array is an array of string vectors; in 
* other words, for some int i, argvs[i] is an array of strings. 
* You should be able to use argvs[i] in calls to one of the execv*() 
* functions. 
*/ 
typedef struct { 
    char *argvs[MAX_PROGS + 1][MAX_ARGS + 1]; 
    int num_progs; /* Number of argument vectors; if > 1, piping is requested */ 
    char *infile; /* Name of stdin redirect file; NULL if no redirection */ 
    char *outfile; /* Name of stdout redirect file; NULL if no redirection */ 
    int append;  /* Is output redirection appending? */ 
    int bg;   /* Put command into background? */ 
} Command_line; 

Und mein Code, die eine dieser Strukturen verarbeitet (ich habe die #includes weggelassen).

pid_t runproc(int fd[][2], int num, Command_line *cmd); 

void execute_command_line(Command_line *cmd) { 
    int n; 
    int temp_pipe[2]; 
    int fd[MAX_PROGS-1][2]; 
    pid_t pids[MAX_PROGS]; 

    /* Clears pipes (sets all values to -1*/ 
    for(n = 0; n < cmd->num_progs; n++){ 
    fd[n][0] = -1; 
    fd[n][1] = -1; 
    } 

    /*Uses temp_pipe to connect write end of nth pipe to read end of (n+1)th 
    pipe*/ 
    for(n = 0; n < cmd->num_progs - 1; n++){ 
    pipe(temp_pipe); 
    fd[n][1] = temp_pipe[1]; 
    fd[n+1][0] = temp_pipe[0]; 
    } 

    /*If input file redirection is occuring, redirects read end of first pipe to 
    file*/ 
    if(cmd->infile){ 
    fd[0][0] = open(cmd->infile, O_RDONLY); 
    if(fd[0][0] < 0){ 
     printf("Error executing command\n"); 
     exit(1); 
    } 
    } 

    /*If output file redirection is occurring, redirects write end of last pipe to 
    file. Sets append option according to append field of command*/ 
    if(cmd->outfile){ 
    if(cmd->append){ 
     fd[cmd->num_progs - 1][1] = open(cmd->outfile, O_APPEND | O_WRONLY); 
     if(fd[cmd->num_progs - 1][1] < 0){ 
printf("Error executing command\n"); 
exit(1); 
     } 
    }else{ 
     fd[cmd->num_progs - 1][1] = open(cmd->outfile, O_WRONLY); 
     if(fd[cmd->num_progs - 1][1] < 0){ 
printf("Error executing command\n"); 
exit(1); 
     } 
    } 
    } 

    /*Runs runproc for every program in pipe, stores return values (pids of 
    children) in array*/ 
    for(n = 0; n < cmd->num_progs; n++){ 
    pids[n] = runproc(fd, n, cmd); 
    } 

    /*Closes all pipes*/ 
    for(n = 0; n < cmd->num_progs; n++){ 
    if(fd[n][0] >= 0) close(fd[n][0]); 
    if(fd[n][1] >= 0) close(fd[n][1]); 
    } 

    /*Waits for all children*/ 
    for(n = 0; n < cmd->num_progs; n++){ 
    wait(NULL); 
    } 

} 

pid_t runproc(int fd[][2], int num, Command_line *cmd){ 
    pid_t pid; 
    int n; 
    int frk_chk; 

    pid = fork(); 
    if(pid < 0){ 
    printf("Error executing command\n"); 
    exit(1); 
    }else if (!pid){ /*Child code*/ 
    /*Redirects stdin/stdout of process to read/write end of corresponding 
     pipe*/ 
    if(fd[num][0] >= 0) dup2(fd[num][0], STDIN_FILENO); 
    if(fd[num][1] >= 0) dup2(fd[num][1], STDOUT_FILENO); 

    /*Closes pipe ends*/ 
    for(n=0; n < cmd->num_progs - 1; n++){ 
     if(fd[num][0] >= 0) close(fd[num][0]); 
     if(fd[num][1] >= 0) close(fd[num][1]); 
    } 

    /*If backgrounding: forks, parent exits, child executes program. 
     If not backgrounding: program just executes*/ 
    if(cmd->bg){ 
     if((frk_chk = fork()) < 0){ 
printf("Error executing command\n"); 
exit(1); 
     }else if(frk_chk){ 
exit(0); 
     }else{ 
if(!(cmd->infile) && num == 0) close(STDIN_FILENO); 
execvp(cmd->argvs[num][0], cmd->argvs[num]); 
     } 
    }else{ 
     if(!num){ 
dup2(fd[0][1], STDOUT_FILENO); 
     } 
     execvp(cmd->argvs[num][0], cmd->argvs[num]); 
    } 
    printf("Error executing command\n"); 
    exit(1); 
    }else{ /*Parent code*/ 
    /*Returns pid of child, used for reaping loop*/ 
    return pid; 
    } 
} 

Antwort

0

Im run_proc() im /*close pipe ends*/ Schleife, sollte es sein

for(n=0; n < cmd->num_progs - 1; n++) 
    { 
     if(fd[n][0] >= 0) close(fd[n][0]); 
     if(fd[n][1] >= 0) close(fd[n][1]); 
    }