]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandocdb.c
Improve build system and autodetection.
[mandoc.git] / mandocdb.c
index 152fe1c645681b007231b553a32591da708335c4..4203282f366c5ad660ff08029a0b3d479c74f5bd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.150 2014/06/19 00:45:37 schwarze Exp $ */
+/*     $Id: mandocdb.c,v 1.158 2014/08/16 19:00:01 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
  * 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 <sys/stat.h>
+#include <sys/types.h>
 #include <sys/wait.h>
 
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#if HAVE_FTS
 #include <fts.h>
+#else
+#include "compat_fts.h"
+#endif
 #include <getopt.h>
 #include <limits.h>
 #include <stddef.h>
@@ -36,7 +39,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef HAVE_OHASH
+#if HAVE_OHASH
 #include <ohash.h>
 #else
 #include "compat_ohash.h"
@@ -145,8 +148,8 @@ static      int      dbopen(int);
 static void     dbprune(void);
 static void     filescan(const char *);
 static void    *hash_alloc(size_t, void *);
-static void     hash_free(void *, size_t, void *);
-static void    *hash_halloc(size_t, void *);
+static void     hash_free(void *, void *);
+static void    *hash_calloc(size_t, size_t, void *);
 static void     mlink_add(struct mlink *, const struct stat *);
 static void     mlink_check(struct mpage *, struct mlink *);
 static void     mlink_free(struct mlink *);
@@ -336,8 +339,8 @@ main(int argc, char *argv[])
        memset(&dirs, 0, sizeof(struct manpaths));
 
        mpages_info.alloc  = mlinks_info.alloc  = hash_alloc;
-       mpages_info.halloc = mlinks_info.halloc = hash_halloc;
-       mpages_info.hfree  = mlinks_info.hfree  = hash_free;
+       mpages_info.calloc = mlinks_info.calloc = hash_calloc;
+       mpages_info.free  = mlinks_info.free  = hash_free;
 
        mpages_info.key_offset = offsetof(struct mpage, inodev);
        mlinks_info.key_offset = offsetof(struct mlink, file);
@@ -355,7 +358,8 @@ main(int argc, char *argv[])
         */
 #define        CHECKOP(_op, _ch) do \
        if (OP_DEFAULT != (_op)) { \
-               fprintf(stderr, "-%c: Conflicting option\n", (_ch)); \
+               fprintf(stderr, "%s: -%c: Conflicting option\n", \
+                   progname, (_ch)); \
                goto usage; \
        } while (/*CONSTCOND*/0)
 
@@ -391,8 +395,9 @@ main(int argc, char *argv[])
                        break;
                case 'T':
                        if (strcmp(optarg, "utf8")) {
-                               fprintf(stderr, "-T%s: Unsupported "
-                                   "output format\n", optarg);
+                               fprintf(stderr, "%s: -T%s: "
+                                   "Unsupported output format\n",
+                                   progname, optarg);
                                goto usage;
                        }
                        write_utf8 = 1;
@@ -419,7 +424,8 @@ main(int argc, char *argv[])
        argv += optind;
 
        if (OP_CONFFILE == op && argc > 0) {
-               fprintf(stderr, "-C: Too many arguments\n");
+               fprintf(stderr, "%s: -C: Too many arguments\n",
+                   progname);
                goto usage;
        }
 
@@ -506,8 +512,6 @@ main(int argc, char *argv[])
                                goto out;
                        if (0 == treescan())
                                goto out;
-                       if (0 == set_basedir(dirs.paths[j]))
-                               goto out;
                        if (0 == dbopen(0))
                                goto out;
 
@@ -1090,8 +1094,8 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
        enum mandoclevel         lvl;
 
        str_info.alloc = hash_alloc;
-       str_info.halloc = hash_halloc;
-       str_info.hfree = hash_free;
+       str_info.calloc = hash_calloc;
+       str_info.free = hash_free;
        str_info.key_offset = offsetof(struct str, key);
 
        if (0 == nodb)
