EDIT:インデントの一部が正しく機能することができませんが、コードは完全で正しくブロックされています。ごめんなさい。私の単純なUNIXシェルでのリダイレクトとパイプラインの問題
私は単純なUNIXシェルの一部を実装しなければなりませんでした。リダイレクション、配管、バックグラウンドをサポートする必要があります。私は、Command_lineという構造体を作成するパーサを提供されました(以下の構造体プロトタイプを含みます)。私の仕事は、これらのCommand_linesを処理する関数(リダイレクト、バックグラウンド、配管を処理し、プログラムを実行する)を書くことです。
私はほとんどそれを動作させましたが、何らかの理由でそれが正しくコマンドの形式を処理していませんprogram1 | program2 - ファイル。たとえば、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;
そして、これらの構造体のいずれかを処理する私のコード、(私はの#includeを残してきた):
はここで構造体です。 run_proc()
内
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;
}
}