[BACK]Return to manpath.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mandoc

Annotation of src/usr.bin/mandoc/manpath.c, Revision 1.15

1.15    ! schwarze    1: /*     $OpenBSD: manpath.c,v 1.14 2015/03/27 17:36:56 schwarze Exp $   */
1.1       schwarze    2: /*
1.12      schwarze    3:  * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
1.1       schwarze    4:  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
1.13      schwarze   10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1.1       schwarze   11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1.13      schwarze   12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1.1       schwarze   13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
1.11      schwarze   18: #include <sys/types.h>
                     19: #include <sys/stat.h>
1.3       schwarze   20:
1.1       schwarze   21: #include <ctype.h>
                     22: #include <limits.h>
                     23: #include <stdio.h>
                     24: #include <stdlib.h>
                     25: #include <string.h>
                     26:
1.8       schwarze   27: #include "mandoc_aux.h"
1.14      schwarze   28: #include "manconf.h"
1.1       schwarze   29:
                     30: #define MAN_CONF_FILE  "/etc/man.conf"
1.12      schwarze   31: #define MANPATH_DEFAULT        "/usr/share/man:/usr/X11R6/man:/usr/local/man"
1.1       schwarze   32:
1.14      schwarze   33: static void     manconf_file(struct manconf *, const char *);
1.11      schwarze   34: static void     manpath_add(struct manpaths *, const char *, int);
                     35: static void     manpath_parseline(struct manpaths *, char *, int);
1.1       schwarze   36:
1.14      schwarze   37:
1.1       schwarze   38: void
1.14      schwarze   39: manconf_parse(struct manconf *conf, const char *file,
1.2       schwarze   40:                char *defp, char *auxp)
1.1       schwarze   41: {
1.4       schwarze   42:        char            *insert;
1.1       schwarze   43:
1.4       schwarze   44:        /* Always prepend -m. */
1.14      schwarze   45:        manpath_parseline(&conf->manpath, auxp, 1);
1.1       schwarze   46:
1.4       schwarze   47:        /* If -M is given, it overrides everything else. */
                     48:        if (NULL != defp) {
1.14      schwarze   49:                manpath_parseline(&conf->manpath, defp, 1);
1.4       schwarze   50:                return;
                     51:        }
                     52:
                     53:        /* MANPATH and man.conf(5) cooperate. */
                     54:        defp = getenv("MANPATH");
                     55:        if (NULL == file)
                     56:                file = MAN_CONF_FILE;
                     57:
                     58:        /* No MANPATH; use man.conf(5) only. */
                     59:        if (NULL == defp || '\0' == defp[0]) {
1.14      schwarze   60:                manconf_file(conf, file);
1.4       schwarze   61:                return;
                     62:        }
                     63:
                     64:        /* Prepend man.conf(5) to MANPATH. */
                     65:        if (':' == defp[0]) {
1.14      schwarze   66:                manconf_file(conf, file);
                     67:                manpath_parseline(&conf->manpath, defp, 0);
1.4       schwarze   68:                return;
                     69:        }
1.1       schwarze   70:
1.4       schwarze   71:        /* Append man.conf(5) to MANPATH. */
1.6       schwarze   72:        if (':' == defp[strlen(defp) - 1]) {
1.14      schwarze   73:                manpath_parseline(&conf->manpath, defp, 0);
                     74:                manconf_file(conf, file);
1.4       schwarze   75:                return;
                     76:        }
                     77:
                     78:        /* Insert man.conf(5) into MANPATH. */
                     79:        insert = strstr(defp, "::");
                     80:        if (NULL != insert) {
                     81:                *insert++ = '\0';
1.14      schwarze   82:                manpath_parseline(&conf->manpath, defp, 0);
                     83:                manconf_file(conf, file);
                     84:                manpath_parseline(&conf->manpath, insert + 1, 0);
1.4       schwarze   85:                return;
                     86:        }
                     87:
                     88:        /* MANPATH overrides man.conf(5) completely. */
