/* mush.c * by Douglas Jones * a Minimally Usable SHell * augmented with use of $PATH as the search path */ /* Note: the logic for envp was not immediately apparent and is * outside the scope of this assignment. Getting it right is * needed to use this shell to launch cc and other utilities that * need to access the environment. */ #include #include #include #include char command[100]; char *argv[100]; char *opath; /* pointer to $PATH (the original) */ char *path; /* a copy of the path */ char *patha[100];/* NULL terminated array of pointers to path components */ char **myenvp; /* the environment passed to the main program */ /* as documented in the execve man page */ void getpath(){ /* initialize patha from $PATH */ /* the logic here is cribbed from parseargv */ int i = 0; /* patha index */ int j = 0; /* text index */ opath = getenv( "PATH" ); path = strcpy( malloc( strlen( opath ) + 1 ), opath ); for (;;) { /* no need to skip blanks */ if (path[j] == '\000') break; patha[i] = &path[j]; i++; while ((path[j] != ':') /* path delimiter is colon */ &&(path[j] != '\000')) { j++; } if (path[j] == '\000') break; path[j] = '\000'; j++; } patha[i] = NULL; } void getcommand(){ char ch; int i = 0; putchar('>'); do { ch = getchar(); command[i] = ch; i++; } while (ch != '\n'); command[i-1] = '\000'; } void parseargv(){ int i = 0; /* argv index */ int j = 0; /* text index */ for (;;) { while (command[j] == ' ') j++; if (command[j] == '\000') break; argv[i] = &command[j]; i++; while ((command[j] != ' ') &&(command[j] != '\000')) { j++; } if (command[j] == '\000') break; command[j] = '\000'; j++; } argv[i] = NULL; } void launch(){ if (fork() == 0) { /*child*/ int i = 0; /* patha index */ execve( argv[0], argv, myenvp ); /* first, try it as itself */ while (patha[i] != NULL) { /* try successive path prefixes */ char filename[100]; strncpy( filename, patha[i], 99 ); filename[99] = '\000'; /* insurance */ strncat( filename, "/", 99 - strlen( filename ) ); strncat( filename, argv[0], 99 - strlen( filename ) ); execve( filename, argv, myenvp ); /* try one prefix */ i = i + 1; } printf("no such command\n"); exit( EXIT_FAILURE ); /* a minor bug fix */ } else { /*parent*/ wait( NULL ); } } main( int argc, char *argv[], char *envp[] ){ myenvp = envp; getpath(); for (;;) { getcommand(); parseargv(); launch(); } }