diff --git a/tsh.c b/tsh.c index 8166269..157cfb4 100644 --- a/tsh.c +++ b/tsh.c @@ -168,23 +168,31 @@ void eval(char *cmdline) char *argv[MAXARGS]; // Save flags for process int bg = parseline(cmdline, argv); // See whether cmd is back or foreground and parse cmdline struct job_t *job; + + sigset_t mask, prev_mask; + sigfillset(&mask); + sigprocmask(SIG_BLOCK, &mask, &prev_mask); if (argv[0] != NULL) { // Do nothing, but don't crash on empty line if (!builtin_cmd(argv)) { // if cmdline is not a builtin - int pid = fork(); // fork process + int pid = fork(); // fork process if (pid == 0) { // Child Process + + setpgid(getpid(), 0); + sigprocmask(SIG_SETMASK, &prev_mask, NULL); + if (execve(argv[0], argv, environ) != 0) { // if exec failed printf("%s Command not found.\n", argv[0]); exit(1); } } else { // Parent Process - wait(NULL); addjob(jobs, pid, bg ? BG : FG, cmdline); + sigprocmask(SIG_SETMASK, &prev_mask, NULL); if (bg) { job = getjobpid(jobs, pid); printf("[%d] (%d) %s", job->jid, pid, cmdline); } else { - // waitfg(pid); + waitfg(pid); } } } @@ -272,26 +280,55 @@ int builtin_cmd(char **argv) */ void do_bgfg(char **argv) { - // struct job_t* job; - // if (argv[1][0] == '%') { // if job is chosing via jid - // printf("jid: %s", &argv[1][1]); - // job = getjobjid(jobs, atoi(&argv[1][1])); - // } else { // if job is chosing via pid - // printf("pid: %s", argv[1]); - // job = getjobpid(jobs, atoi(argv[1])); - // } - - // if (job != NULL) { - // if (!strcmp(argv[0], "bg")) { // Do this if bg - // if (job->state == ST) { - // job->state = BG; - // } - // } else { // Do this if fg - // if (job->state == ST || job->state == BG) { - // job->state = FG; - // } - // } - // } + struct job_t *job_1; + char *j = argv[1]; + int JID; + pid_t PID; + + if(j==NULL){ // if no arg + fprintf(stderr,"%s command requires PID or %%jobid argument\n",argv[0]); + return; + } + + + else if(j[0] == '%'){ // case1 job id , ex) %5 + JID = atoi(&j[1]); + if(!JID){ + printf("%s: argument must be a PID or %%jobid\n", argv[0]); + return; + } + job_1 = getjobjid(jobs, JID); + if(job_1 == NULL){ // if not existing job + printf("%s no such job\n", argv[1]); + return; + } + } + else{ // case2 process id, ex) 5 + PID = atoi(j); + if(!PID){ + printf("%s: argument must be a PID or %%jobid\n", argv[0]); + return; + } + job_1 = getjobpid(jobs, PID); + if(job_1 == NULL){ // if non existant proc + printf("(%s) no such process\n", argv[1]); + return; + } + } + + PID = job_1->pid; + + if(!strcmp("bg", argv[0])){ //background job + job_1->state = BG; + printf("[%d] (%d) %s", job_1->jid, job_1->pid, job_1->cmdline); + kill(-PID, SIGCONT); + + } + else{ //foreground job + job_1->state = FG; + kill(-PID, SIGCONT); + waitfg(job_1->pid); + } return; } @@ -319,8 +356,34 @@ void waitfg(pid_t pid) */ void sigchld_handler(int sig) { - deletejob(jobs, fgpid(jobs)); - return; + int tmp_errno = errno; + sigset_t mask, prev_mask; + int child_status; + pid_t wpid; + sigfillset(&mask); + + while ((wpid = waitpid(-1, &child_status, WNOHANG | WUNTRACED)) > 1) { + if (wpid < 0) { + unix_error("waitpid error"); + return; + } + sigprocmask(SIG_BLOCK, &mask, &prev_mask); + struct job_t *job = getjobpid(jobs, wpid); + + if (WIFSTOPPED(child_status)) { + printf("Job [%d] (%d) stopped by signal %d\n", job->jid, jobs->pid, SIGTSTP); + job->state = ST; + } else if (WIFEXITED(child_status)) { + deletejob(jobs, wpid); + } else if (WIFSIGNALED(child_status)) { + printf("Job [%d] (%d) terminated by signal %d\n", job->jid, jobs->pid, SIGINT); + deletejob(jobs, wpid); + } + + sigprocmask(SIG_SETMASK, &prev_mask, NULL); + } + + errno = tmp_errno; } /* @@ -330,6 +393,15 @@ void sigchld_handler(int sig) */ void sigint_handler(int sig) { + int tmp_errno = errno; + pid_t fg_pid = fgpid(jobs); + + if (fg_pid) { + kill(-fg_pid, SIGINT); + } + + errno = tmp_errno; + return; } @@ -340,6 +412,18 @@ void sigint_handler(int sig) */ void sigtstp_handler(int sig) { + int tmp_errno = errno; + sigset_t mask, prev_mask; + + sigfillset(&mask); + sigprocmask(SIG_BLOCK, &mask, &prev_mask); + + pid_t fg_pid = fgpid(jobs); + + kill(-fg_pid, SIGTSTP); + + sigprocmask(SIG_SETMASK, &prev_mask, NULL); + errno = tmp_errno; return; }