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

1.9     ! schwarze    1: /*     $Id: manpath.c,v 1.8 2014/03/21 22:17:01 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:
1.8       schwarze   26: #include "mandoc_aux.h"
1.1       schwarze   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. */
1.6       schwarze   69:        if (':' == defp[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;
1.6       schwarze  113:        size_t           i;
1.1       schwarze  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:
1.9     ! schwarze  122:        dirs->paths = mandoc_realloc(dirs->paths,
        !           123:            (dirs->sz + 1) * sizeof(char *));
1.1       schwarze  124:
                    125:        dirs->paths[dirs->sz++] = mandoc_strdup(cp);
                    126: }
                    127:
                    128: void
                    129: manpath_free(struct manpaths *p)
                    130: {
1.6       schwarze  131:        size_t           i;
1.1       schwarze  132:
                    133:        for (i = 0; i < p->sz; i++)
                    134:                free(p->paths[i]);
                    135:
                    136:        free(p->paths);
                    137: }
                    138:
                    139: void
1.2       schwarze  140: manpath_manconf(struct manpaths *dirs, const char *file)
1.1       schwarze  141: {
                    142:        FILE            *stream;
                    143:        char            *p, *q;
                    144:        size_t           len, keysz;
                    145:
                    146:        keysz = strlen(MAN_CONF_KEY);
                    147:        assert(keysz > 0);
                    148:
                    149:        if (NULL == (stream = fopen(file, "r")))
                    150:                return;
                    151:
                    152:        while (NULL != (p = fgetln(stream, &len))) {
                    153:                if (0 == len || '\n' != p[--len])
                    154:                        break;
                    155:                p[len] = '\0';
                    156:                while (isspace((unsigned char)*p))
                    157:                        p++;
                    158:                if (strncmp(MAN_CONF_KEY, p, keysz))
                    159:                        continue;
                    160:                p += keysz;
1.7       schwarze  161:                while (isspace((unsigned char)*p))
1.1       schwarze  162:                        p++;
                    163:                if ('\0' == *p)
                    164:                        continue;
                    165:                if (NULL == (q = strrchr(p, '/')))
                    166:                        continue;
                    167:                *q = '\0';
                    168:                manpath_add(dirs, p);
                    169:        }
                    170:
                    171:        fclose(stream);
                    172: }