-/* $Id: catman.c,v 1.1 2011/11/26 19:54:13 kristaps Exp $ */
+/* $Id: catman.c,v 1.8 2011/12/18 18:51:01 kristaps Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
exit(EXIT_FAILURE); \
} while (/* CONSTCOND */0)
-static int indexhtml(char *);
-static int jobstart(const char *, const char *, pid_t *);
-static int jobwait(pid_t);
-static int manup(const struct manpaths *, const char *);
+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 *);
main(int argc, char *argv[])
{
int ch;
- char *aux, *base;
- const char *dir;
+ char *aux, *base, *conf_file;
struct manpaths dirs;
+ char buf[MAXPATHLEN];
extern char *optarg;
extern int optind;
++progname;
aux = base = 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) {
+ case ('C'):
+ conf_file = optarg;
+ break;
case ('f'):
force = 1;
break;
base = optarg;
break;
case ('o'):
- dir = optarg;
+ xstrlcpy(buf, optarg, MAXPATHLEN);
break;
case ('v'):
verbose++;
}
memset(&dirs, 0, sizeof(struct manpaths));
- manpath_parse(&dirs, base, aux);
- ch = manup(&dirs, dir);
+ manpath_parse(&dirs, conf_file, base, aux);
+ ch = manup(&dirs, buf);
manpath_free(&dirs);
return(ch ? EXIT_SUCCESS : EXIT_FAILURE);
}
fprintf(stderr, "usage: %s "
"[-fv] "
+ "[-C file] "
"[-o path] "
"[-m manpath] "
"[-M manpath]\n",
return(rc);
}
-/*
- * 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
* found to be out of date.
* Returns -1 on fatal error, 1 on success.
*/
static int
-indexhtml(char *dst)
+indexhtml(char *src, size_t ssz, char *dst, size_t dsz)
{
- DB *db;
+ DB *idx;
DBT key, val;
- size_t sz;
int c, rc;
unsigned int fl;
const char *f;
char fname[MAXPATHLEN];
pid_t pid;
- sz = strlen(dst);
pid = -1;
xstrlcpy(fname, dst, MAXPATHLEN);
xstrlcat(fname, "/mandoc.index", MAXPATHLEN);
- db = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL);
- if (NULL == db) {
+ idx = dbopen(fname, O_RDONLY, 0, DB_RECNO, NULL);
+ if (NULL == idx) {
perror(fname);
return(-1);
}
fl = R_FIRST;
- while (0 == (c = (*db->seq)(db, &key, &val, fl))) {
+ while (0 == (c = (*idx->seq)(idx, &key, &val, fl))) {
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, f, MAXPATHLEN);
- xstrlcat(dst, ".html", MAXPATHLEN);
- if (-1 == (rc = isnewer(dst, f))) {
- fprintf(stderr, "%s: Manpage missing\n", f);
+ 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 = '/';
- if ( ! jobstart(dst, f, &pid))
+
+ if ( ! filecpy(dst, src))
break;
if (verbose)
printf("%s\n", dst);
}
- (*db->close)(db);
+ (*idx->close)(idx);
if (c < 0)
perror(fname);
- if ( ! jobwait(pid))
- c = -1;
+ else if (0 == c)
+ fprintf(stderr, "%s: Corrupt index\n", fname);
return(1 == c ? 1 : -1);
}
if (verbose)
printf("%s\n", dst);
- dst[(int)dsz] = '\0';
+ dst[(int)dsz] = src[(int)ssz] = '\0';
- return(indexhtml(dst));
+ return(indexhtml(src, ssz, dst, dsz));
}
/*
* Returns 1 on success, 0 on failure.
*/
static int
-manup(const struct manpaths *dirs, const char *dir)
+manup(const struct manpaths *dirs, char *base)
{
char dst[MAXPATHLEN],
src[MAXPATHLEN];
size_t sz;
FILE *f;
- xstrlcpy(dst, dir, MAXPATHLEN);
- xstrlcat(dst, "/etc", MAXPATHLEN);
+ /* 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, "/man.conf", MAXPATHLEN);
-
- if (verbose)
- printf("%s\n", dst);
-
+ xstrlcat(dst, "/catman.conf", MAXPATHLEN);
if (NULL == (f = fopen(dst, "w"))) {
perror(dst);
return(0);
- }
-
- xstrlcpy(dst, dir, MAXPATHLEN);
- sz = strlen(dst);
+ } 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)