diff options
| author | _ov4 <ov4@ov4.org> | 2026-08-31 07:22:10 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-08-31 07:22:10 +0000 |
| commit | e00a6103ab63d177efeab47b08338426d21f538f (patch) | |
| tree | 339c82b704a77618f718928a5481f5353e3bab4c /src/ground.cc | |
| parent | 37718fa2b27b12e1ffee4541205268bb51627d42 (diff) | |
ground
Diffstat (limited to 'src/ground.cc')
| -rw-r--r-- | src/ground.cc | 103 |
1 files changed, 103 insertions, 0 deletions
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; +} + +} |
