115423Swpaul/*
215423Swpaul * Copyright (c) 1995, 1996
315423Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
415423Swpaul *
515423Swpaul * Redistribution and use in source and binary forms, with or without
615423Swpaul * modification, are permitted provided that the following conditions
715423Swpaul * are met:
815423Swpaul * 1. Redistributions of source code must retain the above copyright
915423Swpaul *    notice, this list of conditions and the following disclaimer.
1015423Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1115423Swpaul *    notice, this list of conditions and the following disclaimer in the
1215423Swpaul *    documentation and/or other materials provided with the distribution.
1315423Swpaul * 3. All advertising materials mentioning features or use of this software
1415423Swpaul *    must display the following acknowledgement:
1515423Swpaul *	This product includes software developed by Bill Paul.
1615423Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1715423Swpaul *    may be used to endorse or promote products derived from this software
1815423Swpaul *    without specific prior written permission.
1915423Swpaul *
2015423Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2115423Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2215423Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2315423Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2415423Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2515423Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2615423Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2715423Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2815423Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2915423Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3015423Swpaul * SUCH DAMAGE.
3115423Swpaul */
3215423Swpaul
33114601Sobrien#include <sys/cdefs.h>
34114601Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.sbin/yp_mkdb/yp_mkdb.c 228722 2011-12-19 20:44:44Z dim $");
3530777Scharnier
3630777Scharnier#include <err.h>
3715423Swpaul#include <fcntl.h>
3815423Swpaul#include <limits.h>
39228722Sdim#include <stdint.h>
4030777Scharnier#include <stdio.h>
4115423Swpaul#include <stdlib.h>
4230777Scharnier#include <string.h>
4330777Scharnier#include <time.h>
4415423Swpaul#include <unistd.h>
4515423Swpaul#include <rpc/rpc.h>
4615423Swpaul#include <rpcsvc/yp.h>
4730777Scharnier#include <sys/param.h>
4830777Scharnier#include <sys/types.h>
4930777Scharnier#include <sys/stat.h>
5015423Swpaul#include "yp_extern.h"
5116133Swpaul#include "ypxfr_extern.h"
5215423Swpaul
5315423Swpaulchar *yp_dir = "";	/* No particular default needed. */
5415423Swpaulint _rpcpmstart = 0;
5515423Swpaulint debug = 1;
5615423Swpaul
5790298Sdesstatic void
5890298Sdesusage(void)
5915423Swpaul{
6030777Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
6130777Scharnier	"usage: yp_mkdb -c",
6230777Scharnier	"       yp_mkdb -u dbname",
6350159Swpaul	"       yp_mkdb [-c] [-b] [-s] [-f] [-i inputfile] [-o outputfile]",
6430777Scharnier	"               [-d domainname ] [-m mastername] inputfile dbname");
6515423Swpaul	exit(1);
6615423Swpaul}
6715423Swpaul
6815423Swpaul#define PERM_SECURE (S_IRUSR|S_IWUSR)
6915423Swpaul
7090298Sdesstatic DB *
7190298Sdesopen_db(char *path, int flags)
7215423Swpaul{
7315423Swpaul	extern HASHINFO openinfo;
7415423Swpaul
7515423Swpaul	return(dbopen(path, flags, PERM_SECURE, DB_HASH, &openinfo));
7615423Swpaul}
7715423Swpaul
7890298Sdesstatic void
7990298Sdesunwind(char *map)
8015423Swpaul{
8115423Swpaul	DB *dbp;
8215423Swpaul	DBT key, data;
8315423Swpaul
8415423Swpaul	dbp = open_db(map, O_RDONLY);
8515423Swpaul
8615423Swpaul	if (dbp == NULL)
8715423Swpaul		err(1, "open_db(%s) failed", map);
8815423Swpaul
8915423Swpaul	key.data = NULL;
9090297Sdes	while (yp_next_record(dbp, &key, &data, 1, 1) == YP_TRUE)
91228722Sdim		printf("%.*s %.*s\n", (int)key.size, key.data, (int)data.size,
92228722Sdim		    data.data);
9315423Swpaul
9415423Swpaul	(void)(dbp->close)(dbp);
9515423Swpaul	return;
9615423Swpaul}
9715423Swpaul
9890298Sdesint
9990298Sdesmain(int argc, char *argv[])
10015423Swpaul{
10115423Swpaul	int ch;
10215423Swpaul	int un = 0;
10315423Swpaul	int clear = 0;
10450159Swpaul	int filter_plusminus = 0;
10515423Swpaul	char *infile = NULL;
10615423Swpaul	char *map = NULL;
10715423Swpaul	char *domain = NULL;
10815423Swpaul	char *infilename = NULL;
10915423Swpaul	char *outfilename = NULL;
11015423Swpaul	char *mastername = NULL;
11119155Swpaul	int interdom = 0;
11219155Swpaul	int secure = 0;
11315423Swpaul	DB *dbp;
11415423Swpaul	DBT key, data;
11515423Swpaul	char buf[10240];
11615423Swpaul	char *keybuf, *datbuf;
11715423Swpaul	FILE *ifp;
11815423Swpaul	char hname[MAXHOSTNAMELEN + 2];
11915423Swpaul
12050746Ssheldonh	while ((ch = getopt(argc, argv, "uhcbsfd:i:o:m:")) != -1) {
12190297Sdes		switch (ch) {
12250159Swpaul		case 'f':
12350159Swpaul			filter_plusminus++;
12450159Swpaul			break;
12515423Swpaul		case 'u':
12615423Swpaul			un++;
12715423Swpaul			break;
12815423Swpaul		case 'c':
12915423Swpaul			clear++;
13015423Swpaul			break;
13119155Swpaul		case 'b':
13219155Swpaul			interdom++;
13319155Swpaul			break;
13419155Swpaul		case 's':
13519155Swpaul			secure++;
13619155Swpaul			break;
13715423Swpaul		case 'd':
13815423Swpaul			domain = optarg;
13915423Swpaul			break;
14015423Swpaul		case 'i':
14115423Swpaul			infilename = optarg;
14215423Swpaul			break;
14315423Swpaul		case 'o':
14415423Swpaul			outfilename = optarg;
14515423Swpaul			break;
14615423Swpaul		case 'm':
14715423Swpaul			mastername = optarg;
14815423Swpaul			break;
14915423Swpaul		case 'h':
15015423Swpaul		default:
15115423Swpaul			usage();
15215423Swpaul			break;
15315423Swpaul		}
15415423Swpaul	}
15515423Swpaul
15615423Swpaul	argc -= optind;
15715423Swpaul	argv += optind;
15815423Swpaul
15915423Swpaul	if (un) {
16015423Swpaul		map = argv[0];
16115423Swpaul		if (map == NULL)
16215423Swpaul			usage();
16315423Swpaul		unwind(map);
16415423Swpaul		exit(0);
16515423Swpaul
16615423Swpaul	}
16715423Swpaul
16815423Swpaul	infile = argv[0];
16915423Swpaul	map = argv[1];
17015423Swpaul
17115423Swpaul	if (infile == NULL || map == NULL) {
17215423Swpaul		if (clear)
17315423Swpaul			goto doclear;
17415423Swpaul		usage();
17515423Swpaul	}
17615423Swpaul
17715423Swpaul	if (mastername == NULL) {
17815423Swpaul		if (gethostname((char *)&hname, sizeof(hname)) == -1)
17915423Swpaul			err(1, "gethostname() failed");
18015423Swpaul		mastername = (char *)&hname;
18115423Swpaul	}
18215423Swpaul
18315423Swpaul	/*
18415423Swpaul	 * Note that while we can read from stdin, we can't
18515423Swpaul	 * write to stdout; the db library doesn't let you
18615423Swpaul	 * write to a file stream like that.
18715423Swpaul	 */
18815423Swpaul
18915423Swpaul	if (!strcmp(infile, "-")) {
19015423Swpaul		ifp = stdin;
19115423Swpaul	} else {
19215423Swpaul		if ((ifp = fopen(infile, "r")) == NULL)
19315423Swpaul			err(1, "failed to open %s", infile);
19415423Swpaul	}
19515423Swpaul
19615423Swpaul	if ((dbp = open_db(map, O_RDWR|O_EXLOCK|O_EXCL|O_CREAT)) == NULL)
19715423Swpaul		err(1, "open_db(%s) failed", map);
19815423Swpaul
19919155Swpaul	if (interdom) {
20019155Swpaul		key.data = "YP_INTERDOMAIN";
20119155Swpaul		key.size = sizeof("YP_INTERDOMAIN") - 1;
20219155Swpaul		data.data = "";
20319155Swpaul		data.size = 0;
20419155Swpaul		yp_put_record(dbp, &key, &data, 0);
20519155Swpaul	}
20619155Swpaul
20719155Swpaul	if (secure) {
20819155Swpaul		key.data = "YP_SECURE";
20919155Swpaul		key.size = sizeof("YP_SECURE") - 1;
21019155Swpaul		data.data = "";
21119155Swpaul		data.size = 0;
21219155Swpaul		yp_put_record(dbp, &key, &data, 0);
21319155Swpaul	}
21419155Swpaul
21515423Swpaul	key.data = "YP_MASTER_NAME";
21615423Swpaul	key.size = sizeof("YP_MASTER_NAME") - 1;
21715423Swpaul	data.data = mastername;
21815423Swpaul	data.size = strlen(mastername);
21916133Swpaul	yp_put_record(dbp, &key, &data, 0);
22015423Swpaul
22115423Swpaul	key.data = "YP_LAST_MODIFIED";
22215423Swpaul	key.size = sizeof("YP_LAST_MODIFIED") - 1;
223228722Sdim	snprintf(buf, sizeof(buf), "%jd", (intmax_t)time(NULL));
22416133Swpaul	data.data = (char *)&buf;
22515423Swpaul	data.size = strlen(buf);
22616133Swpaul	yp_put_record(dbp, &key, &data, 0);
22715423Swpaul
22815423Swpaul	if (infilename) {
22915423Swpaul		key.data = "YP_INPUT_FILE";
23015423Swpaul		key.size = sizeof("YP_INPUT_FILE") - 1;
23115423Swpaul		data.data = infilename;
23215423Swpaul		data.size = strlen(infilename);
23316133Swpaul		yp_put_record(dbp, &key, &data, 0);
23415423Swpaul	}
23515423Swpaul
23615423Swpaul	if (outfilename) {
23715423Swpaul		key.data = "YP_OUTPUT_FILE";
23815423Swpaul		key.size = sizeof("YP_OUTPUT_FILE") - 1;
23915423Swpaul		data.data = outfilename;
24015423Swpaul		data.size = strlen(outfilename);
24116133Swpaul		yp_put_record(dbp, &key, &data, 0);
24215423Swpaul	}
24315423Swpaul
24415423Swpaul	if (domain) {
24515423Swpaul		key.data = "YP_DOMAIN_NAME";
24615423Swpaul		key.size = sizeof("YP_DOMAIN_NAME") - 1;
24715423Swpaul		data.data = domain;
24815423Swpaul		data.size = strlen(domain);
24916133Swpaul		yp_put_record(dbp, &key, &data, 0);
25015423Swpaul	}
25115423Swpaul
25290297Sdes	while (fgets((char *)&buf, sizeof(buf), ifp)) {
25315423Swpaul		char *sep = NULL;
25415423Swpaul		int rval;
25515423Swpaul
25615423Swpaul		/* NUL terminate */
25715423Swpaul		if ((sep = strchr(buf, '\n')))
25815423Swpaul			*sep = '\0';
25915423Swpaul
26015423Swpaul		/* handle backslash line continuations */
26190297Sdes		while (buf[strlen(buf) - 1] == '\\') {
26215423Swpaul			fgets((char *)&buf[strlen(buf) - 1],
26315423Swpaul					sizeof(buf) - strlen(buf), ifp);
26415423Swpaul			if ((sep = strchr(buf, '\n')))
26515423Swpaul				*sep = '\0';
26615423Swpaul		}
26715423Swpaul
26815423Swpaul		/* find the separation between the key and data */
26915423Swpaul		if ((sep = strpbrk(buf, " \t")) == NULL) {
27015423Swpaul			warnx("bad input -- no white space: %s", buf);
27115423Swpaul			continue;
27215423Swpaul		}
27315423Swpaul
27415423Swpaul		/* separate the strings */
27515423Swpaul		keybuf = (char *)&buf;
27615423Swpaul		datbuf = sep + 1;
27715423Swpaul		*sep = '\0';
27815423Swpaul
27915423Swpaul		/* set datbuf to start at first non-whitespace character */
28015423Swpaul		while (*datbuf == ' ' || *datbuf == '\t')
28115423Swpaul			datbuf++;
28215423Swpaul
28315423Swpaul		/* Check for silliness. */
28450159Swpaul		if (filter_plusminus) {
28550159Swpaul			if  (*keybuf == '+' || *keybuf == '-' ||
28650159Swpaul			     *datbuf == '+' || *datbuf == '-') {
28750159Swpaul				warnx("bad character at "
28850159Swpaul				    "start of line: %s", buf);
28950159Swpaul				continue;
29050159Swpaul			}
29115423Swpaul		}
29215423Swpaul
29315423Swpaul		if (strlen(keybuf) > YPMAXRECORD) {
29415423Swpaul			warnx("key too long: %s", keybuf);
29515423Swpaul			continue;
29615423Swpaul		}
29715423Swpaul
29822496Swpaul		if (!strlen(keybuf)) {
29922496Swpaul			warnx("no key -- check source file for blank lines");
30022496Swpaul			continue;
30122496Swpaul		}
30222496Swpaul
30315423Swpaul		if (strlen(datbuf) > YPMAXRECORD) {
30415423Swpaul			warnx("data too long: %s", datbuf);
30515423Swpaul			continue;
30615423Swpaul		}
30715423Swpaul
30815423Swpaul		key.data = keybuf;
30915423Swpaul		key.size = strlen(keybuf);
31015423Swpaul		data.data = datbuf;
31115423Swpaul		data.size = strlen(datbuf);
31215423Swpaul
31316133Swpaul		if ((rval = yp_put_record(dbp, &key, &data, 0)) != YP_TRUE) {
31490297Sdes			switch (rval) {
31515423Swpaul			case YP_FALSE:
31615423Swpaul				warnx("duplicate key '%s' - skipping", keybuf);
31715423Swpaul				break;
31815423Swpaul			case YP_BADDB:
31915423Swpaul			default:
32015423Swpaul				err(1,"failed to write new record - exiting");
32115423Swpaul				break;
32215423Swpaul			}
32315423Swpaul		}
32415423Swpaul
32515423Swpaul	}
32615423Swpaul
32715423Swpaul	(void)(dbp->close)(dbp);
32815423Swpaul
32915423Swpauldoclear:
33015423Swpaul
33115423Swpaul	if (clear) {
33215423Swpaul		char in = 0;
33315423Swpaul		char *out = NULL;
33415423Swpaul		int stat;
33595658Sdes		if ((stat = callrpc("localhost", YPPROG,YPVERS, YPPROC_CLEAR,
33695658Sdes			(xdrproc_t)xdr_void, &in,
33795658Sdes			(xdrproc_t)xdr_void, out)) != RPC_SUCCESS) {
33815423Swpaul			warnx("failed to send 'clear' to local ypserv: %s",
33915423Swpaul				clnt_sperrno((enum clnt_stat) stat));
34015423Swpaul		}
34115423Swpaul	}
34215423Swpaul
34315423Swpaul	exit(0);
34415423Swpaul}
345