Last active
October 19, 2019 00:07
-
-
Save kuriringohankamehameha/11b3f0acbf932c6705183214034d9c37 to your computer and use it in GitHub Desktop.
Shell Shell Handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<stdio.h> | |
#include<stdlib.h> | |
#include<pthread.h> | |
#include<string.h> | |
#include<unistd.h> | |
#include<sys/types.h> | |
#include<signal.h> | |
static void shellHandler(int signo, siginfo_t* info, void* context) | |
{ | |
// Passes it into the child first | |
if (signo == SIGINT || signo == SIGKILL || signo == SIGQUIT) | |
{ | |
printf("Ahoy\n"); | |
kill(childPID, signo); | |
kill(parentPID, SIGCHLD); | |
} | |
else if (signo == SIGTSTP) | |
{ | |
// Suspend Signal | |
printf("Suspend Signal\n"); | |
int fg_pid = findFG_STATUS(jobSet); | |
if (fg_pid != -1) | |
{ | |
jobSet = changeStatus(jobSet, fg_pid, STATUS_SUSPENDED); | |
kill(fg_pid, SIGSTOP); | |
} | |
} | |
else if (signo == SIGCHLD) | |
{ | |
printf("Child Handler\n"); | |
if (!isSuspended) | |
{ | |
pid_t child = info->si_pid; | |
jobSet = removeJob(jobSet, child); | |
signal(signo, SIG_DFL); | |
} | |
else{ | |
printf("Case 2\n"); | |
isSuspended = false; | |
kill(info->si_pid, SIGTSTP); | |
} | |
} | |
else | |
{ | |
signal(signo, SIG_IGN); | |
printf("\n"); | |
printPrompt(); | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
int signalArray[] = {SIGINT, SIGKILL, SIGTSTP, -1}; | |
sigset_t set = createSignalSet(signalArray); | |
struct sigaction sa; | |
sa.sa_handler = shellHandler; | |
sa.sa_flags = SA_SIGINFO; | |
// Parent must be blocked from these signals | |
sigprocmask(SIG_BLOCK, &set, NULL); | |
int pid = fork(); | |
if (pid == 0) | |
{ | |
// Child | |
if (isBackground == true) | |
{ | |
printf("[bg]\t%d\n",getpid()); | |
setpgid(0, 0); | |
} | |
else | |
{ | |
// Add to foreground process group | |
pid_t cgrp = getpgrp(); | |
tcsetpgrp(STDIN_FILENO, cgrp); | |
setpgid(getpid(), getppid()); | |
} | |
//The child must receive the previously blocked signals | |
sigprocmask(SIG\_UNBLOCK, &set, NULL); | |
sigaction(SIGINT, &sa, NULL); | |
sigaction(SIGTSTP, &sa, NULL); | |
sigaction(SIGSTOP, &sa, NULL); | |
childPID = getpid(); | |
} | |
else | |
{ | |
// Parent | |
parentPID = getpid(); | |
setpgid(0, 0); | |
if (isBackground) | |
{ | |
Node node; | |
[node.pid](https://node.pid) = pid; | |
node.status = STATUS\_BACKGROUND; | |
char* name = (char*) malloc (sizeof(char)); | |
strcpy(name, argVector[0]); | |
jobSet = insert(jobSet, node); | |
setpgrp(); | |
} | |
else | |
{ | |
int status; | |
if((waitpid(pid, &status, WUNTRACED | WNOHANG) >= 0)){ | |
printf("PID = %d\\t", pid); | |
if (WIFEXITED(status)){ | |
printf("Normal Exit\\n"); | |
} | |
else if (WIFSIGNALED(status)){ | |
printf("Job terminated by signal %d\\n", WTERMSIG(status)); | |
} | |
else if (WIFSTOPPED(status)){ | |
printf("Job stopped by signal %d\\n", WTERMSIG(status)); | |
isSuspended = true; | |
} | |
sigaction(SIGCHLD, &sa, NULL); | |
} | |
waitpid(pid, NULL, 0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment