]> git.cameronkatri.com Git - mandoc.git/blob - manpath.c
Allow man.conf file to be assignable.
[mandoc.git] / manpath.c
1 /* $Id: manpath.c,v 1.3 2011/11/24 10:44:56 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 <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 {
95 #ifdef USE_MANPATH
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
126 manpath_manconf(MAN_CONF_FILE, dirs);
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
142 manpath_manconf(const char *file, struct manpaths *dirs)
143 {
144 FILE *stream;
145 char *p, *q;
146 size_t len, keysz;
147
148 keysz = strlen(MAN_CONF_KEY);
149 assert(keysz > 0);
150
151 if (NULL == (stream = fopen(file, "r")))
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 }