diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/mandoc/main.c | 298 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.1 | 55 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 34 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc_msg.c | 44 | ||||
-rw-r--r-- | usr.bin/mandoc/manpath.c | 90 | ||||
-rw-r--r-- | usr.bin/mandoc/read.c | 35 | ||||
-rw-r--r-- | usr.bin/mandoc/tag.c | 30 |
7 files changed, 344 insertions, 242 deletions
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 51549ee3057..66d6a1173b0 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.230 2019/07/03 16:33:06 espie Exp $ */ +/* $OpenBSD: main.c,v 1.231 2019/07/10 19:38:56 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org> @@ -92,13 +92,10 @@ static int fs_lookup(const struct manpaths *, static int fs_search(const struct mansearch *, const struct manpaths *, int, char**, struct manpage **, size_t *); -static int koptions(int *, char *); -static void moptions(int *, char *); static void outdata_alloc(struct curparse *); static void parse(struct curparse *, int, const char *); -static void passthrough(const char *, int, int); +static void passthrough(int, int); static pid_t spawn_pager(struct tag_files *); -static int toptions(struct curparse *, char *); static void usage(enum argmode) __attribute__((__noreturn__)); static int woptions(struct curparse *, char *); @@ -137,8 +134,10 @@ main(int argc, char *argv[]) strncmp(progname, "makewhatis", 10) == 0) return mandocdb(argc, argv); - if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) { + mandoc_msg(MANDOCERR_PLEDGE, 0, 0, "%s", strerror(errno)); + return mandoc_msg_getrc(); + } /* Search options. */ @@ -198,19 +197,29 @@ main(int argc, char *argv[]) outmode = OUTMODE_ALL; break; case 'I': - if (strncmp(optarg, "os=", 3)) { - warnx("-I %s: Bad argument", optarg); - return (int)MANDOCLEVEL_BADARG; + if (strncmp(optarg, "os=", 3) != 0) { + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, + "-I %s", optarg); + return mandoc_msg_getrc(); } if (curp.os_s != NULL) { - warnx("-I %s: Duplicate argument", optarg); - return (int)MANDOCLEVEL_BADARG; + mandoc_msg(MANDOCERR_BADARG_DUPE, 0, 0, + "-I %s", optarg); + return mandoc_msg_getrc(); } curp.os_s = mandoc_strdup(optarg + 3); break; case 'K': - if ( ! koptions(&options, optarg)) - return (int)MANDOCLEVEL_BADARG; + options &= ~(MPARSE_UTF8 | MPARSE_LATIN1); + if (strcmp(optarg, "utf-8") == 0) + options |= MPARSE_UTF8; + else if (strcmp(optarg, "iso-8859-1") == 0) + options |= MPARSE_LATIN1; + else if (strcmp(optarg, "us-ascii") != 0) { + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, + "-K %s", optarg); + return mandoc_msg_getrc(); + } break; case 'k': search.argmode = ARG_EXPR; @@ -235,12 +244,37 @@ main(int argc, char *argv[]) search.sec = optarg; break; case 'T': - if ( ! toptions(&curp, optarg)) - return (int)MANDOCLEVEL_BADARG; + if (strcmp(optarg, "ascii") == 0) + curp.outtype = OUTT_ASCII; + else if (strcmp(optarg, "lint") == 0) { + curp.outtype = OUTT_LINT; + mandoc_msg_setoutfile(stdout); + mandoc_msg_setmin(MANDOCERR_BASE); + } else if (strcmp(optarg, "tree") == 0) + curp.outtype = OUTT_TREE; + else if (strcmp(optarg, "man") == 0) + curp.outtype = OUTT_MAN; + else if (strcmp(optarg, "html") == 0) + curp.outtype = OUTT_HTML; + else if (strcmp(optarg, "markdown") == 0) + curp.outtype = OUTT_MARKDOWN; + else if (strcmp(optarg, "utf8") == 0) + curp.outtype = OUTT_UTF8; + else if (strcmp(optarg, "locale") == 0) + curp.outtype = OUTT_LOCALE; + else if (strcmp(optarg, "ps") == 0) + curp.outtype = OUTT_PS; + else if (strcmp(optarg, "pdf") == 0) + curp.outtype = OUTT_PDF; + else { + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, + "-T %s", optarg); + return mandoc_msg_getrc(); + } break; case 'W': - if ( ! woptions(&curp, optarg)) - return (int)MANDOCLEVEL_BADARG; + if (woptions(&curp, optarg) == -1) + return mandoc_msg_getrc(); break; case 'w': outmode = OUTMODE_FLN; @@ -278,7 +312,7 @@ main(int argc, char *argv[]) while (oarg != NULL) { if (manconf_output(&conf.output, strsep(&oarg, ","), 0) == -1) - return (int)MANDOCLEVEL_BADARG; + return mandoc_msg_getrc(); } } } @@ -301,9 +335,13 @@ main(int argc, char *argv[]) conf.output.indent = 3; } - if (!use_pager) - if (pledge("stdio rpath", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (use_pager == 0) { + if (pledge("stdio rpath", NULL) == -1) { + mandoc_msg(MANDOCERR_PLEDGE, 0, 0, + "%s", strerror(errno)); + return mandoc_msg_getrc(); + } + } /* Parse arguments. */ @@ -365,7 +403,7 @@ main(int argc, char *argv[]) usage(search.argmode); if (sz == 0 && search.argmode == ARG_NAME) - fs_search(&search, &conf.manpath, + (void)fs_search(&search, &conf.manpath, argc, argv, &res, &sz); if (search.argmode == ARG_NAME) { @@ -373,7 +411,10 @@ main(int argc, char *argv[]) if (strchr(argv[c], '/') == NULL) continue; if (access(argv[c], R_OK) == -1) { - warn("%s", argv[c]); + mandoc_msg_setinfilename(argv[c]); + mandoc_msg(MANDOCERR_BADARG_BAD, + 0, 0, "%s", strerror(errno)); + mandoc_msg_setinfilename(NULL); continue; } res = mandoc_reallocarray(res, @@ -458,15 +499,25 @@ main(int argc, char *argv[]) /* mandoc(1) */ if (use_pager) { - if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) { + mandoc_msg(MANDOCERR_PLEDGE, 0, 0, + "%s", strerror(errno)); + return mandoc_msg_getrc(); + } } else { - if (pledge("stdio rpath", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (pledge("stdio rpath", NULL) == -1) { + mandoc_msg(MANDOCERR_PLEDGE, 0, 0, + "%s", strerror(errno)); + return mandoc_msg_getrc(); + } } - if (search.argmode == ARG_FILE) - moptions(&options, auxpaths); + if (search.argmode == ARG_FILE && auxpaths != NULL) { + if (strcmp(auxpaths, "doc") == 0) + options |= MPARSE_MDOC; + else if (strcmp(auxpaths, "an") == 0) + options |= MPARSE_MAN; + } mchars_alloc(); curp.mp = mparse_alloc(options, curp.os_e, curp.os_s); @@ -508,6 +559,7 @@ main(int argc, char *argv[]) } else thisarg = *argv; + mandoc_msg_setinfilename(thisarg); fd = mparse_open(curp.mp, thisarg); if (fd != -1) { if (use_pager) { @@ -517,22 +569,21 @@ main(int argc, char *argv[]) tag_files->tagname = conf.output.tag; } - mandoc_msg_setinfilename(thisarg); if (resp == NULL || resp->form == FORM_SRC) parse(&curp, fd, thisarg); else - passthrough(resp->file, fd, - conf.output.synopsisonly); - mandoc_msg_setinfilename(NULL); + passthrough(fd, conf.output.synopsisonly); if (ferror(stdout)) { if (tag_files != NULL) { - warn("%s", tag_files->ofn); + mandoc_msg(MANDOCERR_WRITE, 0, 0, + "%s: %s", tag_files->ofn, + strerror(errno)); tag_unlink(); tag_files = NULL; } else - warn("stdout"); - mandoc_msg_setrc(MANDOCLEVEL_SYSERR); + mandoc_msg(MANDOCERR_WRITE, 0, 0, + "%s", strerror(errno)); break; } @@ -542,8 +593,10 @@ main(int argc, char *argv[]) terminal_sepline(curp.outdata); } } else - mandoc_msg(MANDOCERR_FILE, 0, 0, - "%s: %s", thisarg, strerror(errno)); + mandoc_msg(resp == NULL ? MANDOCERR_BADARG_BAD : + MANDOCERR_OPEN, 0, 0, "%s", strerror(errno)); + + mandoc_msg_setinfilename(NULL); if (curp.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK) break; @@ -635,8 +688,8 @@ out: continue; if (pid == -1) { - warn("wait"); - mandoc_msg_setrc(MANDOCLEVEL_SYSERR); + mandoc_msg(MANDOCERR_WAIT, 0, 0, + "%s", strerror(errno)); break; } if (!WIFSTOPPED(status)) @@ -652,7 +705,6 @@ out: static void usage(enum argmode argmode) { - switch (argmode) { case ARG_FILE: fputs("usage: mandoc [-ac] [-I os=name] " @@ -717,7 +769,8 @@ fs_lookup(const struct manpaths *paths, size_t ipath, paths->paths[ipath], sec, name); globres = glob(file, 0, NULL, &globinfo); if (globres != 0 && globres != GLOB_NOMATCH) - warn("%s: glob", file); + mandoc_msg(MANDOCERR_GLOB, 0, 0, + "%s: %s", file, strerror(errno)); free(file); if (globres == 0) file = mandoc_strdup(*globinfo.gl_pathv); @@ -728,21 +781,21 @@ fs_lookup(const struct manpaths *paths, size_t ipath, free(file); } if (res != NULL || ipath + 1 != paths->sz) - return 0; + return -1; mandoc_asprintf(&file, "%s.%s", name, sec); globres = stat(file, &sb); free(file); - return globres != -1; + return globres; found: warnx("outdated mandoc.db lacks %s(%s) entry, run makewhatis %s", name, sec, paths->paths[ipath]); if (res == NULL) { free(file); - return 1; + return 0; } - *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); + *res = mandoc_reallocarray(*res, ++*ressz, sizeof(**res)); page = *res + (*ressz - 1); page->file = file; page->names = NULL; @@ -751,7 +804,7 @@ found: page->ipath = ipath; page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; page->form = form; - return 1; + return 0; } static int @@ -773,14 +826,14 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths, for (ipath = 0; ipath < paths->sz; ipath++) { if (cfg->sec != NULL) { if (fs_lookup(paths, ipath, cfg->sec, - cfg->arch, *argv, res, ressz) && + cfg->arch, *argv, res, ressz) != -1 && cfg->firstmatch) - return 1; + return 0; } else for (isec = 0; isec < nsec; isec++) if (fs_lookup(paths, ipath, sections[isec], - cfg->arch, *argv, res, ressz) && + cfg->arch, *argv, res, ressz) != -1 && cfg->firstmatch) - return 1; + return 0; } if (res != NULL && *ressz == lastsz && strchr(*argv, '/') == NULL) { @@ -799,7 +852,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths, argv++; argc--; } - return 0; + return -1; } static void @@ -906,7 +959,7 @@ check_xr(void) search.firstmatch = 1; if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz)) continue; - if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz)) + if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz) != -1) continue; if (xr->count == 1) mandoc_msg(MANDOCERR_XR_BAD, xr->line, @@ -946,34 +999,34 @@ outdata_alloc(struct curparse *curp) } static void -passthrough(const char *file, int fd, int synopsis_only) +passthrough(int fd, int synopsis_only) { const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"; const char synr[] = "SYNOPSIS"; FILE *stream; - const char *syscall; char *line, *cp; size_t linesz; ssize_t len, written; - int print; + int lno, print; + stream = NULL; line = NULL; linesz = 0; if (fflush(stdout) == EOF) { - syscall = "fflush"; - goto fail; + mandoc_msg(MANDOCERR_FFLUSH, 0, 0, "%s", strerror(errno)); + goto done; } - if ((stream = fdopen(fd, "r")) == NULL) { close(fd); - syscall = "fdopen"; - goto fail; + mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno)); + goto done; } - print = 0; + lno = print = 0; while ((len = getline(&line, &linesz, stream)) != -1) { + lno++; cp = line; if (synopsis_only) { if (print) { @@ -991,94 +1044,20 @@ passthrough(const char *file, int fd, int synopsis_only) } } for (; len > 0; len -= written) { - if ((written = write(STDOUT_FILENO, cp, len)) != -1) - continue; - fclose(stream); - syscall = "write"; - goto fail; + if ((written = write(STDOUT_FILENO, cp, len)) == -1) { + mandoc_msg(MANDOCERR_WRITE, 0, 0, + "%s", strerror(errno)); + goto done; + } } } - - if (ferror(stream)) { - fclose(stream); - syscall = "getline"; - goto fail; - } + if (ferror(stream)) + mandoc_msg(MANDOCERR_GETLINE, lno, 0, "%s", strerror(errno)); done: free(line); - fclose(stream); - return; - -fail: - free(line); - warn("%s: SYSERR: %s", file, syscall); - mandoc_msg_setrc(MANDOCLEVEL_SYSERR); -} - -static int -koptions(int *options, char *arg) -{ - - if ( ! strcmp(arg, "utf-8")) { - *options |= MPARSE_UTF8; - *options &= ~MPARSE_LATIN1; - } else if ( ! strcmp(arg, "iso-8859-1")) { - *options |= MPARSE_LATIN1; - *options &= ~MPARSE_UTF8; - } else if ( ! strcmp(arg, "us-ascii")) { - *options &= ~(MPARSE_UTF8 | MPARSE_LATIN1); - } else { - warnx("-K %s: Bad argument", arg); - return 0; - } - return 1; -} - -static void -moptions(int *options, char *arg) -{ - - if (arg == NULL) - return; - if (strcmp(arg, "doc") == 0) - *options |= MPARSE_MDOC; - else if (strcmp(arg, "an") == 0) - *options |= MPARSE_MAN; -} - -static int -toptions(struct curparse *curp, char *arg) -{ - - if (0 == strcmp(arg, "ascii")) - curp->outtype = OUTT_ASCII; - else if (0 == strcmp(arg, "lint")) { - curp->outtype = OUTT_LINT; - mandoc_msg_setoutfile(stdout); - mandoc_msg_setmin(MANDOCERR_BASE); - } else if (0 == strcmp(arg, "tree")) - curp->outtype = OUTT_TREE; - else if (0 == strcmp(arg, "man")) - curp->outtype = OUTT_MAN; - else if (0 == strcmp(arg, "html")) - curp->outtype = OUTT_HTML; - else if (0 == strcmp(arg, "markdown")) - curp->outtype = OUTT_MARKDOWN; - else if (0 == strcmp(arg, "utf8")) - curp->outtype = OUTT_UTF8; - else if (0 == strcmp(arg, "locale")) - curp->outtype = OUTT_LOCALE; - else if (0 == strcmp(arg, "ps")) - curp->outtype = OUTT_PS; - else if (0 == strcmp(arg, "pdf")) - curp->outtype = OUTT_PDF; - else { - warnx("-T %s: Bad argument", arg); - return 0; - } - - return 1; + if (stream != NULL) + fclose(stream); } static int @@ -1122,7 +1101,7 @@ woptions(struct curparse *curp, char *arg) mandoc_msg_setmin(MANDOCERR_UNSUPP); break; case 7: - mandoc_msg_setmin(MANDOCERR_MAX); + mandoc_msg_setmin(MANDOCERR_BADARG); break; case 8: mandoc_msg_setmin(MANDOCERR_BASE); @@ -1133,11 +1112,11 @@ woptions(struct curparse *curp, char *arg) curp->os_e = MANDOC_OS_NETBSD; break; default: - warnx("-W %s: Bad argument", o); - return 0; + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-W %s", o); + return -1; } } - return 1; + return 0; } static pid_t @@ -1198,22 +1177,28 @@ spawn_pager(struct tag_files *tag_files) switch (pager_pid = fork()) { case -1: - err((int)MANDOCLEVEL_SYSERR, "fork"); + mandoc_msg(MANDOCERR_FORK, 0, 0, "%s", strerror(errno)); + exit(mandoc_msg_getrc()); case 0: break; default: (void)setpgid(pager_pid, 0); (void)tcsetpgrp(tag_files->ofd, pager_pid); - if (pledge("stdio rpath tmppath tty proc", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (pledge("stdio rpath tmppath tty proc", NULL) == -1) { + mandoc_msg(MANDOCERR_PLEDGE, 0, 0, + "%s", strerror(errno)); + exit(mandoc_msg_getrc()); + } tag_files->pager_pid = pager_pid; return pager_pid; } /* The child process becomes the pager. */ - if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) - err((int)MANDOCLEVEL_SYSERR, "pager stdout"); + if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) { + mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno)); + _exit(mandoc_msg_getrc()); + } close(tag_files->ofd); assert(tag_files->tfd == -1); @@ -1223,5 +1208,6 @@ spawn_pager(struct tag_files *tag_files) nanosleep(&timeout, NULL); execvp(argv[0], argv); - err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]); + mandoc_msg(MANDOCERR_EXEC, 0, 0, "%s: %s", argv[0], strerror(errno)); + _exit(mandoc_msg_getrc()); } diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1 index ef4169477a9..79ef8b019b2 100644 --- a/usr.bin/mandoc/mandoc.1 +++ b/usr.bin/mandoc/mandoc.1 @@ -1,7 +1,7 @@ -.\" $OpenBSD: mandoc.1,v 1.163 2019/05/26 01:16:09 naddy Exp $ +.\" $OpenBSD: mandoc.1,v 1.164 2019/07/10 19:38:56 schwarze Exp $ .\" .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> -.\" Copyright (c) 2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org> +.\" Copyright (c) 2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org> .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: May 26 2019 $ +.Dd $Mdocdate: July 10 2019 $ .Dt MANDOC 1 .Os .Sh NAME @@ -698,7 +698,7 @@ No input files have been read. .It 6 An operating system error occurred, for example exhaustion of memory, file descriptors, or process table entries. -Such errors cause +Such errors may cause .Nm to exit at once, possibly in the middle of parsing or formatting a file. .El @@ -778,6 +778,13 @@ fields. .Pp Message levels have the following meanings: .Bl -tag -width "warning" +.It Cm syserr +An operating system error occurred. +There isn't necessarily anything wrong with the input files. +Output may all the same be missing or incomplete. +.It Cm badarg +Invalid command line arguments were specified. +No input files have been read and no output is produced. .It Cm unsupp An input file uses unsupported low-level .Xr roff 7 @@ -826,8 +833,7 @@ Messages of the .Cm error , and .Cm unsupp -levels except those about non-existent or unreadable input files -are hidden unless their level, or a lower level, is requested using a +levels are hidden unless their level, or a lower level, is requested using a .Fl W option or .Fl T Cm lint @@ -2242,6 +2248,43 @@ macro or of an undefined macro. The macro is ignored, and its arguments are handled as if they were a text line. .El +.Ss Bad command line arguments +.Bl -ohang +.It Sy "bad command line argument" +The argument following one of the +.Fl IKMmOTW +command line options is invalid, or a +.Ar file +given as a command line argument cannot be opened. +.It Sy "duplicate command line argument" +The +.Fl I +command line option was specified twice. +.It Sy "option has a superfluous value" +An argument to the +.Fl O +option has a value but does not accept one. +.It Sy "missing option value" +An argument to the +.Fl O +option has no argument but requires one. +.It Sy "bad option value" +An argument to the +.Fl O +.Cm indent +or +.Cm width +option has an invalid value. +.It Sy "duplicate option value" +The same +.Fl O +option is specified more than once. +.It Sy "no such tag" +The +.Fl O Cm tag +option was specified but the tag was not found in any of the displayed +manual pages. +.El .Sh SEE ALSO .Xr apropos 1 , .Xr man 1 , diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index 835ee2c95e2..458437ff9be 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -1,7 +1,7 @@ -/* $OpenBSD: mandoc.h,v 1.204 2018/12/15 23:33:20 schwarze Exp $ */ +/* $OpenBSD: mandoc.h,v 1.205 2019/07/10 19:38:56 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2012-2018 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2012-2019 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -193,7 +193,6 @@ enum mandocerr { MANDOCERR_TBLDATA_BLK, /* data block open at end of tbl: macro */ /* related to document structure and macros */ - MANDOCERR_FILE, /* cannot open file */ MANDOCERR_PROLOG_REP, /* duplicate prologue macro: macro */ MANDOCERR_DT_LATE, /* skipping late title macro: Dt args */ MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */ @@ -242,6 +241,35 @@ enum mandocerr { MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */ MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */ + MANDOCERR_BADARG, /* ===== start of bad invocations ===== */ + + MANDOCERR_BADARG_BAD, /* bad argument */ + MANDOCERR_BADARG_DUPE, /* duplicate argument */ + MANDOCERR_BADVAL, /* does not take a value */ + MANDOCERR_BADVAL_MISS, /* missing argument value */ + MANDOCERR_BADVAL_BAD, /* bad argument value */ + MANDOCERR_BADVAL_DUPE, /* duplicate argument value */ + MANDOCERR_TAG, /* no such tag */ + + MANDOCERR_SYSERR, /* ===== start of system errors ===== */ + + MANDOCERR_DUP, + MANDOCERR_EXEC, + MANDOCERR_FDOPEN, + MANDOCERR_FFLUSH, + MANDOCERR_FORK, + MANDOCERR_FSTAT, + MANDOCERR_GETLINE, + MANDOCERR_GLOB, + MANDOCERR_GZCLOSE, + MANDOCERR_GZDOPEN, + MANDOCERR_MKSTEMP, + MANDOCERR_OPEN, + MANDOCERR_PLEDGE, + MANDOCERR_READ, + MANDOCERR_WAIT, + MANDOCERR_WRITE, + MANDOCERR_MAX }; diff --git a/usr.bin/mandoc/mandoc_msg.c b/usr.bin/mandoc/mandoc_msg.c index 9d229ac58a6..3f1f777c6bd 100644 --- a/usr.bin/mandoc/mandoc_msg.c +++ b/usr.bin/mandoc/mandoc_msg.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mandoc_msg.c,v 1.4 2019/01/10 06:27:23 schwarze Exp $ */ +/* $OpenBSD: mandoc_msg.c,v 1.5 2019/07/10 19:38:56 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,8 +27,8 @@ static const enum mandocerr lowest_type[MANDOCLEVEL_MAX] = { MANDOCERR_WARNING, MANDOCERR_ERROR, MANDOCERR_UNSUPP, - MANDOCERR_MAX, - MANDOCERR_MAX + MANDOCERR_BADARG, + MANDOCERR_SYSERR }; static const char *const level_name[MANDOCLEVEL_MAX] = { @@ -191,7 +191,6 @@ static const char *const type_message[MANDOCERR_MAX] = { "data block open at end of tbl", /* related to document structure and macros */ - NULL, "duplicate prologue macro", "skipping late title macro", "input stack limit exceeded, infinite loop?", @@ -238,11 +237,40 @@ static const char *const type_message[MANDOCERR_MAX] = { "eqn delim option in tbl", "unsupported tbl layout modifier", "ignoring macro in table", + + /* bad command line arguments */ + NULL, + "bad command line argument", + "duplicate command line argument", + "option has a superfluous value", + "missing option value", + "bad option value", + "duplicate option value", + "no such tag", + + /* system errors */ + NULL, + "dup", + "exec", + "fdopen", + "fflush", + "fork", + "fstat", + "getline", + "glob", + "gzclose", + "gzdopen", + "mkstemp", + "open", + "pledge", + "read", + "wait", + "write", }; static FILE *fileptr = NULL; static const char *filename = NULL; -static enum mandocerr min_type = MANDOCERR_MAX; +static enum mandocerr min_type = MANDOCERR_BADARG; static enum mandoclevel rc = MANDOCLEVEL_OK; @@ -295,10 +323,10 @@ mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...) va_list ap; enum mandoclevel level; - if (t < min_type && t != MANDOCERR_FILE) + if (t < min_type) return; - level = MANDOCLEVEL_UNSUPP; + level = MANDOCLEVEL_SYSERR; while (t < lowest_type[level]) level--; mandoc_msg_setrc(level); diff --git a/usr.bin/mandoc/manpath.c b/usr.bin/mandoc/manpath.c index 2e5ffcb15e5..2ac9d86c219 100644 --- a/usr.bin/mandoc/manpath.c +++ b/usr.bin/mandoc/manpath.c @@ -1,6 +1,6 @@ -/* $OpenBSD: manpath.c,v 1.26 2019/05/03 18:38:45 schwarze Exp $ */ +/* $OpenBSD: manpath.c,v 1.27 2019/07/10 19:38:56 schwarze Exp $ */ /* - * Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any @@ -19,13 +19,14 @@ #include <sys/stat.h> #include <ctype.h> -#include <err.h> +#include <errno.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mandoc_aux.h" +#include "mandoc.h" #include "manconf.h" #define MAN_CONF_FILE "/etc/man.conf" @@ -33,8 +34,8 @@ #define MANPATH_DEFAULT "/usr/share/man:/usr/X11R6/man:/usr/local/man" static void manconf_file(struct manconf *, const char *); -static void manpath_add(struct manpaths *, const char *, int); -static void manpath_parseline(struct manpaths *, char *, int); +static void manpath_add(struct manpaths *, const char *, char); +static void manpath_parseline(struct manpaths *, char *, char); void @@ -44,11 +45,11 @@ manconf_parse(struct manconf *conf, const char *file, char *insert; /* Always prepend -m. */ - manpath_parseline(&conf->manpath, auxp, 1); + manpath_parseline(&conf->manpath, auxp, 'm'); /* If -M is given, it overrides everything else. */ if (NULL != defp) { - manpath_parseline(&conf->manpath, defp, 1); + manpath_parseline(&conf->manpath, defp, 'M'); return; } @@ -66,13 +67,13 @@ manconf_parse(struct manconf *conf, const char *file, /* Prepend man.conf(5) to MANPATH. */ if (':' == defp[0]) { manconf_file(conf, file); - manpath_parseline(&conf->manpath, defp, 0); + manpath_parseline(&conf->manpath, defp, '\0'); return; } /* Append man.conf(5) to MANPATH. */ if (':' == defp[strlen(defp) - 1]) { - manpath_parseline(&conf->manpath, defp, 0); + manpath_parseline(&conf->manpath, defp, '\0'); manconf_file(conf, file); return; } @@ -81,28 +82,28 @@ manconf_parse(struct manconf *conf, const char *file, insert = strstr(defp, "::"); if (NULL != insert) { *insert++ = '\0'; - manpath_parseline(&conf->manpath, defp, 0); + manpath_parseline(&conf->manpath, defp, '\0'); manconf_file(conf, file); - manpath_parseline(&conf->manpath, insert + 1, 0); + manpath_parseline(&conf->manpath, insert + 1, '\0'); return; } /* MANPATH overrides man.conf(5) completely. */ - manpath_parseline(&conf->manpath, defp, 0); + manpath_parseline(&conf->manpath, defp, '\0'); } void manpath_base(struct manpaths *dirs) { char path_base[] = MANPATH_BASE; - manpath_parseline(dirs, path_base, 0); + manpath_parseline(dirs, path_base, '\0'); } /* * Parse a FULL pathname from a colon-separated list of arrays. */ static void -manpath_parseline(struct manpaths *dirs, char *path, int complain) +manpath_parseline(struct manpaths *dirs, char *path, char option) { char *dir; @@ -110,7 +111,7 @@ manpath_parseline(struct manpaths *dirs, char *path, int complain) return; for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) - manpath_add(dirs, dir, complain); + manpath_add(dirs, dir, option); } /* @@ -118,33 +119,32 @@ manpath_parseline(struct manpaths *dirs, char *path, int complain) * Grow the array one-by-one for simplicity's sake. */ static void -manpath_add(struct manpaths *dirs, const char *dir, int complain) +manpath_add(struct manpaths *dirs, const char *dir, char option) { char buf[PATH_MAX]; struct stat sb; char *cp; size_t i; - if (NULL == (cp = realpath(dir, buf))) { - if (complain) - warn("manpath: %s", dir); - return; - } + if ((cp = realpath(dir, buf)) == NULL) + goto fail; for (i = 0; i < dirs->sz; i++) - if (0 == strcmp(dirs->paths[i], dir)) + if (strcmp(dirs->paths[i], dir) == 0) return; - if (stat(cp, &sb) == -1) { - if (complain) - warn("manpath: %s", dir); - return; - } + if (stat(cp, &sb) == -1) + goto fail; dirs->paths = mandoc_reallocarray(dirs->paths, - dirs->sz + 1, sizeof(char *)); - + dirs->sz + 1, sizeof(*dirs->paths)); dirs->paths[dirs->sz++] = mandoc_strdup(cp); + return; + +fail: + if (option != '\0') + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, + "-%c %s: %s", option, dir, strerror(errno)); } void @@ -210,7 +210,7 @@ manconf_file(struct manconf *conf, const char *file) *ep = '\0'; /* FALLTHROUGH */ case 0: /* manpath */ - manpath_add(&conf->manpath, cp, 0); + manpath_add(&conf->manpath, cp, '\0'); *manpath_default = '\0'; break; case 1: /* output */ @@ -225,7 +225,7 @@ manconf_file(struct manconf *conf, const char *file) out: if (*manpath_default != '\0') - manpath_parseline(&conf->manpath, manpath_default, 0); + manpath_parseline(&conf->manpath, manpath_default, '\0'); } int @@ -243,7 +243,7 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile) for (tok = 0; tok < ntoks; tok++) { len = strlen(toks[tok]); - if ( ! strncmp(cp, toks[tok], len) && + if (strncmp(cp, toks[tok], len) == 0 && strchr(" = ", cp[len]) != NULL) { cp += len; if (*cp == '=') @@ -255,11 +255,11 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile) } if (tok < 6 && *cp == '\0') { - warnx("-O %s=?: Missing argument value", toks[tok]); + mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]); return -1; } if (tok > 6 && tok < ntoks && *cp != '\0') { - warnx("-O %s: Does not take a value: %s", toks[tok], cp); + mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp); return -1; } @@ -300,7 +300,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile) conf->indent = strtonum(cp, 0, 1000, &errstr); if (errstr == NULL) return 0; - warnx("-O indent=%s is %s", cp, errstr); + mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0, + "-O indent=%s is %s", cp, errstr); return -1; case 5: if (conf->width) { @@ -310,7 +311,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile) conf->width = strtonum(cp, 1, 1000, &errstr); if (errstr == NULL) return 0; - warnx("-O width=%s is %s", cp, errstr); + mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0, + "-O width=%s is %s", cp, errstr); return -1; case 6: if (conf->tag != NULL) { @@ -332,12 +334,16 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile) conf->toc = 1; return 0; default: - warnx("-O %s: Bad argument", cp); + mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-O %s", cp); + return -1; + } + if (fromfile) { + free(oldval); + return 0; + } else { + mandoc_msg(MANDOCERR_BADVAL_DUPE, 0, 0, + "-O %s=%s: already set to %s", toks[tok], cp, oldval); + free(oldval); return -1; } - if (fromfile == 0) - warnx("-O %s=%s: Option already set to %s", - toks[tok], cp, oldval); - free(oldval); - return -1; } diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c index 65bf2a56475..6dfe2003abd 100644 --- a/usr.bin/mandoc/read.c +++ b/usr.bin/mandoc/read.c @@ -1,4 +1,4 @@ -/* $OpenBSD: read.c,v 1.184 2019/06/03 19:58:00 schwarze Exp $ */ +/* $OpenBSD: read.c,v 1.185 2019/07/10 19:38:56 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org> @@ -429,9 +429,8 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) int gzerrnum, retval; if (fstat(fd, &st) == -1) { - mandoc_msg(MANDOCERR_FILE, 0, 0, - "fstat: %s", strerror(errno)); - return 0; + mandoc_msg(MANDOCERR_FSTAT, 0, 0, "%s", strerror(errno)); + return -1; } /* @@ -444,13 +443,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) if (curp->gzip == 0 && S_ISREG(st.st_mode)) { if (st.st_size > 0x7fffffff) { mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL); - return 0; + return -1; } *with_mmap = 1; fb->sz = (size_t)st.st_size; fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0); if (fb->buf != MAP_FAILED) - return 1; + return 0; } if (curp->gzip) { @@ -462,15 +461,15 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) * which this function must not do. */ if ((fd = dup(fd)) == -1) { - mandoc_msg(MANDOCERR_FILE, 0, 0, - "dup: %s", strerror(errno)); - return 0; + mandoc_msg(MANDOCERR_DUP, 0, 0, + "%s", strerror(errno)); + return -1; } if ((gz = gzdopen(fd, "rb")) == NULL) { - mandoc_msg(MANDOCERR_FILE, 0, 0, - "gzdopen: %s", strerror(errno)); + mandoc_msg(MANDOCERR_GZDOPEN, 0, 0, + "%s", strerror(errno)); close(fd); - return 0; + return -1; } } else gz = NULL; @@ -482,7 +481,7 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) *with_mmap = 0; off = 0; - retval = 0; + retval = -1; fb->sz = 0; fb->buf = NULL; for (;;) { @@ -498,13 +497,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) read(fd, fb->buf + (int)off, fb->sz - off); if (ssz == 0) { fb->sz = off; - retval = 1; + retval = 0; break; } if (ssz == -1) { if (curp->gzip) (void)gzerror(gz, &gzerrnum); - mandoc_msg(MANDOCERR_FILE, 0, 0, "read: %s", + mandoc_msg(MANDOCERR_READ, 0, 0, "%s", curp->gzip && gzerrnum != Z_ERRNO ? zError(gzerrnum) : strerror(errno)); break; @@ -513,10 +512,10 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap) } if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK) - mandoc_msg(MANDOCERR_FILE, 0, 0, "gzclose: %s", + mandoc_msg(MANDOCERR_GZCLOSE, 0, 0, "%s", gzerrnum == Z_ERRNO ? strerror(errno) : zError(gzerrnum)); - if (retval == 0) { + if (retval == -1) { free(fb->buf); fb->buf = NULL; } @@ -555,7 +554,7 @@ mparse_readfd(struct mparse *curp, int fd, const char *filename) mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL); return; } - if (read_whole_file(curp, fd, &blk, &with_mmap) == 0) + if (read_whole_file(curp, fd, &blk, &with_mmap) == -1) return; /* diff --git a/usr.bin/mandoc/tag.c b/usr.bin/mandoc/tag.c index 6ae6faa2a7e..df05a19885a 100644 --- a/usr.bin/mandoc/tag.c +++ b/usr.bin/mandoc/tag.c @@ -1,6 +1,6 @@ -/* $OpenBSD: tag.c,v 1.21 2018/11/22 11:30:15 schwarze Exp $ */ +/* $OpenBSD: tag.c,v 1.22 2019/07/10 19:38:56 schwarze Exp $ */ /* - * Copyright (c) 2015, 2016, 2018 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2015, 2016, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ */ #include <sys/types.h> -#include <err.h> +#include <errno.h> #include <limits.h> #include <signal.h> #include <stddef.h> @@ -28,6 +28,7 @@ #include "mandoc_aux.h" #include "mandoc_ohash.h" +#include "mandoc.h" #include "tag.h" struct tag_entry { @@ -79,8 +80,10 @@ tag_init(void) /* Save the original standard output for use by the pager. */ - if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) + if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) { + mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno)); goto fail; + } /* Create both temporary output files. */ @@ -88,12 +91,20 @@ tag_init(void) sizeof(tag_files.ofn)); (void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX", sizeof(tag_files.tfn)); - if ((ofd = mkstemp(tag_files.ofn)) == -1) + if ((ofd = mkstemp(tag_files.ofn)) == -1) { + mandoc_msg(MANDOCERR_MKSTEMP, 0, 0, + "%s: %s", tag_files.ofn, strerror(errno)); goto fail; - if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) + } + if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) { + mandoc_msg(MANDOCERR_MKSTEMP, 0, 0, + "%s: %s", tag_files.tfn, strerror(errno)); goto fail; - if (dup2(ofd, STDOUT_FILENO) == -1) + } + if (dup2(ofd, STDOUT_FILENO) == -1) { + mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno)); goto fail; + } close(ofd); /* @@ -217,10 +228,11 @@ tag_write(void) return; if (tag_files.tagname != NULL && ohash_find(&tag_data, ohash_qlookup(&tag_data, tag_files.tagname)) == NULL) { - warnx("%s: no such tag", tag_files.tagname); + mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname); tag_files.tagname = NULL; } - stream = fdopen(tag_files.tfd, "w"); + if ((stream = fdopen(tag_files.tfd, "w")) == NULL) + mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno)); entry = ohash_first(&tag_data, &slot); while (entry != NULL) { if (stream != NULL && entry->prio >= 0) |