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