source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Fix an issue reported by deraadt@:  When hitting Ctrl-Backslash
@ 2015-11-14 23:58 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-11-14 23:58 UTC (permalink / raw)
  To: source

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 <err.h>
 #endif
+#include <errno.h>
 #include <fcntl.h>
 #include <glob.h>
 #include <signal.h>
@@ -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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-11-14 23:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-14 23:58 mdocml: Fix an issue reported by deraadt@: When hitting Ctrl-Backslash schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).