]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
script: support sig{stop/cont}
authorKarel Zak <kzak@redhat.com>
Fri, 8 Sep 2017 07:48:29 +0000 (09:48 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 8 Sep 2017 07:48:29 +0000 (09:48 +0200)
* call wait() only when child exited
* suspend all session (including script master process) when child get
  SIGSTOP and send SIGCONT to child when master process resume

This allows to suspend all session and later use "fg" shell command to
resume.

$ ps af
14722 pts/1    Ss     0:00 bash
 4870 pts/1    S+     0:00  \_ ./script
 4871 pts/6    Ss+    0:00      \_ bash -i

$ kill -SIGSTOP 4871

and script session on another terminal:

$ script
Script started, file is typescript

[1]+  Stopped                 ./script

$ fg 1
./script

... session again usable ...
^D
Script done, file is typescript

Signed-off-by: Karel Zak <kzak@redhat.com>
term-utils/script.c

index ffc7017b9ff187a9ebdaa998001c309029384b4a..604e47a46437beaa4bf814d1db1bf5e5b5a64b35 100644 (file)
@@ -403,8 +403,15 @@ static void handle_signal(struct script_control *ctl, int fd)
        switch (info.ssi_signo) {
        case SIGCHLD:
                DBG(SIGNAL, ul_debug(" get signal SIGCHLD"));
-               wait_for_child(ctl, 0);
-               ctl->poll_timeout = 10;
+               if (info.ssi_code == CLD_EXITED) {
+                       wait_for_child(ctl, 0);
+                       ctl->poll_timeout = 10;
+               } else if (info.ssi_status == SIGSTOP && ctl->child) {
+                       DBG(SIGNAL, ul_debug(" child stop by SIGSTOP -- stop parent too"));
+                       kill(getpid(), SIGSTOP);
+                       DBG(SIGNAL, ul_debug(" resume"));
+                       kill(ctl->child, SIGCONT);
+               }
                return;
        case SIGWINCH:
                DBG(SIGNAL, ul_debug(" get signal SIGWINCH"));