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
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
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]));
// }
struct job_t *job_1;
char *j = argv[1];
int JID;
pid_t PID;
// 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;
// }
// }
// }
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,9 +356,35 @@ void waitfg(pid_t pid)
*/
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;
}
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
@ -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;
}