[BACK]Return to manpath.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/manpath.c, Revision 1.11

1.11    ! schwarze    1: /*     $Id: manpath.c,v 1.10 2013/05/29 22:48:10 schwarze Exp $ */
1.1       kristaps    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:  */
                     18: #ifdef HAVE_CONFIG_H
                     19: #include "config.h"
                     20: #endif
                     21:
                     22: #include <assert.h>
                     23: #include <ctype.h>
                     24: #include <limits.h>
                     25: #include <stdio.h>
                     26: #include <stdlib.h>
                     27: #include <string.h>
                     28:
                     29: #include "mandoc.h"
                     30: #include "manpath.h"
                     31:
                     32: #define MAN_CONF_FILE  "/etc/man.conf"
                     33: #define MAN_CONF_KEY   "_whatdb"
                     34:
                     35: static void     manpath_add(struct manpaths *, const char *);
1.6       kristaps   36: static void     manpath_parseline(struct manpaths *, char *);
1.1       kristaps   37:
                     38: void
1.5       schwarze   39: manpath_parse(struct manpaths *dirs, const char *file,
                     40:                char *defp, char *auxp)
1.1       kristaps   41: {
1.6       kristaps   42: #ifdef USE_MANPATH
1.11    ! schwarze   43:        char             cmd[(PATH_MAX * 3) + 20];
1.6       kristaps   44:        FILE            *stream;
                     45:        char            *buf;
                     46:        size_t           sz, bsz;
                     47:
                     48:        strlcpy(cmd, "manpath", sizeof(cmd));
                     49:        if (file) {
                     50:                strlcat(cmd, " -C ", sizeof(cmd));
                     51:                strlcat(cmd, file, sizeof(cmd));
                     52:        }
                     53:        if (auxp) {
                     54:                strlcat(cmd, " -m ", sizeof(cmd));
                     55:                strlcat(cmd, auxp, sizeof(cmd));
                     56:        }
                     57:        if (defp) {
                     58:                strlcat(cmd, " -M ", sizeof(cmd));
                     59:                strlcat(cmd, defp, sizeof(cmd));
                     60:        }
                     61:
                     62:        /* Open manpath(1).  Ignore errors. */
                     63:
                     64:        stream = popen(cmd, "r");
                     65:        if (NULL == stream)
                     66:                return;
                     67:
                     68:        buf = NULL;
                     69:        bsz = 0;
                     70:
                     71:        /* Read in as much output as we can. */
                     72:
                     73:        do {
                     74:                buf = mandoc_realloc(buf, bsz + 1024);
1.9       kristaps   75:                sz = fread(buf + bsz, 1, 1024, stream);
1.6       kristaps   76:                bsz += sz;
                     77:        } while (sz > 0);
                     78:
                     79:        if ( ! ferror(stream) && feof(stream) &&
                     80:                        bsz && '\n' == buf[bsz - 1]) {
                     81:                buf[bsz - 1] = '\0';
                     82:                manpath_parseline(dirs, buf);
                     83:        }
1.1       kristaps   84:
1.6       kristaps   85:        free(buf);
                     86:        pclose(stream);
                     87: #else
1.8       kristaps   88:        char            *insert;
1.4       schwarze   89:
1.8       kristaps   90:        /* Always prepend -m. */
1.10      schwarze   91:        manpath_parseline(dirs, auxp);
                     92:
1.8       kristaps   93:        /* If -M is given, it overrides everything else. */
                     94:        if (NULL != defp) {
                     95:                manpath_parseline(dirs, defp);
                     96:                return;
                     97:        }
1.1       kristaps   98:
1.8       kristaps   99:        /* MANPATH and man.conf(5) cooperate. */
                    100:        defp = getenv("MANPATH");
                    101:        if (NULL == file)
                    102:                file = MAN_CONF_FILE;
                    103:
                    104:        /* No MANPATH; use man.conf(5) only. */
                    105:        if (NULL == defp || '\0' == defp[0]) {
                    106:                manpath_manconf(dirs, file);
                    107:                return;
                    108:        }
                    109:
                    110:        /* Prepend man.conf(5) to MANPATH. */
                    111:        if (':' == defp[0]) {
                    112:                manpath_manconf(dirs, file);
1.1       kristaps  113:                manpath_parseline(dirs, defp);
1.8       kristaps  114:                return;
                    115:        }
                    116:
                    117:        /* Append man.conf(5) to MANPATH. */
1.9       kristaps  118:        if (':' == defp[strlen(defp) - 1]) {
1.8       kristaps  119:                manpath_parseline(dirs, defp);
                    120:                manpath_manconf(dirs, file);
                    121:                return;
                    122:        }
                    123:
                    124:        /* Insert man.conf(5) into MANPATH. */
                    125:        insert = strstr(defp, "::");
                    126:        if (NULL != insert) {
                    127:                *insert++ = '\0';
                    128:                manpath_parseline(dirs, defp);
                    129:                manpath_manconf(dirs, file);
                    130:                manpath_parseline(dirs, insert + 1);
                    131:                return;
                    132:        }
                    133:
                    134:        /* MANPATH overrides man.conf(5) completely. */
                    135:        manpath_parseline(dirs, defp);
1.6       kristaps  136: #endif
1.1       kristaps  137: }
                    138:
                    139: /*
                    140:  * Parse a FULL pathname from a colon-separated list of arrays.
                    141:  */
