summaryrefslogtreecommitdiffstats
path: root/term-utils/script.c
diff options
context:
space:
mode:
authorKarel Zak2015-06-17 13:25:46 +0200
committerKarel Zak2015-06-17 13:25:46 +0200
commitd35ffe808a0e42967cf69d4651582cd0b7ed1e08 (patch)
tree2e426fec5f81a641cdf253c822ce4dc99ab854aa /term-utils/script.c
parentscript: debug poll() results (diff)
downloadkernel-qcow2-util-linux-d35ffe808a0e42967cf69d4651582cd0b7ed1e08.tar.gz
kernel-qcow2-util-linux-d35ffe808a0e42967cf69d4651582cd0b7ed1e08.tar.xz
kernel-qcow2-util-linux-d35ffe808a0e42967cf69d4651582cd0b7ed1e08.zip
script: cleanup signals usage
* don't call anything from assert() * fork() block cleanup to make it more readable * restore original signal mask in child (do_shell()) * close signal FD in child (do_shell()) Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'term-utils/script.c')
-rw-r--r--term-utils/script.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/term-utils/script.c b/term-utils/script.c
index bf03b6297..74539c1c5 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -124,6 +124,7 @@ struct script_control {
die:1; /* terminate program */
sigset_t sigset; /* catch SIGCHLD and SIGWINCH with signalfd() */
+ sigset_t sigorg; /* original signal mask */
int sigfd; /* file descriptor for signalfd() */
};
@@ -315,7 +316,11 @@ static void handle_signal(struct script_control *ctl, int fd)
DBG(SIGNAL, ul_debug("signal FD %d active", fd));
bytes = read(fd, &info, sizeof(info));
- assert(bytes == sizeof(info));
+ if (bytes != sizeof(info)) {
+ if (errno == EAGAIN)
+ return;
+ fail(ctl);
+ }
switch (info.ssi_signo) {
case SIGCHLD:
@@ -442,7 +447,7 @@ static void getslave(struct script_control *ctl)
ioctl(ctl->slave, TIOCSCTTY, 0);
}
-static void __attribute__((__noreturn__)) doshell(struct script_control *ctl)
+static void __attribute__((__noreturn__)) do_shell(struct script_control *ctl)
{
char *shname;
@@ -450,6 +455,7 @@ static void __attribute__((__noreturn__)) doshell(struct script_control *ctl)
/* close things irrelevant for this process */
close(ctl->master);
+ close(ctl->sigfd);
dup2(ctl->slave, STDIN_FILENO);
dup2(ctl->slave, STDOUT_FILENO);
@@ -464,6 +470,8 @@ static void __attribute__((__noreturn__)) doshell(struct script_control *ctl)
else
shname = ctl->shell;
+ sigprocmask(SIG_SETMASK, &ctl->sigorg, NULL);
+
/*
* When invoked from within /etc/csh.login, script spawns a csh shell
* that spawns programs that cannot be killed with a SIGTERM. This is
@@ -663,10 +671,13 @@ int main(int argc, char **argv)
utempter_add_record(ctl.master, NULL);
#endif
/* setup signal handler */
- assert(sigemptyset(&ctl.sigset) == 0);
- assert(sigaddset(&ctl.sigset, SIGCHLD) == 0);
- assert(sigaddset(&ctl.sigset, SIGWINCH) == 0);
- assert(sigprocmask(SIG_BLOCK, &ctl.sigset, NULL) == 0);
+ sigemptyset(&ctl.sigset);
+ sigaddset(&ctl.sigset, SIGCHLD);
+ sigaddset(&ctl.sigset, SIGWINCH);
+
+ /* block signals used for signalfd() to prevent the signals being
+ * handled according to their default dispositions */
+ sigprocmask(SIG_BLOCK, &ctl.sigset, &ctl.sigorg);
if ((ctl.sigfd = signalfd(-1, &ctl.sigset, 0)) < 0)
err(EXIT_FAILURE, _("cannot set signal handler"));
@@ -676,13 +687,19 @@ int main(int argc, char **argv)
fflush(stdout);
ctl.child = fork();
- if (ctl.child < 0) {
+ switch (ctl.child) {
+ case -1: /* error */
warn(_("fork failed"));
fail(&ctl);
+ break;
+ case 0: /* child */
+ do_shell(&ctl);
+ break;
+ default: /* parent */
+ do_io(&ctl);
+ break;
}
- if (ctl.child == 0)
- doshell(&ctl);
- do_io(&ctl);
- /* should not happen, do_io() calls done() */
+
+ /* should not happen, all used functions are non-return */
return EXIT_FAILURE;
}