From 3258c68b4000930085486b62a429c8912720e4f1 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Sat, 5 Oct 2013 20:30:05 +0000 Subject: Cleanup suggested by gcc-4.8.1, following hints by Christos Zoulas: - avoid bad qualifier casting in roff.c, roff_parsetext() by changing the mandoc_escape arguments to "const char const **" - avoid bad qualifier casting in mandocdb.c, index_merge() - do not complain about unused variables in test-*.c - garbage collect a few unused variables elsewhere --- Makefile | 14 +- apropos_db.c | 5 +- catman.c | 509 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mandocdb.c | 6 +- 4 files changed, 522 insertions(+), 12 deletions(-) create mode 100644 catman.c diff --git a/Makefile b/Makefile index 044d0872..f9f33742 100644 --- a/Makefile +++ b/Makefile @@ -390,31 +390,31 @@ config.h: config.h.pre config.h.post rm -f config.log ( cat config.h.pre; \ echo; \ - if $(CC) $(CFLAGS) -Werror -o test-fgetln test-fgetln.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-fgetln test-fgetln.c >> config.log 2>&1; then \ echo '#define HAVE_FGETLN'; \ rm test-fgetln; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-strptime test-strptime.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strptime test-strptime.c >> config.log 2>&1; then \ echo '#define HAVE_STRPTIME'; \ rm test-strptime; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \ echo '#define HAVE_GETSUBOPT'; \ rm test-getsubopt; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-strlcat test-strlcat.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcat test-strlcat.c >> config.log 2>&1; then \ echo '#define HAVE_STRLCAT'; \ rm test-strlcat; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-mmap test-mmap.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-mmap test-mmap.c >> config.log 2>&1; then \ echo '#define HAVE_MMAP'; \ rm test-mmap; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \ echo '#define HAVE_STRLCPY'; \ rm test-strlcpy; \ fi; \ - if $(CC) $(CFLAGS) -Werror -o test-betoh64 test-betoh64.c >> config.log 2>&1; then \ + if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-betoh64 test-betoh64.c >> config.log 2>&1; then \ echo '#define HAVE_BETOH64'; \ rm test-betoh64; \ fi; \ diff --git a/apropos_db.c b/apropos_db.c index 61002ee5..1ec3c9c2 100644 --- a/apropos_db.c +++ b/apropos_db.c @@ -1,4 +1,4 @@ -/* $Id: apropos_db.c,v 1.32.2.1 2013/10/02 21:03:26 schwarze Exp $ */ +/* $Id: apropos_db.c,v 1.32.2.2 2013/10/05 20:30:05 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -414,11 +414,10 @@ apropos_search(int pathsz, char **paths, const struct opts *opts, { struct rectree tree; struct mchars *mc; - int i, rc; + int i; memset(&tree, 0, sizeof(struct rectree)); - rc = 0; mc = mchars_alloc(); *sz = 0; *resp = NULL; diff --git a/catman.c b/catman.c new file mode 100644 index 00000000..2a75dc4e --- /dev/null +++ b/catman.c @@ -0,0 +1,509 @@ +/* $Id: catman.c,v 1.11.2.1 2013/10/05 20:30:05 schwarze Exp $ */ +/* + * Copyright (c) 2011 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +# include +#else +# include +#endif + +#include "manpath.h" +#include "mandocdb.h" + +#define xstrlcpy(_dst, _src, _sz) \ + do if (strlcpy((_dst), (_src), (_sz)) >= (_sz)) { \ + fprintf(stderr, "%s: Path too long", (_dst)); \ + exit(EXIT_FAILURE); \ + } while (/* CONSTCOND */0) + +#define xstrlcat(_dst, _src, _sz) \ + do if (strlcat((_dst), (_src), (_sz)) >= (_sz)) { \ + fprintf(stderr, "%s: Path too long", (_dst)); \ + exit(EXIT_FAILURE); \ + } while (/* CONSTCOND */0) + +static int indexhtml(char *, size_t, char *, size_t); +static int manup(const struct manpaths *, char *); +static int mkpath(char *, mode_t, mode_t); +static int treecpy(char *, char *); +static int update(char *, char *); +static void usage(void); + +static const char *progname; +static int verbose; +static int force; + +int +main(int argc, char *argv[]) +{ + int ch; + char *aux, *base, *conf_file; + struct manpaths dirs; + char buf[MAXPATHLEN]; + extern char *optarg; + extern int optind; + + progname = strrchr(argv[0], '/'); + if (progname == NULL) + progname = argv[0]; + else + ++progname; + + aux = base = conf_file = NULL; + xstrlcpy(buf, "/var/www/cache/man.cgi", MAXPATHLEN); + + while (-1 != (ch = getopt(argc, argv, "C:fm:M:o:v"))) + switch (ch) { + case ('C'): + conf_file = optarg; + break; + case ('f'): + force = 1; + break; + case ('m'): + aux = optarg; + break; + case ('M'): + base = optarg; + break; + case ('o'): + xstrlcpy(buf, optarg, MAXPATHLEN); + break; + case ('v'): + verbose++; + break; + default: + usage(); + return(EXIT_FAILURE); + } + + argc -= optind; + argv += optind; + + if (argc > 0) { + usage(); + return(EXIT_FAILURE); + } + + memset(&dirs, 0, sizeof(struct manpaths)); + manpath_parse(&dirs, conf_file, base, aux); + ch = manup(&dirs, buf); + manpath_free(&dirs); + return(ch ? EXIT_SUCCESS : EXIT_FAILURE); +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: %s " + "[-fv] " + "[-C file] " + "[-o path] " + "[-m manpath] " + "[-M manpath]\n", + progname); +} + +/* + * If "src" file doesn't exist (errors out), return -1. Otherwise, + * return 1 if "src" is newer (which also happens "dst" doesn't exist) + * and 0 otherwise. + */ +static int +isnewer(const char *dst, const char *src) +{ + struct stat s1, s2; + + if (-1 == stat(src, &s1)) + return(-1); + if (force) + return(1); + + return(-1 == stat(dst, &s2) ? 1 : s1.st_mtime > s2.st_mtime); +} + +/* + * Copy the contents of one file into another. + * Returns 0 on failure, 1 on success. + */ +static int +filecpy(const char *dst, const char *src) +{ + char buf[BUFSIZ]; + int sfd, dfd, rc; + ssize_t rsz, wsz; + + sfd = dfd = -1; + rc = 0; + + if (-1 == (dfd = open(dst, O_CREAT|O_TRUNC|O_WRONLY, 0644))) { + perror(dst); + goto out; + } else if (-1 == (sfd = open(src, O_RDONLY, 0))) { + perror(src); + goto out; + } + + while ((rsz = read(sfd, buf, BUFSIZ)) > 0) + if (-1 == (wsz = write(dfd, buf, (size_t)rsz))) { + perror(dst); + goto out; + } else if (wsz < rsz) { + fprintf(stderr, "%s: Short write\n", dst); + goto out; + } + + if (rsz < 0) + perror(src); + else + rc = 1; +out: + if (-1 != sfd) + close(sfd); + if (-1 != dfd) + close(dfd); + + return(rc); +} + +/* + * Pass over the recno database and re-create HTML pages if they're + * found to be out of date. + * Returns -1 on fatal error, 1 on success. + */ +static int +indexhtml(char *src, size_t ssz, char *dst, size_t dsz) +{ + DB *idx; + DBT key, val; + int c, rc; + unsigned int fl; + const char *f; + char *d; + char fname[MAXPATHLEN]; + + xstrlcpy(fname, dst, MAXPATHLEN); + xstrlcat(fname, "/", MAXPATHLEN); + xstrlcat(fname, MANDOC_IDX, MAXPATHLEN); + + idx = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL); + if (NULL == idx) { + perror(fname); + return(-1); + } + + fl = R_FIRST; + while (0 == (c = (*idx->seq)(idx, &key, &val, fl))) { + fl = R_NEXT; + /* + * If the record is zero-length, then it's unassigned. + * Skip past these. + */ + if (0 == val.size) + continue; + + f = (const char *)val.data + 1; + if (NULL == memchr(f, '\0', val.size - 1)) + break; + + src[(int)ssz] = dst[(int)dsz] = '\0'; + + xstrlcat(dst, "/", MAXPATHLEN); + xstrlcat(dst, f, MAXPATHLEN); + + xstrlcat(src, "/", MAXPATHLEN); + xstrlcat(src, f, MAXPATHLEN); + + if (-1 == (rc = isnewer(dst, src))) { + fprintf(stderr, "%s: File missing\n", f); + break; + } else if (0 == rc) + continue; + + d = strrchr(dst, '/'); + assert(NULL != d); + *d = '\0'; + + if (-1 == mkpath(dst, 0755, 0755)) { + perror(dst); + break; + } + + *d = '/'; + + if ( ! filecpy(dst, src)) + break; + if (verbose) + printf("%s\n", dst); + } + + (*idx->close)(idx); + + if (c < 0) + perror(fname); + else if (0 == c) + fprintf(stderr, "%s: Corrupt index\n", fname); + + return(1 == c ? 1 : -1); +} + +/* + * Copy both recno and btree databases into the destination. + * Call in to begin recreating HTML files. + * Return -1 on fatal error and 1 if the update went well. + */ +static int +update(char *dst, char *src) +{ + size_t dsz, ssz; + + dsz = strlen(dst); + ssz = strlen(src); + + xstrlcat(src, "/", MAXPATHLEN); + xstrlcat(dst, "/", MAXPATHLEN); + + xstrlcat(src, MANDOC_DB, MAXPATHLEN); + xstrlcat(dst, MANDOC_DB, MAXPATHLEN); + + if ( ! filecpy(dst, src)) + return(-1); + if (verbose) + printf("%s\n", dst); + + dst[(int)dsz] = src[(int)ssz] = '\0'; + + xstrlcat(src, "/", MAXPATHLEN); + xstrlcat(dst, "/", MAXPATHLEN); + + xstrlcat(src, MANDOC_IDX, MAXPATHLEN); + xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); + + if ( ! filecpy(dst, src)) + return(-1); + if (verbose) + printf("%s\n", dst); + + dst[(int)dsz] = src[(int)ssz] = '\0'; + + return(indexhtml(src, ssz, dst, dsz)); +} + +/* + * See if btree or recno databases in the destination are out of date + * with respect to a single manpath component. + * Return -1 on fatal error, 0 if the source is no longer valid (and + * shouldn't be listed), and 1 if the update went well. + */ +static int +treecpy(char *dst, char *src) +{ + size_t dsz, ssz; + int rc; + + dsz = strlen(dst); + ssz = strlen(src); + + xstrlcat(src, "/", MAXPATHLEN); + xstrlcat(dst, "/", MAXPATHLEN); + + xstrlcat(src, MANDOC_IDX, MAXPATHLEN); + xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); + + if (-1 == (rc = isnewer(dst, src))) + return(0); + + dst[(int)dsz] = src[(int)ssz] = '\0'; + + if (1 == rc) + return(update(dst, src)); + + xstrlcat(src, "/", MAXPATHLEN); + xstrlcat(dst, "/", MAXPATHLEN); + + xstrlcat(src, MANDOC_DB, MAXPATHLEN); + xstrlcat(dst, MANDOC_DB, MAXPATHLEN); + + if (-1 == (rc = isnewer(dst, src))) + return(0); + else if (rc == 0) + return(1); + + dst[(int)dsz] = src[(int)ssz] = '\0'; + + return(update(dst, src)); +} + +/* + * Update the destination's file-tree with respect to changes in the + * source manpath components. + * "Change" is defined by an updated index or btree database. + * Returns 1 on success, 0 on failure. + */ +static int +manup(const struct manpaths *dirs, char *base) +{ + char dst[MAXPATHLEN], + src[MAXPATHLEN]; + const char *path; + size_t i; + int c; + size_t sz; + FILE *f; + + /* Create the path and file for the catman.conf file. */ + + sz = strlen(base); + xstrlcpy(dst, base, MAXPATHLEN); + xstrlcat(dst, "/etc", MAXPATHLEN); + if (-1 == mkpath(dst, 0755, 0755)) { + perror(dst); + return(0); + } + + xstrlcat(dst, "/catman.conf", MAXPATHLEN); + if (NULL == (f = fopen(dst, "w"))) { + perror(dst); + return(0); + } else if (verbose) + printf("%s\n", dst); + + for (i = 0; i < dirs->sz; i++) { + path = dirs->paths[i]; + dst[(int)sz] = '\0'; + xstrlcat(dst, path, MAXPATHLEN); + if (-1 == mkpath(dst, 0755, 0755)) { + perror(dst); + break; + } + + xstrlcpy(src, path, MAXPATHLEN); + if (-1 == (c = treecpy(dst, src))) + break; + else if (0 == c) + continue; + + /* + * We want to use a relative path here because manpath.h + * will realpath() when invoked with man.cgi, and we'll + * make sure to chdir() into the cache directory before. + * + * This allows the cache directory to be in an arbitrary + * place, working in both chroot() and non-chroot() + * "safe" modes. + */ + assert('/' == path[0]); + fprintf(f, "_whatdb %s/whatis.db\n", path + 1); + } + + fclose(f); + return(i == dirs->sz); +} + +/* + * Copyright (c) 1983, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +static int +mkpath(char *path, mode_t mode, mode_t dir_mode) +{ + struct stat sb; + char *slash; + int done, exists; + + slash = path; + + for (;;) { + /* LINTED */ + slash += strspn(slash, "/"); + /* LINTED */ + slash += strcspn(slash, "/"); + + done = (*slash == '\0'); + *slash = '\0'; + + /* skip existing path components */ + exists = !stat(path, &sb); + if (!done && exists && S_ISDIR(sb.st_mode)) { + *slash = '/'; + continue; + } + + if (mkdir(path, done ? mode : dir_mode) == 0) { + if (mode > 0777 && chmod(path, mode) < 0) + return (-1); + } else { + if (!exists) { + /* Not there */ + return (-1); + } + if (!S_ISDIR(sb.st_mode)) { + /* Is there, but isn't a directory */ + errno = ENOTDIR; + return (-1); + } + } + + if (done) + break; + + *slash = '/'; + } + + return (0); +} diff --git a/mandocdb.c b/mandocdb.c index 028377cc..eb0b5052 100644 --- a/mandocdb.c +++ b/mandocdb.c @@ -1,4 +1,4 @@ -/* $Id: mandocdb.c,v 1.49.2.7 2013/10/02 21:03:26 schwarze Exp $ */ +/* $Id: mandocdb.c,v 1.49.2.8 2013/10/05 20:30:05 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2011, 2012 Ingo Schwarze @@ -620,6 +620,8 @@ index_merge(const struct of *of, struct mparse *mp, uint64_t vbuf[2]; char type; + static char emptystring[] = ""; + if (warnings) { files = NULL; hash_reset(&files); @@ -738,7 +740,7 @@ index_merge(const struct of *of, struct mparse *mp, val.data = NULL; val.size = 0; if (0 == skip) - val.data = ""; + val.data = emptystring; else { ch = (*files->get)(files, &key, &val, 0); if (ch < 0) { -- cgit v1.2.3-56-ge451