aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-08-31 07:15:15 +0000
committer_ov4 <ov4@ov4.org>2026-08-31 07:15:15 +0000
commite530251700f214d5f3738753511da2e6b4170ac2 (patch)
tree957fe82713027391e7acd62f082ffc38d25de1bf /src
parentb48f96db8e80e1866be8b92132ece590b3a9ffb9 (diff)
handler
Diffstat (limited to 'src')
-rw-r--r--src/handler.cc150
-rw-r--r--src/main.cc173
2 files changed, 151 insertions, 172 deletions
diff --git a/src/handler.cc b/src/handler.cc
new file mode 100644
index 0000000..afc1fc1
--- /dev/null
+++ b/src/handler.cc
@@ -0,0 +1,150 @@
+#include "handler.h"
+
+namespace ov4
+{
+
+extern char **environ;
+sigset_t BLOCK_HANDLER;
+
+void init()
+{
+ sigemptyset(&BLOCK_HANDLER);
+ sigaddset(&BLOCK_HANDLER, SIGINT);
+ sigaddset(&BLOCK_HANDLER, SIGTSTP);
+ sigaddset(&BLOCK_HANDLER, SIGCHLD);
+}
+
+/*
+ * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
+ * a child job terminates (becomes a zombie), or stops because it
+ * received a SIGSTOP or SIGTSTP signal. The handler reaps all
+ * available zombie children, but doesn't wait for any other
+ * currently running children to terminate.
+ */
+void sigchld_handler(int sig)
+{
+ int errno_backup = errno;
+
+ sigset_t prev;
+ block_handler(&prev);
+
+ int status, pid;
+ atomic_debug("SIGCHLD\n");
+
+ while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0)
+ {
+ if (WIFSIGNALED(status) || WIFSTOPPED(status))
+ {
+ int jid = pid2jid(pid);
+ atomic_print("Job [");
+ atomic_print(jid);
+ atomic_print("] (");
+ atomic_print(pid);
+ atomic_print(") ");
+ if (!WIFSTOPPED(status) && WTERMSIG(status) == SIGINT)
+ atomic_print("terminated");
+ else if (WIFSTOPPED(status))
+ atomic_print("stopped");
+ else
+ atomic_print("idk");
+ atomic_print(" by signal ");
+ if (WIFSTOPPED(status))
+ atomic_print(WSTOPSIG(status));
+ else
+ atomic_print(WTERMSIG(status));
+ atomic_print("\n");
+ }
+
+ if (WIFSTOPPED(status))
+ {
+ atomic_debug("suspended pid: ");
+ atomic_debug(pid);
+ atomic_debug("\n");
+ sigset_t prev_inner;
+ block_all(&prev_inner);
+ job_suspend(jobs, pid);
+ sigprocmask(SIG_SETMASK, &prev_inner, nullptr);
+ }
+ else {
+ atomic_debug("terminated pid: ");
+ atomic_debug(pid);
+ sigset_t prev_inner;
+ block_all(&prev_inner);
+ deletejob(jobs, pid);
+ sigprocmask(SIG_SETMASK, &prev_inner, nullptr);
+ }
+ }
+
+ sigprocmask(SIG_SETMASK, &prev, nullptr);
+
+ errno = errno_backup;
+ return;
+}
+
+/*
+ * sigint_handler - The kernel sends a SIGINT to the shell whenver the
+ * user types ctrl-c at the keyboard. Catch it and send it along
+ * to the foreground job.
+ */
+void sigint_handler(int sig)
+{
+ int errno_backup = errno;
+
+ sigset_t prev;
+ block_handler(&prev);
+
+ int pid = fgpid(jobs);
+ if (pid != 0)
+ {
+ kill(-pid, SIGINT);
+ }
+
+ sigprocmask(SIG_SETMASK, &prev, nullptr);
+
+ errno = errno_backup;
+ return;
+}
+
+/*
+ * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
+ * the user types ctrl-z at the keyboard. Catch it and suspend the
+ * foreground job by sending it a SIGTSTP.
+ */
+void sigtstp_handler(int sig)
+{
+ int errno_backup = errno;
+
+ sigset_t prev;
+ block_handler(&prev);
+
+ int pid = fgpid(jobs);
+ if (pid != 0)
+ {
+ kill(-pid, SIGTSTP);
+ }
+
+ sigprocmask(SIG_SETMASK, &prev, nullptr);
+
+ errno = errno_backup;
+ return;
+}
+
+int block_all(sigset_t *prev)
+{
+ sigset_t set;
+ sigfillset(&set);
+ return sigprocmask(SIG_SETMASK, &set, prev);
+}
+
+int block_handler(sigset_t *prev)
+{
+ return sigprocmask(SIG_BLOCK, &BLOCK_HANDLER, prev);
+}
+
+void sigquit_handler(int sig)
+{
+ printf("Terminating after receipt of SIGQUIT signal\n");
+ exit(1);
+}
+
+}
diff --git a/src/main.cc b/src/main.cc
index ffcf52d..ba926f8 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -19,11 +19,11 @@
#include "util.h"
#include "job.h"
#include "parse.h"
+#include "handler.h"
using namespace std;
using namespace ov4;
-/* Misc manifest constants */
/* Job states */
@@ -43,7 +43,6 @@ using namespace ov4;
*/
/* Global variables */
-extern char **environ; /* defined in libc */
char prompt[] = "tsh> "; /* command line prompt (DO NOT CHANGE) */
char sbuf[MAXLINE]; /* for composing sprintf messages */
@@ -51,7 +50,6 @@ char sbuf[MAXLINE]; /* for composing sprintf messages */
vector<string> builtin_cmd_list = {"quit", "fg", "bg", "jobs"};
-sigset_t BLOCK_HANDLER;
/* End global variables */
@@ -63,11 +61,6 @@ int builtin_cmd(char *c_str);
void do_bgfg(char **argv);
void waitfg(pid_t pid);
-void sigchld_handler(int sig);
-void sigtstp_handler(int sig);
-void sigint_handler(int sig);
-
-void sigquit_handler(int sig);
void usage(void);
@@ -79,10 +72,7 @@ handler_t *Signal(int signum, handler_t *handler);
// built-in commands
void builtin_command_quit();
-inline int block_all(sigset_t*);
-inline int block_handler(sigset_t*);
-void init();
/*
* main - The shell's main routine
@@ -342,138 +332,6 @@ void waitfg(pid_t pid)
return;
}
-/*****************
- * Signal handlers
- *****************/
-
-/*
- * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
- * a child job terminates (becomes a zombie), or stops because it
- * received a SIGSTOP or SIGTSTP signal. The handler reaps all
- * available zombie children, but doesn't wait for any other
- * currently running children to terminate.
- */
-void sigchld_handler(int sig)
-{
- int errno_backup = errno;
-
- sigset_t prev;
- block_handler(&prev);
-
- int status, pid;
- atomic_debug("SIGCHLD\n");
-
- while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0)
- {
- if (WIFSIGNALED(status) || WIFSTOPPED(status))
- {
- int jid = pid2jid(pid);
- atomic_print("Job [");
- atomic_print(jid);
- atomic_print("] (");
- atomic_print(pid);
- atomic_print(") ");
- if (!WIFSTOPPED(status) && WTERMSIG(status) == SIGINT)
- atomic_print("terminated");
- else if (WIFSTOPPED(status))
- atomic_print("stopped");
- else
- atomic_print("idk");
- atomic_print(" by signal ");
- if (WIFSTOPPED(status))
- atomic_print(WSTOPSIG(status));
- else
- atomic_print(WTERMSIG(status));
- atomic_print("\n");
- }
-
- if (WIFSTOPPED(status))
- {
- atomic_debug("suspended pid: ");
- atomic_debug(pid);
- atomic_debug("\n");
- sigset_t prev_inner;
- block_all(&prev_inner);
- job_suspend(jobs, pid);
- sigprocmask(SIG_SETMASK, &prev_inner, nullptr);
- }
- else {
- atomic_debug("terminated pid: ");
- atomic_debug(pid);
- sigset_t prev_inner;
- block_all(&prev_inner);
- deletejob(jobs, pid);
- sigprocmask(SIG_SETMASK, &prev_inner, nullptr);
- }
- }
-
- sigprocmask(SIG_SETMASK, &prev, nullptr);
-
- errno = errno_backup;
- return;
-}
-
-/*
- * sigint_handler - The kernel sends a SIGINT to the shell whenver the
- * user types ctrl-c at the keyboard. Catch it and send it along
- * to the foreground job.
- */
-void sigint_handler(int sig)
-{
- int errno_backup = errno;
-
- sigset_t prev;
- block_handler(&prev);
-
- int pid = fgpid(jobs);
- if (pid != 0)
- {
- kill(-pid, SIGINT);
- }
-
- sigprocmask(SIG_SETMASK, &prev, nullptr);
-
- errno = errno_backup;
- return;
-}
-
-/*
- * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
- * the user types ctrl-z at the keyboard. Catch it and suspend the
- * foreground job by sending it a SIGTSTP.
- */
-void sigtstp_handler(int sig)
-{
- int errno_backup = errno;
-
- sigset_t prev;
- block_handler(&prev);
-
- int pid = fgpid(jobs);
- if (pid != 0)
- {
- kill(-pid, SIGTSTP);
- }
-
- sigprocmask(SIG_SETMASK, &prev, nullptr);
-
- errno = errno_backup;
- return;
-}
-
-/*********************
- * End signal handlers
- *********************/
-
-/***********************************************
- * Helper routines that manipulate the job list
- **********************************************/
-
-/* clearjob - Clear the entries in a job struct */
-
-/******************************
- * end job list helper routines
- ******************************/
/***********************
@@ -526,41 +384,12 @@ handler_t *Signal(int signum, handler_t *handler)
return (old_action.sa_handler);
}
-/*
- * sigquit_handler - The driver program can gracefully terminate the
- * child shell by sending it a SIGQUIT signal.
- */
-void sigquit_handler(int sig)
-{
- printf("Terminating after receipt of SIGQUIT signal\n");
- exit(1);
-}
-
void builtin_command_quit()
{
exit(0);
}
-// return true if suspended, otherwise false
-inline int block_all(sigset_t *prev)
-{
- sigset_t set;
- sigfillset(&set);
- return sigprocmask(SIG_SETMASK, &set, prev);
-}
-inline int block_handler(sigset_t *prev)
-{
- return sigprocmask(SIG_BLOCK, &BLOCK_HANDLER, prev);
-}
-
-void init()
-{
- sigemptyset(&BLOCK_HANDLER);
- sigaddset(&BLOCK_HANDLER, SIGINT);
- sigaddset(&BLOCK_HANDLER, SIGTSTP);
- sigaddset(&BLOCK_HANDLER, SIGCHLD);
-}