// J12345 // 山田 太郎 // gcc ex1.c // 起動方法 ./a.out PATH=/bin:/usr/bin 等, // 操作方法 bashやcshと同様にコマンドと引数を入れる // 終了方法 EOFを入力,具体的にはコントロールDを押す. // // $Id: ex1a.c,v 1.1 2006-11-08 23:03:28+09 kaiya Exp kaiya $ #include #include #include #include #include #include #ifndef LINE_MAX #define LINE_MAX 2048 #endif extern char** environ; // 環境変数のリスト extern int errno; // エラーコード /* * str: input string, maybe with "\n" * return: NULL when parse error, list of args when success. */ char** str2args(char* str); /* * argv: list of string * return: 1 when argv is valid, 0 when it is not. * valid string: string with '=' */ int checkArgs(char **argv); main(int argc, char* argv[]){ char buf[LINE_MAX]; if(!checkArgs(argv+1)){ fprintf(stderr, "Invalid args\n"); exit(3); } environ=argv+1; while(fgets(buf, LINE_MAX, stdin)!=NULL){ pid_t ch; if((ch=fork())==0){ // child char** args; if((args=str2args(buf))==NULL){ // parse error. fprintf(stderr, "invalid inputs, type again.\n"); exit(4); } execvp(*args, args); fprintf(stderr, "exec failed code %d\n", errno); exit(2); }else if(ch>0){ // parent int stat; wait(&stat); }else{ // fail fprintf(stderr, "fork fail\n"); exit(1); } } } /** * コマンド文字列群を文字の配列に分離する * @param str ユーザーの入力文字列 コマンド 引数等が空白文字で区切られている * @return コマンド等を分離した文字列の配列,関数内のstatic変数を利用 **/ char** str2args(char* str){ char* args[LINE_MAX]; // ★ 修正 static char* rets[LINE_MAX]; // ★ 追加 wastefull, but easy char* ptr; int argc=0; for(ptr=str; *ptr; ptr++){ char* etr; if(isspace(*ptr)) continue; for(etr=ptr; *etr && !isspace(*etr); etr++) ; if(*etr){ *etr='\0'; args[argc++]=ptr; ptr=etr; }else{ args[argc++]=ptr; break; } if(argc>=LINE_MAX) return NULL; } // ★ 追加部分開始 // args[argc]=NULL; { int i; for(i=0; argc>0; i++, argc--){ rets[i]=args[argc-1]; } rets[i]=NULL; } return rets; // ★ 追加部分終了 } int checkArgs(char** args){ int ret=0; // default fail; if(args==NULL) return 0; for(ret=0; *args; args++){ if(strchr(*args, '=')==NULL) return 0; else ret=1; } return ret; }