/*BEGIN externalCall function--passes user input to external shell. Used only if user inputs a command not implemented in this shell*/ int externalCall(char **args){ /*check for the background execution argument '&'*/ BGCheck(args); /*fork/exec statement--case 0 is the child process, default is the parent, -1 is an error*/ switch(childPID = fork()){ case -1: debug("Fork error"); break; case 0: debug("Externalcall fork case 0"); /*allocate memory for, build, and push PARENT environment variable (used a previously made char* to save space*/ shell = (char*)malloc(sizeof(char) *(strlen(initCall) + 8)); strcat(shell, "PARENT="); strcat(shell, initCall); putenv(shell); /*check for I/O Redirect, both in and out(all other calls currently used only check for output redirection)*/ IORedirect(args, 2); execvp(args[0], args); exit(-1); //exit with error code, shouldn't ever reach this line default: if(!noWait){ debug("Externalcall wait"); waitpid(childPID, &status, WUNTRACED); } } return childPID; }
//#iii. dir <directory> - list the contents of <directory> int dir(char **args){ int i = 2; numArgs = 0; debug("Dir called"); /*count the arguments*/ while(args[++numArgs] != NULL); /*allocate space for, and build the new set of arguments*/ out = (char**)malloc(sizeof(char*) * (numArgs + 1)); out[0] = (char *)malloc(sizeof(char) * 3); strcpy(out[0], "ls"); out[1] = (char *)malloc(sizeof(char) * 4); strcpy(out[1], "-al"); out[2] = NULL; //in case of no additional arguments debug("Setting Args. List to follow:"); debug(out[0]); debug(out[1]); /*set the new list of arguments, terminated with a NULL pointer*/ while(i < numArgs+1){ out[i] = (char *)malloc(sizeof(char) * ((strlen(args[i-1]))+1)); strcpy(out[i], args[i-1]); debug(out[i]); ++i; out[i] = NULL; } /*fork/exec statement--case 0 is the child process, default is the parent, -1 is an error*/ switch(childPID = fork()){ case -1: debug("Fork error"); break; case 0: debug("Dir fork case 0"); debug("Checking for I/O Redirection"); IORedirect(out, 1); debug("I/O Redirection check complete. Executing call."); execvp("ls", out); exit(-1); default: if(!noWait){ debug("Dir wait"); waitpid(childPID, &status, WUNTRACED); } } free(out); return childPID; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; struct job_t *jobinfo; pid_t pid; sigset_t wait; /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) /* parsing error */ return; if (tok.argv[0] == NULL) /* ignore empty lines */ return; if(!buildinCmd(&tok)){ blockAllSignal(); if((pid = fork()) == 0){ //child if(setpgid(0, 0) < 0){ unix_error("process set prcess group error\n"); } IORedirect(&tok); unblockAllSignal(); if(execve(tok.argv[0], tok.argv, environ) == -1){ printf("%s, command not found\n", tok.argv[0]); exit(0); } }else{ //parent if(!bg){ addjob(job_list, pid, FG, cmdline); sigemptyset(&wait); sigsuspend(&wait); unblockAllSignal(); while(fgpid(job_list) != 0) { sigsuspend(&wait); } }else{ addjob(job_list, pid, BG, cmdline); jobinfo = getjobpid(job_list, pid); printf("[%d] (%d) %s\n", jobinfo->jid, jobinfo->pid, jobinfo->cmdline); unblockAllSignal(); } } } return; }
//#vi. help - display the user manual using the more filter int help(char **args){ debug("Help called"); /*fork/exec statement--case 0 is the child process, default is the parent, -1 is an error*/ switch(childPID = fork()){ case -1: debug("Fork error"); break; case 0: IORedirect(args, 1); /*Display the readme file using the more filter*/ execlp("more", "more", readme, NULL); exit(-1); default: if(!noWait) waitpid(childPID, &status, WUNTRACED); } return childPID; }
//#iv. environ - list all the environment strings int envrn(char **args){ debug("Environ called"); env = environ; /*fork/exec statement--case 0 is the child process, default is the parent, -1 is an error*/ switch(childPID = fork()){ case -1: debug("Fork Error"); break; case 0: IORedirect(args, 1); while(*env) puts(*env++); exit(0); default: if(!noWait) waitpid(childPID, &status, WUNTRACED); } return childPID; }
//#v. echo <comment> - display <comment> on the display followed by //#a new line (multiple spaces/tabs may be reduced to a single space) int echo(char **args){ int i = 1; debug("Echo called"); /*fork/exec statement--case 0 is the child process, default is the parent, -1 is an error*/ switch(childPID = fork()){ case -1: debug("Fork error"); break; case 0: IORedirect(args, 1); /*print all arguments on a single line, each followed by a single space.*/ while(args[i] != NULL){ printf("%s ", args[i]); ++i; } printf("\n"); //end the line with a newline character exit(0); default: if(!noWait) waitpid(childPID, &status, WUNTRACED); } return childPID; }