/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { if(fgpid(jobs)!=0) if(kill(-fgpid(jobs),SIGTSTP)<0) unix_error("kill function error"); return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { struct job_t *job=getjobpid(jobs,fgpid(jobs)); if(job!=NULL) kill(-fgpid(jobs),SIGTSTP); return; }
/* ts * 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) { if(fgpid(jobs)!=0) if(kill(-fgpid(jobs),SIGINT))/*sending sigint to entire process group */ unix_error("kill function error"); return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { if(fgpid(jobs) == 0) return; kill(-fgpid(jobs), SIGTSTP); }
/* * 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) { if(fgpid(jobs) == 0) return; kill(-fgpid(jobs), SIGINT); }
/* * handle the parent process */ void handle_parent_process(struct cmdline_tokens* toks, int bg, pid_t pid, sigset_t* oldset, char* cmdline) { sigset_t emptyset; if(!addjob(job_list, pid, bg?BG:FG, cmdline)){ unix_error("error in addjob"); } struct job_t* job = getjobpid(job_list, pid); if(!bg){ if(sigprocmask(SIG_SETMASK, oldset, NULL)){ unix_error("error in parent process's sigprocmask"); } if(sigemptyset(&emptyset)){ unix_error("set is not empty"); } while(fgpid(job_list) && job -> state == FG) sigsuspend(&emptyset); } else { printf("[%d] (%d) %s\n", job->jid, job->pid, job->cmdline); if(sigprocmask(SIG_SETMASK, oldset, NULL)){ unix_error("error in parent process's sigprocmask"); } } }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { //wait until foreground job terminates while(pid == fgpid(jobs)) sleep(0); 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, but doesn't wait for any other * currently running children to terminate. */ void sigchld_handler(int sig) { int info; pid_t pid; while ((pid = waitpid(fgpid(jobs), &info, WNOHANG|WUNTRACED)) > 0) { if (WIFSTOPPED(info)) // Job exited by external process { sigtstp_handler(20); } else if (WIFSIGNALED(info)) // job terminated due to faulty signal { sigint_handler(-2); } else if (WIFEXITED(info)) // Job exits normalls { deletejob(jobs, pid); } } if ((errno != ECHILD && pid == -1) || pid > 0) // After the loop pid is -1, or pid is 0 { unix_error("WAITPID ERROR 404"); } return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { while(pid == fgpid(jobs)) // wait for the process in the foreground to finish { sleep(0); } }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) // ~ 15 lines { //char buf[40]; //char buf2[7]; //char buf3[7]; //char buf4[7]; //sprintf(buf, "here\n"); //puts(buf); pid_t pidfg = fgpid(jobs); //sprintf(buf2, "here2\n"); //puts(buf2); struct job_t* fgjob = getjobpid(jobs, pidfg); //sprintf(buf3, "here3\n"); //puts(buf3); if(pidfg>0 && fgjob>0){ fgjob->state = ST; //sprintf(buf, "Job [%d] (%d) stopped by signal %d", fgjob->jid, pidfg, sig); //puts(buf); kill(-pidfg, SIGTSTP); } //sprintf(buf4, "here4\n"); //puts(buf4); return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { //using busy loop sleep 0 and wait till fgpid is 0 or a different process while(pid == fgpid(jobs)) { sleep(0); } }
/* * 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 fpid; if ((fpid = fgpid(jobs)) != 0) kill(-fpid, SIGINT); return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { pid_t pid = fgpid(jobs); if(pid != 0) kill(-pid, sig); 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, but doesn't wait for any other * currently running children to terminate. */ void sigchld_handler(int sig) { int status; pid_t pid; while ((pid = waitpid(fgpid(jobs), &status, WNOHANG|WUNTRACED)) > 0) { if (WIFSTOPPED(status)){ //change state if stopped getjobpid(jobs, pid)->state = ST; int jid = pid2jid(pid); printf("Job [%d] (%d) Stopped by signal %d\n", jid, pid, WSTOPSIG(status)); } else if (WIFSIGNALED(status)){ //delete is signaled int jid = pid2jid(pid); printf("Job [%d] (%d) terminated by signal %d\n", jid, pid, WTERMSIG(status)); deletejob(jobs, pid); } else if (WIFEXITED(status)){ //exited deletejob(jobs, pid); } } return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { pid_t pid = fgpid(job_list); kill(-pid, SIGTSTP); 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 = fgpid(job_list); kill(-pid, SIGINT); return; }
/* *fg_job - restart a stopped job and put it to foreground */ void fg_job(struct cmdline_tokens* tok) { pid_t pid; struct job_t* job; int jid; sigset_t mask; sigemptyset(&mask); int argc=tok->argc; if(tok->argv[argc-1][0]=='%') //recognizing the process by job ID { jid=atoi(tok->argv[argc-1]+1); job=getjobjid(job_list,jid); pid=job->pid; }else{ //recognizing the process by process ID pid=atoi(tok->argv[argc-1]); job=getjobpid(job_list,pid); } job->state=FG; kill(pid,SIGCONT); /* since the job state is changed to foreground, the parent process shall wait*/ while(fgpid(job_list)) { sigsuspend(&mask); } }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { while(pid==fgpid(jobs)){ sleep(1); } return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) // ~ 20 { // luke driving // brittany driving if(DEBUG == 1) printf("waitfg entered\n"); sigset_t mask, prev_mask; // block child sigset_t empty_mask; sigemptyset(&mask); sigemptyset(&prev_mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGSTOP); sigaddset(&mask, SIGINT); /* sigfillset(&all_but_child); sigdelset(&all_but_child,SIGCHLD);*/ sigemptyset(&empty_mask); sigprocmask(SIG_BLOCK, &mask, &prev_mask); while(pid==fgpid(jobs)){ if(DEBUG == 1) { printf("waitfg while: pid: %d \n",pid); } //suspend process sigsuspend(&empty_mask);// suspend empty set of signals? } if(DEBUG == 1) printf("waitfg while loop has finished\n"); // reenable sigprocmask(SIG_SETMASK, &prev_mask, NULL); //deletejob(jobs, pid); return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { while (1) { if (pid == fgpid(jobs)) sleep(1); else 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) { pid_t pid; int status; while (( pid = waitpid(-1,&status, WNOHANG | WUNTRACED)) > 0) // reaping whatever is ready no hang { if(WIFSTOPPED(status) ) { if((getjobpid(jobs,pid)->state) != ST) { printf("Job [%d] (%d) Stopped by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGTSTP); } getjobpid(jobs, pid)->state = ST; return; } else if(WIFSIGNALED(status) && fgpid(jobs) ==pid ) { if(pid != 0){ printf("Job [%d] (%d) Terminated by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGINT); } kill(-pid,SIGINT); } deletejob(jobs, pid); } 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, SIGTSTP, SIGTTIN or SIGTTOU 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) { pid_t pid; int status; while((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0){ if(pid == fgpid(job_list)){ if(tcgetpgrp(STDIN_FILENO) != shell_pid) { tcsetpgrp(STDIN_FILENO, shell_pid); } } if(WIFEXITED(status)){ deletejob(job_list, pid); } else if(WIFSIGNALED(status)){ printf("Job [%d] (%d) terminated by signal %d\n", pid2jid(pid), pid, WTERMSIG(status)); deletejob(job_list, pid); } else if (WIFSTOPPED(status)) { printf("Job [%d] (%d) stopped by signal %d\n", pid2jid(pid), pid, WSTOPSIG(status)); getjobpid(job_list, pid)->state = ST; } } return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid, int output_fd) { // A busy loop.Check if the current pid is a foreground pid. S.T. If the current foreground pid is suspended. while (fgpid(jobs) == pid) { sleep(1); } return; }
/* wait_fg_job - Use Sigsuspend to save some time :-) */ void wait_fg_job(int state) { sigset_t emptymask; Sigemptyset(&emptymask); while ((fgpid(job_list) != 0) && (FG == state)) { Sigsuspend(&emptymask); } }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { pid_t fg_pid = fgpid(jobs); if(fg_pid == 0) return ; #ifdef DEBUG_SIGTSTP printf("--------------SIGTSTP-----------------\n"); printf("fg_pid = %d\n",fg_pid); listjobs(jobs); #endif struct job_t* fg_job = getjobpid(jobs, fg_pid); printf("Job [%d] (%d) stopped by signal %d\n", fg_job->jid, fg_job->pid, sig); fg_job->state = ST; kill(-fg_pid, SIGTSTP); #ifdef DEBUG_SIGTSTP printf("after kill"); listjobs(jobs); printf("--------------------------------------\n"); #endif return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { pid_t pid = fgpid(jobs); if(pid > 1) { kill(-pid, SIGTSTP); } 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 = fgpid(jobs); if(pid > 1) { kill(-pid, SIGINT); } return; }
/* * waitfg - Block until process pid is no longer the foreground process */ void waitfg(pid_t pid) { // Busy Loop while(fgpid(jobs) == pid) { sleep(100); } 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 = fgpid(jobs); if (pid == 0) return; kill(-pid, SIGINT); return; }
/* * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever * the user types ctrl-z at the keyboard. Catch it and suspend the * foreground job by sending it a SIGTSTP. */ void sigtstp_handler(int sig) { pid_t fpid; if ((fpid = fgpid(jobs)) != 0) kill(-fpid, SIGTSTP); return; return; }