[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.11

1.11    ! schwarze    1: /*     $OpenBSD$ */
1.1       schwarze    2: /*
1.11    ! schwarze    3:  * Copyright (c) 2011, 2014 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:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     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 <assert.h>
                     22: #include <ctype.h>
                     23: #include <limits.h>
                     24: #include <stdio.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
                     27:
1.8       schwarze   28: #include "mandoc_aux.h"
1.1       schwarze   29: #include "manpath.h"
                     30:
                     31: #define MAN_CONF_FILE  "/etc/man.conf"
                     32: #define MAN_CONF_KEY   "_whatdb"
                     33:
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:
                     37: void
1.2       schwarze   38: manpath_parse(struct manpaths *dirs, const char *file,
                     39:                char *defp, char *auxp)
1.1       schwarze   40: {
1.4       schwarze   41:        char            *insert;
1.1       schwarze   42:
1.4       schwarze   43:        /* Always prepend -m. */
1.11    ! schwarze   44:        manpath_parseline(dirs, auxp, 1);
1.1       schwarze   45:
1.4       schwarze   46:        /* If -M is given, it overrides everything else. */
                     47:        if (NULL != defp) {
1.11    ! schwarze   48:                manpath_parseline(dirs, defp, 1);
1.4       schwarze   49:                return;
                     50:        }
                     51:
                     52:        /* MANPATH and man.conf(5) cooperate. */
                     53:        defp = getenv("MANPATH");
                     54:        if (NULL == file)
                     55:                file = MAN_CONF_FILE;
                     56:
                     57:        /* No MANPATH; use man.conf(5) only. */
                     58:        if (NULL == defp || '\0' == defp[0]) {
                     59:                manpath_manconf(dirs, file);
                     60:                return;
                     61:        }
                     62:
                     63:        /* Prepend man.conf(5) to MANPATH. */
                     64:        if (':' == defp[0]) {
                     65:                manpath_manconf(dirs, file);
1.11    ! schwarze   66:                manpath_parseline(dirs, defp, 0);
1.4       schwarze   67:                return;
                     68:        }
1.1       schwarze   69:
1.4       schwarze   70:        /* Append man.conf(5) to MANPATH. */
1.6       schwarze   71:        if (':' == defp[strlen(defp) - 1]) {
1.11    ! schwarze   72:                manpath_parseline(dirs, defp, 0);
1.4       schwarze   73:                manpath_manconf(dirs, file);
                     74:                return;
                     75:        }
                     76:
                     77:        /* Insert man.conf(5) into MANPATH. */
                     78:        insert = strstr(defp, "::");
                     79:        if (NULL != insert) {
                     80:                *insert++ = '\0';
1.11    ! schwarze   81:                manpath_parseline(dirs, defp, 0);
1.4       schwarze   82:                manpath_manconf(dirs, file);
1.11    ! schwarze   83:                manpath_parseline(dirs, insert + 1, 0);
1.4       schwarze   84:                return;
                     85:        }
                     86:
                     87:        /* MANPATH overrides man.conf(5) completely. */
1.11    ! schwarze   88:        manpath_parseline(dirs, defp, 0);
1.1       schwarze   89: }
                     90:
                     91: /*
                     92:  * Parse a FULL pathname from a colon-separated list of arrays.
                     93:  */
1.3       schwarze   94: static void
1.11    ! schwarze   95: manpath_parseline(struct manpaths *dirs, char *path, int complain)
1.1       schwarze   96: {
                     97:        char    *dir;
                     98:
                     99:        if (NULL == path)
                    100:                return;
                    101:
                    102:        for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
1.11    ! schwarze  103:                manpath_add(dirs, dir, complain);
1.1       schwarze  104: }
                    105:
                    106: /*
                    107:  * Add a directory to the array, ignoring bad directories.
                    108:  * Grow the array one-by-one for simplicity's sake.
                    109:  */
                    110: static void
1.11    ! schwarze  111: manpath_add(struct manpaths *dirs, const char *dir, int complain)
1.1       schwarze  112: {
                    113:        char             buf[PATH_MAX];
1.11    ! schwarze  114:        struct stat      sb;
1.1       schwarze  115:        char            *cp;
1.6       schwarze  116:        size_t           i;
1.1       schwarze  117:
1.11    ! schwarze  118:        if (NULL == (cp = realpath(dir, buf))) {
        !           119:                if (complain) {
        !           120:                        fputs("manpath: ", stderr);
        !           121:                        perror(dir);
        !           122:                }
1.1       schwarze  123:                return;
1.11    ! schwarze  124:        }
1.1       schwarze  125:
                    126:        for (i = 0; i < dirs->sz; i++)
                    127:                if (0 == strcmp(dirs->paths[i], dir))
                    128:                        return;
                    129:
1.11    ! schwarze  130:        if (stat(cp, &sb) == -1) {
        !           131:                if (complain) {
        !           132:                        fputs("manpath: ", stderr);
        !           133:                        perror(dir);
        !           134:                }
        !           135:                return;
        !           136:        }
        !           137:
1.10      schwarze  138:        dirs->paths = mandoc_reallocarray(dirs->paths,
                    139:            dirs->sz + 1, sizeof(char *));
1.1       schwarze  140:
                    141:        dirs->paths[dirs->sz++] = mandoc_strdup(cp);
                    142: }
                    143:
                    144: void
                    145: manpath_free(struct manpaths *p)
                    146: {
1.6       schwarze  147:        size_t           i;
1.1       schwarze  148:
                    149:        for (i = 0; i < p->sz; i++)
                    150:                free(p->paths[i]);
                    151:
                    152:        free(p->paths);
                    153: }
                    154:
                    155: void
1.2       schwarze  156: manpath_manconf(struct manpaths *dirs, const char *file)
1.1       schwarze  157: {
                    158:        FILE            *stream;
                    159:        char            *p, *q;
                    160:        size_t           len, keysz;
                    161:
                    162:        keysz = strlen(MAN_CONF_KEY);
                    163:        assert(keysz > 0);
                    164:
                    165:        if (NULL == (stream = fopen(file, "r")))
                    166:                return;
                    167:
                    168:        while (NULL != (p = fgetln(stream, &len))) {
                    169:                if (0 == len || '\n' != p[--len])
                    170:                        break;
                    171:                p[len] = '\0';
                    172:                while (isspace((unsigned char)*p))
                    173:                        p++;
                    174:                if (strncmp(MAN_CONF_KEY, p, keysz))
                    175:                        continue;
                    176:                p += keysz;
1.7       schwarze  177:                while (isspace((unsigned char)*p))
1.1       schwarze  178:                        p++;
                    179:                if ('\0' == *p)
                    180:                        continue;
                    181:                if (NULL == (q = strrchr(p, '/')))
                    182:                        continue;
                    183:                *q = '\0';
1.11    ! schwarze  184:                manpath_add(dirs, p, 0);
1.1       schwarze  185:        }
                    186:
                    187:        fclose(stream);
                    188: }