/* do_fg - Execute the builtin fg command */ void do_fg(char **argv) { struct job_t * job; pid_t pid; if (verbose) printf("do_fg: entering\n"); job = treat_argv(argv); job->jb_state = FG; pid = jobs_fgpid(); assert(kill(-pid, SIGCONT) != -1); if (verbose) printf("do_fg: sigcont %d \n", pid); waitfg(pid); if (verbose) printf("do_fg: exiting\n"); return; }
/* waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { sigset_t vide; sigset_t masque; if (verbose) printf("waitfg: entering\n"); sigemptyset(&masque); sigemptyset(&vide); sigaddset(&masque, SIGCHLD); assert(sigprocmask(SIG_SETMASK, &masque, NULL) != -1); while(pid==jobs_fgpid()) { sigsuspend(&vide); } sigprocmask(SIG_SETMASK, &vide, NULL); if (verbose) printf("waitfg: exiting\n"); return; }
/* * sigint_handler - The kernel sends a SIGINT to the shell whenver the * user types ctrl-c at the keyboard. Catch it and send it along * to the foreground job. */ void sigint_handler(int sig) { int pid; if (verbose) printf("sigint_handler: entering\n"); if ((pid = jobs_fgpid())) kill(pid,sig); /* sig or SIGINT */ if (verbose) printf("sigint_handler: exiting\n"); return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and supid : 6031, getpid 6030 spend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { int pid; if (verbose) printf("sigtstp_handler: entering\n"); ; if ((pid = jobs_fgpid())) kill(pid,SIGSTOP); /* sig or SIGTSTP */ if (verbose) printf("sigtstp_handler: exiting\n"); return; }
/* * sigint_handler - The kernel sends a SIGINT to the shell whenver the * user types ctrl-c at the keyboard. Catch it and send it along * to the foreground job. */ void sigint_handler(int sig) { pid_t pid; if (verbose) printf("sigint_handler: entering\n"); if ((pid = jobs_fgpid()) > 0){ /* send SIGINT signal to the job of PID=pid*/ kill(pid,SIGINT); } if (verbose) printf("sigint_handler: exiting\n"); return; }
/* * 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 */ void sigchld_handler(int sig) { struct job_t* job; int status, pid; if (verbose) printf("sigchld_handler: entering\n"); if ((pid = waitpid(-1,&status,WNOHANG | WUNTRACED)) == -1) pid = jobs_fgpid(); if (pid > 0) { job = jobs_getjobpid(pid); if (WIFSTOPPED(status)) { job->jb_state = ST; printf("[%d] (%d) : Stopped\n",job->jb_jid,job->jb_pid); } else if (WIFEXITED(status)) { printf("[%d] (%d) : Exited\n",job->jb_jid,job->jb_pid); jobs_deletejob(pid); } else if (WIFSIGNALED(status)) { printf("[%d] (%d) : Exited by User\n",job->jb_jid,job->jb_pid); jobs_deletejob(pid); } else { printf("Error on : [%d] (%d) - %s \n",job->jb_jid,job->jb_pid,job->jb_cmdline); } } if (verbose) printf("sigchld_handler: exiting\n"); return; }