From d35ffe808a0e42967cf69d4651582cd0b7ed1e08 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 17 Jun 2015 13:25:46 +0200 Subject: 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 --- term-utils/script.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'term-utils/script.c') 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; } -- cgit v1.2.3-55-g7522