/* treat_argv - Determine pid or jobid and return the associated job structure */ struct job_t * treat_argv(char **argv) { struct job_t *jobp = NULL; /* Ignore command if no argument */ if (argv[1] == NULL) { printf("%s command requires PID or %%jobid argument\n", argv[0]); return NULL; } /* Parse the required PID or %JID arg */ if (isdigit((int) argv[1][0])) { pid_t pid = atoi(argv[1]); if (!(jobp = jobs_getjobpid(pid))) { printf("(%d): No such process\n", (int) pid); return NULL; } } else if (argv[1][0] == '%') { int jid = atoi(&argv[1][1]); if (!(jobp = jobs_getjobjid(jid))) { printf("%s: No such job\n", argv[1]); return NULL; } } else { printf("%s: argument must be a PID or %%jobid\n", argv[0]); return NULL; } return jobp; }
/* waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { struct job_t *job; if (verbose) { printf("Entering wait FG\n"); } job=jobs_getjobpid(pid); if (job == NULL) { if (verbose) { printf("Non existing job : exiting wait FG\n"); } return; } while (job->jb_pid == pid && job->jb_state == FG) { sleep(1); if (verbose) { fprintf(stderr, "Waiting\n"); } } if (verbose) { printf("Exiting wait FG\n"); } return; }
/* waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { struct job_t *j; sigset_t maskchld; sigset_t masknormal; j = jobs_getjobpid(pid); if (!j) return; /* maskchld initialization (no signal) */ sigemptyset(&maskchld); /* Adding SIGCHLD signal to maskchld */ sigaddset(&maskchld, SIGCHLD); /* Initialize masknormal with previous blocked signals, then block */ /* all previous blocked signals and all signals in maskchld signals. */ /* This call ensures that a SIGCHLD isn't caught by a sighandler */ sigprocmask(SIG_BLOCK, &maskchld, &masknormal); while (j->jb_pid == pid && j->jb_state == FG) { /* Wait for a signal which isn't blocked in masknormal set, */ /* ignoring mask previously sets by sigprocmask calls, */ /* potentially catching some previous blocked signals */ /* (i.e. blocked SIGCHLD) */ sigsuspend(&masknormal); } /* Back to previous blocked signals only */ sigprocmask(SIG_SETMASK, &masknormal, NULL); 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) { pid_t pid; int status; struct job_t *job; if (verbose) printf("sigchld_handler: entering\n"); while ((pid = waitpid(-1,&status,WUNTRACED)) > 0){ job = jobs_getjobpid(pid); if (WIFEXITED(status)){ /*if job exited normally*/ printf("[%d] (%d) Terminated \t\t %s\n",job->jb_jid,pid,job->jb_cmdline); if(!jobs_deletejob(pid)) /* delete the job */ unix_error("error while deleting job"); } else if (WIFSTOPPED(status)){/*if job received a stop signal*/ job->jb_state = ST; /* change the job state */ printf("[%d] (%d) Suspended \t\t %s\n",job->jb_jid,pid,job->jb_cmdline); } else if (WIFSIGNALED(status)){/*if job was killed*/ printf("[%d] (%d) Killed \t\t %s\n",job->jb_jid,pid,job->jb_cmdline); if(!jobs_deletejob(pid)) /* delete the job */ unix_error("error while deleting job"); } if (verbose) printf("sigchld_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; }