/* * Simple Unix Shell. * * Loop reading lines from standard input. * Split each line into blank-separated tokens. * Call the forkexec() function to fork and exec the tokens as a * command and arguments. * * This is an example of the fork() and exec() system calls mentioned * in Chapter 1 of the Linux Shells by Example book. * * To compile this on Unix: cc -o simshell thisfile.c * Compiled and linked output will be put in file "simshell". * * -IAN! idallen@ncf.ca */ #include #include #include #include #include #include /* * Fork and then submit the arguments to the Unix "execvp" function that * replaces the current executing process image with the given command * binary and its arguments. PATH is used; execvp tries to find * the command name in each of the components of the PATH. The parent * waits for the forked child to finish. */ static int forkexec( int argc, char **argv ){ int pid; switch( pid=fork() ) { case -1: /* ERROR */ perror("fork"); return 1; case 0: /* CHILD */ execvp(argv[0],argv); perror(argv[0]); printf("*** Could not execute '%s'\n", argv[0]); exit(1); // forked child process exits non-zero default:{ /* PARENT */ int status; wait( &status ); return (status == 0) ? 0 : 1; } } /*NOTREACHED*/ } #define CMD_BUFSIZ 4096 #define CMD_NARGS 1024 #define CMD_DELIM " \t\n" int main(int argc, char **argv){ char buf[CMD_BUFSIZ]; // buffer to hold command line char *edge[CMD_NARGS]; // edge vector of pointers to each token char **ep; // iterates over edge vector char **eend; // pointer to end of edge vector char *strbuf; // first arg to strtok int ecount; // count of tokens char *token; // token returned by strtok int i; // misc for(;;){ /* * Prompt and get one line of input. */ printf("simsh$ "); if ( fgets(buf,sizeof(buf),stdin) == NULL ) { if ( ferror(stdin) ) { perror("standard input"); printf("\n*** Error reading stdin\n"); } else { printf("\n*** EOF\n"); } break; } if ( strchr(buf,'\n') == NULL ) { printf("\n*** EOF or line longer than %d chars\n", CMD_BUFSIZ); break; } /* * Fill the edge vector with pointers to tokens. * The last pointer must be set to NULL. */ ep = edge; // start filling here eend = edge + CMD_NARGS; // stop filling here strbuf = buf; // strtok gets buf on first time through while( (token=strtok(strbuf,CMD_DELIM)) != NULL ) { if( ep >= eend ) { printf("*** More than %d args\n", CMD_NARGS); break; } *ep++ = token; strbuf = NULL; // strtok gets NULL on subsequent times } if ( ep >= eend ) ep = eend - 1; *ep = NULL; ecount = ep - edge; /* * DEBUG: display the list of tokens. */ for( i=0; i