Added signal handlers and template for do_bgfg
parent
5f0ea2601b
commit
dd3bdf6667
132
tsh.c
132
tsh.c
|
@ -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
|
||||
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,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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue