1 /* 2 * Simple Unix Shell. 3 * 4 * Loop reading lines from standard input. 5 * Split each line into blank-separated tokens. 6 * Call the forkexec() function to fork and exec the tokens as a 7 * command and arguments. 8 * 9 * This is an example of the fork() and exec() system calls mentioned 10 * in Chapter 1 of the Linux Shells by Example book. 11 * 12 * To compile this on Unix: cc -o simshell thisfile.c 13 * Compiled and linked output will be put in file "simshell". 14 * 15 * -IAN! idallen@ncf.ca 16 */ 17 #include 18 #include 19 #include 20 #include 21 #include 22 #include 23 24 /* 25 * Fork and then submit the arguments to the Unix "execvp" function that 26 * replaces the current executing process image with the given command 27 * binary and its arguments. PATH is used; execvp tries to find 28 * the command name in each of the components of the PATH. The parent 29 * waits for the forked child to finish. 30 */ 31 static int 32 forkexec( int argc, char **argv ){ 33 int pid; 34 35 switch( pid=fork() ) { 36 case -1: /* ERROR */ 37 perror("fork"); 38 return 1; 39 case 0: /* CHILD */ 40 execvp(argv[0],argv); 41 perror(argv[0]); 42 printf("*** Could not execute '%s'\n", argv[0]); 43 exit(1); // forked child process exits non-zero 44 default:{ /* PARENT */ 45 int status; 46 wait( &status ); 47 return (status == 0) ? 0 : 1; 48 } 49 } 50 /*NOTREACHED*/ 51 } 52 53 #define CMD_BUFSIZ 4096 54 #define CMD_NARGS 1024 55 #define CMD_DELIM " \t\n" 56 int 57 main(int argc, char **argv){ 58 char buf[CMD_BUFSIZ]; // buffer to hold command line 59 char *edge[CMD_NARGS]; // edge vector of pointers to each token 60 char **ep; // iterates over edge vector 61 char **eend; // pointer to end of edge vector 62 char *strbuf; // first arg to strtok 63 int ecount; // count of tokens 64 char *token; // token returned by strtok 65 int i; // misc 66 67 for(;;){ 68 /* 69 * Prompt and get one line of input. 70 */ 71 printf("simsh$ "); 72 if ( fgets(buf,sizeof(buf),stdin) == NULL ) { 73 if ( ferror(stdin) ) { 74 perror("standard input"); 75 printf("\n*** Error reading stdin\n"); 76 } else { 77 printf("\n*** EOF\n"); 78 } 79 break; 80 } 81 if ( strchr(buf,'\n') == NULL ) { 82 printf("\n*** EOF or line longer than %d chars\n", 83 CMD_BUFSIZ); 84 break; 85 } 86 87 /* 88 * Fill the edge vector with pointers to tokens. 89 * The last pointer must be set to NULL. 90 */ 91 ep = edge; // start filling here 92 eend = edge + CMD_NARGS; // stop filling here 93 strbuf = buf; // strtok gets buf on first time through 94 while( (token=strtok(strbuf,CMD_DELIM)) != NULL ) { 95 if( ep >= eend ) { 96 printf("*** More than %d args\n", CMD_NARGS); 97 break; 98 } 99 *ep++ = token; 100 strbuf = NULL; // strtok gets NULL on subsequent times 101 } 102 if ( ep >= eend ) 103 ep = eend - 1; 104 *ep = NULL; 105 ecount = ep - edge; 106 107 /* 108 * DEBUG: display the list of tokens. 109 */ 110 for( i=0; i