Annotation of src/usr.bin/info_mkdb/info_mkdb.c, Revision 1.2
1.2 ! millert 1: /* $OpenBSD: info_mkdb.c,v 1.1 1996/07/22 03:16:31 tholo Exp $ */
1.1 tholo 2:
3: /*-
4: * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by SigmaSoft, Th. Lockert.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #ifndef lint
1.2 ! millert 34: static char rcsid[] = "$OpenBSD: info_mkdb.c,v 1.1 1996/07/22 03:16:31 tholo Exp $";
1.1 tholo 35: #endif /* not lint */
36:
37: #include <sys/param.h>
38: #include <sys/stat.h>
39:
40: #include <db.h>
41: #include <err.h>
42: #include <errno.h>
43: #include <fcntl.h>
44: #include <limits.h>
45: #include <stdio.h>
46: #include <stdlib.h>
47: #include <string.h>
48: #include <ctype.h>
49: #include <unistd.h>
50:
51: void db_build __P((char **));
52: void dounlink __P((void));
53: void usage __P((void));
54: int igetnext __P((char **, char **));
55: int main __P((int, char *[]));
56:
57: DB *infodbp;
58: int verbose;
59: char *infoname, buf[8 * 1024];
60:
61: HASHINFO openinfo = {
62: 4096, /* bsize */
63: 16, /* ffactor */
64: 256, /* nelem */
65: 2048 * 1024, /* cachesize */
66: NULL, /* hash() */
67: 0 /* lorder */
68: };
69:
70: /*
71: * info_mkdb creates a capability hash database for quick retrieval of capability
72: * records. The database contains 2 types of entries: records and references
73: * marked by the first byte in the data. A record entry contains the actual
74: * capability record whereas a reference contains the name (key) under which
75: * the correct record is stored.
76: */
77: int
78: main(argc, argv)
79: int argc;
80: char *argv[];
81: {
82: int c;
83:
84: infoname = NULL;
1.2 ! millert 85: while ((c = getopt(argc, argv, "f:v")) != -1) {
1.1 tholo 86: switch(c) {
87: case 'f':
88: infoname = optarg;
89: break;
90: case 'v':
91: verbose = 1;
92: break;
93: case '?':
94: default:
95: usage();
96: }
97: }
98: argc -= optind;
99: argv += optind;
100:
101: if (*argv == NULL)
102: usage();
103:
104: /*
105: * The database file is the first argument if no name is specified.
106: * Make arrangements to unlink it if exit badly.
107: */
108: (void)snprintf(buf, sizeof(buf), "%s.db", infoname ? infoname : *argv);
109: if ((infoname = strdup(buf)) == NULL) {
110: err(1, "strdup");
111: /* NOTREACHED */
112: }
113: if ((infodbp = dbopen(infoname, O_CREAT | O_TRUNC | O_RDWR,
114: DEFFILEMODE, DB_HASH, &openinfo)) == NULL) {
115: err(1, "%s", buf);
116: /* NOTREACHED */
117: }
118:
119: if (atexit(dounlink)) {
120: err(1, "atexit");
121: /* NOTREACHED */
122: }
123:
124: db_build(argv);
125:
126: if (infodbp->close(infodbp) < 0) {
127: err(1, "%s", infoname);
128: /* NOTREACHED */
129: }
130: infoname = NULL;
131: exit(0);
132: /* NOTREACHED */
133: }
134:
135: void
136: dounlink()
137: {
138: if (infoname != NULL)
139: (void)unlink(infoname);
140: }
141:
142: /*
143: * Any changes to these definitions should be made also in the getcap(3)
144: * library routines.
145: */
146: #define RECOK (char)0
147: #define TCERR (char)1
148: #define SHADOW (char)2
149:
150: /*
151: * db_build() builds the name and capability databases according to the
152: * details above.
153: */
154: void
155: db_build(ifiles)
156: char **ifiles;
157: {
158: DBT key, data;
159: recno_t reccnt;
160: size_t len, bplen;
161: int st;
162: char *bp, *p, *t;
163:
164: data.data = NULL;
165: key.data = NULL;
166: for (reccnt = 0, bplen = 0; (st = igetnext(&bp, ifiles)) > 0;) {
167:
168: /*
169: * Allocate enough memory to store record, terminating
170: * NULL and one extra byte.
171: */
172: len = strlen(bp);
173: if (bplen <= len + 2) {
174: bplen += MAX(256, len + 2);
175: if ((data.data = realloc(data.data, bplen)) == NULL) {
176: err(1, "realloc");
177: /* NOTREACHED */
178: }
179: }
180:
181: /* Find the end of the name field. */
182: if ((p = strchr(bp, ',')) == NULL) {
183: warnx("no name field: %.*s", (int)MIN(len, 20), bp);
184: continue;
185: }
186:
187: if (isspace(*bp)) {
188: warnx("bad name field: %.*s", (int)MIN(len, 20), bp);
189: continue;
190: }
191:
192: /* First byte of stored record indicates status. */
193: switch(st) {
194: case 1:
195: ((char *)(data.data))[0] = RECOK;
196: break;
197: case 2:
198: ((char *)(data.data))[0] = TCERR;
199: warnx("Record not use expanded: %.*s", (int)(p - bp), bp);
200: break;
201: }
202:
203: /* Create the stored record. */
204: (void) memmove(&((u_char *)(data.data))[1], bp, len + 1);
205: data.size = len + 2;
206: for (t = memchr((char *)data.data + 1, ',', data.size - 1) ; t ; t = memchr(t, ',', data.size - (t - (char *)data.data)))
207: *t++ = ':';
208:
209: if (memchr((char *)data.data + 1, '\0', data.size - 2)) {
210: warnx("NUL in entry: %.*s", (int)MIN(len, 20), bp);
211: continue;
212: }
213:
214: /* Store the record under the name field. */
215: key.data = bp;
216: key.size = p - bp;
217:
218: switch(infodbp->put(infodbp, &key, &data, R_NOOVERWRITE)) {
219: case -1:
220: err(1, "put");
221: /* NOTREACHED */
222: case 1:
223: warnx("ignored duplicate: %.*s",
224: (int)key.size, (char *)key.data);
225: continue;
226: }
227: ++reccnt;
228:
229: /* If only one name, ignore the rest. */
230: if ((p = strchr(bp, '|')) == NULL)
231: continue;
232:
233: /* The rest of the names reference the entire name. */
234: ((char *)(data.data))[0] = SHADOW;
235: (void) memmove(&((u_char *)(data.data))[1], key.data, key.size);
236: data.size = key.size + 1;
237:
238: /* Store references for other names. */
239: for (p = t = bp;; ++p) {
240: if (p > t && (*p == ',' || *p == '|')) {
241: key.size = p - t;
242: key.data = t;
243:
244: switch(infodbp->put(infodbp,
245: &key, &data, R_NOOVERWRITE)) {
246: case -1:
247: err(1, "put");
248: /* NOTREACHED */
249: case 1:
250: warnx("ignored duplicate: %.*s",
251: (int)key.size, (char *)key.data);
252: }
253: t = p + 1;
254: }
255: if (*p == ',')
256: break;
257: }
258: }
259:
260: switch(st) {
261: case -1:
262: err(1, "file argument");
263: /* NOTREACHED */
264: case -2:
265: errx(1, "potential reference loop detected");
266: /* NOTREACHED */
267: }
268:
269: if (verbose)
270: (void)printf("info_mkdb: %d capability records\n", reccnt);
271: }
272:
273: void
274: usage()
275: {
276: (void)fprintf(stderr,
277: "usage: info_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
278: exit(1);
279: }