/* * doit.c - By: Theo Van Dinter (felicity@kluge.net) * * CS3013 - Homework #1 * * Programmed: 96/09/05 * * This program is pretty simple ... Run any command line parameters * like a shell, or act as a shell if no command line parameters are given. * * The mini-shell lacks a great deal of configurability which comes * with most "standard" shells. It is limited by the fact that the * mini-shell only accepts a command line, and then executes it. Most * shells allow you to set environment variables which allows you to * configure how the shell responds to your commands, etc. * * At the most basic level however, the mini-shell has the same * function structure as the other shells. The main differences are * "bell & whistles" in the 'standard' shells. * */ #include #include #include #include #include #include void fork_proc(char **); int main(int argc, char *argv[]) { char *argvnew[101]; /* New ARGV */ int loo, max, start; char input[1024]; if (argc>1) { max=argc; /* Set max equal to the current argc */ if (max>100) /* Don't allow an overrun of memory. */ max=100; for (loo=1;loo "); if (fgets(input,1024,stdin)==NULL) /* Error or EOF (probably EOF) */ { printf("\n"); break; } while(input[strlen(input)-1]=='\n') /* Strip newline (if exists) */ input[strlen(input)-1]='\0'; loo=0; while(input[loo]==' ') /* Skip initial whitespace */ loo++; if (loo) /* There was whitespace to skip ... */ strcpy(input,input+loo); if (!strncasecmp(input,"exit",4)) /* They typed 'exit' ... ;) */ break; max=0; /* Initialize variables for this iteration */ start=0; if (strlen(input)) /* If there's something to parse */ { for(loo=0;loo<=strlen(input);loo++) /* Loop through string */ /* space or EOS */ if (input[loo]==' '||input[loo]=='\0') { /* copy string section into the argv-like array */ if (max==100) /* too big! */ { printf("Too many parameters, limiting to 99 total.\n"); break; } else { argvnew[max]=(char *)malloc(loo-start+1); strncpy(argvnew[max],input+start,loo-start); argvnew[max][loo-start]='\0'; max++; while(input[loo+1]==' ') /* Skip extra whitespace */ { loo++; } start=loo+1; } } argvnew[max]=NULL; /* argv needs to have a NULL at the end of the array */ fork_proc(argvnew); /* Run it */ for(max-=1;max>=0;max--) /* Free the memory for the next time */ free(argvnew[max]); } } } return 0; } /* * Routine: fork_proc * * Input: argv-like array * * Returns: Nothing * * Purpose: Will fork and execvp based on the argv-like array. * */ void fork_proc(char *argvnew[]) { int loo,pid,max; struct rusage *child_info; float temp; child_info=(struct rusage*)malloc(sizeof(struct rusage)); pid=fork(); /* Fork */ if (pid==-1) /* Error! */ { printf("Can't fork!\n"); exit(1); } else if (pid) /* Parent */ { loo=wait3(NULL,0,child_info); if (loo==-1) { printf("Error on wait!\n"); exit(1); } else if (loo==0) { printf("No child to wait for.\n"); exit(1); } /* Print out the child usage stats */ printf("\nStats on child (PID %5d):",pid); printf("\n---------------------------\n"); temp=(float)child_info->ru_utime.tv_sec; temp+=(float)child_info->ru_utime.tv_usec/1000000; printf("User CPU Time Used : %f seconds (%ds,%dusec)\n",temp, child_info->ru_utime.tv_sec,child_info->ru_utime.tv_usec); temp=(float)child_info->ru_stime.tv_sec; temp+=(float)child_info->ru_stime.tv_usec/1000000; printf("System CPU Time Used : %f seconds (%ds,%dusec)\n",temp, child_info->ru_stime.tv_sec,child_info->ru_stime.tv_usec); printf("# of Involuntary Preemptions: %ld\n",child_info->ru_nivcsw); printf("# of Voluntary Preemptions : %ld\n",child_info->ru_nvcsw); printf("# of Page Faults : %ld\n",child_info->ru_majflt); printf("# of Page Faults (int cache): %ld\n",child_info->ru_minflt); } else /* Child */ { #ifdef DEBUG /* Debug Section ... Check the argvnew array */ loo=0; /* Compile with the -DDEBUG option to use .. */ while(argvnew[loo]!=NULL) { printf("%2d: [%s]\n",loo,argvnew[loo]); loo++; } printf("\n"); #endif execvp(argvnew[0],argvnew); printf("Can't execvp...\n"); /* If we made it here, there was an error */ exit(1); } free(child_info); return; }