yp_mkdb.c revision 22496
1223637Sbz/*
2126353Smlaier * Copyright (c) 1995, 1996
3126353Smlaier *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4126353Smlaier *
5130617Smlaier * Redistribution and use in source and binary forms, with or without
6126353Smlaier * modification, are permitted provided that the following conditions
7126353Smlaier * are met:
8126353Smlaier * 1. Redistributions of source code must retain the above copyright
9126353Smlaier *    notice, this list of conditions and the following disclaimer.
10126353Smlaier * 2. Redistributions in binary form must reproduce the above copyright
11126353Smlaier *    notice, this list of conditions and the following disclaimer in the
12126353Smlaier *    documentation and/or other materials provided with the distribution.
13126353Smlaier * 3. All advertising materials mentioning features or use of this software
14126353Smlaier *    must display the following acknowledgement:
15126353Smlaier *	This product includes software developed by Bill Paul.
16126353Smlaier * 4. Neither the name of the author nor the names of any co-contributors
17126353Smlaier *    may be used to endorse or promote products derived from this software
18126353Smlaier *    without specific prior written permission.
19126353Smlaier *
20126353Smlaier * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21126353Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22126353Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23126353Smlaier * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24126353Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25126353Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26126353Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27126353Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29126353Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30126353Smlaier * SUCH DAMAGE.
31126353Smlaier *
32126353Smlaier *	$FreeBSD: head/usr.sbin/yp_mkdb/yp_mkdb.c 22496 1997-02-09 19:34:53Z wpaul $
33126353Smlaier */
34127082Sobrien
35127082Sobrien#include <stdio.h>
36127082Sobrien#include <string.h>
37126353Smlaier#include <fcntl.h>
38126353Smlaier#include <sys/param.h>
39126353Smlaier#include <sys/types.h>
40145840Smlaier#include <sys/stat.h>
41126353Smlaier#include <limits.h>
42223637Sbz#include <stdlib.h>
43223637Sbz#include <unistd.h>
44223637Sbz#include <errno.h>
45223637Sbz#include <time.h>
46126353Smlaier#include <err.h>
47126353Smlaier#include <rpc/rpc.h>
48126353Smlaier#include <rpcsvc/yp.h>
49126353Smlaier#include "yp_extern.h"
50126353Smlaier#include "ypxfr_extern.h"
51171172Smlaier
52126353Smlaier#ifndef lint
53126353Smlaierstatic const char rcsid[] = "$FreeBSD: head/usr.sbin/yp_mkdb/yp_mkdb.c 22496 1997-02-09 19:34:53Z wpaul $";
54126353Smlaier#endif
55126353Smlaier
56126353Smlaierchar *yp_dir = "";	/* No particular default needed. */
57126353Smlaierchar *progname = "yp_mkdb";
58263029Sglebiusint _rpcpmstart = 0;
59126353Smlaierint debug = 1;
60126353Smlaier
61126353Smlaierstatic void usage()
62126353Smlaier{
63126353Smlaier	fprintf(stderr, "usage: %s -c\n", progname);
64126353Smlaier	fprintf(stderr, "usage: %s -u dbname\n", progname);
65126353Smlaier	fprintf(stderr, "usage: %s [-c] [-b] [-s] [-i inputfile] \
66126353Smlaier[-o outputfile]\n", progname);
67126353Smlaier	fprintf(stderr, "               [-d domainname ] [-m mastername] \
68126353Smlaierinputfile dbname\n");
69126353Smlaier	exit(1);
70126353Smlaier}
71145840Smlaier
72145840Smlaier#define PERM_SECURE (S_IRUSR|S_IWUSR)
73145840Smlaier
74126353Smlaierstatic DB *open_db(path, flags)
75130617Smlaier	char *path;
76130617Smlaier	int flags;
77171172Smlaier{
78171172Smlaier	extern HASHINFO openinfo;
79223637Sbz
80223637Sbz	return(dbopen(path, flags, PERM_SECURE, DB_HASH, &openinfo));
81223637Sbz}
82145840Smlaier
83145840Smlaierstatic void unwind(map)
84145840Smlaier	char *map;
85145840Smlaier{
86145840Smlaier	DB *dbp;
87145840Smlaier	DBT key, data;
88145840Smlaier
89126353Smlaier	dbp = open_db(map, O_RDONLY);
90145840Smlaier
91126353Smlaier	if (dbp == NULL)
92171172Smlaier		err(1, "open_db(%s) failed", map);
93145840Smlaier
94130617Smlaier	key.data = NULL;
95130617Smlaier	while(yp_next_record(dbp, &key, &data, 1, 1) == YP_TRUE)
96130617Smlaier		printf("%.*s %.*s\n", key.size,key.data,data.size,data.data);
97130617Smlaier
98130617Smlaier	(void)(dbp->close)(dbp);
99145840Smlaier	return;
100126353Smlaier}
101126353Smlaier
102171172Smlaiermain (argc, argv)
103171172Smlaier	int argc;
104171172Smlaier	char *argv[];
105171172Smlaier{
106126353Smlaier	int ch;
107126353Smlaier	int un = 0;
108171172Smlaier	int clear = 0;
109171172Smlaier	char *infile = NULL;
110171172Smlaier	char *map = NULL;
111126353Smlaier	char *domain = NULL;
112126353Smlaier	char *infilename = NULL;
113126353Smlaier	char *outfilename = NULL;
114126353Smlaier	char *mastername = NULL;
115126353Smlaier	int interdom = 0;
116171172Smlaier	int secure = 0;
117130617Smlaier	DB *dbp;
118130617Smlaier	DBT key, data;
119126353Smlaier	char buf[10240];
120126353Smlaier	char *keybuf, *datbuf;
121171172Smlaier	FILE *ifp;
122171172Smlaier	char hname[MAXHOSTNAMELEN + 2];
123126353Smlaier
124126353Smlaier	while ((ch = getopt(argc, argv, "uhcbsd:i:o:m:")) != EOF) {
125126353Smlaier		switch(ch) {
126126353Smlaier		case 'u':
127126353Smlaier			un++;
128126353Smlaier			break;
129130617Smlaier		case 'c':
130130617Smlaier			clear++;
131126353Smlaier			break;
132171172Smlaier		case 'b':
133171172Smlaier			interdom++;
134171172Smlaier			break;
135171172Smlaier		case 's':
136171172Smlaier			secure++;
137171172Smlaier			break;
138171172Smlaier		case 'd':
139171172Smlaier			domain = optarg;
140171172Smlaier			break;
141126353Smlaier		case 'i':
142126353Smlaier			infilename = optarg;
143126353Smlaier			break;
144126353Smlaier		case 'o':
145171172Smlaier			outfilename = optarg;
146171172Smlaier			break;
147171172Smlaier		case 'm':
148171172Smlaier			mastername = optarg;
149171172Smlaier			break;
150126353Smlaier		case 'h':
151126353Smlaier		default:
152126353Smlaier			usage();
153126353Smlaier			break;
154126353Smlaier		}
155126353Smlaier	}
156126353Smlaier
157126353Smlaier	argc -= optind;
158126353Smlaier	argv += optind;
159126353Smlaier
160126353Smlaier	if (un) {
161126353Smlaier		map = argv[0];
162126353Smlaier		if (map == NULL)
163145840Smlaier			usage();
164126353Smlaier		unwind(map);
165126353Smlaier		exit(0);
166126353Smlaier
167126353Smlaier	}
168126353Smlaier
169126353Smlaier	infile = argv[0];
170126353Smlaier	map = argv[1];
171126353Smlaier
172126353Smlaier	if (infile == NULL || map == NULL) {
173145840Smlaier		if (clear)
174126353Smlaier			goto doclear;
175126353Smlaier		usage();
176126353Smlaier	}
177126353Smlaier
178126353Smlaier	if (mastername == NULL) {
179126353Smlaier		if (gethostname((char *)&hname, sizeof(hname)) == -1)
180126353Smlaier			err(1, "gethostname() failed");
181126353Smlaier		mastername = (char *)&hname;
182126353Smlaier	}
183145840Smlaier
184126353Smlaier	/*
185126353Smlaier	 * Note that while we can read from stdin, we can't
186126353Smlaier	 * write to stdout; the db library doesn't let you
187126353Smlaier	 * write to a file stream like that.
188126353Smlaier	 */
189126353Smlaier
190126353Smlaier	if (!strcmp(infile, "-")) {
191126353Smlaier		ifp = stdin;
192126353Smlaier	} else {
193145840Smlaier		if ((ifp = fopen(infile, "r")) == NULL)
194126353Smlaier			err(1, "failed to open %s", infile);
195126353Smlaier	}
196126353Smlaier
197126353Smlaier	if ((dbp = open_db(map, O_RDWR|O_EXLOCK|O_EXCL|O_CREAT)) == NULL)
198126353Smlaier		err(1, "open_db(%s) failed", map);
199126353Smlaier
200126353Smlaier	if (interdom) {
201126353Smlaier		key.data = "YP_INTERDOMAIN";
202126353Smlaier		key.size = sizeof("YP_INTERDOMAIN") - 1;
203126353Smlaier		data.data = "";
204126353Smlaier		data.size = 0;
205126353Smlaier		yp_put_record(dbp, &key, &data, 0);
206126353Smlaier	}
207126353Smlaier
208126353Smlaier	if (secure) {
209126353Smlaier		key.data = "YP_SECURE";
210130617Smlaier		key.size = sizeof("YP_SECURE") - 1;
211223637Sbz		data.data = "";
212126353Smlaier		data.size = 0;
213126353Smlaier		yp_put_record(dbp, &key, &data, 0);
214126353Smlaier	}
215223637Sbz
216130617Smlaier	key.data = "YP_MASTER_NAME";
217130617Smlaier	key.size = sizeof("YP_MASTER_NAME") - 1;
218126353Smlaier	data.data = mastername;
219126353Smlaier	data.size = strlen(mastername);
220126353Smlaier	yp_put_record(dbp, &key, &data, 0);
221126353Smlaier
222171172Smlaier	key.data = "YP_LAST_MODIFIED";
223126353Smlaier	key.size = sizeof("YP_LAST_MODIFIED") - 1;
224126353Smlaier	snprintf(buf, sizeof(buf), "%lu", time(NULL));
225126353Smlaier	data.data = (char *)&buf;
226126353Smlaier	data.size = strlen(buf);
227126353Smlaier	yp_put_record(dbp, &key, &data, 0);
228126353Smlaier
229171172Smlaier	if (infilename) {
230223637Sbz		key.data = "YP_INPUT_FILE";
231171172Smlaier		key.size = sizeof("YP_INPUT_FILE") - 1;
232126353Smlaier		data.data = infilename;
233126353Smlaier		data.size = strlen(infilename);
234126353Smlaier		yp_put_record(dbp, &key, &data, 0);
235126353Smlaier	}
236126353Smlaier
237126353Smlaier	if (outfilename) {
238223057Sbz		key.data = "YP_OUTPUT_FILE";
239145840Smlaier		key.size = sizeof("YP_OUTPUT_FILE") - 1;
240223637Sbz		data.data = outfilename;
241223637Sbz		data.size = strlen(outfilename);
242223637Sbz		yp_put_record(dbp, &key, &data, 0);
243223637Sbz	}
244223637Sbz
245126353Smlaier	if (domain) {
246126353Smlaier		key.data = "YP_DOMAIN_NAME";
247126353Smlaier		key.size = sizeof("YP_DOMAIN_NAME") - 1;
248126353Smlaier		data.data = domain;
249126353Smlaier		data.size = strlen(domain);
250126353Smlaier		yp_put_record(dbp, &key, &data, 0);
251126353Smlaier	}
252126353Smlaier
253126353Smlaier	while(fgets((char *)&buf, sizeof(buf), ifp)) {
254127024Smlaier		char *sep = NULL;
255126355Smlaier		int rval;
256126355Smlaier
257126355Smlaier		/* NUL terminate */
258126353Smlaier		if ((sep = strchr(buf, '\n')))
259126353Smlaier			*sep = '\0';
260126353Smlaier
261126353Smlaier		/* handle backslash line continuations */
262126353Smlaier		while(buf[strlen(buf) - 1] == '\\') {
263126353Smlaier			fgets((char *)&buf[strlen(buf) - 1],
264126353Smlaier					sizeof(buf) - strlen(buf), ifp);
265126353Smlaier			if ((sep = strchr(buf, '\n')))
266126353Smlaier				*sep = '\0';
267126353Smlaier		}
268126353Smlaier
269126353Smlaier		/* find the separation between the key and data */
270126353Smlaier		if ((sep = strpbrk(buf, " \t")) == NULL) {
271126353Smlaier			warnx("bad input -- no white space: %s", buf);
272126353Smlaier			continue;
273126353Smlaier		}
274126353Smlaier
275126353Smlaier		/* separate the strings */
276126353Smlaier		keybuf = (char *)&buf;
277126353Smlaier		datbuf = sep + 1;
278126353Smlaier		*sep = '\0';
279126353Smlaier
280126353Smlaier		/* set datbuf to start at first non-whitespace character */
281126353Smlaier		while (*datbuf == ' ' || *datbuf == '\t')
282126353Smlaier			datbuf++;
283126353Smlaier
284126353Smlaier		/* Check for silliness. */
285126353Smlaier		if  (*keybuf == '+' || *keybuf == '-' ||
286126353Smlaier		     *datbuf == '+' || *datbuf == '-') {
287126353Smlaier			warnx("bad character at start of line: %s", buf);
288126353Smlaier			continue;
289126353Smlaier		}
290126353Smlaier
291126353Smlaier		if (strlen(keybuf) > YPMAXRECORD) {
292126353Smlaier			warnx("key too long: %s", keybuf);
293126353Smlaier			continue;
294126353Smlaier		}
295126353Smlaier
296126353Smlaier		if (!strlen(keybuf)) {
297126353Smlaier			warnx("no key -- check source file for blank lines");
298126353Smlaier			continue;
299126353Smlaier		}
300126353Smlaier
301145840Smlaier		if (strlen(datbuf) > YPMAXRECORD) {
302126353Smlaier			warnx("data too long: %s", datbuf);
303145840Smlaier			continue;
304126353Smlaier		}
305145840Smlaier
306145840Smlaier		key.data = keybuf;
307171172Smlaier		key.size = strlen(keybuf);
308126353Smlaier		data.data = datbuf;
309145840Smlaier		data.size = strlen(datbuf);
310145840Smlaier
311126353Smlaier		if ((rval = yp_put_record(dbp, &key, &data, 0)) != YP_TRUE) {
312145840Smlaier			switch(rval) {
313126353Smlaier			case YP_FALSE:
314145840Smlaier				warnx("duplicate key '%s' - skipping", keybuf);
315145840Smlaier				break;
316145840Smlaier			case YP_BADDB:
317145840Smlaier			default:
318145840Smlaier				err(1,"failed to write new record - exiting");
319145840Smlaier				break;
320145840Smlaier			}
321145840Smlaier		}
322130617Smlaier
323130617Smlaier	}
324145840Smlaier
325145840Smlaier	(void)(dbp->close)(dbp);
326130617Smlaier
327130617Smlaierdoclear:
328130617Smlaier
329126353Smlaier	if (clear) {
330126353Smlaier		char in = 0;
331126353Smlaier		char *out = NULL;
332126353Smlaier		int stat;
333126353Smlaier		if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR,
334126353Smlaier			xdr_void, (void *)&in,
335145840Smlaier			xdr_void, (void *)out)) != RPC_SUCCESS) {
336126353Smlaier			warnx("failed to send 'clear' to local ypserv: %s",
337130617Smlaier				clnt_sperrno((enum clnt_stat) stat));
338126353Smlaier		}
339130617Smlaier	}
340130617Smlaier
341145840Smlaier	exit(0);
342145840Smlaier}
343145840Smlaier