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

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