aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/main.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2018-04-19 16:25:24 +0000
committerIngo Schwarze <schwarze@openbsd.org>2018-04-19 16:25:24 +0000
commitd839f1a31781f443242ffdea67c7266ad9c9901d (patch)
treefd66a157b8dc8f2ecfcbe94a2ef6b70f57fd226e /main.c
parent06eb86b87d44317103ec40cf10b2ed1e9f5d0927 (diff)
downloadmandoc-d839f1a31781f443242ffdea67c7266ad9c9901d.tar.gz
mandoc-d839f1a31781f443242ffdea67c7266ad9c9901d.tar.zst
mandoc-d839f1a31781f443242ffdea67c7266ad9c9901d.zip
Compatibility with man-db:
In page name mode (= man(1) default mode), also try to interpret names containing slashes as absolute or relative file names. Missing feature reported by Nate Bargmann on <groff at gnu dot org>, and the man-db maintainer Colin Watson <cjwatson at debian dot org> kindly explained to me how this is supposed to work.
Diffstat (limited to 'main.c')
-rw-r--r--main.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/main.c b/main.c
index 7ae27dca..67827b2b 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.304 2018/04/13 19:55:30 schwarze Exp $ */
+/* $Id: main.c,v 1.305 2018/04/19 16:25:24 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -132,7 +132,7 @@ main(int argc, char *argv[])
size_t i, sz;
int prio, best_prio;
enum outmode outmode;
- int fd;
+ int fd, startdir;
int show_usage;
int options;
int use_pager;
@@ -386,15 +386,34 @@ main(int argc, char *argv[])
argc, argv, &res, &sz))
usage(search.argmode);
- if (sz == 0) {
- if (search.argmode == ARG_NAME)
- fs_search(&search, &conf.manpath,
- argc, argv, &res, &sz);
- else
- warnx("nothing appropriate");
+ if (sz == 0 && search.argmode == ARG_NAME)
+ fs_search(&search, &conf.manpath,
+ argc, argv, &res, &sz);
+
+ if (search.argmode == ARG_NAME) {
+ for (c = 0; c < argc; c++) {
+ if (strchr(argv[c], '/') == NULL)
+ continue;
+ if (access(argv[c], R_OK) == -1) {
+ warn("%s", argv[c]);
+ continue;
+ }
+ res = mandoc_reallocarray(res,
+ sz + 1, sizeof(*res));
+ res[sz].file = mandoc_strdup(argv[c]);
+ res[sz].names = NULL;
+ res[sz].output = NULL;
+ res[sz].ipath = SIZE_MAX;
+ res[sz].bits = 0;
+ res[sz].sec = 10;
+ res[sz].form = FORM_SRC;
+ sz++;
+ }
}
if (sz == 0) {
+ if (search.argmode != ARG_NAME)
+ warnx("nothing appropriate");
rc = MANDOCLEVEL_BADARG;
goto out;
}
@@ -478,7 +497,29 @@ main(int argc, char *argv[])
parse(&curp, STDIN_FILENO, "<stdin>");
}
+ /*
+ * Remember the original working directory, if possible.
+ * This will be needed if some names on the command line
+ * are page names and some are relative file names.
+ * Do not error out if the current directory is not
+ * readable: Maybe it won't be needed after all.
+ */
+ startdir = open(".", O_RDONLY | O_DIRECTORY);
+
while (argc > 0) {
+
+ /*
+ * Changing directories is not needed in ARG_FILE mode.
+ * Do it on a best-effort basis. Even in case of
+ * failure, some functionality may still work.
+ */
+ if (resp != NULL) {
+ if (resp->ipath != SIZE_MAX)
+ (void)chdir(conf.manpath.paths[resp->ipath]);
+ else if (startdir != -1)
+ (void)fchdir(startdir);
+ }
+
fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv);
if (fd != -1) {
if (use_pager) {
@@ -488,11 +529,9 @@ main(int argc, char *argv[])
if (resp == NULL)
parse(&curp, fd, *argv);
- else if (resp->form == FORM_SRC) {
- /* For .so only; ignore failure. */
- (void)chdir(conf.manpath.paths[resp->ipath]);
+ else if (resp->form == FORM_SRC)
parse(&curp, fd, resp->file);
- } else
+ else
passthrough(resp->file, fd,
conf.output.synopsisonly);
@@ -525,6 +564,10 @@ main(int argc, char *argv[])
if (--argc)
mparse_reset(curp.mp);
}
+ if (startdir != -1) {
+ (void)fchdir(startdir);
+ close(startdir);
+ }
if (curp.outdata != NULL) {
switch (curp.outtype) {
@@ -745,7 +788,8 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
cfg->firstmatch)
return 1;
}
- if (res != NULL && *ressz == lastsz)
+ if (res != NULL && *ressz == lastsz &&
+ strchr(*argv, '/') == NULL)
warnx("No entry for %s in the manual.", *argv);
lastsz = *ressz;
argv++;