I am trying to write a basic shell in C. One of the things I need to do is to have both background and foreground. Control-C should kill the foreground process (if one exists) and should not kill background processes.
I wrote a signal handler for SIGINT, which kills the foreground process. The only problem is, if I have a background process, it kills too. From what I understand, when Control-C is pressed, SIGINT is queued for different processes, and if it is processed, where it stops. My shell should handle it, so it should not be passed to the background process correctly?
Here is my code:
pid_t foreground_pid; int main(int argc, char *argv[]) { signal(SIGINT, INThandler); char *buf; while(1) { fgets(buf, 128, stdin); */ error checking */ */ split buf into null terminated char* array (arg_array) and count the number of args (num_args) */ handlerCommand(buf, arg_array, num_args); zombieTerminator(); } void handleCommand(char *command, char **args, int num) { pid_t pid; if ((pid = fork()) < 0) printf("error\n"); else if (pid == 0) { // Child if (!strcmp(args[num-1], "&")) { /* redirect stdin to /dev/null */ } execvp(args[0], args); printf("error\n"); exit(127); } // parent - either wait (foreground) or continue (background) if (!strcmp(args[num-1], "&")) { printf(" [%ld] : %s\n", (long)pid, command); } else { foreground_pid = pid; if ((pid = waitpid(pid, &status, 0)) < 0) fprintf(stderr, "waitpid error\n"); } return; } /** Terminates any zombie processes that finished in the background */ void zombieTerminator(void) { int status; pid_t pid; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { if (pid != foreground_pid) { printf(" [%ld] exited with status: %d\n", (long)pid, WEXITSTATUS(status)); } } } /** Handles the control-c signal from the keyboard */ void INThandler(int sig) { if (foreground_pid) { kill(foreground_pid, SIGKILL); foreground_pid = 0; } else { printf("\n%s\? ", cwd); } fflush(stdout); }
When I start the foreground process:
sleep(100)
Then I can press contorl-c and it will leave. As it should. However, if I run the background process:
sleep(100) &
I get a new prompt, as it should, but if I click on control-c nothing will happen. But the background process is killed.
I would like to know how to stop the background process that will be killed. Any ideas?:)