From 6d9469d916bb80aa76c82097e60b725de1661d5c Mon Sep 17 00:00:00 2001 From: _ov4 Date: Tue, 1 Sep 2026 10:41:39 +0000 Subject: real foreground/background --- include/eval.h | 21 +-------------------- include/ground.h | 3 +++ include/handler.h | 11 +++++++---- src/eval.cc | 29 +++++++++++++++++++++++++++-- src/ground.cc | 8 ++++++++ src/handler.cc | 26 +++++++++++++++++++------- src/init.cc | 3 +++ 7 files changed, 68 insertions(+), 33 deletions(-) diff --git a/include/eval.h b/include/eval.h index 919d03f..5e8a1c7 100644 --- a/include/eval.h +++ b/include/eval.h @@ -1,25 +1,6 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "global.h" -#include "util/io.h" -#include "command/builtin.h" -#include "job.h" -#include "ground.h" -#include "parse.h" -#include "path.h" +#include "all.h" namespace ov4 { diff --git a/include/ground.h b/include/ground.h index d57f085..a1985eb 100644 --- a/include/ground.h +++ b/include/ground.h @@ -13,6 +13,9 @@ namespace ov4 { +extern pid_t shell_pgid; +extern int tty_fd; + void waitfg(pid_t pid); void do_bgfg(char **argv); diff --git a/include/handler.h b/include/handler.h index 225fc93..100c548 100644 --- a/include/handler.h +++ b/include/handler.h @@ -1,7 +1,5 @@ #pragma once -#include "global.h" - #include #include #include @@ -12,20 +10,25 @@ #include #include -#include "util/io.h" -#include "job.h" +#include "all.h" namespace ov4 { typedef void handler_t(int); +extern sigset_t + block_sig_TTOU, + block_job, + block_io; + void signal_init(); handler_t *Signal(int signum, handler_t *handler); void sigchld_handler(int sig); void sigint_handler(int sig); void sigtstp_handler(int sig); void sigquit_handler(int sig); + int block_all(sigset_t *prev); int block_handler(sigset_t *prev); 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + 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 + 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); } -- cgit v1.3.1-4-g156e