@@ -1197,8 +1201,9 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
                        goto nextpage;
                } else if (NULL != mdoc) {
                        mpage->form = FORM_SRC;
-                       mpage->sec =
-                           mandoc_strdup(mdoc_meta(mdoc)->msec);
+                       mpage->sec = mdoc_meta(mdoc)->msec;
+                       mpage->sec = mandoc_strdup(
+                           NULL == mpage->sec ? "" : mpage->sec);
                        mpage->arch = mdoc_meta(mdoc)->arch;
                        mpage->arch = mandoc_strdup(
                            NULL == mpage->arch ? "" : mpage->arch);
@@ -1305,10 +1310,10 @@ names_check(void)
                say("", "%s", sqlite3_errmsg(db));
 
        while (SQLITE_ROW == (irc = sqlite3_step(stmt))) {
-               name = sqlite3_column_text(stmt, 0);
-               sec  = sqlite3_column_text(stmt, 1);
-               arch = sqlite3_column_text(stmt, 2);
-               key  = sqlite3_column_text(stmt, 3);
+               name = (const char *)sqlite3_column_text(stmt, 0);
+               sec  = (const char *)sqlite3_column_text(stmt, 1);
+               arch = (const char *)sqlite3_column_text(stmt, 2);
+               key  = (const char *)sqlite3_column_text(stmt, 3);
                say("", "%s(%s%s%s) lacks mlink \"%s\"", name, sec,
                    '\0' == *arch ? "" : "/",
                    '\0' == *arch ? "" : arch, key);
@@ -2350,10 +2355,10 @@ prepare_statements:
 }
 
 static void *
-hash_halloc(size_t sz, void *arg)
+hash_calloc(size_t n, size_t sz, void *arg)
 {
 
-       return(mandoc_calloc(1, sz));
+       return(mandoc_calloc(n, sz));
 }
 
 static void *
@@ -2364,7 +2369,7 @@ hash_alloc(size_t sz, void *arg)
 }
 
 static void
-hash_free(void *p, size_t sz, void *arg)
+hash_free(void *p, void *arg)
 {
 
        free(p);
@@ -2374,39 +2379,56 @@ static int
 set_basedir(const char *targetdir)
 {
        static char      startdir[PATH_MAX];
-       static int       fd;
+       static int       getcwd_status;  /* 1 = ok, 2 = failure */
+       static int       chdir_status;  /* 1 = changed directory */
        char            *cp;
 
        /*
-        * Remember where we started by keeping a fd open to the origin
-        * path component: throughout this utility, we chdir() a lot to
-        * handle relative paths, and by doing this, we can return to
-        * the starting point.
+        * Remember the original working directory, if possible.
+        * This will be needed if the second or a later directory
+        * on the command line is given as a relative path.
+        * Do not error out if the current directory is not
+        * searchable: Maybe it won't be needed after all.
         */
-       if ('\0' == *startdir) {
-               if (NULL == getcwd(startdir, PATH_MAX)) {
-                       exitcode = (int)MANDOCLEVEL_SYSERR;
-                       say("", "&getcwd");
-                       return(0);
-               }
-               if (-1 == (fd = open(startdir, O_RDONLY, 0))) {
+       if (0 == getcwd_status) {
+               if (NULL == getcwd(startdir, sizeof(startdir))) {
+                       getcwd_status = 2;
+                       (void)strlcpy(startdir, strerror(errno),
+                           sizeof(startdir));
+               } else
+                       getcwd_status = 1;
+       }
+
+       /*
+        * We are leaving the old base directory.
+        * Do not use it any longer, not even for messages.
+        */
+       *basedir = '\0';
+
+       /*
+        * If and only if the directory was changed earlier and
+        * the next directory to process is given as a relative path,
+        * first go back, or bail out if that is impossible.
+        */
+       if (chdir_status && '/' != *targetdir) {
+               if (2 == getcwd_status) {
                        exitcode = (int)MANDOCLEVEL_SYSERR;
-                       say("", "&open %s", startdir);
+                       say("", "getcwd: %s", startdir);
                        return(0);
                }
-       } else {
-               if (-1 == fd)
-                       return(0);
-               if (-1 == fchdir(fd)) {
-                       close(fd);
-                       basedir[0] = '\0';
+               if (-1 == chdir(startdir)) {
                        exitcode = (int)MANDOCLEVEL_SYSERR;
                        say("", "&chdir %s", startdir);
                        return(0);
                }
        }
+
+       /*
+        * Always resolve basedir to the canonicalized absolute
+        * pathname and append a trailing slash, such that
+        * we can reliably check whether files are inside.
+        */
        if (NULL == realpath(targetdir, basedir)) {
-               basedir[0] = '\0';
                exitcode = (int)MANDOCLEVEL_BADARG;
                say("", "&%s: realpath", targetdir);
                return(0);
@@ -2415,6 +2437,7 @@ set_basedir(const char *targetdir)
                say("", "&chdir");
                return(0);
        }
+       chdir_status = 1;
        cp = strchr(basedir, '\0');
        if ('/' != cp[-1]) {
                if (cp - basedir >= PATH_MAX - 1) {
@@ -2437,7 +2460,7 @@ say(const char *file, const char *format, ...)
        if ('\0' != *basedir)
                fprintf(stderr, "%s", basedir);
        if ('\0' != *basedir && '\0' != *file)
-               fputs("//", stderr);
+               fputc('/', stderr);
        if ('\0' != *file)
                fprintf(stderr, "%s", file);