From 9ef16b96be75b66de146889e69c4b0130a151f7c Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Tue, 17 Mar 2015 07:33:07 +0000 Subject: When the user exits the pager before the pager has drained all input from man(1), man(1) dies from SIGPIPE. Exiting man(1) is fine in this case, generating more output would be pointless, but without handling SIGPIPE, the exit code from man(1) was wrong and csh(1) printed an ugly message "Broken pipe". Fix this by handling SIGPIPE explicitly. Issue noticed by deraadt@. --- main.c | 15 +++++++++++++-- read.c | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index f0cd8ca0..eb5a54eb 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.225 2015/03/10 13:50:03 schwarze Exp $ */ +/* $Id: main.c,v 1.226 2015/03/17 07:33:07 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,7 @@ static int fs_lookup(const struct manpaths *, static void fs_search(const struct mansearch *, const struct manpaths *, int, char**, struct manpage **, size_t *); +static void handle_sigpipe(int); static int koptions(int *, char *); #if HAVE_SQLITE3 int mandocdb(int, char**); @@ -111,6 +113,7 @@ static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; static char help_arg[] = "help"; static char *help_argv[] = {help_arg, NULL}; static const char *progname; +static enum mandoclevel rc; int @@ -127,7 +130,7 @@ main(int argc, char *argv[]) size_t isec, i, sz; int prio, best_prio, synopsis_only; char sec; - enum mandoclevel rc, rctmp; + enum mandoclevel rctmp; enum outmode outmode; int fd; int show_usage; @@ -940,6 +943,13 @@ mmsg(enum mandocerr t, enum mandoclevel lvl, fputc('\n', stderr); } +static void +handle_sigpipe(int signum) +{ + + exit(rc); +} + static pid_t spawn_pager(void) { @@ -972,6 +982,7 @@ spawn_pager(void) exit((int)MANDOCLEVEL_SYSERR); } close(fildes[1]); + signal(SIGPIPE, handle_sigpipe); return(pager_pid); } diff --git a/read.c b/read.c index 471d4150..397e6cd7 100644 --- a/read.c +++ b/read.c @@ -1,4 +1,4 @@ -/* $Id: read.c,v 1.131 2015/03/11 13:05:20 schwarze Exp $ */ +/* $Id: read.c,v 1.132 2015/03/17 07:33:07 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -846,6 +847,7 @@ mparse_open(struct mparse *curp, int *fd, const char *file) perror("dup"); exit((int)MANDOCLEVEL_SYSERR); } + signal(SIGPIPE, SIG_DFL); execlp("gunzip", "gunzip", "-c", file, NULL); perror("exec"); exit((int)MANDOCLEVEL_SYSERR); -- cgit v1.2.3-56-ge451