/* $OpenBSD: config.c,v 1.2 1996/06/26 05:36:59 deraadt Exp $ */ /* $NetBSD: config.c,v 1.7 1995/09/28 06:05:21 tls 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 1/31/95"; #else static char rcsid[] = "$OpenBSD: config.c,v 1.2 1996/06/26 05:36:59 deraadt Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include "config.h" #include "pathnames.h" struct _head head; static char *default_config[] = { "_version Mastodon", "_manpath /usr/man /usr/X11R6/man /usr/local/man", "_order 1 8 6 2 3 4 5 7 9", "_save /bin/gzip .gz", "_cat *.Z /bin/zcat %s", "_cat *.gz /bin/gunzip -c %s", "_cat *.z /bin/gunzip -c %s", "_cat * /bin/cat %s", "_suffix *", "_text /usr/bin/groff -Tascii -mandoc", "_ps /usr/bin/groff -Tps -mandoc", (char *) 0, /* THIS MUST BE THE LAST LINE */ }; /* * process a config file (or default config) line */ void process(int saveok, char *p) { char *t; TAG *tp; ENTRY *ep; /* Skip leading space. */ for (; *p != '\0' && isspace(*p); ++p); /* Skip empty/comment lines. */ if (*p == '\0' || *p == '#') return; /* Find first token. */ for (t = p; *t && !isspace(*t); ++t); if (*t == '\0') /* Need more than one token. */ return; *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 _cat, _man, _text, & _ps take the rest of the line as a single entity, everything else is white space 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, "_cat") || !strcmp(p, "_man") || !strcmp(p, "_text") || !strcmp(p, "_ps") ) { while (*++t && isspace(*t)); if ((ep = calloc(1, sizeof (ENTRY))) == NULL || (ep->s = strdup(t)) == NULL) err(1, NULL); TAILQ_INSERT_TAIL(&tp->list, ep, q); } else { if (strcmp(p, "_save") == 0 && (geteuid() == 0 || !saveok) ) return; for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) { if ((ep = calloc(1, sizeof (ENTRY))) == NULL || (ep->s = strdup(p)) == NULL) err(1, NULL); TAILQ_INSERT_TAIL(&tp->list, ep, q); } } } /* * 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; { FILE *cfp; size_t len; int lcnt; char *p; char bfr[200]; int saveok; TAG *defp; ENTRY *ent; char *s_path; TAILQ_INIT(&head); if (fname == NULL) { saveok = 1; fname = _PATH_MANCONF; } else saveok = 0; if ((cfp = fopen(fname, "r")) != NULL) { for (lcnt = 1; fgets(bfr, sizeof bfr, cfp); ++lcnt) { if ((len = strlen(bfr)) == 1) /* Skip empty lines. */ continue; p = bfr; if (p[len - 1] != '\n') { /* Skip corrupted lines. */ warnx("%s: line %d corrupted", fname, lcnt); continue; } p[len - 1] = '\0'; /* Terminate the line. */ process(saveok, p); } debug(fname); fclose(cfp); } else { /* no config file: drop back to defaults */ for (lcnt = 0; default_config[lcnt]; lcnt++) { strcpy(bfr, default_config[lcnt]); process(1, bfr); } debug("default"); } /* merge PATH elements with _manpath */ if ((defp = getlist("_manpath")) != NULL && (s_path = getenv("PATH")) != NULL) { s_path = strdup(s_path); for (p = strtok(s_path, ":"); p != NULL; p =strtok(NULL, ":")) { int psize = strlen(p); if (psize > 5 && strcmp(&p[psize-4], "/bin") == 0) { memcpy(&p[psize-4], "/man", 4); for (ent = defp->list.tqh_first; ent != NULL; ent = ent->q.tqe_next) if (strcmp(p, ent->s) == 0) break; if (ent == NULL) { if ((ent = malloc(sizeof (ENTRY))) == NULL || (ent->s = strdup(p)) == NULL) err(1, NULL); TAILQ_INSERT_TAIL(&defp->list, ent, q); } } } } } /* config */ /* * 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, NULL); 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 debug(l) char *l; { #ifdef DEBUG 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); } #endif }