diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | catman.8 | 111 | ||||
-rw-r--r-- | catman.c | 512 | ||||
-rw-r--r-- | index.sgml | 18 |
4 files changed, 5 insertions, 638 deletions
@@ -26,7 +26,7 @@ CFLAGS += -DUSE_WCHAR # If your system has manpath(1), uncomment this. This is most any # system that's not OpenBSD or NetBSD. If uncommented, manpage(1) and # mandocdb(8) will use manpath(1) to get the MANPATH variable. -#CFLAGS += -DUSE_MANPATH +CFLAGS += -DUSE_MANPATH # If your system supports static binaries only, uncomment this. This # appears only to be BSD UNIX systems (Mac OS X has no support and Linux diff --git a/catman.8 b/catman.8 deleted file mode 100644 index 241737b8..00000000 --- a/catman.8 +++ /dev/null @@ -1,111 +0,0 @@ -.\" $Id$ -.\" -.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> -.\" -.\" 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. -.\" -.Dd $Mdocdate$ -.Dt CATMAN 8 -.Os -.Sh NAME -.Nm catman -.Nd update a man.cgi manpage cache -.Sh SYNOPSIS -.Nm catman -.Op Fl fv -.Op Fl C Ar file -.Op Fl M Ar manpath -.Op Fl m Ar manpath -.Op Fl o Ar path -.Sh DESCRIPTION -The -.Nm -utility updates cached manpages for a jailed -.Xr man.cgi 7 . -.Pp -By default, -.Nm -searches for -.Xr mandocdb 8 -databases in the default paths stipulated by -.Xr man 1 -and updates the cache in -.Pa /var/www/cache/man.cgi . -.Pp -Its arguments are as follows: -.Bl -tag -width Ds -.It Fl f -Force an update to all files. -.It Fl v -Print each file being updated. -.It Fl C Ar file -Specify an alternative configuration -.Ar file -in -.Xr man.conf 5 -format. -.It Fl M Ar manpath -Use the colon-separated path instead of the default list of paths -searched for -.Xr mandocdb 8 -databases. -Invalid paths, or paths without manual databases, are ignored. -.It Fl m Ar manpath -Prepend the colon-separated paths to the list of paths searched -for -.Xr mandocdb 8 -databases. -Invalid paths, or paths without manual databases, are ignored. -.It Fl o Ar path -Update into the directory tree under -.Ar path . -.El -.Pp -Cache updates occur when a -.Xr mandocdb 8 -database is older than the cached copy unless -.Fl f -is specified, in which case files are always considered out of date. -Cached manual pages are only updated if older than the master copy. -.Sh ENVIRONMENT -.Bl -tag -width Ds -.It Ev MANPATH -Colon-separated paths modifying the default list of paths searched for -manual databases. -Invalid paths, or paths without manual databases, are ignored. -Overridden by -.Fl M . -If -.Ev MANPATH -begins with a -.Sq \&: , -it is appended to the default list; -else if it ends with -.Sq \&: , -it is prepended to the default list; else if it contains -.Sq \&:: , -the default list is inserted between the colons. -If none of these conditions are met, it overrides the default list. -.El -.Sh EXIT STATUS -.Ex -std -.Sh SEE ALSO -.Xr mandoc 1 , -.Xr man.cgi 7 , -.Xr mandocdb 8 -.Sh AUTHORS -The -.Nm -utility was written by -.An Kristaps Dzonsons , -.Mt kristaps@bsd.lv . diff --git a/catman.c b/catman.c deleted file mode 100644 index bde01c10..00000000 --- a/catman.c +++ /dev/null @@ -1,512 +0,0 @@ -/* $Id$ */ -/* - * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * - * 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 <sys/param.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#ifdef __linux__ -# include <db_185.h> -#else -# include <db.h> -#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]; - pid_t pid; - - pid = -1; - - 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); -} @@ -37,7 +37,7 @@ <A HREF="demandoc.1.html">demandoc</A>, for emitting only text parts of manuals; <A HREF="mandocdb.8.html">mandocdb</A>, for indexing manuals; and <A HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, and - <A HREF="man.cgi.7.html">man.cgi</A> (via <A HREF="catman.8.html">catman</A>) for semantic search of manual content. + <A HREF="man.cgi.7.html">man.cgi</A> for semantic search of manual content. It is a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv</A> project. </P> <P> @@ -49,8 +49,8 @@ <P> <SPAN CLASS="nm">mdocml</SPAN> is in plain-old ANSI C and should build and run on any modern system; however, you'll need <A HREF="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">libdb</A> to build <A - HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, <A HREF="man.cgi.7.html">man.cgi</A>, <A - HREF="catman.8.html">catman</A>, and <A HREF="mandocdb.8.html">mandocdb</A> (this is installed by default on BSD UNIX + HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, <A HREF="man.cgi.7.html">man.cgi</A>, + and <A HREF="mandocdb.8.html">mandocdb</A> (this is installed by default on BSD UNIX systems — see the <I>Makefile</I> if you're running Linux). To build and install into <I>/usr/local/</I>, just run <CODE>make install</CODE>. Be careful: the <B>preconv</B>, <B>apropos</B>, and <B>whatis</B> binary names are usually taken by existing utilities. @@ -249,16 +249,6 @@ </TD> </TR> <TR> - <TD VALIGN="top"><A HREF="catman.8.html">catman(8)</A></TD> - <TD VALIGN="top"> - update a man.cgi manpage cache - (<A HREF="catman.8.txt">text</A> | - <A HREF="catman.8.xhtml">xhtml</A> | - <A HREF="catman.8.pdf">pdf</A> | - <A HREF="catman.8.ps">ps</A>) - </TD> - </TR> - <TR> <TD VALIGN="top"><A HREF="mandocdb.8.html">mandocdb(8)</A></TD> <TD VALIGN="top"> index UNIX manuals @@ -328,7 +318,7 @@ </P> <P> The <A HREF="man.cgi.7.html">man.cgi</A> script is also now available for wider testing. It interfaces with <A - HREF="mandocdb.8.html">mandocdb</A> manuals cached by <A HREF="catman.8.html">catman</A>. HTML output is generated + HREF="mandocdb.8.html">mandocdb</A> manuals cached by <DEL><A HREF="catman.8.html">catman</A></DEL>. HTML output is generated on-the-fly by <A HREF="mandoc.3.html">libmandoc</A> or internal methods to convert pre-formatted pages. </P> <P> |