gboolean ck_job_cancel (CkJob *job) { if (job->priv->child_pid > 0) { kill (job->priv->child_pid, SIGTERM); wait_on_job (job); return TRUE; } return FALSE; }
static void maybe_complete_job (CkJob *job) { if (job->priv->out_watch_id == 0 && job->priv->err_watch_id == 0) { int status; status = wait_on_job (job); g_debug ("Emitting completed"); g_signal_emit (job, signals [COMPLETED], 0, status); } }
/* Continue job with specifed pgid in the foreground */ void resume_foreground_job(pid_t pgid) { job_t* j = find_job(pgid); //obtain job with specified processs group ID j->bg = false; //if was in background before, it is no longer process_t* p; for (p = j->first_process; p; p = p->next) { if (p->stopped) { //ID stopped processes in specified job and resume them p->stopped = false; p->status = -1; } } tcsetpgrp(shell_terminal, j->pgid); //move the job to the terminal foreground continue_job(j); //send SIGCONT signal wait_on_job(j); //suspend dsh until job exits or stops tcsetpgrp(shell_terminal, shell_pgid); //when foregroung job exits or stops, return control to dsh }
void spawn_job(job_t *j, bool fg) { pid_t pid; process_t *p; int read_fd = -1; /* Check for input/output redirection; If present, set the IO descriptors * to the appropriate files given by the user */ /* A job can contain a pipeline; Loop through process and set up pipes accordingly */ /* For each command (process), fork to create a new process context, * set the process group, and execute the command */ /* The code below provides an example on how to set the process context for each command */ for(p = j->first_process; p; p = p->next) { //if job has multiple processes it means they are linked by pipes, so assign accordingly int fd[2] = {-1,-1}; if(p->next != NULL){ pipe(fd); } switch (pid = fork()) { case -1: /* fork failure */ perror("fork"); exit(EXIT_FAILURE); case 0: /* child */ /* establish a new process group, and put the child in * foreground if requested */ if (j->pgid < 0) {/* init sets -ve to a new process */ j->pgid = getpid(); fprintf(stdout, "%d(Launched): %s\n", j->pgid, j->commandinfo); } p->pid = 0; if (!setpgid(0,j->pgid)) if(fg) // If success and fg is set tcsetpgrp(shell_terminal, j->pgid); // assign the terminal /* Set the handling for job control signals back to the default. */ signal(SIGTTOU, SIG_DFL); if (read_fd > 0) { dup2(read_fd, STDIN_FILENO); } else if (j->mystdin == INPUT_FD) { dup2(open(j->ifile, O_RDONLY), STDIN_FILENO); } if (fd[1] > 0) { dup2(fd[1], STDOUT_FILENO); } else if (j->mystdout == OUTPUT_FD) { dup2(open(j->ofile, O_WRONLY|O_CREAT|O_TRUNC, 0664), STDOUT_FILENO); } dup2(log_fd, STDERR_FILENO); execvp(p->argv[0], p->argv); perror("now you done f****d up"); //exec only returns on failure, so exit exit(1); default: /* parent */ /* establish child process group here to avoid race * conditions. */ p->pid = pid; if (j->pgid <= 0) j->pgid = pid; setpgid(pid, j->pgid); if (read_fd > 0) close(read_fd); if (fd[1] > 0) close(fd[1]); read_fd = fd[0]; } } if (fg) { wait_on_job(j); } tcsetpgrp(shell_terminal, shell_pgid); }