loksh-noxz

[fork] a Linux port of OpenBSD's ksh
git clone git://git.noxz.tech/loksh-noxz
Log | Files | Refs | Submodules | README

commit 116a1847123df86241856d5e744c0afeb35a2f78
parent a99bdd3932b8f9f1e19ada06d6936b7d04125028
Author: Chris Noxz <chris@noxz.tech>
Date:   Tue,  9 Mar 2021 19:19:54 +0100

Restore suspend

Diffstat:
Mc_sh.c | 21+++++++++++++++++++++
Mjobs.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msh.h | 1+
3 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/c_sh.c b/c_sh.c @@ -845,6 +845,26 @@ c_exec(char **wp) return 0; } +static int +c_suspend(char **wp) +{ + if (wp[1] != NULL) { + bi_errorf("too many arguments"); + return 1; + } + if (Flag(FLOGIN)) { + /* Can't suspend an orphaned process group. */ + pid_t parent = getppid(); + if (getpgid(parent) == getpgid(0) || + getsid(parent) != getsid(0)) { + bi_errorf("can't suspend a login shell"); + return 1; + } + } + j_suspend(); + return 0; +} + /* dummy function, special case in comexec() */ int c_builtin(char **wp) @@ -883,5 +903,6 @@ const struct builtin shbuiltins [] = { {"ulimit", c_ulimit}, {"+umask", c_umask}, {"*=unset", c_unset}, + {"suspend", c_suspend}, {NULL, NULL} }; diff --git a/jobs.c b/jobs.c @@ -193,6 +193,57 @@ j_init(int mflagset) tty_init(true); } +/* suspend the shell */ +void +j_suspend(void) +{ + struct sigaction sa, osa; + + /* Restore tty and pgrp. */ + if (ttypgrp_ok) { + tcsetattr(tty_fd, TCSADRAIN, &tty_state); + if (restore_ttypgrp >= 0) { + if (tcsetpgrp(tty_fd, restore_ttypgrp) == -1) { + warningf(false, "%s: tcsetpgrp() failed: %s", + __func__, strerror(errno)); + } else { + if (setpgid(0, restore_ttypgrp) == -1) { + warningf(false, + "%s: setpgid() failed: %s", + __func__, strerror(errno)); + } + } + } + } + + /* Suspend the shell. */ + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(SIGTSTP, &sa, &osa); + kill(0, SIGTSTP); + + /* Back from suspend, reset signals, pgrp and tty. */ + sigaction(SIGTSTP, &osa, NULL); + if (ttypgrp_ok) { + if (restore_ttypgrp >= 0) { + if (setpgid(0, kshpid) == -1) { + warningf(false, "%s: setpgid() failed: %s", + __func__, strerror(errno)); + ttypgrp_ok = 0; + } else { + if (tcsetpgrp(tty_fd, kshpid) == -1) { + warningf(false, + "%s: tcsetpgrp() failed: %s", + __func__, strerror(errno)); + ttypgrp_ok = 0; + } + } + } + tty_init(true); + } +} + /* job cleanup before shell exit */ void j_exit(void) diff --git a/sh.h b/sh.h @@ -501,6 +501,7 @@ void coproc_cleanup(int); struct temp *maketemp(Area *, Temp_type, struct temp **); /* jobs.c */ void j_init(int); +void j_suspend(void); void j_exit(void); void j_change(void); int exchild(struct op *, int, volatile int *, int);