version 1.148, 2014/05/07 16:19:03 |
version 1.155, 2014/08/06 15:09:05 |
Line 145 static int dbopen(int); |
|
Line 145 static int dbopen(int); |
|
static void dbprune(void); |
static void dbprune(void); |
static void filescan(const char *); |
static void filescan(const char *); |
static void *hash_alloc(size_t, void *); |
static void *hash_alloc(size_t, void *); |
static void hash_free(void *, size_t, void *); |
static void hash_free(void *, void *); |
static void *hash_halloc(size_t, void *); |
static void *hash_calloc(size_t, size_t, void *); |
static void mlink_add(struct mlink *, const struct stat *); |
static void mlink_add(struct mlink *, const struct stat *); |
static void mlink_check(struct mpage *, struct mlink *); |
static void mlink_check(struct mpage *, struct mlink *); |
static void mlink_free(struct mlink *); |
static void mlink_free(struct mlink *); |
Line 336 main(int argc, char *argv[]) |
|
Line 336 main(int argc, char *argv[]) |
|
memset(&dirs, 0, sizeof(struct manpaths)); |
memset(&dirs, 0, sizeof(struct manpaths)); |
|
|
mpages_info.alloc = mlinks_info.alloc = hash_alloc; |
mpages_info.alloc = mlinks_info.alloc = hash_alloc; |
mpages_info.halloc = mlinks_info.halloc = hash_halloc; |
mpages_info.calloc = mlinks_info.calloc = hash_calloc; |
mpages_info.hfree = mlinks_info.hfree = hash_free; |
mpages_info.free = mlinks_info.free = hash_free; |
|
|
mpages_info.key_offset = offsetof(struct mpage, inodev); |
mpages_info.key_offset = offsetof(struct mpage, inodev); |
mlinks_info.key_offset = offsetof(struct mlink, file); |
mlinks_info.key_offset = offsetof(struct mlink, file); |
Line 355 main(int argc, char *argv[]) |
|
Line 355 main(int argc, char *argv[]) |
|
*/ |
*/ |
#define CHECKOP(_op, _ch) do \ |
#define CHECKOP(_op, _ch) do \ |
if (OP_DEFAULT != (_op)) { \ |
if (OP_DEFAULT != (_op)) { \ |
fprintf(stderr, "-%c: Conflicting option\n", (_ch)); \ |
fprintf(stderr, "%s: -%c: Conflicting option\n", \ |
|
progname, (_ch)); \ |
goto usage; \ |
goto usage; \ |
} while (/*CONSTCOND*/0) |
} while (/*CONSTCOND*/0) |
|
|
Line 391 main(int argc, char *argv[]) |
|
Line 392 main(int argc, char *argv[]) |
|
break; |
break; |
case 'T': |
case 'T': |
if (strcmp(optarg, "utf8")) { |
if (strcmp(optarg, "utf8")) { |
fprintf(stderr, "-T%s: Unsupported " |
fprintf(stderr, "%s: -T%s: " |
"output format\n", optarg); |
"Unsupported output format\n", |
|
progname, optarg); |
goto usage; |
goto usage; |
} |
} |
write_utf8 = 1; |
write_utf8 = 1; |
Line 419 main(int argc, char *argv[]) |
|
Line 421 main(int argc, char *argv[]) |
|
argv += optind; |
argv += optind; |
|
|
if (OP_CONFFILE == op && argc > 0) { |
if (OP_CONFFILE == op && argc > 0) { |
fprintf(stderr, "-C: Too many arguments\n"); |
fprintf(stderr, "%s: -C: Too many arguments\n", |
|
progname); |
goto usage; |
goto usage; |
} |
} |
|
|
Line 433 main(int argc, char *argv[]) |
|
Line 436 main(int argc, char *argv[]) |
|
if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { |
if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { |
|
|
/* |
/* |
* All of these deal with a specific directory. |
* Most of these deal with a specific directory. |
* Jump into that directory first. |
* Jump into that directory first. |
*/ |
*/ |
if (0 == set_basedir(path_arg)) |
if (OP_TEST != op && 0 == set_basedir(path_arg)) |
goto out; |
goto out; |
|
|
if (dbopen(1)) { |
if (dbopen(1)) { |
Line 506 main(int argc, char *argv[]) |
|
Line 509 main(int argc, char *argv[]) |
|
goto out; |
goto out; |
if (0 == treescan()) |
if (0 == treescan()) |
goto out; |
goto out; |
if (0 == set_basedir(dirs.paths[j])) |
|
goto out; |
|
if (0 == dbopen(0)) |
if (0 == dbopen(0)) |
goto out; |
goto out; |
|
|
Line 525 main(int argc, char *argv[]) |
|
Line 526 main(int argc, char *argv[]) |
|
} |
} |
} |
} |
out: |
out: |
set_basedir(NULL); |
|
manpath_free(&dirs); |
manpath_free(&dirs); |
mchars_free(mc); |
mchars_free(mc); |
mparse_free(mp); |
mparse_free(mp); |
Line 800 filescan(const char *file) |
|
Line 800 filescan(const char *file) |
|
return; |
return; |
} |
} |
|
|
if (strstr(buf, basedir) == buf) |
if (OP_TEST == op) |
start = buf + strlen(basedir) + 1; |
|
else if (OP_TEST == op) |
|
start = buf; |
start = buf; |
|
else if (strstr(buf, basedir) == buf) |
|
start = buf + strlen(basedir); |
else { |
else { |
exitcode = (int)MANDOCLEVEL_BADARG; |
exitcode = (int)MANDOCLEVEL_BADARG; |
say("", "%s: outside base directory", buf); |
say("", "%s: outside base directory", buf); |
Line 829 filescan(const char *file) |
|
Line 829 filescan(const char *file) |
|
say(file, "Filename too long"); |
say(file, "Filename too long"); |
return; |
return; |
} |
} |
start = strstr(buf, basedir) == buf ? |
start = buf; |
buf + strlen(basedir) + 1 : buf; |
if (OP_TEST != op && strstr(buf, basedir) == buf) |
|
start += strlen(basedir); |
} |
} |
|
|
mlink = mandoc_calloc(1, sizeof(struct mlink)); |
mlink = mandoc_calloc(1, sizeof(struct mlink)); |
Line 1090 mpages_merge(struct mchars *mc, struct mparse *mp) |
|
Line 1091 mpages_merge(struct mchars *mc, struct mparse *mp) |
|
enum mandoclevel lvl; |
enum mandoclevel lvl; |
|
|
str_info.alloc = hash_alloc; |
str_info.alloc = hash_alloc; |
str_info.halloc = hash_halloc; |
str_info.calloc = hash_calloc; |
str_info.hfree = hash_free; |
str_info.free = hash_free; |
str_info.key_offset = offsetof(struct str, key); |
str_info.key_offset = offsetof(struct str, key); |
|
|
if (0 == nodb) |
if (0 == nodb) |
Line 1197 mpages_merge(struct mchars *mc, struct mparse *mp) |
|
Line 1198 mpages_merge(struct mchars *mc, struct mparse *mp) |
|
goto nextpage; |
goto nextpage; |
} else if (NULL != mdoc) { |
} else if (NULL != mdoc) { |
mpage->form = FORM_SRC; |
mpage->form = FORM_SRC; |
mpage->sec = |
mpage->sec = mdoc_meta(mdoc)->msec; |
mandoc_strdup(mdoc_meta(mdoc)->msec); |
mpage->sec = mandoc_strdup( |
|
NULL == mpage->sec ? "" : mpage->sec); |
mpage->arch = mdoc_meta(mdoc)->arch; |
mpage->arch = mdoc_meta(mdoc)->arch; |
mpage->arch = mandoc_strdup( |
mpage->arch = mandoc_strdup( |
NULL == mpage->arch ? "" : mpage->arch); |
NULL == mpage->arch ? "" : mpage->arch); |
Line 1305 names_check(void) |
|
Line 1307 names_check(void) |
|
say("", "%s", sqlite3_errmsg(db)); |
say("", "%s", sqlite3_errmsg(db)); |
|
|
while (SQLITE_ROW == (irc = sqlite3_step(stmt))) { |
while (SQLITE_ROW == (irc = sqlite3_step(stmt))) { |
name = sqlite3_column_text(stmt, 0); |
name = (const char *)sqlite3_column_text(stmt, 0); |
sec = sqlite3_column_text(stmt, 1); |
sec = (const char *)sqlite3_column_text(stmt, 1); |
arch = sqlite3_column_text(stmt, 2); |
arch = (const char *)sqlite3_column_text(stmt, 2); |
key = sqlite3_column_text(stmt, 3); |
key = (const char *)sqlite3_column_text(stmt, 3); |
say("", "%s(%s%s%s) lacks mlink \"%s\"", name, sec, |
say("", "%s(%s%s%s) lacks mlink \"%s\"", name, sec, |
'\0' == *arch ? "" : "/", |
'\0' == *arch ? "" : "/", |
'\0' == *arch ? "" : arch, key); |
'\0' == *arch ? "" : arch, key); |
Line 2230 dbopen(int real) |
|
Line 2232 dbopen(int real) |
|
rc = sqlite3_open_v2(MANDOC_DB, &db, ofl, NULL); |
rc = sqlite3_open_v2(MANDOC_DB, &db, ofl, NULL); |
if (SQLITE_OK != rc) { |
if (SQLITE_OK != rc) { |
exitcode = (int)MANDOCLEVEL_SYSERR; |
exitcode = (int)MANDOCLEVEL_SYSERR; |
say(MANDOC_DB, "%s", sqlite3_errstr(rc)); |
if (SQLITE_CANTOPEN != rc) |
|
say(MANDOC_DB, "%s", sqlite3_errstr(rc)); |
return(0); |
return(0); |
} |
} |
goto prepare_statements; |
goto prepare_statements; |
Line 2349 prepare_statements: |
|
Line 2352 prepare_statements: |
|
} |
} |
|
|
static void * |
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 * |
static void * |
Line 2363 hash_alloc(size_t sz, void *arg) |
|
Line 2366 hash_alloc(size_t sz, void *arg) |
|
} |
} |
|
|
static void |
static void |
hash_free(void *p, size_t sz, void *arg) |
hash_free(void *p, void *arg) |
{ |
{ |
|
|
free(p); |
free(p); |
|
|
set_basedir(const char *targetdir) |
set_basedir(const char *targetdir) |
{ |
{ |
static char startdir[PATH_MAX]; |
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 |
* Remember the original working directory, if possible. |
* path component: throughout this utility, we chdir() a lot to |
* This will be needed if the second or a later directory |
* handle relative paths, and by doing this, we can return to |
* on the command line is given as a relative path. |
* the starting point. |
* Do not error out if the current directory is not |
|
* searchable: Maybe it won't be needed after all. |
*/ |
*/ |
if ('\0' == *startdir) { |
if (0 == getcwd_status) { |
if (NULL == getcwd(startdir, PATH_MAX)) { |
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; |
exitcode = (int)MANDOCLEVEL_SYSERR; |
if (NULL != targetdir) |
say("", "getcwd: %s", startdir); |
say("", "&getcwd"); |
|
return(0); |
return(0); |
} |
} |
if (-1 == (fd = open(startdir, O_RDONLY, 0))) { |
if (-1 == chdir(startdir)) { |
exitcode = (int)MANDOCLEVEL_SYSERR; |
exitcode = (int)MANDOCLEVEL_SYSERR; |
say("", "&open %s", startdir); |
|
return(0); |
|
} |
|
if (NULL == targetdir) |
|
targetdir = startdir; |
|
} else { |
|
if (-1 == fd) |
|
return(0); |
|
if (-1 == fchdir(fd)) { |
|
close(fd); |
|
basedir[0] = '\0'; |
|
exitcode = (int)MANDOCLEVEL_SYSERR; |
|
say("", "&chdir %s", startdir); |
say("", "&chdir %s", startdir); |
return(0); |
return(0); |
} |
} |
if (NULL == targetdir) { |
|
close(fd); |
|
return(1); |
|
} |
|
} |
} |
|
|
|
/* |
|
* 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)) { |
if (NULL == realpath(targetdir, basedir)) { |
basedir[0] = '\0'; |
|
exitcode = (int)MANDOCLEVEL_BADARG; |
exitcode = (int)MANDOCLEVEL_BADARG; |
say("", "&%s: realpath", targetdir); |
say("", "&%s: realpath", targetdir); |
return(0); |
return(0); |
Line 2420 set_basedir(const char *targetdir) |
|
Line 2434 set_basedir(const char *targetdir) |
|
say("", "&chdir"); |
say("", "&chdir"); |
return(0); |
return(0); |
} |
} |
|
chdir_status = 1; |
|
cp = strchr(basedir, '\0'); |
|
if ('/' != cp[-1]) { |
|
if (cp - basedir >= PATH_MAX - 1) { |
|
exitcode = (int)MANDOCLEVEL_SYSERR; |
|
say("", "Filename too long"); |
|
return(0); |
|
} |
|
*cp++ = '/'; |
|
*cp = '\0'; |
|
} |
return(1); |
return(1); |
} |
} |
|
|
Line 2432 say(const char *file, const char *format, ...) |
|
Line 2457 say(const char *file, const char *format, ...) |
|
if ('\0' != *basedir) |
if ('\0' != *basedir) |
fprintf(stderr, "%s", basedir); |
fprintf(stderr, "%s", basedir); |
if ('\0' != *basedir && '\0' != *file) |
if ('\0' != *basedir && '\0' != *file) |
fputs("//", stderr); |
fputc('/', stderr); |
if ('\0' != *file) |
if ('\0' != *file) |
fprintf(stderr, "%s", file); |
fprintf(stderr, "%s", file); |
|
|