1331722Seadler/*
216728Swpaul * Copyright (c) 1995, 1996
316728Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
416728Swpaul *
516728Swpaul * Redistribution and use in source and binary forms, with or without
616728Swpaul * modification, are permitted provided that the following conditions
716728Swpaul * are met:
816728Swpaul * 1. Redistributions of source code must retain the above copyright
916728Swpaul *    notice, this list of conditions and the following disclaimer.
1016728Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1116728Swpaul *    notice, this list of conditions and the following disclaimer in the
1216728Swpaul *    documentation and/or other materials provided with the distribution.
1316728Swpaul * 3. All advertising materials mentioning features or use of this software
1416728Swpaul *    must display the following acknowledgement:
1516728Swpaul *	This product includes software developed by Bill Paul.
1616728Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1716728Swpaul *    may be used to endorse or promote products derived from this software
1816728Swpaul *    without specific prior written permission.
1916728Swpaul *
2016728Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2116728Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2216728Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2316728Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2416728Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2516728Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2616728Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2716728Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2816728Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2916728Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3016728Swpaul * SUCH DAMAGE.
3116728Swpaul *
3216728Swpaul * netid map generator program
3316728Swpaul *
3416728Swpaul * Written by Bill Paul <wpaul@ctr.columbia.edu>
3516728Swpaul * Center for Telecommunications Research
3616728Swpaul * Columbia University, New York City
3716728Swpaul */
3816728Swpaul
3917115Sbde#include <sys/types.h>
4017115Sbde
4117115Sbde#include <rpc/rpc.h>
4217115Sbde#include <rpcsvc/yp_prot.h>
4317115Sbde#include <rpcsvc/ypclnt.h>
4417115Sbde
4517115Sbde#include <err.h>
4617115Sbde#include <grp.h>
4731385Scharnier#include <netdb.h>
4817115Sbde#include <pwd.h>
4916728Swpaul#include <stdio.h>
5016728Swpaul#include <stdlib.h>
5116728Swpaul#include <string.h>
5231385Scharnier#include <unistd.h>
5317115Sbde
5416728Swpaul#include "hash.h"
5516728Swpaul
5616728Swpaul#ifndef lint
5731385Scharnierstatic const char rcsid[] =
5850476Speter  "$FreeBSD$";
5931385Scharnier#endif /* not lint */
6016728Swpaul
6116728Swpaul#define LINSIZ 1024
6216728Swpaul#define OPSYS "unix"
6316728Swpaul
6416728Swpaul/* Default location of group file. */
6516728Swpaulchar *groupfile = _PATH_GROUP;
6616728Swpaul/* Default location of master.passwd file. */
6716728Swpaulchar *passfile = _PATH_PASSWD;
6816728Swpaul/* Default location of hosts file. */
6916728Swpaulchar *hostsfile = _PATH_HOSTS;
7016728Swpaul/* Default location of netid file */
7116728Swpaulchar *netidfile = "/etc/netid";
7216728Swpaul
7316728Swpaul/*
7416728Swpaul * Stored hash table of 'reverse' group member database
7516728Swpaul * which we will construct.
7616728Swpaul */
7716728Swpaulstruct member_entry *mtable[TABLESIZE];
7816728Swpaul
7916728Swpaul/*
8016728Swpaul * Dupe table: used to keep track of entries so we don't
8116728Swpaul * print the same thing twice.
8216728Swpaul */
8316728Swpaulstruct member_entry *dtable[TABLESIZE];
8416728Swpaul
8590779Simpextern struct group *_getgrent(void);
8690779Simpextern int _setgrent(void);
8790779Simpextern void _endgrent(void);
8831385Scharnier
8931385Scharnierstatic void
9090779Simpusage(void)
9116728Swpaul{
9231385Scharnier	fprintf (stderr, "%s\n%s\n",
9331385Scharnier	"usage: mknetid [-q] [-g group_file] [-p passwd_file] [-h hosts_file]",
94106811Smaxim	"               [-n netid_file] [-d domain]");
9516728Swpaul	exit(1);
9616728Swpaul}
9716728Swpaul
9816728Swpaulextern FILE *_gr_fp;
9916728Swpaul
10031385Scharnierint
10190779Simpmain(int argc, char *argv[])
10216728Swpaul{
10316728Swpaul	FILE *gfp, *pfp, *hfp, *nfp;
10416728Swpaul	char readbuf[LINSIZ];
10516728Swpaul	char writebuf[LINSIZ];
10616728Swpaul	struct group *gr;
10716728Swpaul	struct grouplist *glist;
10816728Swpaul	char *domain;
10916728Swpaul	int ch;
11016728Swpaul	gid_t i;
11116728Swpaul	char *ptr, *pidptr, *gidptr, *hptr;
11216728Swpaul	int quiet = 0;
11316728Swpaul
114106811Smaxim	domain = NULL;
11524349Simp	while ((ch = getopt(argc, argv, "g:p:h:n:d:q")) != -1) {
11616728Swpaul		switch(ch) {
11716728Swpaul		case 'g':
11816728Swpaul			groupfile = optarg;
11916728Swpaul			break;
12016728Swpaul		case 'p':
12116728Swpaul			passfile = optarg;
12216728Swpaul			break;
12316728Swpaul		case 'h':
12416728Swpaul			hostsfile = optarg;
12516728Swpaul			break;
12616728Swpaul		case 'n':
12716728Swpaul			netidfile = optarg;
12816728Swpaul			break;
12916728Swpaul		case 'd':
13016728Swpaul			domain = optarg;
13116728Swpaul			break;
13216728Swpaul		case 'q':
13316728Swpaul			quiet++;
13416728Swpaul			break;
13516728Swpaul		default:
13631385Scharnier			usage();
13716728Swpaul			break;
13816728Swpaul		}
13916728Swpaul	}
14016728Swpaul
14116728Swpaul	if (domain == NULL) {
14216728Swpaul		if (yp_get_default_domain(&domain))
14316728Swpaul			errx(1, "no domain name specified and default \
14416728Swpauldomain not set");
14516728Swpaul	}
14616728Swpaul
14716728Swpaul	if ((gfp = fopen(groupfile, "r")) == NULL) {
14816728Swpaul		err(1, "%s", groupfile);
14916728Swpaul	}
15016728Swpaul
15116728Swpaul	if ((pfp = fopen(passfile, "r")) == NULL) {
15216728Swpaul		err(1, "%s", passfile);
15316728Swpaul	}
15416728Swpaul
15516728Swpaul	if ((hfp = fopen(hostsfile, "r")) == NULL) {
15616728Swpaul		err(1, "%s", hostsfile);
15716728Swpaul	}
15816728Swpaul
15916728Swpaul	if ((nfp = fopen(netidfile, "r")) == NULL) {
16016728Swpaul		/* netid is optional -- just continue */
16116728Swpaul		nfp = NULL;
16216728Swpaul	}
16316728Swpaul
16416728Swpaul	_gr_fp = gfp;
16516728Swpaul
16616728Swpaul	/* Load all the group membership info into a hash table. */
16716728Swpaul
16816728Swpaul	_setgrent();
16916728Swpaul	while((gr = _getgrent()) != NULL) {
17016728Swpaul		while(*gr->gr_mem) {
17116728Swpaul			mstore(mtable, *gr->gr_mem, gr->gr_gid, 0);
17216728Swpaul			gr->gr_mem++;
17316728Swpaul		}
17416728Swpaul	}
17516728Swpaul
17616728Swpaul	fclose(gfp);
17716728Swpaul	_endgrent();
17816728Swpaul
17916728Swpaul	/*
18016728Swpaul	 * Now parse the passwd database, spewing out the extra
18116728Swpaul	 * group information we just stored if necessary.
18216728Swpaul	 */
18316728Swpaul	while(fgets(readbuf, LINSIZ, pfp)) {
184106811Smaxim		/* Ignore comments: ^[ \t]*# */
185106811Smaxim		for (ptr = readbuf; *ptr != '\0'; ptr++)
186106811Smaxim			if (*ptr != ' ' && *ptr != '\t')
187106811Smaxim				break;
188106811Smaxim		if (*ptr == '#' || *ptr == '\0')
189106811Smaxim			continue;
190106811Smaxim		if ((ptr = strchr(readbuf, ':')) == NULL) {
19116728Swpaul			warnx("bad passwd file entry: %s", readbuf);
192106811Smaxim			continue;
193106811Smaxim		}
19416728Swpaul		*ptr = '\0';
19516728Swpaul		ptr++;
196106811Smaxim		if ((ptr = strchr(ptr, ':')) == NULL) {
19716728Swpaul			warnx("bad passwd file entry: %s", readbuf);
198106811Smaxim			continue;
199106811Smaxim		}
20016728Swpaul		*ptr = '\0';
20116728Swpaul		ptr++;
20216728Swpaul		pidptr = ptr;
203106811Smaxim		if ((ptr = strchr(ptr, ':')) == NULL) {
20416728Swpaul			warnx("bad passwd file entry: %s", readbuf);
205106811Smaxim			continue;
206106811Smaxim		}
20716728Swpaul		*ptr = '\0';
20816728Swpaul		ptr++;
20916728Swpaul		gidptr = ptr;
210106811Smaxim		if ((ptr = strchr(ptr, ':')) == NULL) {
21116728Swpaul			warnx("bad passwd file entry: %s", readbuf);
212106811Smaxim			continue;
213106811Smaxim		}
21416728Swpaul		*ptr = '\0';
21516728Swpaul		i = atol(gidptr);
21616728Swpaul
21716728Swpaul		snprintf(writebuf, sizeof(writebuf), "%s.%s@%s", OPSYS,
21816728Swpaul							pidptr, domain);
21916728Swpaul
22016728Swpaul		if (lookup(dtable, writebuf)) {
22116728Swpaul			if (!quiet)
22216728Swpaul				warnx("duplicate netid '%s.%s@%s' -- skipping",
22316728Swpaul						OPSYS, pidptr, domain);
22416728Swpaul			continue;
22516728Swpaul		} else {
22616728Swpaul			mstore(dtable, writebuf, 0, 1);
22716728Swpaul		}
22816793Swpaul		printf("%s.%s@%s %s:%s", OPSYS, pidptr, domain, pidptr, gidptr);
22916728Swpaul		if ((glist = lookup(mtable, (char *)&readbuf)) != NULL) {
23016728Swpaul			while(glist) {
23116728Swpaul				if (glist->groupid != i)
23237297Sbde					printf(",%lu", (u_long)glist->groupid);
23316728Swpaul				glist = glist->next;
23416728Swpaul			}
23516728Swpaul		}
23616728Swpaul		printf ("\n");
23716728Swpaul	}
23816728Swpaul
23916728Swpaul	fclose(pfp);
24016728Swpaul
24116728Swpaul	/*
24216728Swpaul	 * Now parse the hosts database (this part sucks).
24316728Swpaul	 */
24416728Swpaul
24516728Swpaul	while ((ptr = fgets(readbuf, LINSIZ, hfp))) {
24616728Swpaul		if (*ptr == '#')
24716728Swpaul			continue;
24816728Swpaul		if (!(hptr = strpbrk(ptr, "#\n")))
24916728Swpaul			continue;
25016728Swpaul		*hptr = '\0';
25116728Swpaul		if (!(hptr = strpbrk(ptr, " \t")))
25216728Swpaul			continue;
25316728Swpaul		*hptr++ = '\0';
25416728Swpaul		ptr = hptr;
25516728Swpaul		while (*ptr == ' ' || *ptr == '\t')
25616728Swpaul			ptr++;
25716728Swpaul		if (!(hptr = strpbrk(ptr, " \t")))
25816728Swpaul			continue;
25916728Swpaul		*hptr++ = '\0';
26016728Swpaul		snprintf(writebuf, sizeof(writebuf), "%s.%s@%s", OPSYS,
26116728Swpaul								ptr, domain);
26216728Swpaul		if (lookup(dtable, (char *)&writebuf)) {
26316728Swpaul			if (!quiet)
26416728Swpaul				warnx("duplicate netid '%s' -- skipping",
26516728Swpaul								writebuf);
26616728Swpaul			continue;
26716728Swpaul		} else {
26816728Swpaul			mstore(dtable, (char *)&writebuf, 0, 1);
26916728Swpaul		}
27016793Swpaul		printf ("%s.%s@%s 0:%s\n", OPSYS, ptr, domain, ptr);
27116728Swpaul	}
27216728Swpaul
27316728Swpaul	fclose(hfp);
27416728Swpaul
27516728Swpaul	/*
27616728Swpaul	 * Lastly, copy out any extra information in the netid
27716728Swpaul	 * file. If it's not open, just ignore it: it's optional anyway.
27816728Swpaul	 */
27916728Swpaul
28016728Swpaul	if (nfp != NULL) {
28116728Swpaul		while(fgets(readbuf, LINSIZ, nfp)) {
28216728Swpaul			if (readbuf[0] == '#')
28316728Swpaul				continue;
28416728Swpaul			if ((ptr = strpbrk((char*)&readbuf, " \t")) == NULL) {
28516728Swpaul				warnx("bad netid entry: '%s'", readbuf);
28616728Swpaul				continue;
28716728Swpaul			}
28816728Swpaul
28916728Swpaul			writebuf[0] = *ptr;
29016728Swpaul			*ptr = '\0';
29116728Swpaul			if (lookup(dtable, (char *)&readbuf)) {
29216728Swpaul				if (!quiet)
29316728Swpaul					warnx("duplicate netid '%s' -- skipping",
29416728Swpaul								readbuf);
29516728Swpaul				continue;
29616728Swpaul			} else {
29716728Swpaul				mstore(dtable, (char *)&readbuf, 0, 1);
29816728Swpaul			}
29916728Swpaul			*ptr = writebuf[0];
30016728Swpaul			printf("%s",readbuf);
30116728Swpaul		}
30216728Swpaul		fclose(nfp);
30316728Swpaul	}
30416728Swpaul
30516728Swpaul	exit(0);
30616728Swpaul}
307