// J12345 // 山田 太郎 // gcc ex1.c // 起動方法 ./a.out PATH=/bin:/usr/bin LANG=dutch 等, // 操作方法 bashやcshと同様にコマンドと引数を入れる // 終了方法 EOFを入力,具体的にはコントロールDを押す. // // $Id: ex1a.c,v 2.1 2004-10-20 17:23:52+09 kaiya Exp kaiya $ #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); } } } char** str2args(char* str){ static char* args[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; return args; } 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; }