Commit | Line | Data |
---|---|---|
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 | 9 | static 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 | 15 | static 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 |
31 | void db_build __P((char **)); |
32 | void dounlink __P((void)); | |
33 | void usage __P((void)); | |
06c161de | 34 | |
78d11288 KB |
35 | DB *capdbp; |
36 | int verbose; | |
37 | char *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 | 46 | int |
06c161de EA |
47 | main(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 |
95 | void |
96 | dounlink() | |
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 | 114 | void |
78d11288 KB |
115 | db_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 | 218 | void |
06c161de EA |
219 | usage() |
220 | { | |
0825a747 | 221 | (void)fprintf(stderr, |
0d7a9f9e | 222 | "usage: cap_mkdb [-v] [-f outfile] file1 [file2 ...]\n"); |
0825a747 | 223 | exit(1); |
06c161de | 224 | } |