Annotation of mandoc/manpath.c, Revision 1.7
1.7 ! kristaps 1: /* $Id: manpath.c,v 1.6 2011/12/13 20:56:46 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.4 schwarze 90: manpath_parseline(dirs, auxp);
91:
92: if (NULL == defp)
1.1 kristaps 93: defp = getenv("MANPATH");
94:
95: if (NULL == defp)
1.6 kristaps 96: manpath_manconf(dirs, file ? file : MAN_CONF_FILE);
1.1 kristaps 97: else
98: manpath_parseline(dirs, defp);
1.6 kristaps 99: #endif
1.1 kristaps 100: }
101:
102: /*
103: * Parse a FULL pathname from a colon-separated list of arrays.
104: */
1.6 kristaps 105: static void
1.4 schwarze 106: manpath_parseline(struct manpaths *dirs, char *path)
1.1 kristaps 107: {
108: char *dir;
109:
110: if (NULL == path)
111: return;
112:
113: for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
114: manpath_add(dirs, dir);
115: }
116:
117: /*
118: * Add a directory to the array, ignoring bad directories.
119: * Grow the array one-by-one for simplicity's sake.
120: */
121: static void
1.4 schwarze 122: manpath_add(struct manpaths *dirs, const char *dir)
1.1 kristaps 123: {
124: char buf[PATH_MAX];
125: char *cp;
126: int i;
127:
128: if (NULL == (cp = realpath(dir, buf)))
129: return;
130:
131: for (i = 0; i < dirs->sz; i++)
132: if (0 == strcmp(dirs->paths[i], dir))
133: return;
134:
135: dirs->paths = mandoc_realloc
1.4 schwarze 136: (dirs->paths,
1.1 kristaps 137: ((size_t)dirs->sz + 1) * sizeof(char *));
138:
139: dirs->paths[dirs->sz++] = mandoc_strdup(cp);
1.2 kristaps 140: }
141:
142: void
143: manpath_free(struct manpaths *p)
144: {
145: int i;
146:
147: for (i = 0; i < p->sz; i++)
148: free(p->paths[i]);
149:
150: free(p->paths);
151: }
152:
153: void
1.5 schwarze 154: manpath_manconf(struct manpaths *dirs, const char *file)
1.2 kristaps 155: {
156: FILE *stream;
1.1 kristaps 157: char *p, *q;
1.4 schwarze 158: size_t len, keysz;
1.1 kristaps 159:
160: keysz = strlen(MAN_CONF_KEY);
161: assert(keysz > 0);
162:
1.3 kristaps 163: if (NULL == (stream = fopen(file, "r")))
1.1 kristaps 164: return;
165:
166: while (NULL != (p = fgetln(stream, &len))) {
167: if (0 == len || '\n' != p[--len])
168: break;
169: p[len] = '\0';
170: while (isspace((unsigned char)*p))
171: p++;
172: if (strncmp(MAN_CONF_KEY, p, keysz))
173: continue;
174: p += keysz;
175: while (isspace(*p))
176: p++;
177: if ('\0' == *p)
178: continue;
179: if (NULL == (q = strrchr(p, '/')))
180: continue;
181: *q = '\0';
182: manpath_add(dirs, p);
183: }
184:
185: fclose(stream);
186: }
CVSweb