netgroup_mkdb.c revision 1.4 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1994 Christos Zoulas
3 1.1 christos * All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that the following conditions
7 1.1 christos * are met:
8 1.1 christos * 1. Redistributions of source code must retain the above copyright
9 1.1 christos * notice, this list of conditions and the following disclaimer.
10 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 christos * notice, this list of conditions and the following disclaimer in the
12 1.1 christos * documentation and/or other materials provided with the distribution.
13 1.1 christos * 3. All advertising materials mentioning features or use of this software
14 1.1 christos * must display the following acknowledgement:
15 1.1 christos * This product includes software developed by Christos Zoulas.
16 1.1 christos * 4. The name of the author may not be used to endorse or promote products
17 1.1 christos * derived from this software without specific prior written permission.
18 1.1 christos *
19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 1.1 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 1.1 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 1.1 christos * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 christos * SUCH DAMAGE.
30 1.1 christos */
31 1.1 christos #ifndef lint
32 1.4 christos static char *rcsid = "$Id: netgroup_mkdb.c,v 1.4 1996/04/27 18:54:31 christos Exp $";
33 1.1 christos #endif
34 1.1 christos
35 1.1 christos #include <sys/types.h>
36 1.2 christos #include <sys/param.h>
37 1.1 christos #include <sys/stat.h>
38 1.1 christos #include <stdlib.h>
39 1.1 christos #include <stddef.h>
40 1.1 christos #include <unistd.h>
41 1.1 christos #include <fcntl.h>
42 1.1 christos #include <db.h>
43 1.1 christos #include <err.h>
44 1.1 christos #include <errno.h>
45 1.1 christos #include <stdio.h>
46 1.1 christos #include <string.h>
47 1.4 christos #define _NETGROUP_PRIVATE
48 1.1 christos #include <netgroup.h>
49 1.1 christos #include <assert.h>
50 1.1 christos
51 1.1 christos #include "str.h"
52 1.1 christos #include "util.h"
53 1.1 christos
54 1.4 christos #define DEBUG_NG
55 1.4 christos
56 1.1 christos #define NEW(a) (a *) emalloc(sizeof(a))
57 1.1 christos
58 1.1 christos struct nentry {
59 1.1 christos int n_type;
60 1.1 christos size_t n_size; /* Buffer size required for printing */
61 1.1 christos union {
62 1.1 christos char *_name;
63 1.1 christos struct netgroup *_group;
64 1.1 christos } _n;
65 1.1 christos #define n_name _n._name
66 1.1 christos #define n_group _n._group
67 1.1 christos struct nentry *n_next;
68 1.1 christos };
69 1.1 christos
70 1.1 christos
71 1.1 christos static DB *ng_insert __P((DB *, const char *));
72 1.1 christos static void ng_reventry __P((DB *, DB *, struct nentry *, char *,
73 1.1 christos size_t, struct stringlist *));
74 1.1 christos
75 1.1 christos static void ng_print __P((struct nentry *, struct string *));
76 1.1 christos static void ng_rprint __P((DB *, struct string *));
77 1.1 christos static DB *ng_reverse __P((DB *, size_t));
78 1.1 christos static DB *ng_load __P((const char *));
79 1.1 christos static void ng_write __P((DB *, DB *, int));
80 1.1 christos static void ng_rwrite __P((DB *, DB *, int));
81 1.1 christos static void usage __P((void));
82 1.2 christos static void cleanup __P((void));
83 1.1 christos
84 1.1 christos #ifdef DEBUG_NG
85 1.4 christos static int debug = 0;
86 1.1 christos static void ng_dump __P((DB *));
87 1.1 christos static void ng_rdump __P((DB *));
88 1.1 christos #endif /* DEBUG_NG */
89 1.1 christos
90 1.4 christos
91 1.3 christos static const char ng_empty[] = "";
92 1.3 christos #define NG_EMPTY(a) ((a) ? (a) : ng_empty)
93 1.3 christos
94 1.1 christos static char *dbname = _PATH_NETGROUP_DB;
95 1.1 christos
96 1.1 christos int
97 1.1 christos main(argc, argv)
98 1.2 christos int argc;
99 1.2 christos char **argv;
100 1.1 christos {
101 1.2 christos DB *db, *ndb, *hdb, *udb;
102 1.2 christos int ch;
103 1.2 christos char buf[MAXPATHLEN];
104 1.2 christos char *fname = _PATH_NETGROUP;
105 1.2 christos
106 1.1 christos
107 1.4 christos while ((ch = getopt(argc, argv, "do:")) != EOF)
108 1.1 christos switch (ch) {
109 1.4 christos #ifdef DEBUG_NG
110 1.4 christos case 'd':
111 1.4 christos debug++;
112 1.4 christos break;
113 1.4 christos #endif
114 1.1 christos case 'o':
115 1.1 christos dbname = optarg;
116 1.1 christos break;
117 1.1 christos
118 1.1 christos case '?':
119 1.1 christos default:
120 1.1 christos usage();
121 1.1 christos }
122 1.1 christos
123 1.1 christos argc -= optind;
124 1.1 christos argv += optind;
125 1.1 christos
126 1.2 christos if (argc == 1)
127 1.2 christos fname = *argv;
128 1.2 christos else if (argc > 1)
129 1.1 christos usage();
130 1.1 christos
131 1.2 christos if (atexit(cleanup))
132 1.2 christos err(1, "Cannot install exit handler");
133 1.2 christos
134 1.1 christos /* Read and parse the netgroup file */
135 1.2 christos ndb = ng_load(fname);
136 1.1 christos #ifdef DEBUG_NG
137 1.4 christos if (debug) {
138 1.4 christos (void) fprintf(stderr, "#### Database\n");
139 1.4 christos ng_dump(ndb);
140 1.4 christos }
141 1.1 christos #endif
142 1.1 christos
143 1.1 christos /* Reverse the database by host */
144 1.1 christos hdb = ng_reverse(ndb, offsetof(struct netgroup, ng_host));
145 1.1 christos #ifdef DEBUG_NG
146 1.4 christos if (debug) {
147 1.4 christos (void) fprintf(stderr, "#### Reverse by host\n");
148 1.4 christos ng_rdump(hdb);
149 1.4 christos }
150 1.1 christos #endif
151 1.1 christos
152 1.1 christos /* Reverse the database by user */
153 1.1 christos udb = ng_reverse(ndb, offsetof(struct netgroup, ng_user));
154 1.1 christos #ifdef DEBUG_NG
155 1.4 christos if (debug) {
156 1.4 christos (void) fprintf(stderr, "#### Reverse by user\n");
157 1.4 christos ng_rdump(udb);
158 1.4 christos }
159 1.1 christos #endif
160 1.1 christos
161 1.2 christos (void) snprintf(buf, sizeof(buf), "%s.tmp", dbname);
162 1.2 christos
163 1.2 christos db = dbopen(buf, O_RDWR | O_CREAT | O_EXCL,
164 1.1 christos (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), DB_HASH, NULL);
165 1.1 christos if (!db)
166 1.2 christos err(1, buf);
167 1.1 christos
168 1.1 christos ng_write(db, ndb, _NG_KEYBYNAME);
169 1.1 christos ng_rwrite(db, udb, _NG_KEYBYUSER);
170 1.1 christos ng_rwrite(db, hdb, _NG_KEYBYHOST);
171 1.2 christos
172 1.2 christos if ((db->close)(db))
173 1.2 christos err(1, "Error closing database");
174 1.2 christos
175 1.2 christos if (rename(buf, dbname) == -1)
176 1.2 christos err(1, "Cannot rename `%s' to `%s'", buf, dbname);
177 1.2 christos
178 1.1 christos return 0;
179 1.1 christos }
180 1.1 christos
181 1.1 christos
182 1.1 christos /*
183 1.2 christos * cleanup(): Remove temporary files upon exit
184 1.2 christos */
185 1.2 christos static void
186 1.2 christos cleanup()
187 1.2 christos {
188 1.2 christos char buf[MAXPATHLEN];
189 1.2 christos (void) snprintf(buf, sizeof(buf), "%s.tmp", dbname);
190 1.2 christos (void) unlink(buf);
191 1.2 christos }
192 1.2 christos
193 1.2 christos
194 1.2 christos
195 1.2 christos /*
196 1.1 christos * ng_load(): Load the netgroup database from a file
197 1.1 christos */
198 1.2 christos static DB *
199 1.1 christos ng_load(fname)
200 1.1 christos const char *fname;
201 1.1 christos {
202 1.1 christos FILE *fp;
203 1.1 christos DB *db;
204 1.1 christos char *buf;
205 1.1 christos size_t size;
206 1.1 christos struct nentry *tail, *head, *e;
207 1.1 christos char *p, *name;
208 1.1 christos struct netgroup *ng;
209 1.1 christos DBT data, key;
210 1.1 christos
211 1.1 christos /* Open the netgroup file */
212 1.1 christos if ((fp = fopen(fname, "r")) == NULL)
213 1.1 christos err(1, fname);
214 1.1 christos
215 1.1 christos db = dbopen(NULL, O_RDWR | O_CREAT | O_EXCL, 0, DB_HASH, NULL);
216 1.1 christos
217 1.1 christos if (db == NULL)
218 1.1 christos err(1, "dbopen");
219 1.1 christos
220 1.1 christos while ((buf = getline(fp, &size)) != NULL) {
221 1.1 christos tail = head = NULL;
222 1.1 christos p = buf;
223 1.1 christos
224 1.1 christos while (p != NULL) {
225 1.1 christos switch (_ng_parse(&p, &name, &ng)) {
226 1.1 christos case _NG_NONE:
227 1.1 christos /* done with this one */
228 1.1 christos p = NULL;
229 1.1 christos free(buf);
230 1.1 christos if (head == NULL)
231 1.1 christos break;
232 1.1 christos
233 1.1 christos key.data = (u_char *) head->n_name;
234 1.1 christos key.size = strlen(head->n_name) + 1;
235 1.1 christos data.data = (u_char *) & head;
236 1.1 christos data.size = sizeof(head);
237 1.1 christos switch ((db->put)(db, &key, &data,
238 1.1 christos R_NOOVERWRITE)) {
239 1.1 christos case 0:
240 1.1 christos break;
241 1.1 christos
242 1.1 christos case 1:
243 1.1 christos warnx("Duplicate entry netgroup `%s'\n",
244 1.1 christos head->n_name);
245 1.1 christos break;
246 1.1 christos
247 1.1 christos case -1:
248 1.1 christos err(1, "put");
249 1.1 christos break;
250 1.1 christos
251 1.1 christos default:
252 1.1 christos abort();
253 1.1 christos break;
254 1.1 christos }
255 1.1 christos break;
256 1.1 christos
257 1.1 christos case _NG_NAME:
258 1.1 christos e = NEW(struct nentry);
259 1.1 christos e->n_type = _NG_NAME;
260 1.1 christos e->n_name = name;
261 1.1 christos e->n_next = NULL;
262 1.1 christos e->n_size = size;
263 1.1 christos if (tail == NULL)
264 1.1 christos head = tail = e;
265 1.1 christos else {
266 1.1 christos tail->n_next = e;
267 1.1 christos tail = e;
268 1.1 christos }
269 1.1 christos break;
270 1.1 christos
271 1.1 christos case _NG_GROUP:
272 1.4 christos if (tail == NULL) {
273 1.4 christos char fmt[BUFSIZ];
274 1.4 christos _ng_print(fmt, sizeof(fmt), ng);
275 1.4 christos errx(1, "no netgroup key for %s", fmt);
276 1.4 christos }
277 1.1 christos else {
278 1.1 christos e = NEW(struct nentry);
279 1.1 christos e->n_type = _NG_GROUP;
280 1.1 christos e->n_group = ng;
281 1.1 christos e->n_next = NULL;
282 1.1 christos e->n_size = size;
283 1.1 christos tail->n_next = e;
284 1.1 christos tail = e;
285 1.1 christos }
286 1.1 christos break;
287 1.1 christos
288 1.1 christos default:
289 1.1 christos abort();
290 1.1 christos break;
291 1.1 christos }
292 1.1 christos }
293 1.1 christos }
294 1.1 christos (void) fclose(fp);
295 1.1 christos return db;
296 1.1 christos }
297 1.1 christos
298 1.1 christos
299 1.1 christos /*
300 1.1 christos * ng_insert(): Insert named key into the database, and return its associated
301 1.1 christos * string database
302 1.1 christos */
303 1.1 christos static DB *
304 1.1 christos ng_insert(db, name)
305 1.1 christos DB *db;
306 1.1 christos const char *name;
307 1.1 christos {
308 1.1 christos DB *xdb = NULL;
309 1.1 christos DBT key, data;
310 1.1 christos
311 1.1 christos key.data = (u_char *) name;
312 1.1 christos key.size = strlen(name) + 1;
313 1.1 christos
314 1.1 christos switch ((db->get)(db, &key, &data, 0)) {
315 1.1 christos case 0:
316 1.1 christos memcpy(&xdb, data.data, sizeof(xdb));
317 1.1 christos break;
318 1.1 christos
319 1.1 christos case 1:
320 1.1 christos xdb = dbopen(NULL, O_RDWR | O_CREAT | O_EXCL, 0, DB_HASH, NULL);
321 1.1 christos if (xdb == NULL)
322 1.1 christos err(1, "dbopen");
323 1.1 christos
324 1.1 christos data.data = (u_char *) & xdb;
325 1.1 christos data.size = sizeof(xdb);
326 1.1 christos switch ((db->put)(db, &key, &data, R_NOOVERWRITE)) {
327 1.1 christos case 0:
328 1.1 christos break;
329 1.1 christos
330 1.1 christos case -1:
331 1.1 christos err(1, "db put `%s'", name);
332 1.1 christos break;
333 1.1 christos
334 1.1 christos case 1:
335 1.1 christos default:
336 1.1 christos abort();
337 1.1 christos }
338 1.1 christos break;
339 1.1 christos
340 1.1 christos case -1:
341 1.1 christos err(1, "db get `%s'", name);
342 1.1 christos break;
343 1.1 christos
344 1.1 christos default:
345 1.1 christos abort();
346 1.1 christos break;
347 1.1 christos }
348 1.1 christos
349 1.1 christos return xdb;
350 1.1 christos }
351 1.1 christos
352 1.1 christos
353 1.1 christos /*
354 1.1 christos * ng_reventry(): Recursively add all the netgroups to the group entry.
355 1.1 christos */
356 1.1 christos static void
357 1.1 christos ng_reventry(db, udb, fe, name, s, ss)
358 1.1 christos DB *db, *udb;
359 1.1 christos struct nentry *fe;
360 1.1 christos char *name;
361 1.1 christos size_t s;
362 1.1 christos struct stringlist *ss;
363 1.1 christos {
364 1.1 christos DBT key, data;
365 1.1 christos struct nentry *e;
366 1.1 christos struct netgroup *ng;
367 1.1 christos char *p;
368 1.1 christos DB *xdb;
369 1.1 christos
370 1.1 christos if (_ng_sl_find(ss, name) != NULL) {
371 1.1 christos warnx("Cycle in netgroup `%s'", name);
372 1.1 christos return;
373 1.1 christos }
374 1.1 christos _ng_sl_add(ss, name);
375 1.1 christos
376 1.1 christos for (e = fe->n_next; e != NULL; e = e->n_next)
377 1.1 christos switch (e->n_type) {
378 1.1 christos case _NG_GROUP:
379 1.1 christos ng = e->n_group;
380 1.1 christos p = _ng_makekey(*((char **)(((char *) ng) + s)),
381 1.1 christos ng->ng_domain, e->n_size);
382 1.1 christos xdb = ng_insert(udb, p);
383 1.1 christos key.data = (u_char *) name;
384 1.1 christos key.size = strlen(name) + 1;
385 1.1 christos data.data = NULL;
386 1.1 christos data.size = 0;
387 1.1 christos switch ((xdb->put)(xdb, &key, &data, R_NOOVERWRITE)) {
388 1.1 christos case 0:
389 1.1 christos case 1:
390 1.1 christos break;
391 1.1 christos
392 1.1 christos case -1:
393 1.1 christos err(1, "db put `%s'", name);
394 1.1 christos return;
395 1.1 christos
396 1.1 christos default:
397 1.1 christos abort();
398 1.1 christos break;
399 1.1 christos }
400 1.1 christos free(p);
401 1.1 christos break;
402 1.1 christos
403 1.1 christos case _NG_NAME:
404 1.1 christos key.data = (u_char *) e->n_name;
405 1.1 christos key.size = strlen(e->n_name) + 1;
406 1.1 christos switch ((db->get)(db, &key, &data, 0)) {
407 1.1 christos case 0:
408 1.1 christos memcpy(&fe, data.data, sizeof(fe));
409 1.1 christos ng_reventry(db, udb, fe, e->n_name, s, ss);
410 1.1 christos break;
411 1.1 christos
412 1.1 christos case 1:
413 1.1 christos break;
414 1.1 christos
415 1.1 christos case -1:
416 1.1 christos err(1, "db get `%s'", e->n_name);
417 1.1 christos return;
418 1.1 christos
419 1.1 christos default:
420 1.1 christos abort();
421 1.1 christos return;
422 1.1 christos }
423 1.1 christos break;
424 1.1 christos
425 1.1 christos default:
426 1.1 christos abort();
427 1.1 christos break;
428 1.1 christos }
429 1.1 christos }
430 1.1 christos
431 1.1 christos
432 1.1 christos /*
433 1.1 christos * ng_reverse(): Reverse the database
434 1.1 christos */
435 1.1 christos static DB *
436 1.1 christos ng_reverse(db, s)
437 1.1 christos DB *db;
438 1.1 christos size_t s;
439 1.1 christos {
440 1.1 christos int pos;
441 1.1 christos struct stringlist *sl;
442 1.1 christos DBT key, data;
443 1.1 christos struct nentry *fe;
444 1.1 christos DB *udb = dbopen(NULL, O_RDWR | O_CREAT | O_EXCL, 0,
445 1.1 christos DB_HASH, NULL);
446 1.1 christos
447 1.1 christos if (udb == NULL)
448 1.1 christos err(1, "dbopen");
449 1.1 christos
450 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
451 1.1 christos switch ((db->seq)(db, &key, &data, pos)) {
452 1.1 christos case 0:
453 1.1 christos sl = _ng_sl_init();
454 1.1 christos memcpy(&fe, data.data, sizeof(fe));
455 1.1 christos ng_reventry(db, udb, fe, (char *) key.data, s, sl);
456 1.1 christos _ng_sl_free(sl, 0);
457 1.1 christos break;
458 1.1 christos
459 1.1 christos case 1:
460 1.1 christos return udb;
461 1.1 christos
462 1.1 christos case -1:
463 1.1 christos err(1, "seq");
464 1.1 christos return udb;
465 1.1 christos }
466 1.1 christos
467 1.1 christos return udb;
468 1.1 christos }
469 1.1 christos
470 1.1 christos
471 1.1 christos /*
472 1.1 christos * ng_print(): Pretty print a netgroup entry
473 1.1 christos */
474 1.1 christos static void
475 1.1 christos ng_print(e, str)
476 1.1 christos struct nentry *e;
477 1.1 christos struct string *str;
478 1.1 christos {
479 1.1 christos char *ptr = emalloc(e->n_size);
480 1.4 christos
481 1.4 christos if (e->n_next == NULL) {
482 1.4 christos str_append(str, "", ' ');
483 1.4 christos return;
484 1.4 christos }
485 1.1 christos
486 1.1 christos for (e = e->n_next; e != NULL; e = e->n_next) {
487 1.1 christos switch (e->n_type) {
488 1.1 christos case _NG_NAME:
489 1.1 christos (void) snprintf(ptr, e->n_size, "%s", e->n_name);
490 1.1 christos break;
491 1.1 christos
492 1.1 christos case _NG_GROUP:
493 1.1 christos (void) snprintf(ptr, e->n_size, "(%s,%s,%s)",
494 1.3 christos NG_EMPTY(e->n_group->ng_host),
495 1.3 christos NG_EMPTY(e->n_group->ng_user),
496 1.3 christos NG_EMPTY(e->n_group->ng_domain));
497 1.1 christos break;
498 1.1 christos
499 1.1 christos default:
500 1.1 christos errx(1, "Internal error: Bad netgroup type\n");
501 1.1 christos break;
502 1.1 christos }
503 1.1 christos str_append(str, ptr, ' ');
504 1.1 christos }
505 1.1 christos free(ptr);
506 1.1 christos }
507 1.1 christos
508 1.1 christos
509 1.1 christos /*
510 1.1 christos * ng_rprint(): Pretty print all reverse netgroup mappings in the given entry
511 1.1 christos */
512 1.1 christos static void
513 1.1 christos ng_rprint(db, str)
514 1.1 christos DB *db;
515 1.1 christos struct string *str;
516 1.1 christos {
517 1.1 christos int pos;
518 1.1 christos DBT key, data;
519 1.1 christos
520 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
521 1.1 christos switch ((db->seq)(db, &key, &data, pos)) {
522 1.1 christos case 0:
523 1.1 christos str_append(str, (char *) key.data, ',');
524 1.1 christos break;
525 1.1 christos
526 1.1 christos case 1:
527 1.1 christos return;
528 1.1 christos
529 1.1 christos default:
530 1.1 christos err(1, "seq");
531 1.1 christos break;
532 1.1 christos }
533 1.1 christos }
534 1.1 christos
535 1.1 christos
536 1.1 christos #ifdef DEBUG_NG
537 1.1 christos /*
538 1.1 christos * ng_dump(): Pretty print all netgroups in the given database
539 1.1 christos */
540 1.1 christos static void
541 1.1 christos ng_dump(db)
542 1.1 christos DB *db;
543 1.1 christos {
544 1.1 christos int pos;
545 1.1 christos DBT key, data;
546 1.1 christos struct nentry *e;
547 1.1 christos struct string buf;
548 1.1 christos
549 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
550 1.1 christos switch ((db->seq)(db, &key, &data, pos)) {
551 1.1 christos case 0:
552 1.1 christos memcpy(&e, data.data, sizeof(e));
553 1.1 christos str_init(&buf);
554 1.1 christos assert(e->n_type == _NG_NAME);
555 1.1 christos
556 1.1 christos ng_print(e, &buf);
557 1.1 christos (void) fprintf(stderr, "%s\t%s\n", e->n_name,
558 1.1 christos buf.s_str ? buf.s_str : "");
559 1.1 christos str_free(&buf);
560 1.1 christos break;
561 1.1 christos
562 1.1 christos case 1:
563 1.1 christos return;
564 1.1 christos
565 1.1 christos default:
566 1.1 christos err(1, "seq");
567 1.1 christos return;
568 1.1 christos }
569 1.1 christos }
570 1.1 christos
571 1.1 christos
572 1.1 christos /*
573 1.1 christos * ng_rdump(): Pretty print all reverse mappings in the given database
574 1.1 christos */
575 1.1 christos static void
576 1.1 christos ng_rdump(db)
577 1.1 christos DB *db;
578 1.1 christos {
579 1.1 christos int pos;
580 1.1 christos DBT key, data;
581 1.1 christos DB *xdb;
582 1.1 christos struct string buf;
583 1.1 christos
584 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
585 1.1 christos switch ((db->seq)(db, &key, &data, pos)) {
586 1.1 christos case 0:
587 1.1 christos memcpy(&xdb, data.data, sizeof(xdb));
588 1.1 christos str_init(&buf);
589 1.1 christos ng_rprint(xdb, &buf);
590 1.1 christos (void) fprintf(stderr, "%s\t%s\n",
591 1.1 christos (char *) key.data,
592 1.1 christos buf.s_str ? buf.s_str : "");
593 1.1 christos str_free(&buf);
594 1.1 christos break;
595 1.1 christos
596 1.1 christos case 1:
597 1.1 christos return;
598 1.1 christos
599 1.1 christos default:
600 1.1 christos err(1, "seq");
601 1.1 christos return;
602 1.1 christos }
603 1.1 christos }
604 1.1 christos #endif /* DEBUG_NG */
605 1.1 christos
606 1.1 christos
607 1.1 christos /*
608 1.1 christos * ng_write(): Dump the database into a file.
609 1.1 christos */
610 1.1 christos static void
611 1.1 christos ng_write(odb, idb, k)
612 1.1 christos DB *odb, *idb;
613 1.1 christos int k;
614 1.1 christos {
615 1.1 christos int pos;
616 1.1 christos DBT key, data;
617 1.1 christos struct nentry *e;
618 1.1 christos struct string skey, sdata;
619 1.1 christos
620 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
621 1.1 christos switch ((idb->seq)(idb, &key, &data, pos)) {
622 1.1 christos case 0:
623 1.1 christos memcpy(&e, data.data, sizeof(e));
624 1.1 christos str_init(&skey);
625 1.1 christos str_init(&sdata);
626 1.1 christos assert(e->n_type == _NG_NAME);
627 1.1 christos
628 1.1 christos str_prepend(&skey, e->n_name, k);
629 1.1 christos ng_print(e, &sdata);
630 1.1 christos key.data = (u_char *) skey.s_str;
631 1.1 christos key.size = skey.s_len + 1;
632 1.1 christos data.data = (u_char *) sdata.s_str;
633 1.1 christos data.size = sdata.s_len + 1;
634 1.1 christos
635 1.1 christos switch ((odb->put)(odb, &key, &data, R_NOOVERWRITE)) {
636 1.1 christos case 0:
637 1.1 christos break;
638 1.1 christos
639 1.1 christos case -1:
640 1.1 christos err(1, "put");
641 1.1 christos break;
642 1.1 christos
643 1.1 christos case 1:
644 1.1 christos default:
645 1.1 christos abort();
646 1.1 christos break;
647 1.1 christos }
648 1.1 christos
649 1.1 christos str_free(&skey);
650 1.1 christos str_free(&sdata);
651 1.1 christos break;
652 1.1 christos
653 1.1 christos case 1:
654 1.1 christos return;
655 1.1 christos
656 1.1 christos default:
657 1.1 christos err(1, "seq");
658 1.1 christos return;
659 1.1 christos }
660 1.1 christos }
661 1.1 christos
662 1.1 christos
663 1.1 christos /*
664 1.1 christos * ng_rwrite(): Write the database
665 1.1 christos */
666 1.1 christos static void
667 1.1 christos ng_rwrite(odb, idb, k)
668 1.1 christos DB *odb;
669 1.1 christos DB *idb;
670 1.1 christos int k;
671 1.1 christos {
672 1.1 christos int pos;
673 1.1 christos DBT key, data;
674 1.1 christos DB *xdb;
675 1.1 christos struct string skey, sdata;
676 1.1 christos
677 1.1 christos for (pos = R_FIRST;; pos = R_NEXT)
678 1.1 christos switch ((idb->seq)(idb, &key, &data, pos)) {
679 1.1 christos case 0:
680 1.1 christos memcpy(&xdb, data.data, sizeof(xdb));
681 1.1 christos str_init(&skey);
682 1.1 christos str_init(&sdata);
683 1.1 christos
684 1.1 christos str_prepend(&skey, (char *) key.data, k);
685 1.1 christos ng_rprint(xdb, &sdata);
686 1.1 christos key.data = (u_char *) skey.s_str;
687 1.1 christos key.size = skey.s_len + 1;
688 1.1 christos data.data = (u_char *) sdata.s_str;
689 1.1 christos data.size = sdata.s_len + 1;
690 1.1 christos
691 1.1 christos switch ((odb->put)(odb, &key, &data, R_NOOVERWRITE)) {
692 1.1 christos case 0:
693 1.1 christos break;
694 1.1 christos
695 1.1 christos case -1:
696 1.1 christos err(1, "put");
697 1.1 christos break;
698 1.1 christos
699 1.1 christos case 1:
700 1.1 christos default:
701 1.1 christos abort();
702 1.1 christos break;
703 1.1 christos }
704 1.1 christos
705 1.1 christos str_free(&skey);
706 1.1 christos str_free(&sdata);
707 1.1 christos break;
708 1.1 christos
709 1.1 christos case 1:
710 1.1 christos return;
711 1.1 christos
712 1.1 christos default:
713 1.1 christos err(1, "seq");
714 1.1 christos return;
715 1.1 christos }
716 1.1 christos }
717 1.1 christos
718 1.1 christos
719 1.1 christos /*
720 1.1 christos * usage(): Print usage message and exit
721 1.1 christos */
722 1.1 christos static void
723 1.1 christos usage()
724 1.1 christos {
725 1.1 christos extern const char *__progname;
726 1.1 christos fprintf(stderr, "usage: %s [-o db] file\n", __progname);
727 1.1 christos exit(1);
728 1.1 christos }
729