1.14      schwarze   89:        manpath_parseline(&conf->manpath, defp, 0);
1.1       schwarze   90: }
                     91:
                     92: /*
                     93:  * Parse a FULL pathname from a colon-separated list of arrays.
                     94:  */
1.3       schwarze   95: static void
1.11      schwarze   96: manpath_parseline(struct manpaths *dirs, char *path, int complain)
1.1       schwarze   97: {
                     98:        char    *dir;
                     99:
                    100:        if (NULL == path)
                    101:                return;
                    102:
                    103:        for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
1.11      schwarze  104:                manpath_add(dirs, dir, complain);
1.1       schwarze  105: }
                    106:
                    107: /*
                    108:  * Add a directory to the array, ignoring bad directories.
                    109:  * Grow the array one-by-one for simplicity's sake.
                    110:  */
                    111: static void
1.11      schwarze  112: manpath_add(struct manpaths *dirs, const char *dir, int complain)
1.1       schwarze  113: {
                    114:        char             buf[PATH_MAX];
1.11      schwarze  115:        struct stat      sb;
1.1       schwarze  116:        char            *cp;
1.6       schwarze  117:        size_t           i;
1.1       schwarze  118:
1.11      schwarze  119:        if (NULL == (cp = realpath(dir, buf))) {
                    120:                if (complain) {
                    121:                        fputs("manpath: ", stderr);
                    122:                        perror(dir);
                    123:                }
1.1       schwarze  124:                return;
1.11      schwarze  125:        }
1.1       schwarze  126:
                    127:        for (i = 0; i < dirs->sz; i++)
                    128:                if (0 == strcmp(dirs->paths[i], dir))
                    129:                        return;
                    130:
1.11      schwarze  131:        if (stat(cp, &sb) == -1) {
                    132:                if (complain) {
                    133:                        fputs("manpath: ", stderr);
                    134:                        perror(dir);
                    135:                }
                    136:                return;
                    137:        }
                    138:
1.10      schwarze  139:        dirs->paths = mandoc_reallocarray(dirs->paths,
                    140:            dirs->sz + 1, sizeof(char *));
1.1       schwarze  141:
                    142:        dirs->paths[dirs->sz++] = mandoc_strdup(cp);
                    143: }
                    144:
                    145: void
1.14      schwarze  146: manconf_free(struct manconf *conf)
1.1       schwarze  147: {
1.6       schwarze  148:        size_t           i;
1.1       schwarze  149:
1.14      schwarze  150:        for (i = 0; i < conf->manpath.sz; i++)
                    151:                free(conf->manpath.paths[i]);
1.1       schwarze  152:
1.14      schwarze  153:        free(conf->manpath.paths);
                    154:        free(conf->output.includes);
                    155:        free(conf->output.man);
                    156:        free(conf->output.paper);
                    157:        free(conf->output.style);
1.1       schwarze  158: }
                    159:
1.14      schwarze  160: static void
                    161: manconf_file(struct manconf *conf, const char *file)
