1 /* $NetBSD: netgroup_mkdb.c,v 1.17 2009/04/18 05:09:15 lukem Exp $ */
4 * Copyright (c) 1994 Christos Zoulas
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: netgroup_mkdb.c,v 1.17 2009/04/18 05:09:15 lukem Exp $");
33 #include <sys/types.h>
34 #include <sys/param.h>
45 #include <stringlist.h>
46 #define _NETGROUP_PRIVATE
55 #define NEW(a) (a *) emalloc(sizeof(a))
59 size_t n_size
; /* Buffer size required for printing */
62 struct netgroup
*_group
;
64 #define n_name _n._name
65 #define n_group _n._group
66 struct nentry
*n_next
;
70 static void cleanup(void);
71 static DB
*ng_insert(DB
*, const char *);
72 static void ng_reventry(DB
*, DB
*, struct nentry
*, char *,
73 size_t, StringList
*);
74 static void ng_print(struct nentry
*, struct string
*);
75 static void ng_rprint(DB
*, struct string
*);
76 static DB
*ng_reverse(DB
*, size_t);
77 static DB
*ng_load(const char *);
78 static void ng_write(DB
*, DB
*, int);
79 static void ng_rwrite(DB
*, DB
*, int);
80 static void usage(void) __dead
;
84 static void ng_dump(DB
*);
85 static void ng_rdump(DB
*);
90 static const char ng_empty
[] = "";
91 #define NG_EMPTY(a) ((a) ? (a) : ng_empty)
93 static const char *dbname
= _PATH_NETGROUP_DB
;
96 main(int argc
, char **argv
)
98 DB
*db
, *ndb
, *hdb
, *udb
;
100 char buf
[MAXPATHLEN
];
101 const char *fname
= _PATH_NETGROUP
;
104 while ((ch
= getopt(argc
, argv
, "dDo:")) != -1)
133 err(1, "Cannot install exit handler");
135 /* Read and parse the netgroup file */
136 ndb
= ng_load(fname
);
139 (void)fprintf(stderr
, "#### Database\n");
144 /* Reverse the database by host */
145 hdb
= ng_reverse(ndb
, offsetof(struct netgroup
, ng_host
));
148 (void)fprintf(stderr
, "#### Reverse by host\n");
153 /* Reverse the database by user */
154 udb
= ng_reverse(ndb
, offsetof(struct netgroup
, ng_user
));
157 (void)fprintf(stderr
, "#### Reverse by user\n");
162 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", dbname
);
164 db
= dbopen(buf
, O_RDWR
| O_CREAT
| O_EXCL
,
165 (S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
), DB_HASH
, NULL
);
169 ng_write(db
, ndb
, _NG_KEYBYNAME
);
170 ng_rwrite(db
, udb
, _NG_KEYBYUSER
);
171 ng_rwrite(db
, hdb
, _NG_KEYBYHOST
);
174 err(1, "Error closing database");
176 if (rename(buf
, dbname
) == -1)
177 err(1, "Cannot rename `%s' to `%s'", buf
, dbname
);
184 * cleanup(): Remove temporary files upon exit
189 char buf
[MAXPATHLEN
];
190 (void)snprintf(buf
, sizeof(buf
), "%s.tmp", dbname
);
197 * ng_load(): Load the netgroup database from a file
200 ng_load(const char *fname
)
206 struct nentry
*tail
, *head
, *e
;
211 /* Open the netgroup file */
212 if ((fp
= fopen(fname
, "r")) == NULL
)
215 db
= dbopen(NULL
, O_RDWR
| O_CREAT
| O_EXCL
, 0, DB_HASH
, NULL
);
220 while ((buf
= fparseln(fp
, &size
, NULL
, NULL
, 0)) != NULL
) {
225 switch (_ng_parse(&p
, &name
, &ng
)) {
227 /* done with this one */
233 key
.data
= (u_char
*)head
->n_name
;
234 key
.size
= strlen(head
->n_name
) + 1;
235 data
.data
= (u_char
*)&head
;
236 data
.size
= sizeof(head
);
237 switch ((db
->put
)(db
, &key
, &data
,
243 warnx("Duplicate entry netgroup `%s'",
258 e
= NEW(struct nentry
);
259 e
->n_type
= _NG_NAME
;
274 _ng_print(fmt
, sizeof(fmt
), ng
);
275 errx(1, "no netgroup key for %s", fmt
);
278 e
= NEW(struct nentry
);
279 e
->n_type
= _NG_GROUP
;
289 errx(1, "Fatal error at `%s'", p
);
304 * ng_insert(): Insert named key into the database, and return its associated
308 ng_insert(DB
*db
, const char *name
)
313 key
.data
= __UNCONST(name
);
314 key
.size
= strlen(name
) + 1;
316 switch ((db
->get
)(db
, &key
, &data
, 0)) {
318 (void)memcpy(&xdb
, data
.data
, sizeof(xdb
));
322 xdb
= dbopen(NULL
, O_RDWR
| O_CREAT
| O_EXCL
, 0, DB_HASH
, NULL
);
326 data
.data
= (u_char
*)&xdb
;
327 data
.size
= sizeof(xdb
);
328 switch ((db
->put
)(db
, &key
, &data
, R_NOOVERWRITE
)) {
333 err(1, "db put `%s'", name
);
343 err(1, "db get `%s'", name
);
356 * ng_reventry(): Recursively add all the netgroups to the group entry.
359 ng_reventry(DB
*db
, DB
*udb
, struct nentry
*fe
, char *name
, size_t s
,
368 if (sl_find(ss
, fe
->n_name
) != NULL
) {
372 sl_add(ss
, fe
->n_name
);
374 for (e
= fe
->n_next
; e
!= NULL
; e
= e
->n_next
)
378 sl_delete(ss
, fe
->n_name
, 0);
380 p
= _ng_makekey(*((char **)(((char *) ng
) + s
)),
381 ng
->ng_domain
, e
->n_size
);
382 xdb
= ng_insert(udb
, p
);
383 key
.data
= (u_char
*)name
;
384 key
.size
= strlen(name
) + 1;
387 switch ((xdb
->put
)(xdb
, &key
, &data
, R_NOOVERWRITE
)) {
393 err(1, "db put `%s'", name
);
404 key
.data
= (u_char
*) e
->n_name
;
405 key
.size
= strlen(e
->n_name
) + 1;
406 switch ((db
->get
)(db
, &key
, &data
, 0)) {
409 (void)memcpy(&rfe
, data
.data
, sizeof(rfe
));
410 ng_reventry(db
, udb
, rfe
, name
, s
, ss
);
417 err(1, "db get `%s'", e
->n_name
);
434 * ng_reverse(): Reverse the database
437 ng_reverse(DB
*db
, size_t s
)
443 DB
*udb
= dbopen(NULL
, O_RDWR
| O_CREAT
| O_EXCL
, 0,
449 for (pos
= R_FIRST
;; pos
= R_NEXT
)
450 switch ((db
->seq
)(db
, &key
, &data
, pos
)) {
453 (void)memcpy(&fe
, data
.data
, sizeof(fe
));
454 ng_reventry(db
, udb
, fe
, (char *) key
.data
, s
, sl
);
471 * ng_print(): Pretty print a netgroup entry
474 ng_print(struct nentry
*e
, struct string
*str
)
478 if (e
->n_next
== NULL
) {
479 str_append(str
, "", ' ');
483 ptr
= emalloc(e
->n_size
);
485 for (e
= e
->n_next
; e
!= NULL
; e
= e
->n_next
) {
488 (void)snprintf(ptr
, e
->n_size
, "%s", e
->n_name
);
492 (void)snprintf(ptr
, e
->n_size
, "(%s,%s,%s)",
493 NG_EMPTY(e
->n_group
->ng_host
),
494 NG_EMPTY(e
->n_group
->ng_user
),
495 NG_EMPTY(e
->n_group
->ng_domain
));
499 errx(1, "Internal error: Bad netgroup type");
502 str_append(str
, ptr
, ' ');
509 * ng_rprint(): Pretty print all reverse netgroup mappings in the given entry
512 ng_rprint(DB
*db
, struct string
*str
)
517 for (pos
= R_FIRST
;; pos
= R_NEXT
)
518 switch ((db
->seq
)(db
, &key
, &data
, pos
)) {
520 str_append(str
, (char *)key
.data
, ',');
535 * ng_dump(): Pretty print all netgroups in the given database
545 for (pos
= R_FIRST
;; pos
= R_NEXT
)
546 switch ((db
->seq
)(db
, &key
, &data
, pos
)) {
548 (void)memcpy(&e
, data
.data
, sizeof(e
));
550 assert(e
->n_type
== _NG_NAME
);
553 (void)fprintf(stderr
, "%s\t%s\n", e
->n_name
,
554 buf
.s_str
? buf
.s_str
: "");
569 * ng_rdump(): Pretty print all reverse mappings in the given database
579 for (pos
= R_FIRST
;; pos
= R_NEXT
)
580 switch ((db
->seq
)(db
, &key
, &data
, pos
)) {
582 (void)memcpy(&xdb
, data
.data
, sizeof(xdb
));
584 ng_rprint(xdb
, &buf
);
585 (void)fprintf(stderr
, "%s\t%s\n",
586 (char *)key
.data
, buf
.s_str
? buf
.s_str
: "");
598 #endif /* DEBUG_NG */
602 * ng_write(): Dump the database into a file.
605 ng_write(DB
*odb
, DB
*idb
, int k
)
610 struct string skey
, sdata
;
612 for (pos
= R_FIRST
;; pos
= R_NEXT
)
613 switch ((idb
->seq
)(idb
, &key
, &data
, pos
)) {
615 memcpy(&e
, data
.data
, sizeof(e
));
618 assert(e
->n_type
== _NG_NAME
);
620 str_prepend(&skey
, e
->n_name
, k
);
622 key
.data
= (u_char
*) skey
.s_str
;
623 key
.size
= skey
.s_len
+ 1;
624 data
.data
= (u_char
*) sdata
.s_str
;
625 data
.size
= sdata
.s_len
+ 1;
627 switch ((odb
->put
)(odb
, &key
, &data
, R_NOOVERWRITE
)) {
656 * ng_rwrite(): Write the database
659 ng_rwrite(DB
*odb
, DB
*idb
, int k
)
664 struct string skey
, sdata
;
666 for (pos
= R_FIRST
;; pos
= R_NEXT
)
667 switch ((idb
->seq
)(idb
, &key
, &data
, pos
)) {
669 memcpy(&xdb
, data
.data
, sizeof(xdb
));
673 str_prepend(&skey
, (char *) key
.data
, k
);
674 ng_rprint(xdb
, &sdata
);
675 key
.data
= (u_char
*) skey
.s_str
;
676 key
.size
= skey
.s_len
+ 1;
677 data
.data
= (u_char
*) sdata
.s_str
;
678 data
.size
= sdata
.s_len
+ 1;
680 switch ((odb
->put
)(odb
, &key
, &data
, R_NOOVERWRITE
)) {
709 * usage(): Print usage message and exit
715 (void)fprintf(stderr
, "Usage: %s [-D] [-o db] [<file>]\n",