]> git.cameronkatri.com Git - mandoc.git/commitdiff
Fix a regression caused in rev. 1.212, reported by kristaps@:
authorIngo Schwarze <schwarze@openbsd.org>
Tue, 10 Mar 2015 03:02:28 +0000 (03:02 +0000)
committerIngo Schwarze <schwarze@openbsd.org>
Tue, 10 Mar 2015 03:02:28 +0000 (03:02 +0000)
When using a pager and the first manual shown is gzip'ed,
the gunzip(1) process ended up as a child of the pager process
such that the man(1) process couldn't wait for it, preventing
proper display of the manual.

Solve this by making the pager a child of the man(1) process
(instead of the other way round), which requires being a bit
more careful about properly closing file descriptors after use
and waiting for the pager before exiting man(1).

main.c

diff --git a/main.c b/main.c
index c5569f6172d044cd2d3d544edd0d482d9087d7e2..80be725e94136047732d9ed3df1b0b4db10598c2 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.223 2015/03/06 09:24:59 kristaps Exp $ */
+/*     $Id: main.c,v 1.224 2015/03/10 03:02:28 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 #include <sys/param.h> /* MACHINE */
+#include <sys/wait.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -481,6 +482,21 @@ out:
 
        free(defos);
 
+       /*
+        * Flush the output and signal end of file.
+        * If a pager is attached, it allows browsing to the end.
+        * Otherwise, it does no harm, we are about to exit anyway.
+        */
+
+       fclose(stdout);
+
+       /*
+        * If we spawned a pager, wait for the user to close it.
+        * Otherwise, this call fails with no adverse effect.
+        */
+
+       wait(NULL);
+
        return((int)rc);
 }
 
@@ -951,18 +967,19 @@ spawn_pager(void)
                    progname, strerror(errno));
                exit((int)MANDOCLEVEL_SYSERR);
        case 0:
+               break;
+       default:
                close(fildes[0]);
                if (dup2(fildes[1], STDOUT_FILENO) == -1) {
                        fprintf(stderr, "%s: dup output: %s\n",
                            progname, strerror(errno));
                        exit((int)MANDOCLEVEL_SYSERR);
                }
+               close(fildes[1]);
                return;
-       default:
-               break;
        }
 
-       /* The original process becomes the pager. */
+       /* The child process becomes the pager. */
 
        close(fildes[1]);
        if (dup2(fildes[0], STDIN_FILENO) == -1) {
@@ -970,6 +987,7 @@ spawn_pager(void)
                    progname, strerror(errno));
                exit((int)MANDOCLEVEL_SYSERR);
        }
+       close(fildes[0]);
 
        pager = getenv("MANPAGER");
        if (pager == NULL || *pager == '\0')