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