bash コマンド (一種のシェル プログラム) を実行する小さな C プログラムがあります。
ユーザーが次のようなコマンドを送信すると:
ls -l | grep .[c,h]$ | トイレ –l
ls
エコー | ls
リンクされたリストデータ構造を使用することにしました。これが実行する関数です
int execute(command *c) {
//create new procces and execute command
int numOfPipe = getNumOfPipes(c); // gets how many commands there is seperated by | (for 1 command with no pipes. getNumOfPipes returns 1
int fds[numOfPipe][2];
pid_t pids[numOfPipe];
int i;
int status;
// create pipes
for( i = 0; i < numOfPipe; i++ ) {
pipe(fds[i]);
}
i=0;
// p set to be the head of the list (first command)
Pipe* p = c->pl->head;
// running throw all nodes
while(i<numOfPipe) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
} else if (pids[i] == 0) {
// children processes
// there is more then one command
if (numOfPipe > 1) {
if (p==c->pl->head) // first node (will be first command)
dup2(fds[i][1],STDOUT_FILENO);
else if(p->next!=NULL) { // not first / last command
dup2(fds[i-1][0],STDIN_FILENO);
dup2(fds[i][1],STDOUT_FILENO);
} else if(p->next==NULL) // last command
dup2(fds[i-1][0],STDIN_FILENO);
// closing all pipes
int j;
for( j = 0; j < numOfPipe; j++ ){
close(fds[j][0]);
close(fds[j][1]);
}
}
// execute command
execvp(p->params[0],p->params);
// on execute error will print this messege and returns COMMAND_ERROR
fprintf(stderr, "%s: command not found\n",p->params[0]);
destroyShell(c);
free(c);
exit(COMMAND_ERROR);
}
// parent closing all end of pipes
int j;
for( j = 0; j < numOfPipe && numOfPipe > 1; j++ ){
close(fds[j][0]);
close(fds[j][1]);
}
// waiting each process
while(wait(&status)!=pids[i]);
// if the command is valid
if (WIFEXITED(status) && WEXITSTATUS(status)==COMMAND_ERROR) {
destroyShell(c);
return WEXITSTATUS(status);
}
p=p->next;
i++;
}
// closing all end of pipes (necessary here????)
int j;
for (j = 0; j < numOfPipe; j++) {
close(fds[j][0]);
close(fds[j][1]);
}
// returns all command's return code
if (WIFEXITED(status))
return WEXITSTATUS(status);
return 0;
}
今では、このコードは予測できない方法で動作しています。単一のコマンドでは動作し、サーバルでは動作する場合と動作しない場合があります....このコードブロックに何時間も費やしましたが、Googleはまったく役に立ちませんでした!!
いくつかのメモ:
- ユーザーが次のようなコマンドを送信した場合:
エコー|ls|123
戻りコードは COMMAND_ERROR マクロ定義になり、次のエラー メッセージが表示されるはずです。
123: コマンドが見つかりません
しかし、どういうわけか私のコードは「echo |」を実行します。ls' を実行し、最初の 2 つのコマンドの出力を表示します。その後、'123' コマンドのエラー メッセージが表示されます。また、いくつかの悪いコマンドの場合-最初に見つかったコマンドに対してのみエラーメッセージを表示することが想定されており、次のコマンドを実行し続けることは想定されていません...
このコマンドの場合:
ls -l | grep .[c,h]$ | トイレ –l
エンドレスループにストックされているようです....
- コマンド *c はリンクされたリストを保持し、リスト内の各ノードは 1 つのコマンドになり、各ノードはコマンドのすべてのパラメーターを保持する配列呼び出しパラメーターを保持します。例:
エコー 1234 | ls /ホーム
___________ ___________
| | | |
| COMMAND 1 | ---> | COMMAND 2 |
|___________| |___________|
| |
| |
______ _______
| | | |
| ECHO | | LS |
|______| |_______|
| | | |
| 1234 | | /HOME |
|______| |_______|
私が十分に明確で、私の問題をよく説明したことを願っています。どうもありがとうございました!