diff --git a/usr.sbin/catman/Makefile b/usr.sbin/catman/Makefile index 513f4aae3d23..6b2ebb7fcb2b 100644 --- a/usr.sbin/catman/Makefile +++ b/usr.sbin/catman/Makefile @@ -1,7 +1,8 @@ -# $NetBSD: Makefile,v 1.4 1997/10/18 04:37:17 lukem Exp $ +# $NetBSD: Makefile,v 1.5 1999/04/04 10:56:38 dante Exp $ BINDIR= /usr/sbin PROG= catman +SRCS= config.c catman.c MAN= catman.8 .include diff --git a/usr.sbin/catman/TODO b/usr.sbin/catman/TODO index 3b498a27c5d7..97889095f4ec 100644 --- a/usr.sbin/catman/TODO +++ b/usr.sbin/catman/TODO @@ -1,2 +1 @@ -Use man.conf Handle hard-linked manpages. diff --git a/usr.sbin/catman/catman.8 b/usr.sbin/catman/catman.8 index cbe44acacbc6..967565c0974f 100644 --- a/usr.sbin/catman/catman.8 +++ b/usr.sbin/catman/catman.8 @@ -27,7 +27,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $NetBSD: catman.8,v 1.8 1997/10/18 04:37:19 lukem Exp $ +.\" $NetBSD: catman.8,v 1.9 1999/04/04 10:56:38 dante Exp $ .\" .Dd July 30, 1993 .Dt CATMAN 8 @@ -38,6 +38,10 @@ .Sh SYNOPSIS .Nm .Op Fl knpsw +.Op Fl m Ar directory +.Op Ar sections +.Nm "" +.Op Fl knpsw .Op Fl M Ar directory .Op Ar sections .Sh DESCRIPTION @@ -58,8 +62,8 @@ The optional argument is one word, and contains the section numbers of all the sections to be checked. For example, if .Ar sections -is ``138'', the -manual pages in sections 1, 3, and 8 will be checked and regenerated. +is ``13f8'', the +manual pages in sections 1, 3f, and 8 will be checked and regenerated. If no .Ar sections argument is provided, @@ -86,6 +90,10 @@ is specified. Only create the .Pa whatis database. +.It Fl m Ar directory +Add +.Ar directory +to the set of directories to be updated. .It Fl M Ar directory Update manual pages in .Ar directory. @@ -95,6 +103,4 @@ Update manual pages in .Xr man 1 , .Xr whatis 1 .Sh BUGS -Currently knows nothing about -.Pa /etc/man.conf -and machine specific man pages. +Currently does not handle hard links. diff --git a/usr.sbin/catman/catman.c b/usr.sbin/catman/catman.c index bc8ac78ecd70..c31d4c5762e4 100644 --- a/usr.sbin/catman/catman.c +++ b/usr.sbin/catman/catman.c @@ -1,7 +1,11 @@ +/* $NetBSD: catman.c,v 1.10 1999/04/04 10:56:38 dante Exp $ */ + /* - * Copyright (c) 1993 Winning Strategies, Inc. + * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * + * Author: Baldassare Dante Profeta + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,67 +16,82 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Winning Strategies, Inc. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 AUTHOR ``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 AUTHOR 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. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ -#include -#ifndef lint -__RCSID("$NetBSD: catman.c,v 1.9 1997/10/24 01:31:35 mrg Exp $"); -#endif /* not lint */ - #include +#include +#include +#include #include #include +#include #include #include #include +#include #include +#include #include #include #include #include -#include +#include +#include "config.h" #include "pathnames.h" -int f_nowhatis; -int f_noaction; -int f_noformat; -int f_ignerr; -int f_noprint; +#ifndef MACHINE +#define MACHINE __ARCHITECTURE__ +#endif -int dowhatis; +int f_nowhatis = 0; +int f_noaction = 0; +int f_noformat = 0; +int f_ignerr = 0; +int f_noprint = 0; +int dowhatis = 0; -char *mp = _PATH_MAN; -char *sp = _MAN_SECTIONS; +int main __P((int, char **)); +static void setdefentries __P((char *, char *, char *)); +static void uniquepath __P((void)); +static void catman __P((void)); +static void scanmandir __P((const char *, const char *)); +static int splitentry __P((char *, char *, char *)); +static void setcatsuffix __P((char *, const char *, const char *)); +static void makecat __P((const char *, const char *, const char *, + const char *)); +static void makewhatis __P((void)); +static void dosystem __P((const char *)); +static void usage __P((void)); -void catman __P((const char *, char *)); -int main __P((int, char **)); -void makewhatis __P((const char *)); -void dosystem __P((const char *)); -void usage __P((void)); int main(argc, argv) int argc; char **argv; { + char *m_path = NULL; + char *m_add = NULL; int c; - while ((c = getopt(argc, argv, "knpswM:")) != -1) { + while ((c = getopt(argc, argv, "km:M:npsw")) != -1) { switch (c) { case 'k': f_ignerr = 1; @@ -89,8 +108,11 @@ main(argc, argv) case 'w': f_noformat = 1; break; + case 'm': + m_add = optarg; + break; case 'M': - mp = optarg; + m_path = optarg; break; case '?': @@ -107,143 +129,501 @@ main(argc, argv) if (argc > 1) usage(); - if (argc == 1) - sp = *argv; + + config(_PATH_MANCONF); + setdefentries(m_path, m_add, (argc == 0)? NULL : argv[argc-1]); + uniquepath(); if (f_noformat == 0 || f_nowhatis == 0) - catman(mp, sp); + catman(); if (f_nowhatis == 0 && dowhatis) - makewhatis(mp); + makewhatis(); - exit(0); + return(0); } - -void -catman(path, section) - const char *path; - char *section; +static void +setdefentries(m_path, m_add, sections) + char *m_path; + char *m_add; + char *sections; { - char mandir[PATH_MAX]; - char catdir[PATH_MAX]; - char manpage[PATH_MAX]; - char catpage[PATH_MAX]; - char sysbuf[1024]; - struct stat manstat; - struct stat catstat; - struct dirent *dp; - DIR *dirp; - char *s, *tmp; - int sectlen, error; + TAG *defp, *defnewp, *sectnewp, *subp; + ENTRY *e_defp, *e_sectp, *e_subp, *ep; + char *p, *slashp, *machine; + char section[10]; + char buf[MAXPATHLEN * 2]; + int i; - for (s = section; *s; s += sectlen) { -#ifdef notdef - tmp = s; - sectlen = 0; - if (isdigit(*tmp)) { - sectlen++; - tmp++; - while (*tmp && isdigit(*tmp) == 0) { - sectlen++; - tmp++; + /* Get the machine type. */ + if ((machine = getenv("MACHINE")) == NULL) + machine = MACHINE; + + /* If there's no _default list, create an empty one. */ + if ((defp = getlist("_default")) == NULL) + defp = addlist("_default"); + + /* + * 0: If one or more sections was specified, rewrite _subdir list. + */ + if (sections != NULL) { + sectnewp = addlist("_section_new"); + for(p=sections; *p;) { + section[0] = *p++; + for(i=1; *p && !isdigit(*p) && i<10; i++) + section[i] = *p++; + section[i] = '\0'; + snprintf(buf, sizeof(buf), "man%s", section); + if(!(e_sectp = malloc(sizeof(ENTRY)))) + err(1, "malloc"); + if(!(e_sectp->s = strdup(buf))) + err(1, "malloc"); + TAILQ_INSERT_TAIL(§newp->list, e_sectp, q); + } + removelist("_subdir"); + renamelist("_section_new", "_subdir"); + } + + /* + * 1: If the user specified a MANPATH variable, or set the -M + * option, we replace the _default list with the user's list, + * appending the entries in the _subdir list and the machine. + */ + if (m_path == NULL) + m_path = getenv("MANPATH"); + if (m_path != NULL) { + while ((e_defp = defp->list.tqh_first) != NULL) { + free(e_defp->s); + TAILQ_REMOVE(&defp->list, e_defp, q); + } + for (p = strtok(m_path, ":"); + p != NULL; p = strtok(NULL, ":")) { + slashp = p[strlen(p) - 1] == '/' ? "" : "/"; + e_subp = (subp = getlist("_subdir")) == NULL ? + NULL : subp->list.tqh_first; + for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) { + if(!strncmp(e_subp->s, "cat", 3)) + continue; + (void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}", + p, slashp, e_subp->s, machine); + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(buf)) == NULL) + err(1, "malloc"); + TAILQ_INSERT_TAIL(&defp->list, ep, q); } } -#else - sectlen = 1; -#endif - if (sectlen == 0) - errx(1, "malformed section string"); + } - snprintf(mandir, sizeof mandir, "%s/%s%.*s", path, - _PATH_MANPAGES, sectlen, s); - snprintf(catdir, sizeof catdir, "%s/%s%.*s", path, - _PATH_CATPAGES, sectlen, s); + /* + * 2: If the user did not specify MANPATH, -M or a section, rewrite + * the _default list to include the _subdir list and the machine. + */ + if (m_path == NULL) { + defp = getlist("_default"); + defnewp = addlist("_default_new"); + e_defp = + defp->list.tqh_first == NULL ? NULL : defp->list.tqh_first; + for (; e_defp; e_defp = e_defp->q.tqe_next) { + slashp = + e_defp->s[strlen(e_defp->s) - 1] == '/' ? "" : "/"; + e_subp = (subp = getlist("_subdir")) == NULL ? + NULL : subp->list.tqh_first; + for (; e_subp; e_subp = e_subp->q.tqe_next) { + if(!strncmp(e_subp->s, "cat", 3)) + continue; + (void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}", + e_defp->s, slashp, e_subp->s, machine); + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(buf)) == NULL) + err(1, "malloc"); + TAILQ_INSERT_TAIL(&defnewp->list, ep, q); + } + } + removelist("_default"); + renamelist("_default_new", "_default"); + } - if ((dirp = opendir(mandir)) == 0) { - warn("can't open %s", mandir); + /* + * 3: If the user set the -m option, insert the user's list before + * whatever list we have, again appending the _subdir list and + * the machine. + */ + if (m_add != NULL) + for (p = strtok(m_add, ":"); p != NULL; p = strtok(NULL, ":")) { + slashp = p[strlen(p) - 1] == '/' ? "" : "/"; + e_subp = (subp = getlist("_subdir")) == NULL ? + NULL : subp->list.tqh_first; + for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) { + if(!strncmp(e_subp->s, "cat", 3)) + continue; + (void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}", + p, slashp, e_subp->s, machine); + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(buf)) == NULL) + err(1, "malloc"); + TAILQ_INSERT_HEAD(&defp->list, ep, q); + } + } +} + +/* + * Remove entries (directory) which are symbolic links to other entries. + * Some examples are showed below: + * 1) if /usr/X11 -> /usr/X11R6 then remove all /usr/X11/man entries. + * 2) if /usr/local/man -> /usr/share/man then remove all /usr/local/man + * entries + */ +static void +uniquepath(void) +{ + TAG *defp, *defnewp; + ENTRY *e_defp; + glob_t manpaths; + struct stat st1; + struct stat st2; + struct stat st3; + int i,j,len,lnk; + char path[PATH_MAX], *p; + + + defp = getlist("_default"); + e_defp = defp->list.tqh_first; + glob(e_defp->s, GLOB_BRACE | GLOB_NOSORT, NULL, &manpaths); + for(e_defp = e_defp->q.tqe_next; e_defp; e_defp = e_defp->q.tqe_next) { + glob(e_defp->s, GLOB_BRACE | GLOB_NOSORT | GLOB_APPEND, NULL, + &manpaths); + } + + defnewp = addlist("_default_new"); + + for(i=0; is = strdup(manpaths.gl_pathv[i]))) + err(1, "malloc"); + TAILQ_INSERT_TAIL(&defnewp->list, e_defp, q); + } + } + + globfree(&manpaths); + + removelist("_default"); + renamelist("_default_new", "_default"); +} + +static void +catman(void) +{ + TAG *pathp; + ENTRY *e_path; + char *mandir; + char catdir[PATH_MAX], *cp; + + + pathp = getlist("_default"); + for(e_path = pathp->list.tqh_first; e_path; + e_path = e_path->q.tqe_next) { + mandir = e_path->s; + strcpy(catdir,mandir); + if(!(cp = strstr(catdir, "man/man"))) + continue; + cp+=4; *cp++ = 'c'; *cp++ = 'a'; *cp = 't'; + scanmandir(catdir, mandir); + } +} + +static void +scanmandir(catdir, mandir) + const char *catdir; + const char *mandir; +{ + TAG *buildp, *crunchp; + ENTRY *e_build, *e_crunch; + char manpage[PATH_MAX]; + char catpage[PATH_MAX]; + char linkname[PATH_MAX]; + char buffer[PATH_MAX], *bp; + char tmp[PATH_MAX]; + char buildsuff[256], buildcmd[256]; + char crunchsuff[256], crunchcmd[256]; + char match[256]; + struct stat manstat; + struct stat catstat; + struct stat lnkstat; + struct dirent *dp; + DIR *dirp; + int len, error; + + if ((dirp = opendir(mandir)) == 0) { + warn("can't open %s", mandir); + return; + } + + if (stat(catdir, &catstat) < 0) { + if (errno != ENOENT) { + warn("can't stat %s", catdir); + closedir(dirp); + return; + } + if (f_noprint == 0) + printf("mkdir %s\n", catdir); + if (f_noaction == 0 && mkdir(catdir,0755) < 0) { + warn("can't create %s", catdir); + closedir(dirp); + return; + } + } + + while ((dp = readdir(dirp)) != NULL) { + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + + snprintf(manpage, sizeof(manpage), "%s/%s", mandir, dp->d_name); + snprintf(catpage, sizeof(catpage), "%s/%s", catdir, dp->d_name); + + buildp = getlist("_build"); + for(e_build = buildp->list.tqh_first; e_build; + e_build = e_build->q.tqe_next) { + splitentry(e_build->s, buildsuff, buildcmd); + snprintf(match, sizeof(match), "*%s", buildsuff); + if(!fnmatch(match, manpage, 0)) + break; + } + + if(e_build == NULL) { + continue; + } else { + crunchp = getlist("_crunch"); + for(e_crunch = crunchp->list.tqh_first; e_crunch; + e_crunch = e_crunch->q.tqe_next) { + splitentry(e_crunch->s, crunchsuff, crunchcmd); + snprintf(match, sizeof(match), "*%s", + crunchsuff); + if(!fnmatch(match, manpage, 0)) + break; + } + } + + if (lstat(manpage, &manstat) <0) { + warn("can't stat %s", manpage); + continue; + } else { + if(S_ISLNK(manstat.st_mode)) { + strcpy(buffer, catpage); + strcpy(linkname, basename(buffer)); + len = readlink(manpage, buffer, PATH_MAX); + if(len == -1) { + warn("can't stat read symbolic link %s", + manpage); + continue; + } + buffer[len] = '\0'; + bp = basename(buffer); + strcpy(tmp, manpage); + snprintf(manpage, sizeof(manpage), "%s/%s", + dirname(tmp), bp); + strcpy(tmp, catpage); + snprintf(catpage, sizeof(catpage), "%s/%s", + dirname(tmp), buffer); + } + else + *linkname='\0'; + } + + if(!e_crunch) { + *crunchsuff = *crunchcmd = '\0'; + } + setcatsuffix(catpage, buildsuff, crunchsuff); + if(*linkname != '\0') + setcatsuffix(linkname, buildsuff, crunchsuff); + + if (stat(manpage, &manstat) < 0) { + warn("can't stat %s", manpage); continue; } - if (stat(catdir, &catstat) < 0) { - if (errno != ENOENT) { - warn("can't stat %s", catdir); - closedir(dirp); - continue; - } - if (f_noprint == 0) - printf("mkdir %s\n", catdir); - if (f_noaction == 0 && mkdir(catdir, 0755) < 0) { - warn("can't create %s", catdir); - closedir(dirp); - return; - } - + if (!S_ISREG(manstat.st_mode)) { + warnx("not a regular file %s",manpage); + continue; } - while ((dp = readdir(dirp)) != NULL) { - if (strcmp(dp->d_name, ".") == 0 || - strcmp(dp->d_name, "..") == 0) - continue; + if ((error = stat(catpage, &catstat)) && + errno != ENOENT) { + warn("can't stat %s", catpage); + continue; + } - sprintf(manpage, "%s/%s", mandir, dp->d_name); - sprintf(catpage, "%s/%s", catdir, dp->d_name); - if ((tmp = strrchr(catpage, '.')) != NULL) - strcpy(tmp, ".0"); - else - continue; - - if (stat(manpage, &manstat) < 0) { - warn("can't stat %s", manpage); - continue; + if ((error && errno == ENOENT) || + manstat.st_mtime >= catstat.st_mtime) { + if (f_noformat) { + dowhatis = 1; + } else { + /* + * reformat out of date manpage + */ + makecat(manpage, catpage, buildcmd, crunchcmd); + dowhatis = 1; } + } - if (!S_ISREG(manstat.st_mode)) { - warnx("not a regular file %s", manpage); - continue; - } - if ((error = stat(catpage, &catstat)) && + if(*linkname != '\0') { + strcpy(tmp, catpage); + snprintf(tmp, sizeof(tmp), "%s/%s", dirname(tmp), + linkname); + if ((error = lstat(tmp, &lnkstat)) && errno != ENOENT) { - warn("can't stat %s", catpage); + warn("can't stat %s", tmp); continue; } - if ((error && errno == ENOENT) || - manstat.st_mtime >= catstat.st_mtime) { - if (f_noformat) + if (error && errno == ENOENT) { + if (f_noformat) { dowhatis = 1; - else { + } else { /* - * manpage is out of date, - * reformat + * create symbolic link */ - sprintf(sysbuf, "nroff -mandoc %s > %s", - manpage, catpage); if (f_noprint == 0) - printf("%s\n", sysbuf); - if (f_noaction == 0) - dosystem(sysbuf); + printf("ln -s %s %s\n", catpage, + linkname); + if (f_noaction == 0) { + strcpy(tmp, catpage); + if(chdir(dirname(tmp)) == -1) { + warn("can't chdir"); + continue; + } + + if(symlink(catpage, linkname) + == -1) { + warn("can't create" + " symbolic" + " link %s", + linkname); + continue; + } + } dowhatis = 1; } } } - closedir(dirp); } + closedir(dirp); } -void -makewhatis(path) - const char *path; +static int +splitentry(s, first, second) + char *s; + char *first; + char *second; { - char sysbuf[1024]; + char *c; + + for(c = s; *c != '\0' && !isspace(*c); ++c); + if(*c == '\0') + return(0); + strncpy(first, s, c-s); + first[c-s] = '\0'; + for(; *c != '\0' && isspace(*c); ++c); + strcpy(second, c); + return(1); +} + +static void +setcatsuffix(catpage, suffix, crunchsuff) + char *catpage; + const char *suffix; + const char *crunchsuff; +{ + TAG *tp; + ENTRY *ep; + char *p; + + for(p = catpage + strlen(catpage); p!=catpage; p--) + if(!fnmatch(suffix, p, 0)) { + if((tp = getlist("_suffix"))) { + ep = tp->list.tqh_first; + sprintf(p, "%s%s", ep->s, crunchsuff); + } else { + sprintf(p, ".0%s", crunchsuff); + } + break; + } +} + +static void +makecat(manpage, catpage, buildcmd, crunchcmd) + const char *manpage; + const char *catpage; + const char *buildcmd; + const char *crunchcmd; +{ + char crunchbuf[1024]; + char sysbuf[2048]; + + snprintf(sysbuf, sizeof(sysbuf), buildcmd, manpage); + + if(*crunchcmd != '\0') { + snprintf(crunchbuf, sizeof(crunchbuf), crunchcmd, catpage); + snprintf(sysbuf, sizeof(sysbuf), "%s | %s", sysbuf, crunchbuf); + } else { + snprintf(sysbuf, sizeof(sysbuf), "%s > %s", sysbuf, catpage); + } - sprintf(sysbuf, "%s %s", _PATH_MAKEWHATIS, path); if (f_noprint == 0) printf("%s\n", sysbuf); if (f_noaction == 0) dosystem(sysbuf); } -void +static void +makewhatis(void) +{ + TAG *whatdbp; + ENTRY *e_whatdb; + char sysbuf[1024]; + + whatdbp = getlist("_whatdb"); + for(e_whatdb = whatdbp->list.tqh_first; e_whatdb; + e_whatdb = e_whatdb->q.tqe_next) { + snprintf(sysbuf, sizeof(sysbuf), "%s %s", + _PATH_WHATIS, dirname(e_whatdb->s)); + if (f_noprint == 0) + printf("%s\n", sysbuf); + if (f_noaction == 0) + dosystem(sysbuf); + } +} + +static void dosystem(cmd) const char *cmd; { @@ -263,10 +643,12 @@ dosystem(cmd) warnx("*** Exited %d (continuing)", status); } -void -usage() +static void +usage(void) { (void)fprintf(stderr, - "usage: catman [-knpsw] [-M manpath] [sections]\n"); + "usage: catman [-knpsw] [-m manpath] [sections]\n"); + (void)fprintf(stderr, + " catman [-knpsw] [-M manpath] [sections]\n"); exit(1); } diff --git a/usr.sbin/catman/config.c b/usr.sbin/catman/config.c new file mode 100644 index 000000000000..b0d3f795cfdc --- /dev/null +++ b/usr.sbin/catman/config.c @@ -0,0 +1,216 @@ +/* $NetBSD: config.c,v 1.1 1999/04/04 10:56:38 dante Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1995 + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 1/31/95"; +#else +__RCSID("$NetBSD: config.c,v 1.1 1999/04/04 10:56:38 dante Exp $"); +#endif +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "pathnames.h" + +struct _head head; + +/* + * config -- + * + * Read the configuration file and build a doubly linked + * list that looks like: + * + * tag1 <-> record <-> record <-> record + * | + * tag2 <-> record <-> record <-> record + */ +void +config(fname) + char *fname; +{ + TAG *tp; + ENTRY *ep; + FILE *cfp; + size_t len; + int lcnt; + char *p, *t; + + if (fname == NULL) + fname = _PATH_MANCONF; + if ((cfp = fopen(fname, "r")) == NULL) + err(1, "%s", fname); + TAILQ_INIT(&head); + for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) { + if (len == 1) /* Skip empty lines. */ + continue; + if (p[len - 1] != '\n') { /* Skip corrupted lines. */ + warnx("%s: line %d corrupted", fname, lcnt); + continue; + } + p[len - 1] = '\0'; /* Terminate the line. */ + + /* Skip leading space. */ + for (; *p != '\0' && isspace((unsigned char)*p); ++p); + /* Skip empty/comment lines. */ + if (*p == '\0' || *p == '#') + continue; + /* Find first token. */ + for (t = p; *t && !isspace((unsigned char)*t); ++t); + if (*t == '\0') /* Need more than one token.*/ + continue; + *t = '\0'; + + for (tp = head.tqh_first; /* Find any matching tag. */ + tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next); + + if (tp == NULL) /* Create a new tag. */ + tp = addlist(p); + + /* + * Attach new records. The keywords _build and _crunch takes + * the rest of the line as a single entity, everything else is + * whitespace separated. + * The reason we're not just using strtok(3) for all of the + * parsing is so we don't get caught if a line has only a + * single token on it. + */ + if (!strcmp(p, "_build") || !strcmp(p, "_crunch")) { + while (*++t && isspace((unsigned char)*t)); + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(t)) == NULL) + err(1, "malloc"); + TAILQ_INSERT_TAIL(&tp->list, ep, q); + } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) { + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(p)) == NULL) + err(1, "malloc"); + TAILQ_INSERT_TAIL(&tp->list, ep, q); + } + } + + fclose(cfp); +} + +/* + * addlist -- + * Add a tag to the list. + */ +TAG * +addlist(name) + char *name; +{ + TAG *tp; + + if ((tp = calloc(1, sizeof(TAG))) == NULL || + (tp->s = strdup(name)) == NULL) + err(1, "malloc"); + TAILQ_INIT(&tp->list); + TAILQ_INSERT_TAIL(&head, tp, q); + return (tp); +} + +/* + * getlist -- + * Return the linked list of entries for a tag if it exists. + */ +TAG * +getlist(name) + char *name; +{ + TAG *tp; + + for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) + if (!strcmp(name, tp->s)) + return (tp); + return (NULL); +} + +void +removelist(name) + char *name; +{ + TAG *tp; + ENTRY *ep; + + tp = getlist(name); + while ((ep = tp->list.tqh_first) != NULL) { + free(ep->s); + TAILQ_REMOVE(&tp->list, ep, q); + } + free(tp->s); + TAILQ_REMOVE(&head, tp, q); + +} + +TAG * +renamelist(oldname, newname) + char *oldname; + char *newname; +{ + TAG *tp; + + if(!(tp = getlist(oldname))) + return (NULL); + free(tp->s); + if(!(tp->s = strdup(newname))) + err(1, "malloc"); + return (tp); +} + +void +debug(l) + char *l; +{ + TAG *tp; + ENTRY *ep; + + (void)printf("%s ===============\n", l); + for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) { + printf("%s\n", tp->s); + for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next) + printf("\t%s\n", ep->s); + } +} diff --git a/usr.sbin/catman/config.h b/usr.sbin/catman/config.h new file mode 100644 index 000000000000..575c6d17419b --- /dev/null +++ b/usr.sbin/catman/config.h @@ -0,0 +1,61 @@ +/* $NetBSD: config.h,v 1.1 1999/04/04 10:56:39 dante Exp $ */ + +/*- + * Copyright (c) 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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. + * + * @(#)config.h 8.4 (Berkeley) 12/18/93 + */ + +typedef struct _tag { + TAILQ_ENTRY(_tag) q; /* Queue of tags. */ + + TAILQ_HEAD(tqh, _entry) list; /* Queue of entries. */ + char *s; /* Associated string. */ + size_t len; /* Length of 's'. */ +} TAG; +typedef struct _entry { + TAILQ_ENTRY(_entry) q; /* Queue of entries. */ + + char *s; /* Associated string. */ + size_t len; /* Length of 's'. */ +} ENTRY; + +TAILQ_HEAD(_head, _tag); +extern struct _head head; + +TAG *addlist __P((char *)); +void config __P((char *)); +void debug __P((char *)); +TAG *getlist __P((char *)); +void removelist __P((char *)); +TAG *renamelist __P((char *, char *)); diff --git a/usr.sbin/catman/pathnames.h b/usr.sbin/catman/pathnames.h index 1de4ca44c88b..fce29dc6b4b0 100644 --- a/usr.sbin/catman/pathnames.h +++ b/usr.sbin/catman/pathnames.h @@ -1,6 +1,8 @@ +/* $NetBSD: pathnames.h,v 1.4 1999/04/04 10:56:39 dante Exp $ */ + /* - * Copyright (c) 1994 Christopher G. Demetriou - * All rights reserved. + * Copyright (c) 1989, 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 @@ -12,25 +14,28 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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 AUTHOR ``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 AUTHOR 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. + * 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. * - * $NetBSD: pathnames.h,v 1.3 1997/10/24 01:31:39 mrg Exp $ + * @(#)pathnames.h 8.3 (Berkeley) 1/2/94 */ -#define _MAN_SECTIONS "123456789" /* l, n, o, and p, too? */ -#define _PATH_MAKEWHATIS "/usr/libexec/makewhatis" -#define _PATH_MANPAGES "man" -#define _PATH_CATPAGES "cat" +#define _PATH_MANCONF "/etc/man.conf" +#define _PATH_PAGER "/usr/bin/more -s" +#define _PATH_TMP "/tmp/man.XXXXXX" +#define _PATH_WHATIS "/usr/libexec/makewhatis"