From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from localhost (fantadrom.bsd.lv [local]) by fantadrom.bsd.lv (OpenSMTPD) with ESMTPA id 8c03d233 for ; Sat, 14 Nov 2015 18:58:17 -0500 (EST) Date: Sat, 14 Nov 2015 18:58:17 -0500 (EST) Message-Id: <8466366505340439677.enqueue@fantadrom.bsd.lv> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: schwarze@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Fix an issue reported by deraadt@: When hitting Ctrl-Backslash X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Log Message: ----------- Fix an issue reported by deraadt@: When hitting Ctrl-Backslash (= SIGQUIT) in the less(1) spawned by man(1), man(1) died uncleanly, leaving behind its temp files, and killed less(1) uncleanly as well with SIGPIPE, leaving the terminal in the wrong state. Fix this by giving less(1) its own process group and handing it control of the terminal, but in such a way that Ctrl-z (= SIGSTOP) still works: In that case, let man(1) stop itself, too, and let it continue the pager when it continues itself. Joint work with millert@ who contributed most of the expertise required, and also most parts of the code. OK deraadt@ millert@ Modified Files: -------------- mdocml: main.c Revision Data ------------- Index: main.c =================================================================== RCS file: /home/cvs/mdocml/mdocml/main.c,v retrieving revision 1.257 retrieving revision 1.258 diff -Lmain.c -Lmain.c -u -p -r1.257 -r1.258 --- main.c +++ main.c @@ -27,6 +27,7 @@ #if HAVE_ERR #include #endif +#include #include #include #include @@ -131,7 +132,9 @@ main(int argc, char *argv[]) int show_usage; int options; int use_pager; + int status; int c; + pid_t pager_pid; #if HAVE_PROGNAME progname = getprogname(); @@ -152,7 +155,7 @@ main(int argc, char *argv[]) #endif #if HAVE_PLEDGE - if (pledge("stdio rpath tmppath proc exec flock", NULL) == -1) + if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1) err((int)MANDOCLEVEL_SYSERR, "pledge"); #endif @@ -427,7 +430,7 @@ main(int argc, char *argv[]) /* mandoc(1) */ #if HAVE_PLEDGE - if (pledge(use_pager ? "stdio rpath tmppath proc exec" : + if (pledge(use_pager ? "stdio rpath tmppath tty proc exec" : "stdio rpath", NULL) == -1) err((int)MANDOCLEVEL_SYSERR, "pledge"); #endif @@ -527,7 +530,29 @@ out: if (tag_files != NULL) { fclose(stdout); tag_write(); - waitpid(spawn_pager(tag_files), NULL, 0); + pager_pid = spawn_pager(tag_files); + for (;;) { + if (waitpid(pager_pid, &status, WUNTRACED) == -1) { + if (errno == EINTR) + continue; + warn("wait"); + rc = MANDOCLEVEL_SYSERR; + break; + } + if (!WIFSTOPPED(status)) + break; + + (void)tcsetpgrp(STDIN_FILENO, getpgid(0)); + kill(0, WSTOPSIG(status)); + + /* + * I'm now stopped. + * When getting SIGCONT, continue here: + */ + + (void)tcsetpgrp(STDIN_FILENO, pager_pid); + kill(pager_pid, SIGCONT); + } tag_unlink(); } @@ -1016,10 +1041,15 @@ spawn_pager(struct tag_files *tag_files) case -1: err((int)MANDOCLEVEL_SYSERR, "fork"); case 0: + /* Set pgrp in both parent and child to avoid racing exec. */ + (void)setpgid(0, 0); break; default: + (void)setpgid(pager_pid, 0); + if (tcsetpgrp(STDIN_FILENO, pager_pid) == -1) + err((int)MANDOCLEVEL_SYSERR, "tcsetpgrp"); #if HAVE_PLEDGE - if (pledge("stdio rpath tmppath", NULL) == -1) + if (pledge("stdio rpath tmppath tty proc", NULL) == -1) err((int)MANDOCLEVEL_SYSERR, "pledge"); #endif return pager_pid; -- To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv