/* Continue job with specifed pgid in the background. Control stays with terminal*/ void resume_background_job(pid_t pgid) { job_t* j = find_job(pgid); //ID the stopped job j->bg = true; //If it was in foreground, now in background process_t* p; for (p = j->first_process; p; p = p->next) { if (p->stopped) { //resume all stopped processes in its process group p->stopped = false; p->status = -1; } } continue_job(j); //sends SIGCONT signal to job }
void builtin_bg(struct job* job) { process* proc = &job->procs[0]; struct job* target = find_stopped(proc->argc, proc->argv); /* Continue job */ if (!target || !continue_job(target)) { print_error("SIGCONT"); } else { /* set as background and notify resume */ target->background = true; printf("[%d] continued\n", target->pgid); } }
void builtin_fg(struct job* job) { process* proc = &job->procs[0]; struct job* target = find_stopped(proc->argc, proc->argv); /* Continue job */ if (!target || !continue_job(target)) { print_error("SIGCONT"); } else { /* set as foreground and wait */ target->background = false; wait_foreground_job(target); } }
/* 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 }
/* * builtin_cmd - If the user has typed a built-in command then execute * it immediately. */ bool builtin_cmd(job_t *last_job, int argc, char **argv) { /* check whether the cmd is a built in command */ if (!strcmp("quit", argv[0])) { /* Your code here */ exit(EXIT_SUCCESS); } else if (!strcmp("jobs", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; job_t* deletedJob = NULL; while(currentJob != NULL) { // print active jobs and then change notified to 0 //if((currentJob->first_process)->completed == true && currentJob->notified == false) { //need to check if every process has completed for a job to be complete, not just the first process if (job_is_completed(currentJob) == true) { printf("%d (Completed): %s\n", currentJob->pgid, currentJob->commandinfo); deletedJob = currentJob; //currentJob->notified = true; } //otherwise it is stopped else if (job_is_stopped(currentJob) == true) { printf("%d (Stopped): %s\n", currentJob->pgid, currentJob->commandinfo); } else { printf("%d (Running): %s\n", currentJob->pgid, currentJob->commandinfo); } currentJob = currentJob->next; // delete job after it is completed, don't need to save notified if (deletedJob != NULL) { if (deletedJob == active_jobs_head) { active_jobs_head = deletedJob->next; free_job(deletedJob); //TBD warning about this? } else { delete_job(deletedJob, active_jobs_head); } deletedJob = NULL; } } return true; } else if (!strcmp("cd", argv[0])) { int chdir_return = chdir(argv[1]); if(chdir_return == -1) { printf("cd: %s: No such file or directory\n", argv[1]); } return true; } else if (!strcmp("bg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { // Need to eventually iterate through all processes? if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } else if (!strcmp("fg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } /* not a builtin command */ return false; }