minor cleanup
[unix-history] / usr / src / usr.bin / cap_mkdb / cap_mkdb.c
CommitLineData
5a884762 1/*-
06c161de
EA
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5a884762 5 * %sccs.include.redist.c%
06c161de
EA
6 */
7
8#ifndef lint
a40b35c0 9static char copyright[] =
06c161de
EA
10"@(#) Copyright (c) 1992 The Regents of the University of California.\n\
11 All rights reserved.\n";
12#endif /* not lint */
13
14#ifndef lint
4bf71922 15static char sccsid[] = "@(#)cap_mkdb.c 5.4 (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>
5a884762
EA
22#include <errno.h>
23#include <fcntl.h>
24#include <limits.h>
06c161de
EA
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
06c161de 28#include <unistd.h>
06c161de
EA
29
30static void db_build __P((char **));
4b9c212b 31static void err __P((int, const char *, ...));
06c161de
EA
32static void getnamefield __P((char **, char *));
33static void usage __P((void));
34
188c396b 35int docapdbunlink, printnl, verbose;
5a884762 36char *capdb, **inputfiles;
06c161de
EA
37
38/*
5a884762
EA
39 * Mkcapdb creates a capability hash database for quick retrieval of capability
40 * records. The database contains 2 types of entries: records and references
41 * marked by the first byte in the data. A record entry contains the actual
42 * capability record whereas a reference contains the name (key) under which
43 * the correct record is stored.
06c161de 44 */
5a884762 45int
06c161de
EA
46main(argc, argv)
47 int argc;
5a884762 48 char *argv[];
06c161de 49{
415e0f84
EA
50 int c, fd;
51 char *outname, buf[MAXPATHLEN + 1], **f;
06c161de
EA
52
53 outname = NULL;
188c396b 54 while ((c = getopt(argc, argv, "f:v")) != EOF) {
06c161de
EA
55 switch(c) {
56 case 'f':
57 outname = optarg;
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
73 inputfiles = argv;
74
75 if (outname == NULL)
76 outname = *inputfiles;
77
5a884762
EA
78#define CAPDBNAMEEXTLEN 3 /* ".db" */
79 if ((capdb = malloc(strlen(outname) + CAPDBNAMEEXTLEN + 1)) == NULL)
4b9c212b 80 err(1, "%s", strerror(errno));
5a884762 81 (void)sprintf(capdb, "%s.db", outname);
06c161de 82
0825a747
KB
83 /*
84 * We want to avoid the confusion of where the capability record
85 * is being read from. Since the user probably intends to read the
86 * ascii file, we should make sure that user knows that the
415e0f84 87 * corresponding .db file will override.
0825a747 88 */
415e0f84
EA
89 for (f = inputfiles; *f != NULL; f++) {
90 (void)sprintf(buf, "%s.db", *f);
188c396b 91 fd = open(buf, O_RDONLY, 0);
0825a747
KB
92 if (fd == -1 && errno != ENOENT)
93 err(1, "%s: %s", buf, strerror(errno));
415e0f84 94 if (fd >= 0) {
188c396b 95 err(0, "%s.db overrides %s.", *f, *f);
415e0f84
EA
96 (void)close(fd);
97 }
98 }
e8e9e2d0 99
0825a747 100 db_build(inputfiles);
06c161de
EA
101 exit(0);
102}
0825a747 103
06c161de
EA
104/*
105 * Any changes to these definitions should be made also in the getcap(3)
106 * library routines.
107 */
a86ecba7
EA
108
109#define RECOK (char)0
110#define TCERR (char)1
111
5a884762 112#define NBUFSIZ (8 * 1024)
06c161de
EA
113
114/*
115 * Db_build() builds the name and capabilty databases according to the
116 * details above.
117 */
5a884762 118void
06c161de
EA
119db_build(inputfiles)
120 char **inputfiles;
121{
122 DB *capdbp;
123 DBT key, data;
0825a747 124 recno_t reccnt;
06c161de 125 size_t lastlen, bplen;
0825a747 126 int st, stdb;
5a884762 127 char *cp, *np, *bp, *nf, namebuf[NBUFSIZ];
0825a747
KB
128
129 if ((capdbp = dbopen(capdb, O_CREAT | O_TRUNC | O_RDWR,
130 DEFFILEMODE, DB_HASH, NULL)) == NULL)
4b9c212b 131 err(1, "%s: %s", capdb, strerror(errno));
5a884762 132 docapdbunlink = 1;
0825a747 133
06c161de 134 lastlen = 0;
5a884762
EA
135 nf = NULL;
136 data.data = NULL;
137 key.data = NULL;
0825a747 138 for (reccnt = 0; (st = cgetnext(&bp, inputfiles)) > 0;) {
06c161de
EA
139 getnamefield(&nf, bp);
140 if ((bplen = strlen(bp)) > lastlen) {
0825a747 141 if ((data.data = realloc(data.data, bplen + 2)) == NULL)
4b9c212b 142 err(1, "%s", strerror(errno));
06c161de
EA
143 lastlen = bplen;
144 }
145
0825a747 146 /* Store record under name field. */
a86ecba7
EA
147 if (st == 2)
148 ((char *)(data.data))[0] = TCERR;
149 else
150 ((char *)(data.data))[0] = RECOK;
0825a747 151
5a884762 152 (void)strcpy(&((char *)(data.data))[1], bp);
06c161de 153 data.size = bplen + 2;
e41e2450
EA
154 key.data = nf;
155 key.size = strlen(nf) + 1;
0825a747
KB
156 if ((stdb =
157 capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) < 0)
4b9c212b
EA
158 err(1, "put: %s", strerror(errno));
159 if (stdb == 1) {
0825a747 160 err(0, "ignored duplicate: %s", nf);
4b9c212b
EA
161 continue;
162 }
0825a747 163 ++reccnt;
06c161de 164
0825a747 165 /* Store references for other names. */
a86ecba7 166 (void)strcpy((char *)(data.data), nf);
06c161de 167
1d6e0482 168 data.size = key.size;
e41e2450
EA
169 key.data = namebuf;
170 np = namebuf;
0825a747 171 for (cp = nf; *cp != '\0'; *np++ = *cp++)
06c161de
EA
172 if (*cp == ':' || *cp == '|') {
173 *np = '\0';
174 key.size = strlen(namebuf) + 1;
0825a747
KB
175 if ((stdb = capdbp->put(capdbp, &key, &data,
176 R_NOOVERWRITE)) < 0)
4b9c212b
EA
177 err(1, "put: %s", strerror(errno));
178 if (stdb == 1)
0825a747
KB
179 err(0,
180 "ignored duplicate: %s", namebuf);
06c161de
EA
181 np = namebuf;
182 continue;
0825a747 183 }
06c161de 184 }
5a884762 185 if (capdbp->close(capdbp) < 0)
4bf71922 186 err(1, "%s: %s", capdb, strerror(errno));
0825a747 187
5a884762 188 if (st == -1)
4bf71922 189 err(1, "file argument: %s", strerror(errno));
5a884762 190 if (st == -2)
4b9c212b 191 err(1, "potential reference loop detected");
0825a747 192
06c161de
EA
193 free(data.data);
194 free(nf);
195 free(bp);
0825a747 196
188c396b
KB
197 if (verbose)
198 (void)printf("cap_mkdb: %d capability records\n", reccnt);
06c161de
EA
199}
200
5a884762 201void
06c161de
EA
202getnamefield(nf, bp)
203 char **nf, *bp;
204{
5a884762 205 static size_t nfsize;
06c161de
EA
206 size_t newsize;
207 char *cp, tmp;
0825a747 208
5a884762 209 for (cp = bp; *cp != ':'; cp++);
06c161de 210
5a884762
EA
211 tmp = *(cp + 1);
212 *(cp + 1) = '\0';
06c161de
EA
213
214 if ((newsize = cp - bp + 1) > nfsize) {
5a884762 215 if ((*nf = realloc(*nf, newsize)) == NULL)
4b9c212b 216 err(1, "%s", strerror(errno));
06c161de
EA
217 nfsize = newsize;
218 }
5a884762
EA
219 (void)strcpy(*nf, bp);
220 *(cp + 1) = tmp;
06c161de
EA
221}
222
5a884762 223void
06c161de
EA
224usage()
225{
0825a747 226 (void)fprintf(stderr,
0d7a9f9e 227 "usage: cap_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
0825a747 228 exit(1);
06c161de
EA
229}
230
06c161de
EA
231#if __STDC__
232#include <stdarg.h>
233#else
234#include <varargs.h>
235#endif
236
5a884762 237void
06c161de 238#if __STDC__
4b9c212b 239err(int fatal, const char *fmt, ...)
06c161de 240#else
5a884762
EA
241err(fmt, va_alist)
242 char *fmt;
0825a747 243 va_dcl
06c161de
EA
244#endif
245{
5a884762 246 va_list ap;
06c161de 247#if __STDC__
5a884762 248 va_start(ap, fmt);
06c161de 249#else
5a884762 250 va_start(ap);
06c161de 251#endif
e8e9e2d0
EA
252
253 if (printnl)
254 (void)fprintf(stderr, "\n");
5a884762
EA
255 (void)fprintf(stderr, "cap_mkdb: ");
256 (void)vfprintf(stderr, fmt, ap);
257 va_end(ap);
258 (void)fprintf(stderr, "\n");
4b9c212b
EA
259 if (fatal) {
260 if (docapdbunlink)
261 (void)unlink(capdb);
262 exit(1);
263 }
06c161de 264}