aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/main.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2020-02-24 21:16:31 +0000
committerIngo Schwarze <schwarze@openbsd.org>2020-02-24 21:16:31 +0000
commit83ad1abc9ffe08ed430d83909fe1297738f5c224 (patch)
tree186ffcaf1c2b771cf58d1837352354e08d5ed7b4 /main.c
parent34bee6097a58670fc58c4e6bcf0516bda8db47d7 (diff)
downloadmandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.tar.gz
mandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.tar.zst
mandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.zip
Marc Espie reported that "man p*ipc" displayed the perlipc(1) manual.
The reason was that as a last resort when failing to find a page name in mandoc.db(5) or at a few well well-defined fully qualified file names, man(1) uses glob(3) to look for candidate files in relevant directories, because some operating systems have weird file name extensions, for example pcap.3pcap and BF_set_key.3ssl on Linux. But during that globbing, the metacharacters "*?[" need to be escaped in the name, section, and path supplied by the user, or you would get weird false positives and misleading warning messages and would be unable to use the fallback for path or file names that actually contain an opening bracket. Feedback and OK espie@.
Diffstat (limited to 'main.c')
-rw-r--r--main.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/main.c b/main.c
index b84a9a2b..862eb9bf 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.343 2020/02/10 13:49:15 schwarze Exp $ */
+/* $Id: main.c,v 1.344 2020/02/24 21:16:31 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
@@ -98,6 +98,7 @@ static int fs_lookup(const struct manpaths *,
static int fs_search(const struct mansearch *,
const struct manpaths *, const char *,
struct manpage **, size_t *);
+static void glob_esc(char **, const char *, const char *);
static void outdata_alloc(struct outstate *, struct manoutput *);
static void parse(struct mparse *, int, const char *,
struct outstate *, struct manoutput *);
@@ -674,6 +675,18 @@ usage(enum argmode argmode)
exit((int)MANDOCLEVEL_BADARG);
}
+static void
+glob_esc(char **dst, const char *src, const char *suffix)
+{
+ while (*src != '\0') {
+ if (strchr("*?[", *src) != NULL)
+ *(*dst)++ = '\\';
+ *(*dst)++ = *src++;
+ }
+ while (*suffix != '\0')
+ *(*dst)++ = *suffix++;
+}
+
static int
fs_lookup(const struct manpaths *paths, size_t ipath,
const char *sec, const char *arch, const char *name,
@@ -682,10 +695,14 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
struct stat sb;
glob_t globinfo;
struct manpage *page;
- char *file;
+ char *file, *cp;
int globres;
enum form form;
+ const char *const slman = "/man";
+ const char *const slash = "/";
+ const char *const sglob = ".[01-9]*";
+
form = FORM_SRC;
mandoc_asprintf(&file, "%s/man%s/%s.%s",
paths->paths[ipath], sec, name, sec);
@@ -709,8 +726,13 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
free(file);
}
- mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*",
- paths->paths[ipath], sec, name);
+ cp = file = mandoc_malloc(strlen(paths->paths[ipath]) * 2 +
+ strlen(slman) + strlen(sec) * 2 + strlen(slash) +
+ strlen(name) * 2 + strlen(sglob) + 1);
+ glob_esc(&cp, paths->paths[ipath], slman);
+ glob_esc(&cp, sec, slash);
+ glob_esc(&cp, name, sglob);
+ *cp = '\0';
globres = glob(file, 0, NULL, &globinfo);
if (globres != 0 && globres != GLOB_NOMATCH)
mandoc_msg(MANDOCERR_GLOB, 0, 0,