/* * 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) { char* argvTask[MAXARGS]; // holds arguments for other calls pid_t npid; // new pid temp var sigset_t mask; parseline(cmdline, argvTask); if(builtin_cmd(argvTask)){} // check for a built in and runs immediately else // reaches for non-built in { sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); // enable mask for parent if(parseline(cmdline, argvTask)) //checking if BG { if(( npid = fork()) == 0) // child run in bg { sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock mask for child setpgid(0,0); if(execve(argvTask[0], argvTask, environ) < 0) { //unix_error( argvTask[0]); printf("%s: Command not found \n",argvTask[0]); exit(0); } } else // parent { addjob(jobs, npid,BG, cmdline); // add bg job to list and parent does not wait printf( "[%d] (%d) %s", maxjid(jobs) , npid , cmdline); sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock the parent } } else // runs if FG { if(( npid = fork()) == 0) // child run in fg { sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock child setpgid(0,0); if(execve(argvTask[0], argvTask, environ) < 0) // use exec call and check for error { printf("%s: Command not found \n",argvTask[0]); exit(0); } } else // parent { addjob(jobs, npid,FG,cmdline); // adding the fg job to jobs list sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock the parent waitfg(npid); //waiting for fg process to finish } } } return; }
// function used to delete job from job list void deletejob(struct job_t *job_list,pid_t pid){ int i; for(i=0;i<20;i++){ if(job_list[i].pid==pid){ clearjob(&job_list[i]); nextjid=maxjid(job_list)+1; break; } } }
/* * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever * a child job terminates (becomes a zombie), or stops because it * received a SIGSTOP or SIGTSTP signal. The handler reaps all * available zombie children, but doesn't wait for any other * currently running children to terminate. */ void sigchld_handler(int sig) { int child_status; // child process status for waitpid pid_t wpid; struct job_t *job; // wait for child process while there is any child left while(maxjid(jobs)) { // -1 : wait for any child // WNOHANG : don't block procedure // WUNTRACED : trace stopped child wpid = waitpid(-1, &child_status, WNOHANG | WUNTRACED); if(wpid == -1) { // handle waitpid error perror("waitpid"); return; } else if(wpid == 0) { // no child was terminated or stopped break; } // find job object with pid // getjobpid never fails job = getjobpid(jobs, wpid); // check child status if(WIFSIGNALED(child_status)) { // child terminated by a signal printf("Job [%d] (%d) terminated by signal %d\n", job->jid, job->pid, WTERMSIG(child_status)); // delete job from job list deletejob(jobs, wpid); } else if(WIFSTOPPED(child_status)) { // child stopped printf("Job [%d] (%d) stopped by signal %d\n", job->jid, job->pid, WSTOPSIG(child_status)); // set state job->state = ST; } else if(WIFEXITED(child_status)) { // child exited properly // delete job from job list deletejob(jobs, wpid); } } }
/* deletejob - Delete a job whose PID=pid from the job list */ int deletejob(struct job_t *jobs, pid_t pid) { int i; if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) { if (jobs[i].pid == pid) { clearjob(&jobs[i]); nextjid = maxjid(jobs)+1; return 1; } } return 0; }
/* * Requires: * "jobs" points to an array of MAXJOBS job structures. * * Effects: * Deletes a job from the jobs list whose PID equals "pid". */ static int deletejob(JobP jobs, pid_t pid) { int i; if (pid < 1) return (0); for (i = 0; i < MAXJOBS; i++) { if (jobs[i].pid == pid) { clearjob(&jobs[i]); nextjid = maxjid(jobs) + 1; return (1); } } return (0); }
/* deletejob - Delete a job whose PID=pid from the job list */ int deletejob(struct job_t *job_list, pid_t pid) { int i; //fprintf(stderr, "try to delete job:%d\n", pid); if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) { if (job_list[i].pid == pid) { clearjob(&job_list[i]); nextjid = maxjid(job_list)+1; return 1; } } return 0; }
/* deletejob - Delete a job whose PID=pid from the job list */ int deletejob(struct job_t *jobs, pid_t pid) { int i; //printf("here in delete job \n" ); if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) { if (jobs[i].pid == pid) { clearjob(&jobs[i]); nextjid = maxjid(jobs)+1; // printf("job found\n"); return 1; } } return 0; }