From e00a6103ab63d177efeab47b08338426d21f538f Mon Sep 17 00:00:00 2001 From: _ov4 Date: Mon, 31 Aug 2026 07:22:10 +0000 Subject: ground --- src/ground.cc | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/ground.cc (limited to 'src/ground.cc') diff --git a/src/ground.cc b/src/ground.cc new file mode 100644 index 0000000..2047ebf --- /dev/null +++ b/src/ground.cc @@ -0,0 +1,103 @@ +#include "ground.h" + +namespace ov4 +{ + +using namespace std; + +/* + * waitfg - Block until process pid is no longer the foreground process + */ +void waitfg(pid_t pid) +{ + sigset_t prev_with_sigchld_unblocked; + // get current blocked signals + sigprocmask(0, nullptr, &prev_with_sigchld_unblocked); + sigdelset(&prev_with_sigchld_unblocked, SIGCHLD); + LOG << "waiting for pid "<< fgpid(jobs) << endl; + while (fgpid(jobs) != 0) + sigsuspend(&prev_with_sigchld_unblocked); + LOG << "finished fg " << endl; + return; +} + +/* + * do_bgfg - Execute the builtin bg and fg commands + */ +void do_bgfg(char **argv) +{ + if ((strcmp(argv[0], "fg") == 0) || (strcmp(argv[0], "bg") == 0)) + { + int x; + job_t *j = nullptr; + sigset_t prev; + if (argv[1] == nullptr) + { + cerr << ((strcmp(argv[0], "fg") == 0) ? "fg" : "bg") << " command requires PID or %jobid argument" << endl; + return; + } + if (argv[1][0] == '%') // jid provided + { + if (!isnum(&argv[1][1])) + { + cerr << ((strcmp(argv[0], "fg") == 0) ? "fg" : "bg") << ": argument must be a PID or %jobid" << endl; + return; + } + x = atoi(&argv[1][1]); // eat % + j = getjobjid(jobs, x); + if (j == nullptr) + { + cerr << argv[1] << ": No such job" << endl; + return; + } + } else { // pid + if (!isnum(&argv[1][0])) + { + cerr << ((strcmp(argv[0], "fg") == 0) ? "fg" : "bg") << ": argument must be a PID or %jobid" << endl; + return; + } + x = atoi(&argv[1][0]); + j = getjobpid(jobs, x); + if (j == nullptr) + { + cerr << "(" << argv[1] << "): No such process" << endl; + return; + } + } + + + block_all(&prev); + if (strcmp(argv[0], "fg") == 0) // fg + { + LOG << "fg" << endl; + j->state = FG; + + sigset_t prev_with_sigchld_blocked = prev; + sigaddset(&prev_with_sigchld_blocked, SIGCHLD); + sigprocmask(SIG_SETMASK, &prev_with_sigchld_blocked, NULL); + if (kill(-(j->pid), SIGCONT) < 0) + { + cerr << "Cannot continue process " << j->pid; + sigprocmask(SIG_SETMASK, &prev, NULL); + return; + } + + waitfg(j->pid); + + sigprocmask(SIG_SETMASK, &prev, NULL); + } else // bg + { + LOG << "bg" << endl; + j->state = BG; + kill(-(j->pid), SIGCONT); + sigprocmask(SIG_SETMASK, &prev, NULL); + // cmdline has nerd '\n' at the end + // so just flush + cout << "[" << j->jid << "] (" << j->pid << ") " << j->cmdline << flush; + } + } + else + cerr << "not fg/bg" << endl; +} + +} -- cgit v1.3.1-4-g156e