diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-09-03 23:21:47 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-09-03 23:21:47 +0000 |
commit | 34ba2d164c86804e434dc4199679b9611f18710a (patch) | |
tree | 08978b0ed256dd3adc9f4dfed4cb45a288df19cd /read.c | |
parent | c770387f803c840900502ca28d15d35e99650baf (diff) | |
download | mandoc-34ba2d164c86804e434dc4199679b9611f18710a.tar.gz |
Add *.gz support to apropos(1) -a, man(1), and even mandoc(1).
Implemented by moving the zip code from makewhatis(8) to the parser lib.
Diffstat (limited to 'read.c')
-rw-r--r-- | read.c | 97 |
1 files changed, 95 insertions, 2 deletions
@@ -20,9 +20,10 @@ #include <sys/types.h> #if HAVE_MMAP -#include <sys/stat.h> #include <sys/mman.h> +#include <sys/stat.h> #endif +#include <sys/wait.h> #include <assert.h> #include <ctype.h> @@ -213,9 +214,16 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { ".so request failed", /* system errors */ + "cannot dup file descriptor", + "cannot exec", + "gunzip failed with code", + "cannot fork", NULL, - "cannot stat file", + "cannot open pipe", "cannot read file", + "gunzip died from signal", + "cannot stat file", + "wait failed", }; static const char * const mandoclevels[MANDOCLEVEL_MAX] = { @@ -776,6 +784,91 @@ out: return(curp->file_status); } +enum mandoclevel +mparse_open(struct mparse *curp, int *fd, const char *file, + pid_t *child_pid) +{ + int pfd[2]; + char *cp; + enum mandocerr err; + + pfd[1] = -1; + curp->file = file; + if ((cp = strrchr(file, '.')) == NULL || + strcmp(cp + 1, "gz")) { + *child_pid = 0; + if ((*fd = open(file, O_RDONLY)) == -1) { + err = MANDOCERR_SYSOPEN; + goto out; + } + return(MANDOCLEVEL_OK); + } + + if (pipe(pfd) == -1) { + err = MANDOCERR_SYSPIPE; + goto out; + } + + switch (*child_pid = fork()) { + case -1: + err = MANDOCERR_SYSFORK; + close(pfd[0]); + close(pfd[1]); + pfd[1] = -1; + break; + case 0: + close(pfd[0]); + if (dup2(pfd[1], STDOUT_FILENO) == -1) { + err = MANDOCERR_SYSDUP; + break; + } + execlp("gunzip", "gunzip", "-c", file, NULL); + err = MANDOCERR_SYSEXEC; + break; + default: + close(pfd[1]); + *fd = pfd[0]; + return(MANDOCLEVEL_OK); + } + +out: + *fd = -1; + *child_pid = 0; + curp->file_status = MANDOCLEVEL_SYSERR; + if (curp->mmsg) + (*curp->mmsg)(err, curp->file_status, file, + 0, 0, strerror(errno)); + if (pfd[1] != -1) + exit(1); + return(curp->file_status); +} + +enum mandoclevel +mparse_wait(struct mparse *curp, pid_t child_pid) +{ + int status; + + if (waitpid(child_pid, &status, 0) == -1) { + mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0, + strerror(errno)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + if (WIFSIGNALED(status)) { + mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0, + "%d", WTERMSIG(status)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + if (WEXITSTATUS(status)) { + mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0, + "%d", WEXITSTATUS(status)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + return(MANDOCLEVEL_OK); +} + struct mparse * mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, const char *defos) |