]> git.cameronkatri.com Git - mandoc.git/blob - manpath.c
Do not cast void pointers to pointers requiring alignment.
[mandoc.git] / manpath.c
1 /* $Id: manpath.c,v 1.7 2011/12/13 21:09:01 kristaps Exp $ */
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 <sys/param.h>
23
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 *);
38 static void manpath_parseline(struct manpaths *, char *);
39
40 void
41 manpath_parse(struct manpaths *dirs, const char *file,
42 char *defp, char *auxp)
43 {
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 }
86
87 free(buf);
88 pclose(stream);
89 #else
90 manpath_parseline(dirs, auxp);
91
92 if (NULL == defp)
93 defp = getenv("MANPATH");
94
95 if (NULL == defp)
96 manpath_manconf(dirs, file ? file : MAN_CONF_FILE);
97 else
98 manpath_parseline(dirs, defp);
99 #endif
100 }
101
102 /*
103 * Parse a FULL pathname from a colon-separated list of arrays.
104 */
105 static void
106 manpath_parseline(struct manpaths *dirs, char *path)
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
122 manpath_add(struct manpaths *dirs, const char *dir)
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
136 (dirs->paths,
137 ((size_t)dirs->sz + 1) * sizeof(char *));
138
139 dirs->paths[dirs->sz++] = mandoc_strdup(cp);
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
154 manpath_manconf(struct manpaths *dirs, const char *file)
155 {
156 FILE *stream;
157 char *p, *q;
158 size_t len, keysz;
159
160 keysz = strlen(MAN_CONF_KEY);
161 assert(keysz > 0);
162
163 if (NULL == (stream = fopen(file, "r")))
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 }