1.6       kristaps  142: static void
1.4       schwarze  143: manpath_parseline(struct manpaths *dirs, char *path)
1.1       kristaps  144: {
                    145:        char    *dir;
                    146:
                    147:        if (NULL == path)
                    148:                return;
                    149:
                    150:        for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
                    151:                manpath_add(dirs, dir);
                    152: }
                    153:
                    154: /*
                    155:  * Add a directory to the array, ignoring bad directories.
                    156:  * Grow the array one-by-one for simplicity's sake.
                    157:  */
                    158: static void
1.4       schwarze  159: manpath_add(struct manpaths *dirs, const char *dir)
1.1       kristaps  160: {
                    161:        char             buf[PATH_MAX];
                    162:        char            *cp;
1.9       kristaps  163:        size_t           i;
1.1       kristaps  164:
                    165:        if (NULL == (cp = realpath(dir, buf)))
                    166:                return;
                    167:
                    168:        for (i = 0; i < dirs->sz; i++)
                    169:                if (0 == strcmp(dirs->paths[i], dir))
                    170:                        return;
                    171:
                    172:        dirs->paths = mandoc_realloc
1.4       schwarze  173:                (dirs->paths,
1.9       kristaps  174:                 (dirs->sz + 1) * sizeof(char *));
1.1       kristaps  175:
                    176:        dirs->paths[dirs->sz++] = mandoc_strdup(cp);
1.2       kristaps  177: }
                    178:
                    179: void
                    180: manpath_free(struct manpaths *p)
                    181: {
1.9       kristaps  182:        size_t           i;
1.2       kristaps  183:
                    184:        for (i = 0; i < p->sz; i++)
                    185:                free(p->paths[i]);
                    186:
                    187:        free(p->paths);
                    188: }
                    189:
                    190: void
1.5       schwarze  191: manpath_manconf(struct manpaths *dirs, const char *file)
1.2       kristaps  192: {
                    193:        FILE            *stream;
1.1       kristaps  194:        char            *p, *q;
1.4       schwarze  195:        size_t           len, keysz;
1.1       kristaps  196:
                    197:        keysz = strlen(MAN_CONF_KEY);
                    198:        assert(keysz > 0);
                    199:
1.3       kristaps  200:        if (NULL == (stream = fopen(file, "r")))
1.1       kristaps  201:                return;
                    202:
                    203:        while (NULL != (p = fgetln(stream, &len))) {
                    204:                if (0 == len || '\n' != p[--len])
                    205:                        break;
                    206:                p[len] = '\0';
                    207:                while (isspace((unsigned char)*p))
                    208:                        p++;
                    209:                if (strncmp(MAN_CONF_KEY, p, keysz))
                    210:                        continue;
                    211:                p += keysz;
                    212:                while (isspace(*p))
                    213:                        p++;
                    214:                if ('\0' == *p)
                    215:                        continue;
                    216:                if (NULL == (q = strrchr(p, '/')))
                    217:                        continue;
                    218:                *q = '\0';
                    219:                manpath_add(dirs, p);
                    220:        }
                    221:
                    222:        fclose(stream);
                    223: }

CVSweb