1.1       schwarze  162: {
1.14      schwarze  163:        const char *const toks[] = { "manpath", "output", "_whatdb" };
1.15    ! schwarze  164:        char manpath_default[] = MANPATH_DEFAULT;
1.13      schwarze  165:
1.1       schwarze  166:        FILE            *stream;
1.13      schwarze  167:        char            *cp, *ep;
                    168:        size_t           len, tok;
1.1       schwarze  169:
1.13      schwarze  170:        if ((stream = fopen(file, "r")) == NULL)
1.15    ! schwarze  171:                goto out;
1.1       schwarze  172:
1.13      schwarze  173:        while ((cp = fgetln(stream, &len)) != NULL) {
                    174:                ep = cp + len;
                    175:                if (ep[-1] != '\n')
1.1       schwarze  176:                        break;
1.13      schwarze  177:                *--ep = '\0';
                    178:                while (isspace((unsigned char)*cp))
                    179:                        cp++;
                    180:                if (*cp == '#')
1.1       schwarze  181:                        continue;
1.13      schwarze  182:
                    183:                for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
                    184:                        len = strlen(toks[tok]);
                    185:                        if (cp + len < ep &&
                    186:                            isspace((unsigned char)cp[len]) &&
                    187:                            !strncmp(cp, toks[tok], len)) {
                    188:                                cp += len;
                    189:                                while (isspace((unsigned char)*cp))
                    190:                                        cp++;
                    191:                                break;
                    192:                        }
                    193:                }
                    194:
                    195:                switch (tok) {
1.14      schwarze  196:                case 2:  /* _whatdb */
1.13      schwarze  197:                        while (ep > cp && ep[-1] != '/')
                    198:                                ep--;
                    199:                        if (ep == cp)
                    200:                                continue;
                    201:                        *ep = '\0';
                    202:                        /* FALLTHROUGH */
                    203:                case 0:  /* manpath */
1.14      schwarze  204:                        manpath_add(&conf->manpath, cp, 0);
1.15    ! schwarze  205:                        *manpath_default = '\0';
1.14      schwarze  206:                        break;
                    207:                case 1:  /* output */
                    208:                        manconf_output(&conf->output, cp);
1.13      schwarze  209:                        break;
                    210:                default:
                    211:                        break;
                    212:                }
1.1       schwarze  213:        }
1.15    ! schwarze  214:        fclose(stream);
1.1       schwarze  215:
1.15    ! schwarze  216: out:
        !           217:        if (*manpath_default != '\0')
        !           218:                manpath_parseline(&conf->manpath, manpath_default, 0);
1.14      schwarze  219: }
                    220:
                    221: void
                    222: manconf_output(struct manoutput *conf, const char *cp)
                    223: {
                    224:        const char *const toks[] = {
                    225:            "includes", "man", "paper", "style",
                    226:            "indent", "width", "fragment", "mdoc"
                    227:        };
                    228:
                    229:        size_t   len, tok;
                    230:
                    231:        for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
                    232:                len = strlen(toks[tok]);
                    233:                if ( ! strncmp(cp, toks[tok], len) &&
                    234:                    strchr(" =  ", cp[len]) != NULL) {
                    235:                        cp += len;
                    236:                        if (*cp == '=')
                    237:                                cp++;
                    238:                        while (isspace((unsigned char)*cp))
                    239:                                cp++;
                    240:                        break;
                    241:                }
                    242:        }
                    243:
                    244:        if (tok < 6 && *cp == '\0')
                    245:                return;
                    246:
                    247:        switch (tok) {
                    248:        case 0:
                    249:                if (conf->includes == NULL)
                    250:                        conf->includes = mandoc_strdup(cp);
                    251:                break;
                    252:        case 1:
                    253:                if (conf->man == NULL)
                    254:                        conf->man = mandoc_strdup(cp);
                    255:                break;
                    256:        case 2:
                    257:                if (conf->paper == NULL)
                    258:                        conf->paper = mandoc_strdup(cp);
                    259:                break;
                    260:        case 3:
                    261:                if (conf->style == NULL)
                    262:                        conf->style = mandoc_strdup(cp);
                    263:                break;
                    264:        case 4:
                    265:                if (conf->indent == 0)
                    266:                        conf->indent = strtonum(cp, 0, 1000, NULL);
                    267:                break;
                    268:        case 5:
                    269:                if (conf->width == 0)
                    270:                        conf->width = strtonum(cp, 58, 1000, NULL);
                    271:                break;
                    272:        case 6:
                    273:                conf->fragment = 1;
                    274:                break;
                    275:        case 7:
                    276:                conf->mdoc = 1;
                    277:                break;
                    278:        default:
                    279:                break;
                    280:        }
1.1       schwarze  281: }