2010-11-29 51 views
0

EDIT: Je ne parviens pas à faire fonctionner correctement certains indentations, mais le code est complet et bloqué correctement. Pardon.Problème de redirection et de traitement en pipeline dans mon shell UNIX simple

Pour une affectation de classe, j'ai dû implémenter une partie d'un simple shell UNIX. Il doit prendre en charge la redirection, la tuyauterie et l'arrière-plan. J'ai été fourni avec un analyseur qui remplit une structure appelée Command_line (j'inclurai le prototype de structure ci-dessous). Mon travail consiste à écrire une fonction qui traite ces lignes de commande (gère la redirection, l'arrière-plan, la tuyauterie et exécute les programmes).

Je l'ai presque fonctionné mais pour une raison quelconque, il ne gère pas correctement les commandes du formulaire program1 | programme2 - fichier. Par exemple, cat < file1.in | chat - file2.in. Le problème ne semble pas être dans la redirection comme j'ai écrit des programmes de test à mettre devant le tuyau qui ne nécessitent pas de redirection mais causent toujours le même problème. Le pipelining fonctionne dans la plupart des cas; c'est juste ces programmes avec "-" comme argument qui causent des problèmes. Lorsque j'exécute l'une de ces lignes de commande problématiques, la sortie du premier programme est imprimée et le processus raccroche (je dois le suspendre et le supprimer manuellement). Il ne donne pas d'invite à l'utilisateur par la suite ou ne réagit pas aux entrées (à part ctrl + z que j'utilise pour suspendre le processus).

Des conseils sur la façon d'obtenir ce travail seraient grandement appréciés.

Voici le struct:

/* 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; 

Et mon code, qui traite de ces struct (je l'ai laissé les #includes).

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

Répondre

0

Dans le run_proc(), dans la boucle /*close pipe ends*/, il devrait être

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