version 1.1, 2011/11/26 19:54:13 |
version 1.11, 2012/06/08 10:33:48 |
|
|
#endif |
#endif |
|
|
#include "manpath.h" |
#include "manpath.h" |
|
#include "mandocdb.h" |
|
|
#define xstrlcpy(_dst, _src, _sz) \ |
#define xstrlcpy(_dst, _src, _sz) \ |
do if (strlcpy((_dst), (_src), (_sz)) >= (_sz)) { \ |
do if (strlcpy((_dst), (_src), (_sz)) >= (_sz)) { \ |
|
|
exit(EXIT_FAILURE); \ |
exit(EXIT_FAILURE); \ |
} while (/* CONSTCOND */0) |
} while (/* CONSTCOND */0) |
|
|
static int indexhtml(char *); |
static int indexhtml(char *, size_t, char *, size_t); |
static int jobstart(const char *, const char *, pid_t *); |
static int manup(const struct manpaths *, char *); |
static int jobwait(pid_t); |
|
static int manup(const struct manpaths *, const char *); |
|
static int mkpath(char *, mode_t, mode_t); |
static int mkpath(char *, mode_t, mode_t); |
static int treecpy(char *, char *); |
static int treecpy(char *, char *); |
static int update(char *, char *); |
static int update(char *, char *); |
|
|
main(int argc, char *argv[]) |
main(int argc, char *argv[]) |
{ |
{ |
int ch; |
int ch; |
char *aux, *base; |
char *aux, *base, *conf_file; |
const char *dir; |
|
struct manpaths dirs; |
struct manpaths dirs; |
|
char buf[MAXPATHLEN]; |
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
|
|
Line 80 main(int argc, char *argv[]) |
|
Line 79 main(int argc, char *argv[]) |
|
else |
else |
++progname; |
++progname; |
|
|
aux = base = NULL; |
aux = base = conf_file = NULL; |
dir = "/var/www/cache/man.cgi"; |
xstrlcpy(buf, "/var/www/cache/man.cgi", MAXPATHLEN); |
|
|
while (-1 != (ch = getopt(argc, argv, "fm:M:o:v"))) |
while (-1 != (ch = getopt(argc, argv, "C:fm:M:o:v"))) |
switch (ch) { |
switch (ch) { |
|
case ('C'): |
|
conf_file = optarg; |
|
break; |
case ('f'): |
case ('f'): |
force = 1; |
force = 1; |
break; |
break; |
Line 95 main(int argc, char *argv[]) |
|
Line 97 main(int argc, char *argv[]) |
|
base = optarg; |
base = optarg; |
break; |
break; |
case ('o'): |
case ('o'): |
dir = optarg; |
xstrlcpy(buf, optarg, MAXPATHLEN); |
break; |
break; |
case ('v'): |
case ('v'): |
verbose++; |
verbose++; |
Line 114 main(int argc, char *argv[]) |
|
Line 116 main(int argc, char *argv[]) |
|
} |
} |
|
|
memset(&dirs, 0, sizeof(struct manpaths)); |
memset(&dirs, 0, sizeof(struct manpaths)); |
manpath_parse(&dirs, base, aux); |
manpath_parse(&dirs, conf_file, base, aux); |
ch = manup(&dirs, dir); |
ch = manup(&dirs, buf); |
manpath_free(&dirs); |
manpath_free(&dirs); |
return(ch ? EXIT_SUCCESS : EXIT_FAILURE); |
return(ch ? EXIT_SUCCESS : EXIT_FAILURE); |
} |
} |
|
|
|
|
fprintf(stderr, "usage: %s " |
fprintf(stderr, "usage: %s " |
"[-fv] " |
"[-fv] " |
|
"[-C file] " |
"[-o path] " |
"[-o path] " |
"[-m manpath] " |
"[-m manpath] " |
"[-M manpath]\n", |
"[-M manpath]\n", |
|
|
} |
} |
|
|
/* |
/* |
* Clean up existing child. |
|
* Return 1 if cleaned up fine (or none was started) and 0 otherwise. |
|
*/ |
|
static int |
|
jobwait(pid_t pid) |
|
{ |
|
int st; |
|
|
|
if (-1 == pid) |
|
return(1); |
|
|
|
if (-1 == waitpid(pid, &st, 0)) { |
|
perror(NULL); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
return(WIFEXITED(st) && 0 == WEXITSTATUS(st)); |
|
} |
|
|
|
/* |
|
* Start a job (child process), first making sure that the prior one has |
|
* finished. |
|
* Return 1 if the prior child exited and the new one started, else 0. |
|
*/ |
|
static int |
|
jobstart(const char *dst, const char *src, pid_t *pid) |
|
{ |
|
int fd; |
|
|
|
if ( ! jobwait(*pid)) |
|
return(0); |
|
|
|
if (-1 == (*pid = fork())) { |
|
perror(NULL); |
|
exit(EXIT_FAILURE); |
|
} else if (*pid > 0) |
|
return(1); |
|
|
|
if (-1 == (fd = open(dst, O_WRONLY|O_TRUNC|O_CREAT, 0644))) { |
|
perror(dst); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
if (-1 == dup2(fd, STDOUT_FILENO)) { |
|
perror(NULL); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
execlp("mandoc", "mandoc", "-T", "html", |
|
"-O", "fragment", |
|
"-O", "man=man.cgi?expr=%N&sec=%S", |
|
src, (char *)NULL); |
|
|
|
perror("mandoc"); |
|
exit(EXIT_FAILURE); |
|
/* NOTREACHED */ |
|
} |
|
|
|
/* |
|
* Pass over the recno database and re-create HTML pages if they're |
* Pass over the recno database and re-create HTML pages if they're |
* found to be out of date. |
* found to be out of date. |
* Returns -1 on fatal error, 1 on success. |
* Returns -1 on fatal error, 1 on success. |
*/ |
*/ |
static int |
static int |
indexhtml(char *dst) |
indexhtml(char *src, size_t ssz, char *dst, size_t dsz) |
{ |
{ |
DB *db; |
DB *idx; |
DBT key, val; |
DBT key, val; |
size_t sz; |
|
int c, rc; |
int c, rc; |
unsigned int fl; |
unsigned int fl; |
const char *f; |
const char *f; |
Line 271 indexhtml(char *dst) |
|
Line 214 indexhtml(char *dst) |
|
char fname[MAXPATHLEN]; |
char fname[MAXPATHLEN]; |
pid_t pid; |
pid_t pid; |
|
|
sz = strlen(dst); |
|
pid = -1; |
pid = -1; |
|
|
xstrlcpy(fname, dst, MAXPATHLEN); |
xstrlcpy(fname, dst, MAXPATHLEN); |
xstrlcat(fname, "/mandoc.index", MAXPATHLEN); |
xstrlcat(fname, "/", MAXPATHLEN); |
|
xstrlcat(fname, MANDOC_IDX, MAXPATHLEN); |
|
|
db = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL); |
idx = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL); |
if (NULL == db) { |
if (NULL == idx) { |
perror(fname); |
perror(fname); |
return(-1); |
return(-1); |
} |
} |
|
|
fl = R_FIRST; |
fl = R_FIRST; |
while (0 == (c = (*db->seq)(db, &key, &val, fl))) { |
while (0 == (c = (*idx->seq)(idx, &key, &val, fl))) { |
fl = R_NEXT; |
fl = R_NEXT; |
f = (const char *)val.data; |
/* |
|
* If the record is zero-length, then it's unassigned. |
|
* Skip past these. |
|
*/ |
|
if (0 == val.size) |
|
continue; |
|
|
dst[(int)sz] = '\0'; |
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, "/", MAXPATHLEN); |
xstrlcat(dst, f, MAXPATHLEN); |
xstrlcat(dst, f, MAXPATHLEN); |
xstrlcat(dst, ".html", MAXPATHLEN); |
|
|
|
if (-1 == (rc = isnewer(dst, f))) { |
xstrlcat(src, "/", MAXPATHLEN); |
fprintf(stderr, "%s: Manpage missing\n", f); |
xstrlcat(src, f, MAXPATHLEN); |
|
|
|
if (-1 == (rc = isnewer(dst, src))) { |
|
fprintf(stderr, "%s: File missing\n", f); |
break; |
break; |
} else if (0 == rc) |
} else if (0 == rc) |
continue; |
continue; |
Line 310 indexhtml(char *dst) |
|
Line 264 indexhtml(char *dst) |
|
} |
} |
|
|
*d = '/'; |
*d = '/'; |
if ( ! jobstart(dst, f, &pid)) |
|
|
if ( ! filecpy(dst, src)) |
break; |
break; |
if (verbose) |
if (verbose) |
printf("%s\n", dst); |
printf("%s\n", dst); |
} |
} |
|
|
(*db->close)(db); |
(*idx->close)(idx); |
|
|
if (c < 0) |
if (c < 0) |
perror(fname); |
perror(fname); |
if ( ! jobwait(pid)) |
else if (0 == c) |
c = -1; |
fprintf(stderr, "%s: Corrupt index\n", fname); |
|
|
return(1 == c ? 1 : -1); |
return(1 == c ? 1 : -1); |
} |
} |
Line 339 update(char *dst, char *src) |
|
Line 294 update(char *dst, char *src) |
|
dsz = strlen(dst); |
dsz = strlen(dst); |
ssz = strlen(src); |
ssz = strlen(src); |
|
|
xstrlcat(src, "/mandoc.db", MAXPATHLEN); |
xstrlcat(src, "/", MAXPATHLEN); |
xstrlcat(dst, "/mandoc.db", MAXPATHLEN); |
xstrlcat(dst, "/", MAXPATHLEN); |
|
|
|
xstrlcat(src, MANDOC_DB, MAXPATHLEN); |
|
xstrlcat(dst, MANDOC_DB, MAXPATHLEN); |
|
|
if ( ! filecpy(dst, src)) |
if ( ! filecpy(dst, src)) |
return(-1); |
return(-1); |
if (verbose) |
if (verbose) |
Line 349 update(char *dst, char *src) |
|
Line 307 update(char *dst, char *src) |
|
|
|
dst[(int)dsz] = src[(int)ssz] = '\0'; |
dst[(int)dsz] = src[(int)ssz] = '\0'; |
|
|
xstrlcat(src, "/mandoc.index", MAXPATHLEN); |
xstrlcat(src, "/", MAXPATHLEN); |
xstrlcat(dst, "/mandoc.index", MAXPATHLEN); |
xstrlcat(dst, "/", MAXPATHLEN); |
|
|
|
xstrlcat(src, MANDOC_IDX, MAXPATHLEN); |
|
xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); |
|
|
if ( ! filecpy(dst, src)) |
if ( ! filecpy(dst, src)) |
return(-1); |
return(-1); |
if (verbose) |
if (verbose) |
printf("%s\n", dst); |
printf("%s\n", dst); |
|
|
dst[(int)dsz] = '\0'; |
dst[(int)dsz] = src[(int)ssz] = '\0'; |
|
|
return(indexhtml(dst)); |
return(indexhtml(src, ssz, dst, dsz)); |
} |
} |
|
|
/* |
/* |
Line 377 treecpy(char *dst, char *src) |
|
Line 338 treecpy(char *dst, char *src) |
|
dsz = strlen(dst); |
dsz = strlen(dst); |
ssz = strlen(src); |
ssz = strlen(src); |
|
|
xstrlcat(src, "/mandoc.index", MAXPATHLEN); |
xstrlcat(src, "/", MAXPATHLEN); |
xstrlcat(dst, "/mandoc.index", MAXPATHLEN); |
xstrlcat(dst, "/", MAXPATHLEN); |
|
|
|
xstrlcat(src, MANDOC_IDX, MAXPATHLEN); |
|
xstrlcat(dst, MANDOC_IDX, MAXPATHLEN); |
|
|
if (-1 == (rc = isnewer(dst, src))) |
if (-1 == (rc = isnewer(dst, src))) |
return(0); |
return(0); |
|
|
Line 388 treecpy(char *dst, char *src) |
|
Line 352 treecpy(char *dst, char *src) |
|
if (1 == rc) |
if (1 == rc) |
return(update(dst, src)); |
return(update(dst, src)); |
|
|
xstrlcat(src, "/mandoc.db", MAXPATHLEN); |
xstrlcat(src, "/", MAXPATHLEN); |
xstrlcat(dst, "/mandoc.db", MAXPATHLEN); |
xstrlcat(dst, "/", MAXPATHLEN); |
|
|
|
xstrlcat(src, MANDOC_DB, MAXPATHLEN); |
|
xstrlcat(dst, MANDOC_DB, MAXPATHLEN); |
|
|
if (-1 == (rc = isnewer(dst, src))) |
if (-1 == (rc = isnewer(dst, src))) |
return(0); |
return(0); |
else if (rc == 0) |
else if (rc == 0) |
Line 408 treecpy(char *dst, char *src) |
|
Line 375 treecpy(char *dst, char *src) |
|
* Returns 1 on success, 0 on failure. |
* Returns 1 on success, 0 on failure. |
*/ |
*/ |
static int |
static int |
manup(const struct manpaths *dirs, const char *dir) |
manup(const struct manpaths *dirs, char *base) |
{ |
{ |
char dst[MAXPATHLEN], |
char dst[MAXPATHLEN], |
src[MAXPATHLEN]; |
src[MAXPATHLEN]; |
const char *path; |
const char *path; |
int i, c; |
size_t i; |
|
int c; |
size_t sz; |
size_t sz; |
FILE *f; |
FILE *f; |
|
|
xstrlcpy(dst, dir, MAXPATHLEN); |
/* Create the path and file for the catman.conf file. */ |
xstrlcat(dst, "/etc", MAXPATHLEN); |
|
|
|
|
sz = strlen(base); |
|
xstrlcpy(dst, base, MAXPATHLEN); |
|
xstrlcat(dst, "/etc", MAXPATHLEN); |
if (-1 == mkpath(dst, 0755, 0755)) { |
if (-1 == mkpath(dst, 0755, 0755)) { |
perror(dst); |
perror(dst); |
return(0); |
return(0); |
} |
} |
|
|
xstrlcat(dst, "/man.conf", MAXPATHLEN); |
xstrlcat(dst, "/catman.conf", MAXPATHLEN); |
|
|
if (verbose) |
|
printf("%s\n", dst); |
|
|
|
if (NULL == (f = fopen(dst, "w"))) { |
if (NULL == (f = fopen(dst, "w"))) { |
perror(dst); |
perror(dst); |
return(0); |
return(0); |
} |
} else if (verbose) |
|
printf("%s\n", dst); |
|
|
xstrlcpy(dst, dir, MAXPATHLEN); |
|
sz = strlen(dst); |
|
|
|
for (i = 0; i < dirs->sz; i++) { |
for (i = 0; i < dirs->sz; i++) { |
path = dirs->paths[i]; |
path = dirs->paths[i]; |
|
|
dst[(int)sz] = '\0'; |
dst[(int)sz] = '\0'; |
xstrlcat(dst, path, MAXPATHLEN); |
xstrlcat(dst, path, MAXPATHLEN); |
|
|
if (-1 == mkpath(dst, 0755, 0755)) { |
if (-1 == mkpath(dst, 0755, 0755)) { |
perror(dst); |
perror(dst); |
break; |
break; |
} |
} |
|
|
xstrlcpy(src, path, MAXPATHLEN); |
xstrlcpy(src, path, MAXPATHLEN); |
|
|
if (-1 == (c = treecpy(dst, src))) |
if (-1 == (c = treecpy(dst, src))) |
break; |
break; |
else if (0 == c) |
else if (0 == c) |