Annotation of mandoc/manpath.c, Revision 1.8
1.8 ! kristaps 1: /* $Id: manpath.c,v 1.7 2011/12/13 21:09:01 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.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. */
! 120: if (':' == defp[(int)strlen(defp) - 1]) {
! 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;
165: int i;
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.1 kristaps 176: ((size_t)dirs->sz + 1) * sizeof(char *));
177:
178: dirs->paths[dirs->sz++] = mandoc_strdup(cp);
1.2 kristaps 179: }
180:
181: void
182: manpath_free(struct manpaths *p)
183: {
184: int i;
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