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

Annotation of mandoc/manpath.c, Revision 1.8

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

CVSweb