=================================================================== RCS file: /cvs/mandoc/main.c,v retrieving revision 1.355 retrieving revision 1.359 diff -u -p -r1.355 -r1.359 --- mandoc/main.c 2021/06/02 18:28:19 1.355 +++ mandoc/main.c 2021/10/04 20:24:06 1.359 @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.355 2021/06/02 18:28:19 schwarze Exp $ */ +/* $Id: main.c,v 1.359 2021/10/04 20:24:06 schwarze Exp $ */ /* * Copyright (c) 2010-2012, 2014-2021 Ingo Schwarze * Copyright (c) 2008-2012 Kristaps Dzonsons @@ -94,10 +94,12 @@ struct outstate { int mandocdb(int, char *[]); static void check_xr(struct manpaths *); -static int fs_lookup(const struct manpaths *, - size_t ipath, const char *, - const char *, const char *, +static void fs_append(char **, size_t, int, + size_t, const char *, enum form, struct manpage **, size_t *); +static int fs_lookup(const struct manpaths *, size_t, + const char *, const char *, const char *, + struct manpage **, size_t *); static int fs_search(const struct mansearch *, const struct manpaths *, const char *, struct manpage **, size_t *); @@ -130,7 +132,7 @@ main(int argc, char *argv[]) struct mparse *mp; /* Opaque parser object. */ const char *conf_file; /* -C: alternate config file. */ const char *os_s; /* -I: Operating system for display. */ - const char *progname, *sec; + const char *progname, *sec, *ep; char *defpaths; /* -M: override manpaths. */ char *auxpaths; /* -m: additional manpaths. */ char *oarg; /* -O: output option string. */ @@ -514,6 +516,9 @@ main(int argc, char *argv[]) memcpy(res + ressz, resn, sizeof(*resn) * resnsz); ressz += resnsz; + free(resn); + resn = NULL; + resnsz = 0; continue; } @@ -534,11 +539,16 @@ main(int argc, char *argv[]) sec++; /* Prefer without suffix. */ if (*sec != '/') prio += 10; /* Wrong dir name. */ - if (search.sec != NULL && - (strlen(sec) <= ssz + 3 || - strcmp(sec + strlen(sec) - ssz, - search.sec) != 0)) - prio += 20; /* Wrong file ext. */ + if (search.sec != NULL) { + ep = strchr(sec, '\0'); + if (ep - sec > 3 && + strncmp(ep - 3, ".gz", 3) == 0) + ep -= 3; + if ((size_t)(ep - sec) < ssz + 3 || + strncmp(ep - ssz, search.sec, + ssz) != 0) /* Wrong file */ + prio += 20; /* extension. */ + } if (prio >= best_prio) continue; best_prio = prio; @@ -547,6 +557,10 @@ main(int argc, char *argv[]) res = mandoc_reallocarray(res, ressz + 1, sizeof(*res)); memcpy(res + ressz++, resn + ib, sizeof(*resn)); + memset(resn + ib, 0, sizeof(*resn)); + mansearch_free(resn, resnsz); + resn = NULL; + resnsz = 0; } /* apropos(1), whatis(1): Process the full search expression. */ @@ -700,6 +714,30 @@ glob_esc(char **dst, const char *src, const char *suff *(*dst)++ = *suffix++; } +static void +fs_append(char **file, size_t filesz, int copy, size_t ipath, + const char *sec, enum form form, struct manpage **res, size_t *ressz) +{ + struct manpage *page; + + *res = mandoc_reallocarray(*res, *ressz + filesz, sizeof(**res)); + page = *res + *ressz; + *ressz += filesz; + for (;;) { + page->file = copy ? mandoc_strdup(*file) : *file; + page->names = NULL; + page->output = NULL; + page->bits = NAME_FILE & NAME_MASK; + page->ipath = ipath; + page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; + page->form = form; + if (--filesz == 0) + break; + file++; + page++; + } +} + static int fs_lookup(const struct manpaths *paths, size_t ipath, const char *sec, const char *arch, const char *name, @@ -707,16 +745,19 @@ fs_lookup(const struct manpaths *paths, size_t ipath, { struct stat sb; glob_t globinfo; - struct manpage *page; - char *file, *cp; + char *file, *cp, secnum[2]; int globres; enum form form; const char *const slman = "/man"; const char *const slash = "/"; const char *const sglob = ".[01-9]*"; + const char *const dot = "."; + const char *const aster = "*"; + memset(&globinfo, 0, sizeof(globinfo)); form = FORM_SRC; + mandoc_asprintf(&file, "%s/man%s/%s.%s", paths->paths[ipath], sec, name, sec); if (stat(file, &sb) != -1) @@ -751,14 +792,34 @@ fs_lookup(const struct manpaths *paths, size_t ipath, mandoc_msg(MANDOCERR_GLOB, 0, 0, "%s: %s", file, strerror(errno)); free(file); + file = NULL; if (globres == 0) - file = mandoc_strdup(*globinfo.gl_pathv); + goto found; globfree(&globinfo); - if (globres == 0) { - if (stat(file, &sb) != -1) - goto found; + + if (sec[1] != '\0' && *ressz == 0) { + secnum[0] = sec[0]; + secnum[1] = '\0'; + cp = file = mandoc_malloc(strlen(paths->paths[ipath]) * 2 + + strlen(slman) + strlen(secnum) * 2 + strlen(slash) + + strlen(name) * 2 + strlen(dot) + + strlen(sec) * 2 + strlen(aster) + 1); + glob_esc(&cp, paths->paths[ipath], slman); + glob_esc(&cp, secnum, slash); + glob_esc(&cp, name, dot); + glob_esc(&cp, sec, aster); + *cp = '\0'; + globres = glob(file, 0, NULL, &globinfo); + if (globres != 0 && globres != GLOB_NOMATCH) + mandoc_msg(MANDOCERR_GLOB, 0, 0, + "%s: %s", file, strerror(errno)); free(file); + file = NULL; + if (globres == 0) + goto found; + globfree(&globinfo); } + if (res != NULL || ipath + 1 != paths->sz) return -1; @@ -770,19 +831,14 @@ fs_lookup(const struct manpaths *paths, size_t ipath, found: warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s", name, sec, BINM_MAKEWHATIS, paths->paths[ipath]); - if (res == NULL) { + if (res == NULL) free(file); - return 0; - } - *res = mandoc_reallocarray(*res, ++*ressz, sizeof(**res)); - page = *res + (*ressz - 1); - page->file = file; - page->names = NULL; - page->output = NULL; - page->bits = NAME_FILE & NAME_MASK; - page->ipath = ipath; - page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; - page->form = form; + else if (file == NULL) + fs_append(globinfo.gl_pathv, globinfo.gl_pathc, 1, + ipath, sec, form, res, ressz); + else + fs_append(&file, 1, 0, ipath, sec, form, res, ressz); + globfree(&globinfo); return 0; } @@ -967,6 +1023,9 @@ parse(struct mparse *mp, int fd, const char *file, case OUTT_LOCALE: case OUTT_PS: terminal_man(outst->outdata, meta); + break; + case OUTT_MARKDOWN: + mandoc_msg(MANDOCERR_MAN_TMARKDOWN, 0, 0, NULL); break; default: break;