2010-11-29 44 views
0

編輯:我無法獲得某些縮進以正常工作,但代碼已完整且被正確阻止。抱歉。在我簡單的UNIX shell中重定向和流水線問題

對於一個類的任務,我必須實現一個簡單的UNIX shell的一部分。它必須支持重定向,管道和背景。我提供了一個解析器來填充名爲Command_line的結構(我將在下面包含結構原型)。我的工作是編寫一個處理這些Command_lines的函數(處理重定向,背景,管道和執行程序)。

我幾乎可以正常工作,但由於某種原因,它不能正確處理格式爲的命令program1 |程序2 - 文件。例如,cat < file1.in | cat - file2.in。這個問題似乎沒有在重定向中,因爲我已經編寫了測試程序放在不需要重定向的管道之前,但仍然會導致相同的問題。流水線在大多數情況下工作;只是這些程序以「 - 」作爲導致問題的論據。

當我運行這些有問題的命令行之一時,第一個程序的輸出被打印,並且進程掛起(我必須手動暫停並終止它)。它不會給用戶提示或反應輸入(除了ctrl + z,我用它來暫停進程)。

任何意見,如何得到這個工作將不勝感激。

這裏的結構:

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

而且我的代碼,用於處理這些結構中的一個(我已經離開了的#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; 
    } 
} 

回答

0

run_proc(),在/*close pipe ends*/循環, 應該

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