4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / cap_mkdb / cap_mkdb.c
CommitLineData
5a884762 1/*-
9f00bf08
KB
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
06c161de 4 *
5a884762 5 * %sccs.include.redist.c%
06c161de
EA
6 */
7
8#ifndef lint
a40b35c0 9static char copyright[] =
9f00bf08
KB
10"@(#) Copyright (c) 1992, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
06c161de
EA
12#endif /* not lint */
13
14#ifndef lint
9f00bf08 15static char sccsid[] = "@(#)cap_mkdb.c 8.1 (Berkeley) %G%";
06c161de
EA
16#endif /* not lint */
17
415e0f84 18#include <sys/param.h>
0825a747 19#include <sys/stat.h>
5a884762 20
06c161de 21#include <db.h>
78d11288 22#include <err.h>
5a884762
EA
23#include <errno.h>
24#include <fcntl.h>
25#include <limits.h>
06c161de
EA
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
06c161de 29#include <unistd.h>
06c161de 30
78d11288
KB
31void db_build __P((char **));
32void dounlink __P((void));
33void usage __P((void));
06c161de 34
78d11288
KB
35DB *capdbp;
36int verbose;
37char *capdb, *capname, buf[8 * 1024];
06c161de
EA
38
39/*
5a884762
EA
40 * Mkcapdb creates a capability hash database for quick retrieval of capability
41 * records. The database contains 2 types of entries: records and references
42 * marked by the first byte in the data. A record entry contains the actual
43 * capability record whereas a reference contains the name (key) under which
44 * the correct record is stored.
06c161de 45 */
5a884762 46int
06c161de
EA
47main(argc, argv)
48 int argc;
5a884762 49 char *argv[];
06c161de 50{
78d11288 51 int c;
06c161de 52
78d11288 53 capname = NULL;
188c396b 54 while ((c = getopt(argc, argv, "f:v")) != EOF) {
06c161de
EA
55 switch(c) {
56 case 'f':
78d11288 57 capname = optarg;
06c161de 58 break;
188c396b
KB
59 case 'v':
60 verbose = 1;
61 break;
06c161de 62 case '?':
5a884762 63 default:
06c161de
EA
64 usage();
65 }
0825a747 66 }
06c161de 67 argc -= optind;
0825a747
KB
68 argv += optind;
69
06c161de
EA
70 if (*argv == NULL)
71 usage();
72
0825a747 73 /*
78d11288
KB
74 * The database file is the first argument if no name is specified.
75 * Make arrangements to unlink it if exit badly.
0825a747 76 */
78d11288
KB
77 (void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv);
78 if ((capname = strdup(buf)) == NULL)
79 err(1, "");
80 if ((capdbp = dbopen(capname,
81 O_CREAT | O_TRUNC | O_RDWR, DEFFILEMODE, DB_HASH, NULL)) == NULL)
82 err(1, "%s", buf);
83
84 if (atexit(dounlink))
85 err(1, "atexit");
e8e9e2d0 86
78d11288
KB
87 db_build(argv);
88
89 if (capdbp->close(capdbp) < 0)
90 err(1, "%s", capname);
91 capname = NULL;
06c161de
EA
92 exit(0);
93}
0825a747 94
78d11288
KB
95void
96dounlink()
97{
98 if (capname != NULL)
99 (void)unlink(capname);
100}
101
06c161de
EA
102/*
103 * Any changes to these definitions should be made also in the getcap(3)
104 * library routines.
105 */
a86ecba7
EA
106#define RECOK (char)0
107#define TCERR (char)1
78d11288 108#define SHADOW (char)2
06c161de
EA
109
110/*
111 * Db_build() builds the name and capabilty databases according to the
112 * details above.
113 */
5a884762 114void
78d11288
KB
115db_build(ifiles)
116 char **ifiles;
06c161de 117{
06c161de 118 DBT key, data;
0825a747 119 recno_t reccnt;
78d11288
KB
120 size_t len, bplen;
121 int st;
122 char *bp, *p, *t;
0825a747 123
5a884762
EA
124 data.data = NULL;
125 key.data = NULL;
78d11288
KB
126 for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) {
127
128 /*
129 * Allocate enough memory to store record, terminating
130 * NULL and one extra byte.
131 */
132 len = strlen(bp);
133 if (bplen <= len + 2) {
134 bplen += MAX(256, len + 2);
135 if ((data.data = realloc(data.data, bplen)) == NULL)
136 err(1, "");
06c161de
EA
137 }
138
490f8ad5
KB
139 /* Find the end of the name field. */
140 if ((p = strchr(bp, ':')) == NULL) {
141 warnx("no name field: %.*s", MIN(len, 20), bp);
142 continue;
143 }
144
145 /* First byte of stored record indicates status. */
146 switch(st) {
147 case 1:
148 ((char *)(data.data))[0] = RECOK;
149 break;
150 case 2:
151 ((char *)(data.data))[0] = TCERR;
152 warnx("Record not tc expanded: %.*s", p - bp, bp);
153 break;
154 }
78d11288
KB
155
156 /* Create the stored record. */
157 memmove(&((u_char *)(data.data))[1], bp, len + 1);
158 data.size = len + 2;
0825a747 159
490f8ad5 160 /* Store the record under the name field. */
78d11288
KB
161 key.data = bp;
162 key.size = p - bp;
163
164 switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) {
165 case -1:
166 err(1, "put");
167 /* NOTREACHED */
168 case 1:
169 warnx("ignored duplicate: %.*s",
170 key.size, (char *)key.data);
4b9c212b
EA
171 continue;
172 }
0825a747 173 ++reccnt;
06c161de 174
78d11288
KB
175 /* If only one name, ignore the rest. */
176 if ((p = strchr(bp, '|')) == NULL)
177 continue;
06c161de 178
78d11288
KB
179 /* The rest of the names reference the entire name. */
180 ((char *)(data.data))[0] = SHADOW;
181 memmove(&((u_char *)(data.data))[1], key.data, key.size);
182 data.size = key.size + 1;
183
184 /* Store references for other names. */
185 for (p = t = bp;; ++p) {
186 if (p > t && (*p == ':' || *p == '|')) {
187 key.size = p - t;
188 key.data = t;
189 switch(capdbp->put(capdbp,
190 &key, &data, R_NOOVERWRITE)) {
191 case -1:
192 err(1, "put");
193 /* NOTREACHED */
194 case 1:
195 warnx("ignored duplicate: %.*s",
196 key.size, (char *)key.data);
197 }
198 t = p + 1;
0825a747 199 }
78d11288
KB
200 if (*p == ':')
201 break;
202 }
06c161de 203 }
0825a747 204
78d11288
KB
205 switch(st) {
206 case -1:
207 err(1, "file argument");
208 /* NOTREACHED */
209 case -2:
210 errx(1, "potential reference loop detected");
211 /* NOTREACHED */
212 }
0825a747 213
188c396b
KB
214 if (verbose)
215 (void)printf("cap_mkdb: %d capability records\n", reccnt);
06c161de
EA
216}
217
5a884762 218void
06c161de
EA
219usage()
220{
0825a747 221 (void)fprintf(stderr,
0d7a9f9e 222 "usage: cap_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
0825a747 223 exit(1);
06c161de 224}