source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Fix an issue reported by deraadt@:  When hitting Ctrl-Backslash
Date: Sat, 14 Nov 2015 18:58:17 -0500 (EST)	[thread overview]
Message-ID: <8466366505340439677.enqueue@fantadrom.bsd.lv> (raw)

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

                 reply	other threads:[~2015-11-14 23:58 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8466366505340439677.enqueue@fantadrom.bsd.lv \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).