Added signal handlers and template for do_bgfg

main
TuDatTr 2021-02-09 20:18:54 +01:00
parent 5f0ea2601b
commit dd3bdf6667
1 changed files with 109 additions and 25 deletions

128
tsh.c
View File

@ -169,22 +169,30 @@ void eval(char *cmdline)
int bg = parseline(cmdline, argv); // See whether cmd is back or foreground and parse cmdline int bg = parseline(cmdline, argv); // See whether cmd is back or foreground and parse cmdline
struct job_t *job; 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 (argv[0] != NULL) { // Do nothing, but don't crash on empty line
if (!builtin_cmd(argv)) { // if cmdline is not a builtin 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 if (pid == 0) { // Child Process
setpgid(getpid(), 0);
sigprocmask(SIG_SETMASK, &prev_mask, NULL);
if (execve(argv[0], argv, environ) != 0) { // if exec failed if (execve(argv[0], argv, environ) != 0) { // if exec failed
printf("%s Command not found.\n", argv[0]); printf("%s Command not found.\n", argv[0]);
exit(1); exit(1);
} }
} else { // Parent Process } else { // Parent Process
wait(NULL);
addjob(jobs, pid, bg ? BG : FG, cmdline); addjob(jobs, pid, bg ? BG : FG, cmdline);
sigprocmask(SIG_SETMASK, &prev_mask, NULL);
if (bg) { if (bg) {
job = getjobpid(jobs, pid); job = getjobpid(jobs, pid);
printf("[%d] (%d) %s", job->jid, pid, cmdline); printf("[%d] (%d) %s", job->jid, pid, cmdline);
} else { } else {
// waitfg(pid); waitfg(pid);
} }
} }
} }
@ -272,26 +280,55 @@ int builtin_cmd(char **argv)
*/ */
void do_bgfg(char **argv) void do_bgfg(char **argv)
{ {
// struct job_t* job; struct job_t *job_1;
// if (argv[1][0] == '%') { // if job is chosing via jid char *j = argv[1];
// printf("jid: %s", &argv[1][1]); int JID;
// job = getjobjid(jobs, atoi(&argv[1][1])); pid_t PID;
// } else { // if job is chosing via pid
// printf("pid: %s", argv[1]);
// job = getjobpid(jobs, atoi(argv[1]));
// }
// if (job != NULL) { if(j==NULL){ // if no arg
// if (!strcmp(argv[0], "bg")) { // Do this if bg fprintf(stderr,"%s command requires PID or %%jobid argument\n",argv[0]);
// if (job->state == ST) { return;
// job->state = BG; }
// }
// } else { // Do this if fg
// if (job->state == ST || job->state == BG) { else if(j[0] == '%'){ // case1 job id , ex) %5
// job->state = FG; 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; return;
} }
@ -319,9 +356,35 @@ void waitfg(pid_t pid)
*/ */
void sigchld_handler(int sig) void sigchld_handler(int sig)
{ {
deletejob(jobs, fgpid(jobs)); 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; 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;
}
/* /*
* sigint_handler - The kernel sends a SIGINT to the shell whenver the * sigint_handler - The kernel sends a SIGINT to the shell whenver the
@ -330,6 +393,15 @@ void sigchld_handler(int sig)
*/ */
void sigint_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; return;
} }
@ -340,6 +412,18 @@ void sigint_handler(int sig)
*/ */
void sigtstp_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; return;
} }