Annotation of mandoc/manpath.c, Revision 1.3
1.3 ! kristaps 1: /* $Id: manpath.c,v 1.2 2011/11/24 10:43:55 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:
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 *);
36:
37: void
38: manpath_parse(struct manpaths *dirs, char *defp, char *auxp)
39: {
40:
41: if (NULL != getenv("MANPATH"))
42: defp = getenv("MANPATH");
43:
44: if (NULL == defp)
45: manpath_parseconf(dirs);
46: else
47: manpath_parseline(dirs, defp);
48:
49: manpath_parseline(dirs, auxp);
50: }
51:
52: /*
53: * Parse a FULL pathname from a colon-separated list of arrays.
54: */
55: void
56: manpath_parseline(struct manpaths *dirs, char *path)
57: {
58: char *dir;
59:
60: if (NULL == path)
61: return;
62:
63: for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
64: manpath_add(dirs, dir);
65: }
66:
67: /*
68: * Add a directory to the array, ignoring bad directories.
69: * Grow the array one-by-one for simplicity's sake.
70: */
71: static void
72: manpath_add(struct manpaths *dirs, const char *dir)
73: {
74: char buf[PATH_MAX];
75: char *cp;
76: int i;
77:
78: if (NULL == (cp = realpath(dir, buf)))
79: return;
80:
81: for (i = 0; i < dirs->sz; i++)
82: if (0 == strcmp(dirs->paths[i], dir))
83: return;
84:
85: dirs->paths = mandoc_realloc
86: (dirs->paths,
87: ((size_t)dirs->sz + 1) * sizeof(char *));
88:
89: dirs->paths[dirs->sz++] = mandoc_strdup(cp);
90: }
91:
92: void
93: manpath_parseconf(struct manpaths *dirs)
94: {
1.2 kristaps 95: #ifdef USE_MANPATH
1.1 kristaps 96: FILE *stream;
97: char *buf;
98: size_t sz, bsz;
99:
100: /* Open manpath(1). Ignore errors. */
101:
102: stream = popen("manpath", "r");
103: if (NULL == stream)
104: return;
105:
106: buf = NULL;
107: bsz = 0;
108:
109: /* Read in as much output as we can. */
110:
111: do {
112: buf = mandoc_realloc(buf, bsz + 1024);
113: sz = fread(buf + (int)bsz, 1, 1024, stream);
114: bsz += sz;
115: } while (sz > 0);
116:
117: if ( ! ferror(stream) && feof(stream) &&
118: bsz && '\n' == buf[bsz - 1]) {
119: buf[bsz - 1] = '\0';
120: manpath_parseline(dirs, buf);
121: }
122:
123: free(buf);
124: pclose(stream);
125: #else
1.3 ! kristaps 126: manpath_manconf(MAN_CONF_FILE, dirs);
1.2 kristaps 127: #endif
128: }
129:
130: void
131: manpath_free(struct manpaths *p)
132: {
133: int i;
134:
135: for (i = 0; i < p->sz; i++)
136: free(p->paths[i]);
137:
138: free(p->paths);
139: }
140:
141: void
1.3 ! kristaps 142: manpath_manconf(const char *file, struct manpaths *dirs)
1.2 kristaps 143: {
144: FILE *stream;
1.1 kristaps 145: char *p, *q;
146: size_t len, keysz;
147:
148: keysz = strlen(MAN_CONF_KEY);
149: assert(keysz > 0);
150:
1.3 ! kristaps 151: if (NULL == (stream = fopen(file, "r")))
1.1 kristaps 152: return;
153:
154: while (NULL != (p = fgetln(stream, &len))) {
155: if (0 == len || '\n' != p[--len])
156: break;
157: p[len] = '\0';
158: while (isspace((unsigned char)*p))
159: p++;
160: if (strncmp(MAN_CONF_KEY, p, keysz))
161: continue;
162: p += keysz;
163: while (isspace(*p))
164: p++;
165: if ('\0' == *p)
166: continue;
167: if (NULL == (q = strrchr(p, '/')))
168: continue;
169: *q = '\0';
170: manpath_add(dirs, p);
171: }
172:
173: fclose(stream);
174: }
CVSweb