00001 /* 00002 shells, version 1, 2, and 3 00003 AUP2, Sec. 5.04, 5.06, 5.10 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include "builtin.h" 00023 #include "statuspr.h" 00024 #include <sys/wait.h> 00025 00026 //#define WANT_SHELL_V1 00027 //#define WANT_SHELL_V2 00028 #define WANT_SHELL_V3 00029 00030 /*[macros]*/ 00031 #define MAXARG 20 00032 #define MAXLINE 200 00033 /*[]*/ 00034 #ifdef WANT_SHELL_V1 00035 /*[execute]*/ 00036 static void execute(int argc, char *argv[]) 00037 { 00038 execvp(argv[0], argv); 00039 printf("Can't execute\n"); 00040 } 00041 /*[]*/ 00042 #endif /* WANT_SHELL_V1 */ 00043 #ifdef WANT_SHELL_V2 00044 #define execute execute2 00045 /*[execute2]*/ 00046 static void execute2(int argc, char *argv[]) 00047 { 00048 pid_t pid; 00049 00050 switch (pid = fork()) { 00051 case -1: /* parent (error) */ 00052 EC_FAIL 00053 case 0: /* child */ 00054 execvp(argv[0], argv); 00055 EC_FAIL 00056 default: /* parent */ 00057 ec_neg1( wait(NULL) ) 00058 } 00059 return; 00060 00061 EC_CLEANUP_BGN 00062 EC_FLUSH("execute2") 00063 if (pid == 0) 00064 _exit(EXIT_FAILURE); 00065 EC_CLEANUP_END 00066 } 00067 /*[]*/ 00068 #endif /* WANT_SHELL_V2 */ 00069 #ifdef WANT_SHELL_V3 00070 #define execute execute3 00071 /*[execute3]*/ 00072 static void execute3(int argc, char *argv[]) 00073 { 00074 pid_t pid; 00075 int status; 00076 00077 switch (pid = fork()) { 00078 case -1: /* parent (error) */ 00079 EC_FAIL 00080 case 0: /* child */ 00081 execvp(argv[0], argv); 00082 EC_FAIL 00083 default: /* parent */ 00084 ec_neg1( waitpid(pid, &status, 0) ) 00085 display_status(pid, status); 00086 } 00087 return; 00088 00089 EC_CLEANUP_BGN 00090 EC_FLUSH("execute3") 00091 if (pid == 0) 00092 _exit(EXIT_FAILURE); 00093 EC_CLEANUP_END 00094 } 00095 /*[]*/ 00096 #endif /* WANT_SHELL_V3 */ 00097 /*[getargs]*/ 00098 static bool getargs(int *argcp, char *argv[], int max, bool *eofp) 00099 { 00100 static char cmd[MAXLINE]; 00101 char *cmdp; 00102 int i; 00103 00104 *eofp = false; 00105 if (fgets(cmd, sizeof(cmd), stdin) == NULL) { 00106 if (ferror(stdin)) 00107 EC_FAIL 00108 *eofp = true; 00109 return false; 00110 } 00111 if (strchr(cmd, '\n') == NULL) { 00112 /* eat up rest of line */ 00113 while (true) { 00114 switch (getchar()) { 00115 case '\n': 00116 break; 00117 case EOF: 00118 if (ferror(stdin)) 00119 EC_FAIL 00120 default: 00121 continue; 00122 } 00123 break; 00124 } 00125 printf("Line too long -- command ignored\n"); 00126 return false; 00127 } 00128 cmdp = cmd; 00129 for (i = 0; i < max; i++) { 00130 if ((argv[i] = strtok(cmdp, " \t\n")) == NULL) 00131 break; 00132 cmdp = NULL; /* tell strtok to keep going */ 00133 } 00134 if (i >= max) { 00135 printf("Too many args -- command ignored\n"); 00136 return false; 00137 } 00138 *argcp = i; 00139 return true; 00140 00141 EC_CLEANUP_BGN 00142 EC_FLUSH("getargs") 00143 return false; 00144 EC_CLEANUP_END 00145 } 00146 /*[main]*/ 00147 int main(void) 00148 { 00149 char *argv[MAXARG]; 00150 int argc; 00151 bool eof; 00152 00153 while (true) { 00154 printf("@ "); 00155 if (getargs(&argc, argv, MAXARG, &eof) && argc > 0) { 00156 if (strchr(argv[0], '=') != NULL) 00157 asg(argc, argv); 00158 else if (strcmp(argv[0], "set") == 0) 00159 set(argc, argv); 00160 else 00161 execute(argc, argv); 00162 } 00163 if (eof) 00164 exit(EXIT_SUCCESS); 00165 00166 } 00167 } 00168 /*[]*/ 00169