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