summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-03-10 03:02:28 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-03-10 03:02:28 +0000
commit9676910fadb6405f5678f83e7e24f8364ca2d684 (patch)
tree80cf34ed325b0274e7406d4dc88be7ed28135db8 /main.c
parentb8c2a568de5de383bd9b2bceb98150f972690eea (diff)
downloadmandoc-9676910fadb6405f5678f83e7e24f8364ca2d684.tar.gz
Fix a regression caused in rev. 1.212, reported by kristaps@:
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).
Diffstat (limited to 'main.c')
-rw-r--r--main.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/main.c b/main.c
index 36cae8cd..00407584 100644
--- a/main.c
+++ b/main.c
@@ -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')