1/*
2 * Copyright (c) 1995
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * reverse netgroup map generator program
33 *
34 * Written by Bill Paul <wpaul@ctr.columbia.edu>
35 * Center for Telecommunications Research
36 * Columbia University, New York City
37 */
38
39#ifndef lint
40static const char rcsid[] =
41  "$FreeBSD: src/libexec/revnetgroup/revnetgroup.c,v 1.13 2005/02/09 20:36:12 ru Exp $";
42#endif /* not lint */
43
44#include <err.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49#include "hash.h"
50
51/* Default location of netgroup file. */
52char *netgroup = "/etc/netgroup";
53
54/* Stored hash table version of 'forward' netgroup database. */
55struct group_entry *gtable[TABLESIZE];
56
57/*
58 * Stored hash table of 'reverse' netgroup member database
59 * which we will construct.
60 */
61struct member_entry *mtable[TABLESIZE];
62
63static void
64usage(void)
65{
66	fprintf (stderr,"usage: revnetgroup -u | -h [-f netgroup_file]\n");
67	exit(1);
68}
69
70int
71main(int argc, char *argv[])
72{
73	FILE *fp;
74	char readbuf[LINSIZ];
75	struct group_entry *gcur;
76	struct member_entry *mcur;
77	char *host, *user, *domain;
78	int ch;
79	char *key = NULL, *data = NULL;
80	int hosts = -1, i;
81
82	if (argc < 2)
83		usage();
84
85	while ((ch = getopt(argc, argv, "uhf:")) != -1) {
86		switch(ch) {
87		case 'u':
88			if (hosts != -1) {
89				warnx("please use only one of -u or -h");
90				usage();
91			}
92			hosts = 0;
93			break;
94		case 'h':
95			if (hosts != -1) {
96				warnx("please use only one of -u or -h");
97				usage();
98			}
99			hosts = 1;
100			break;
101		case 'f':
102			netgroup = optarg;
103			break;
104		default:
105			usage();
106			break;
107		}
108	}
109
110	if (hosts == -1)
111		usage();
112
113	if (strcmp(netgroup, "-")) {
114		if ((fp = fopen(netgroup, "r")) == NULL) {
115			err(1, "%s", netgroup);
116		}
117	} else {
118		fp = stdin;
119	}
120
121	/* Stuff all the netgroup names and members into a hash table. */
122	while (fgets(readbuf, LINSIZ, fp)) {
123		if (readbuf[0] == '#')
124			continue;
125		/* handle backslash line continuations */
126		while(readbuf[strlen(readbuf) - 2] == '\\') {
127			fgets((char *)&readbuf[strlen(readbuf) - 2],
128					sizeof(readbuf) - strlen(readbuf), fp);
129		}
130		data = NULL;
131		if ((data = (char *)(strpbrk(readbuf, " \t") + 1)) < (char *)2)
132			continue;
133		key = (char *)&readbuf;
134		*(data - 1) = '\0';
135		store(gtable, key, data);
136	}
137
138	fclose(fp);
139
140	/*
141	 * Find all members of each netgroup and keep track of which
142	 * group they belong to.
143	 */
144	for (i = 0; i < TABLESIZE; i++) {
145		gcur = gtable[i];
146		while(gcur) {
147			__setnetgrent(gcur->key);
148			while(__getnetgrent(&host, &user, &domain) != 0) {
149				if (hosts) {
150					if (!(host && !strcmp(host,"-"))) {
151						mstore(mtable,
152						       host ? host : "*",
153						       gcur->key,
154						       domain ? domain : "*");
155					}
156				} else {
157					if (!(user && !strcmp(user,"-"))) {
158						mstore(mtable,
159						       user ? user : "*",
160						       gcur->key,
161						       domain ? domain : "*");
162					}
163				}
164			}
165			gcur = gcur->next;
166		}
167	}
168
169	/* Release resources used by the netgroup parser code. */
170	__endnetgrent();
171
172	/* Spew out the results. */
173	for (i = 0; i < TABLESIZE; i++) {
174		mcur = mtable[i];
175		while(mcur) {
176			struct grouplist *tmp;
177			printf ("%s.%s\t", mcur->key, mcur->domain);
178			tmp = mcur->groups;
179			while(tmp) {
180				printf ("%s", tmp->groupname);
181				tmp = tmp->next;
182				if (tmp)
183					printf(",");
184			}
185			mcur = mcur->next;
186			printf ("\n");
187		}
188	}
189
190	/* Let the OS free all our resources. */
191	exit(0);
192}
193