diff options
| author | _ov4 <ov4@ov4.org> | 2026-09-01 10:41:39 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-09-01 10:41:39 +0000 |
| commit | 6d9469d916bb80aa76c82097e60b725de1661d5c (patch) | |
| tree | 1c8d4f046c46d387914bc73fd912dd6eac950a0d /src | |
| parent | 94c449ca42bd29de2c2fd137945550fe110fcd17 (diff) | |
real foreground/background
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.cc | 29 | ||||
| -rw-r--r-- | src/ground.cc | 8 | ||||
| -rw-r--r-- | src/handler.cc | 26 | ||||
| -rw-r--r-- | src/init.cc | 3 |
4 files changed, 57 insertions, 9 deletions
diff --git a/src/eval.cc b/src/eval.cc index 8785dd6..09d1196 100644 --- a/src/eval.cc +++ b/src/eval.cc @@ -1,5 +1,18 @@ #include "eval.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <iostream> +#include <vector> +#include <string> + using namespace std; namespace ov4 @@ -29,17 +42,29 @@ void eval(char *cmdline) if (argv[0] == nullptr) return; if (exe_bultin_command(argv)) return; + // block_io signals can stop shell + // when child is at foreground, parent shell is at background + sigprocmask(SIG_BLOCK, &block_io, nullptr); sigset_t prev; block_all(&prev); - pid_t pid = fork(); string cmd = find_cmd(argv[0]); const char* cmd_c = cmd.c_str(); + + shell_pgid = getpgid(0); + pid_t pid = fork(); + if (pid == 0) // child { - sigprocmask(SIG_SETMASK, &prev, nullptr); setpgid(0, 0); + if (!ground) // foreground + tcsetpgrp(tty_fd, getpgrp()); + + // program inside execve may use SIGTTIN/SIGTTOU so just restore in child + sigprocmask(SIG_UNBLOCK, &block_io, nullptr); + + sigprocmask(SIG_SETMASK, &prev, nullptr); execve(cmd_c, argv, environ); diff --git a/src/ground.cc b/src/ground.cc index 54a333f..265a22d 100644 --- a/src/ground.cc +++ b/src/ground.cc @@ -5,6 +5,9 @@ using namespace std; namespace ov4 { +pid_t shell_pgid; +int tty_fd; + /* * waitfg - Block until process pid is no longer the foreground process */ @@ -17,6 +20,11 @@ void waitfg(pid_t pid) LOG << "waiting for pid "<< fgpid(jobs) << endl; while (fgpid(jobs) != 0) sigsuspend(&prev_with_sigchld_unblocked); + + // set shell to foreground again + tcsetpgrp(tty_fd, shell_pgid); + sigprocmask(SIG_BLOCK, &block_io, nullptr); + LOG << "finished fg " << endl; return; } diff --git a/src/handler.cc b/src/handler.cc index b6399c2..4fa3e2f 100644 --- a/src/handler.cc +++ b/src/handler.cc @@ -4,17 +4,29 @@ namespace ov4 { extern char **environ; -sigset_t BLOCK_HANDLER; + +sigset_t + block_sig_TTOU, + block_job, + block_io; void signal_init() { /* Install the signal handlers */ - sigemptyset(&BLOCK_HANDLER); - sigaddset(&BLOCK_HANDLER, SIGINT); - sigaddset(&BLOCK_HANDLER, SIGTSTP); - sigaddset(&BLOCK_HANDLER, SIGCHLD); - + sigemptyset(&block_job); + sigemptyset(&block_sig_TTOU); + sigemptyset(&block_io); + + sigaddset(&block_job, SIGINT); + sigaddset(&block_job, SIGTSTP); + sigaddset(&block_job, SIGCHLD); + + sigaddset(&block_sig_TTOU, SIGTTOU); + + sigaddset(&block_io, SIGTTOU); + sigaddset(&block_io, SIGTTIN); + Signal(SIGINT, sigint_handler); /* ctrl-c */ Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */ Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */ @@ -161,7 +173,7 @@ int block_all(sigset_t *prev) int block_handler(sigset_t *prev) { - return sigprocmask(SIG_BLOCK, &BLOCK_HANDLER, prev); + return sigprocmask(SIG_BLOCK, &block_job, prev); } void sigquit_handler(int sig) diff --git a/src/init.cc b/src/init.cc index 5f6e325..a38aec4 100644 --- a/src/init.cc +++ b/src/init.cc @@ -1,5 +1,7 @@ #include "init.h" +#include <fcntl.h> + using namespace std; namespace ov4 @@ -15,6 +17,7 @@ Published under GNU AFFERO GENERAL PUBLIC LICENSE (AGPL) Version 3." << endl; signal_init(); + tty_fd = open("/dev/tty", O_RDWR); } |
