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

Annotation of mandoc/manpath.c, Revision 1.9

1.9     ! kristaps    1: /*     $Id: manpath.c,v 1.8 2011/12/24 22:37:16 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);
1.9     ! kristaps   77:                sz = fread(buf + bsz, 1, 1024, stream);
1.6       kristaps   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. */
1.9     ! kristaps  120:        if (':' == defp[strlen(defp) - 1]) {
1.8       kristaps  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;
1.9     ! kristaps  165:        size_t           i;
1.1       kristaps  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.9     ! kristaps  176:                 (dirs->sz + 1) * sizeof(char *));
1.1       kristaps  177:
                    178:        dirs->paths[dirs->sz++] = mandoc_strdup(cp);
1.2       kristaps  179: }
                    180:
                    181: void
                    182: manpath_free(struct manpaths *p)
                    183: {
1.9     ! kristaps  184:        size_t           i;
1.2       kristaps  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