システムコールfork()/ execvp()を使用して、Cで簡単なシェルを開発する必要があります。これまでのところ、私のコードはコマンドを受け取り、strtokを使用してそれを配列argvに分割してから、forkを呼び出して子を作成し、コマンドを実行します。私はほとんどのコマンドが/ bin /ディレクトリにあるubuntuでこれに取り組んでいるので、プログラム名(たとえば/ bin/ls)を追加し、それをexecvpの最初の引数に使用して、それにargv配列を与えます。コマンド「ls」を入力するとプログラムが動作しますが、他のコマンドまたは「ls -l」を試した場合、「ls:invalid option」が表示されます。私はここで何が間違っているのかわかりません。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_LEN 1024
int main(){
char line[BUFFER_LEN]; //get command line
char* argv[100]; //user command
char* path= "/bin/"; //set path at bin
char progpath[20]; //full file path
int argc; //arg count
while(1){
printf("My Shell>> "); //print Shell Prompt
if(!fgets(line, BUFFER_LEN, stdin)){ //get command and put it in line
break; //if user hits CTRL+D break
}
if(strcmp(line, "exit\n")==0){ //check if command is exit
break;
}
char *token; //split command into separate strings
token = strtok(line," ");
int i=0;
while(token!=NULL){
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL; //set last value to NULL for execvp
argc=i; //get arg count
for(i=0; i<argc; i++){
printf("%s\n", argv[i]); //print command/args
}
strcpy(progpath, path); //copy /bin/ to file path
strcat(progpath, argv[0]); //add program to path
for(i=0; i<strlen(progpath); i++){ //delete newline
if(progpath[i]=='\n'){
progpath[i]='\0';
}
}
int pid= fork(); //fork child
if(pid==0){ //Child
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
}else{ //Parent
wait(NULL);
printf("Child exited\n");
}
}
}
無効なオプションは、Enterキーを押したときにfgets()
が'\n'
を保持するためです。
if(!fgets(line, BUFFER_LEN, stdin))
break;
size_t length = strlen(line);
if (line[length - 1] == '\n')
line[length - 1] = '\0';
ls -l
を呼び出そうとすると、オプションとして"-l\n"
が渡されるため、メッセージが表示されます。
あなたは変える必要があります
strcmp(line, "exit\n")
に
strcmp(line, "exit")