Commit | Line | Data |
---|---|---|
d15694cb EA |
1 | /* |
2 | * Copyright (c) 1992 Eric P. Allman. | |
0ca831ff KB |
3 | * Copyright (c) 1992, 1993 |
4 | * The Regents of the University of California. All rights reserved. | |
d15694cb EA |
5 | * |
6 | * %sccs.include.redist.c% | |
7 | */ | |
8 | ||
9 | #ifndef lint | |
4047d96e | 10 | static char sccsid[] = "@(#)makemap.c 8.6.1.1 (Berkeley) %G%"; |
d15694cb EA |
11 | #endif /* not lint */ |
12 | ||
13 | #include <stdio.h> | |
14 | #include <sysexits.h> | |
0831ce43 | 15 | #include <sys/types.h> |
d15694cb EA |
16 | #include <ctype.h> |
17 | #include <string.h> | |
cfe4603e | 18 | #include <sys/errno.h> |
1c30052f EA |
19 | #ifndef ISC_UNIX |
20 | # include <sys/file.h> | |
21 | #endif | |
d15694cb EA |
22 | #include "useful.h" |
23 | #include "conf.h" | |
24 | ||
7c0d4a25 | 25 | #ifdef NDBM |
d15694cb EA |
26 | #include <ndbm.h> |
27 | #endif | |
28 | ||
7c0d4a25 | 29 | #ifdef NEWDB |
d15694cb EA |
30 | #include <db.h> |
31 | #endif | |
32 | ||
33 | enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN }; | |
34 | ||
35 | union dbent | |
36 | { | |
7c0d4a25 | 37 | #ifdef NDBM |
d15694cb EA |
38 | datum dbm; |
39 | #endif | |
7c0d4a25 | 40 | #ifdef NEWDB |
d15694cb EA |
41 | DBT db; |
42 | #endif | |
43 | struct | |
44 | { | |
45 | char *data; | |
0f7e8197 | 46 | size_t size; |
d15694cb EA |
47 | } xx; |
48 | }; | |
49 | ||
50 | #define BUFSIZE 1024 | |
51 | ||
52 | main(argc, argv) | |
53 | int argc; | |
54 | char **argv; | |
55 | { | |
56 | char *progname; | |
57 | bool inclnull = FALSE; | |
58 | bool notrunc = FALSE; | |
59 | bool allowreplace = FALSE; | |
b6c410ad | 60 | bool allowdups = FALSE; |
d15694cb | 61 | bool verbose = FALSE; |
d9f63e05 | 62 | bool foldcase = TRUE; |
d15694cb EA |
63 | int exitstat; |
64 | int opt; | |
65 | char *typename; | |
66 | char *mapname; | |
3e5fd3c1 | 67 | char *ext; |
d15694cb EA |
68 | int lineno; |
69 | int st; | |
70 | int mode; | |
71 | enum type type; | |
cfe4603e | 72 | int fd; |
d15694cb EA |
73 | union |
74 | { | |
7c0d4a25 | 75 | #ifdef NDBM |
d15694cb EA |
76 | DBM *dbm; |
77 | #endif | |
7c0d4a25 | 78 | #ifdef NEWDB |
d15694cb EA |
79 | DB *db; |
80 | #endif | |
81 | void *dbx; | |
82 | } dbp; | |
83 | union dbent key, val; | |
b6c410ad EA |
84 | #ifdef NEWDB |
85 | BTREEINFO bti; | |
86 | #endif | |
d15694cb | 87 | char ibuf[BUFSIZE]; |
d12852be | 88 | char fbuf[MAXNAME]; |
d15694cb EA |
89 | extern char *optarg; |
90 | extern int optind; | |
cfe4603e | 91 | extern bool lockfile(); |
d15694cb EA |
92 | |
93 | progname = argv[0]; | |
94 | ||
b6c410ad | 95 | while ((opt = getopt(argc, argv, "Ndforv")) != EOF) |
d15694cb EA |
96 | { |
97 | switch (opt) | |
98 | { | |
99 | case 'N': | |
100 | inclnull = TRUE; | |
101 | break; | |
102 | ||
b6c410ad EA |
103 | case 'd': |
104 | allowdups = TRUE; | |
105 | break; | |
106 | ||
1b15d3af | 107 | case 'f': |
d9f63e05 | 108 | foldcase = FALSE; |
1b15d3af EA |
109 | break; |
110 | ||
d15694cb EA |
111 | case 'o': |
112 | notrunc = TRUE; | |
113 | break; | |
114 | ||
115 | case 'r': | |
116 | allowreplace = TRUE; | |
117 | break; | |
118 | ||
119 | case 'v': | |
120 | verbose = TRUE; | |
121 | break; | |
122 | ||
123 | default: | |
124 | type = T_ERR; | |
125 | break; | |
126 | } | |
127 | } | |
128 | ||
129 | argc -= optind; | |
130 | argv += optind; | |
131 | if (argc != 2) | |
132 | type = T_ERR; | |
133 | else | |
134 | { | |
135 | typename = argv[0]; | |
136 | mapname = argv[1]; | |
d12852be | 137 | ext = NULL; |
d15694cb EA |
138 | |
139 | if (strcmp(typename, "dbm") == 0) | |
d12852be | 140 | { |
d15694cb | 141 | type = T_DBM; |
d12852be | 142 | } |
d15694cb | 143 | else if (strcmp(typename, "btree") == 0) |
d12852be | 144 | { |
d15694cb | 145 | type = T_BTREE; |
d12852be EA |
146 | ext = ".db"; |
147 | } | |
d15694cb | 148 | else if (strcmp(typename, "hash") == 0) |
d12852be | 149 | { |
d15694cb | 150 | type = T_HASH; |
d12852be EA |
151 | ext = ".db"; |
152 | } | |
d15694cb EA |
153 | else |
154 | type = T_UNKNOWN; | |
155 | } | |
156 | ||
157 | switch (type) | |
158 | { | |
159 | case T_ERR: | |
b6c410ad | 160 | fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname); |
d15694cb EA |
161 | exit(EX_USAGE); |
162 | ||
163 | case T_UNKNOWN: | |
164 | fprintf(stderr, "%s: Unknown database type %s\n", | |
165 | progname, typename); | |
166 | exit(EX_USAGE); | |
167 | ||
7c0d4a25 | 168 | #ifndef NDBM |
d15694cb EA |
169 | case T_DBM: |
170 | #endif | |
7c0d4a25 | 171 | #ifndef NEWDB |
d15694cb | 172 | case T_BTREE: |
d15694cb EA |
173 | case T_HASH: |
174 | #endif | |
175 | fprintf(stderr, "%s: Type %s not supported in this version\n", | |
176 | progname, typename); | |
177 | exit(EX_UNAVAILABLE); | |
b6c410ad EA |
178 | |
179 | #ifdef NEWDB | |
180 | case T_BTREE: | |
181 | bzero(&bti, sizeof bti); | |
182 | if (allowdups) | |
183 | bti.flags |= R_DUP; | |
184 | break; | |
185 | ||
186 | case T_HASH: | |
187 | #endif | |
188 | #ifdef NDBM | |
189 | case T_DBM: | |
190 | #endif | |
191 | if (allowdups) | |
192 | { | |
193 | fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n", | |
194 | progname, typename); | |
195 | exit(EX_UNAVAILABLE); | |
196 | } | |
197 | break; | |
d15694cb EA |
198 | } |
199 | ||
d12852be EA |
200 | /* |
201 | ** Adjust file names. | |
202 | */ | |
203 | ||
204 | if (ext != NULL) | |
205 | { | |
206 | int el, fl; | |
207 | ||
208 | el = strlen(ext); | |
209 | fl = strlen(mapname); | |
210 | if (fl < el || strcmp(&mapname[fl - el], ext) != 0) | |
211 | { | |
212 | strcpy(fbuf, mapname); | |
213 | strcat(fbuf, ext); | |
214 | mapname = fbuf; | |
215 | } | |
216 | } | |
217 | ||
d15694cb EA |
218 | /* |
219 | ** Create the database. | |
220 | */ | |
221 | ||
222 | mode = O_RDWR; | |
cfe4603e EA |
223 | #ifdef O_EXLOCK |
224 | mode |= O_EXLOCK; | |
225 | #endif | |
d15694cb EA |
226 | if (!notrunc) |
227 | mode |= O_CREAT|O_TRUNC; | |
228 | switch (type) | |
229 | { | |
7c0d4a25 | 230 | #ifdef NDBM |
d15694cb EA |
231 | case T_DBM: |
232 | dbp.dbm = dbm_open(mapname, mode, 0644); | |
233 | break; | |
234 | #endif | |
235 | ||
7c0d4a25 | 236 | #ifdef NEWDB |
d15694cb EA |
237 | case T_HASH: |
238 | dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); | |
30975906 EA |
239 | if (dbp.db != NULL) |
240 | (void) (*dbp.db->sync)(dbp.db, 0); | |
d15694cb | 241 | break; |
d15694cb | 242 | |
d15694cb | 243 | case T_BTREE: |
b6c410ad | 244 | dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti); |
30975906 EA |
245 | if (dbp.db != NULL) |
246 | (void) (*dbp.db->sync)(dbp.db, 0); | |
d15694cb EA |
247 | break; |
248 | #endif | |
249 | ||
250 | default: | |
251 | fprintf(stderr, "%s: internal error: type %d\n", progname, type); | |
252 | exit(EX_SOFTWARE); | |
253 | } | |
254 | ||
255 | if (dbp.dbx == NULL) | |
256 | { | |
257 | fprintf(stderr, "%s: cannot create type %s map %s\n", | |
258 | progname, typename, mapname); | |
259 | exit(EX_CANTCREAT); | |
260 | } | |
261 | ||
cfe4603e EA |
262 | #ifndef O_EXLOCK |
263 | switch (type) | |
264 | { | |
265 | # ifdef NDBM | |
266 | case T_DBM: | |
267 | fd = dbm_dirfno(dbp.dbm); | |
268 | if (fd >= 0) | |
269 | lockfile(fd); | |
270 | break; | |
271 | # endif | |
272 | # ifdef NEWDB | |
273 | case T_HASH: | |
274 | case T_BTREE: | |
275 | fd = dbp.db->fd(dbp.db); | |
276 | if (fd >= 0) | |
277 | lockfile(fd); | |
278 | break; | |
279 | # endif | |
280 | } | |
281 | #endif | |
282 | ||
d15694cb EA |
283 | /* |
284 | ** Copy the data | |
285 | */ | |
286 | ||
287 | lineno = 0; | |
288 | exitstat = EX_OK; | |
289 | while (fgets(ibuf, sizeof ibuf, stdin) != NULL) | |
290 | { | |
291 | register char *p; | |
292 | ||
293 | lineno++; | |
294 | ||
295 | /* | |
296 | ** Parse the line. | |
297 | */ | |
298 | ||
299 | p = strchr(ibuf, '\n'); | |
66f20e4b | 300 | if (p != NULL) |
d15694cb | 301 | *p = '\0'; |
66f20e4b EA |
302 | else if (!feof(stdin)) |
303 | { | |
304 | fprintf(stderr, "%s: %s: line %d: line too long (%d bytes max)\n", | |
305 | progname, mapname, lineno, sizeof ibuf); | |
306 | continue; | |
307 | } | |
308 | ||
d15694cb EA |
309 | if (ibuf[0] == '\0' || ibuf[0] == '#') |
310 | continue; | |
311 | if (isspace(ibuf[0])) | |
312 | { | |
313 | fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", | |
314 | progname, mapname, lineno); | |
315 | continue; | |
316 | } | |
317 | key.xx.data = ibuf; | |
318 | for (p = ibuf; *p != '\0' && !isspace(*p); p++) | |
1b15d3af EA |
319 | { |
320 | if (foldcase && isupper(*p)) | |
321 | *p = tolower(*p); | |
322 | } | |
d15694cb EA |
323 | key.xx.size = p - key.xx.data; |
324 | if (inclnull) | |
325 | key.xx.size++; | |
326 | if (*p != '\0') | |
327 | *p++ = '\0'; | |
328 | while (isspace(*p)) | |
329 | p++; | |
330 | if (*p == '\0') | |
331 | { | |
332 | fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", | |
333 | progname, mapname, lineno, key.xx.data); | |
334 | continue; | |
335 | } | |
336 | val.xx.data = p; | |
337 | val.xx.size = strlen(p); | |
338 | if (inclnull) | |
339 | val.xx.size++; | |
340 | ||
341 | /* | |
342 | ** Do the database insert. | |
343 | */ | |
344 | ||
345 | if (verbose) | |
346 | { | |
347 | printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); | |
348 | } | |
349 | ||
350 | switch (type) | |
351 | { | |
7c0d4a25 | 352 | #ifdef NDBM |
d15694cb EA |
353 | case T_DBM: |
354 | st = dbm_store(dbp.dbm, key.dbm, val.dbm, | |
355 | allowreplace ? DBM_REPLACE : DBM_INSERT); | |
356 | break; | |
357 | #endif | |
358 | ||
7c0d4a25 | 359 | #ifdef NEWDB |
d15694cb EA |
360 | case T_BTREE: |
361 | case T_HASH: | |
362 | st = (*dbp.db->put)(dbp.db, &key.db, &val.db, | |
363 | allowreplace ? 0 : R_NOOVERWRITE); | |
364 | break; | |
365 | #endif | |
366 | } | |
367 | ||
368 | if (st < 0) | |
369 | { | |
370 | fprintf(stderr, "%s: %s: line %d: key %s: put error\n", | |
371 | progname, mapname, lineno, key.xx.data); | |
372 | perror(mapname); | |
373 | exitstat = EX_IOERR; | |
374 | } | |
375 | else if (st > 0) | |
376 | { | |
377 | fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", | |
378 | progname, mapname, lineno, key.xx.data); | |
379 | } | |
380 | } | |
381 | ||
382 | /* | |
383 | ** Now close the database. | |
384 | */ | |
385 | ||
386 | switch (type) | |
387 | { | |
7c0d4a25 | 388 | #ifdef NDBM |
d15694cb EA |
389 | case T_DBM: |
390 | dbm_close(dbp.dbm); | |
391 | break; | |
392 | #endif | |
393 | ||
7c0d4a25 | 394 | #ifdef NEWDB |
d15694cb EA |
395 | case T_HASH: |
396 | case T_BTREE: | |
397 | if ((*dbp.db->close)(dbp.db) < 0) | |
398 | { | |
399 | fprintf(stderr, "%s: %s: error on close\n", | |
400 | progname, mapname); | |
401 | perror(mapname); | |
402 | exitstat = EX_IOERR; | |
403 | } | |
404 | #endif | |
405 | } | |
406 | ||
407 | exit (exitstat); | |
408 | } | |
cfe4603e EA |
409 | \f/* |
410 | ** LOCKFILE -- lock a file using flock or (shudder) fcntl locking | |
411 | ** | |
412 | ** Parameters: | |
413 | ** fd -- the file descriptor of the file. | |
414 | ** | |
415 | ** Returns: | |
416 | ** TRUE if the lock was acquired. | |
417 | ** FALSE otherwise. | |
418 | */ | |
419 | ||
420 | bool | |
421 | lockfile(fd) | |
422 | int fd; | |
423 | { | |
424 | # if !HASFLOCK | |
425 | int action; | |
426 | struct flock lfd; | |
427 | extern int errno; | |
428 | ||
429 | bzero(&lfd, sizeof lfd); | |
430 | lfd.l_type = F_WRLCK; | |
431 | action = F_SETLKW; | |
432 | ||
433 | if (fcntl(fd, action, &lfd) >= 0) | |
434 | return TRUE; | |
435 | ||
436 | /* | |
437 | ** On SunOS, if you are testing using -oQ/tmp/mqueue or | |
438 | ** -oA/tmp/aliases or anything like that, and /tmp is mounted | |
439 | ** as type "tmp" (that is, served from swap space), the | |
440 | ** previous fcntl will fail with "Invalid argument" errors. | |
441 | ** Since this is fairly common during testing, we will assume | |
442 | ** that this indicates that the lock is successfully grabbed. | |
443 | */ | |
444 | ||
445 | if (errno == EINVAL) | |
446 | return TRUE; | |
447 | ||
448 | # else /* HASFLOCK */ | |
449 | ||
450 | if (flock(fd, LOCK_EX) >= 0) | |
451 | return TRUE; | |
452 | ||
453 | # endif | |
454 | ||
455 | return FALSE; | |
456 | } |