]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/yp_mkdb/yp_mkdb.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / yp_mkdb / yp_mkdb.c
1 /*
2  * Copyright (c) 1995, 1996
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
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <err.h>
37 #include <fcntl.h>
38 #include <limits.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <time.h>
44 #include <unistd.h>
45 #include <rpc/rpc.h>
46 #include <rpcsvc/yp.h>
47 #include <sys/param.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include "yp_extern.h"
51 #include "ypxfr_extern.h"
52
53 char *yp_dir = "";      /* No particular default needed. */
54 int _rpcpmstart = 0;
55 int debug = 1;
56
57 static void
58 usage(void)
59 {
60         fprintf(stderr, "%s\n%s\n%s\n%s\n",
61         "usage: yp_mkdb -c",
62         "       yp_mkdb -u dbname",
63         "       yp_mkdb [-c] [-b] [-s] [-f] [-i inputfile] [-o outputfile]",
64         "               [-d domainname ] [-m mastername] inputfile dbname");
65         exit(1);
66 }
67
68 #define PERM_SECURE (S_IRUSR|S_IWUSR)
69
70 static DB *
71 open_db(char *path, int flags)
72 {
73         extern HASHINFO openinfo;
74
75         return(dbopen(path, flags, PERM_SECURE, DB_HASH, &openinfo));
76 }
77
78 static void
79 unwind(char *map)
80 {
81         DB *dbp;
82         DBT key, data;
83
84         dbp = open_db(map, O_RDONLY);
85
86         if (dbp == NULL)
87                 err(1, "open_db(%s) failed", map);
88
89         key.data = NULL;
90         while (yp_next_record(dbp, &key, &data, 1, 1) == YP_TRUE)
91                 printf("%.*s %.*s\n", (int)key.size, key.data, (int)data.size,
92                     data.data);
93
94         (void)(dbp->close)(dbp);
95         return;
96 }
97
98 int
99 main(int argc, char *argv[])
100 {
101         int ch;
102         int un = 0;
103         int clear = 0;
104         int filter_plusminus = 0;
105         char *infile = NULL;
106         char *map = NULL;
107         char *domain = NULL;
108         char *infilename = NULL;
109         char *outfilename = NULL;
110         char *mastername = NULL;
111         int interdom = 0;
112         int secure = 0;
113         DB *dbp;
114         DBT key, data;
115         char buf[10240];
116         char *keybuf, *datbuf;
117         FILE *ifp;
118         char hname[MAXHOSTNAMELEN + 2];
119
120         while ((ch = getopt(argc, argv, "uhcbsfd:i:o:m:")) != -1) {
121                 switch (ch) {
122                 case 'f':
123                         filter_plusminus++;
124                         break;
125                 case 'u':
126                         un++;
127                         break;
128                 case 'c':
129                         clear++;
130                         break;
131                 case 'b':
132                         interdom++;
133                         break;
134                 case 's':
135                         secure++;
136                         break;
137                 case 'd':
138                         domain = optarg;
139                         break;
140                 case 'i':
141                         infilename = optarg;
142                         break;
143                 case 'o':
144                         outfilename = optarg;
145                         break;
146                 case 'm':
147                         mastername = optarg;
148                         break;
149                 case 'h':
150                 default:
151                         usage();
152                         break;
153                 }
154         }
155
156         argc -= optind;
157         argv += optind;
158
159         if (un) {
160                 map = argv[0];
161                 if (map == NULL)
162                         usage();
163                 unwind(map);
164                 exit(0);
165
166         }
167
168         infile = argv[0];
169         map = argv[1];
170
171         if (infile == NULL || map == NULL) {
172                 if (clear)
173                         goto doclear;
174                 usage();
175         }
176
177         if (mastername == NULL) {
178                 if (gethostname((char *)&hname, sizeof(hname)) == -1)
179                         err(1, "gethostname() failed");
180                 mastername = (char *)&hname;
181         }
182
183         /*
184          * Note that while we can read from stdin, we can't
185          * write to stdout; the db library doesn't let you
186          * write to a file stream like that.
187          */
188
189         if (!strcmp(infile, "-")) {
190                 ifp = stdin;
191         } else {
192                 if ((ifp = fopen(infile, "r")) == NULL)
193                         err(1, "failed to open %s", infile);
194         }
195
196         if ((dbp = open_db(map, O_RDWR|O_EXLOCK|O_EXCL|O_CREAT)) == NULL)
197                 err(1, "open_db(%s) failed", map);
198
199         if (interdom) {
200                 key.data = "YP_INTERDOMAIN";
201                 key.size = sizeof("YP_INTERDOMAIN") - 1;
202                 data.data = "";
203                 data.size = 0;
204                 yp_put_record(dbp, &key, &data, 0);
205         }
206
207         if (secure) {
208                 key.data = "YP_SECURE";
209                 key.size = sizeof("YP_SECURE") - 1;
210                 data.data = "";
211                 data.size = 0;
212                 yp_put_record(dbp, &key, &data, 0);
213         }
214
215         key.data = "YP_MASTER_NAME";
216         key.size = sizeof("YP_MASTER_NAME") - 1;
217         data.data = mastername;
218         data.size = strlen(mastername);
219         yp_put_record(dbp, &key, &data, 0);
220
221         key.data = "YP_LAST_MODIFIED";
222         key.size = sizeof("YP_LAST_MODIFIED") - 1;
223         snprintf(buf, sizeof(buf), "%jd", (intmax_t)time(NULL));
224         data.data = (char *)&buf;
225         data.size = strlen(buf);
226         yp_put_record(dbp, &key, &data, 0);
227
228         if (infilename) {
229                 key.data = "YP_INPUT_FILE";
230                 key.size = sizeof("YP_INPUT_FILE") - 1;
231                 data.data = infilename;
232                 data.size = strlen(infilename);
233                 yp_put_record(dbp, &key, &data, 0);
234         }
235
236         if (outfilename) {
237                 key.data = "YP_OUTPUT_FILE";
238                 key.size = sizeof("YP_OUTPUT_FILE") - 1;
239                 data.data = outfilename;
240                 data.size = strlen(outfilename);
241                 yp_put_record(dbp, &key, &data, 0);
242         }
243
244         if (domain) {
245                 key.data = "YP_DOMAIN_NAME";
246                 key.size = sizeof("YP_DOMAIN_NAME") - 1;
247                 data.data = domain;
248                 data.size = strlen(domain);
249                 yp_put_record(dbp, &key, &data, 0);
250         }
251
252         while (fgets((char *)&buf, sizeof(buf), ifp)) {
253                 char *sep = NULL;
254                 int rval;
255
256                 /* NUL terminate */
257                 if ((sep = strchr(buf, '\n')))
258                         *sep = '\0';
259
260                 /* handle backslash line continuations */
261                 while (buf[strlen(buf) - 1] == '\\') {
262                         fgets((char *)&buf[strlen(buf) - 1],
263                                         sizeof(buf) - strlen(buf), ifp);
264                         if ((sep = strchr(buf, '\n')))
265                                 *sep = '\0';
266                 }
267
268                 /* find the separation between the key and data */
269                 if ((sep = strpbrk(buf, " \t")) == NULL) {
270                         warnx("bad input -- no white space: %s", buf);
271                         continue;
272                 }
273
274                 /* separate the strings */
275                 keybuf = (char *)&buf;
276                 datbuf = sep + 1;
277                 *sep = '\0';
278
279                 /* set datbuf to start at first non-whitespace character */
280                 while (*datbuf == ' ' || *datbuf == '\t')
281                         datbuf++;
282
283                 /* Check for silliness. */
284                 if (filter_plusminus) {
285                         if  (*keybuf == '+' || *keybuf == '-' ||
286                              *datbuf == '+' || *datbuf == '-') {
287                                 warnx("bad character at "
288                                     "start of line: %s", buf);
289                                 continue;
290                         }
291                 }
292
293                 if (strlen(keybuf) > YPMAXRECORD) {
294                         warnx("key too long: %s", keybuf);
295                         continue;
296                 }
297
298                 if (!strlen(keybuf)) {
299                         warnx("no key -- check source file for blank lines");
300                         continue;
301                 }
302
303                 if (strlen(datbuf) > YPMAXRECORD) {
304                         warnx("data too long: %s", datbuf);
305                         continue;
306                 }
307
308                 key.data = keybuf;
309                 key.size = strlen(keybuf);
310                 data.data = datbuf;
311                 data.size = strlen(datbuf);
312
313                 if ((rval = yp_put_record(dbp, &key, &data, 0)) != YP_TRUE) {
314                         switch (rval) {
315                         case YP_FALSE:
316                                 warnx("duplicate key '%s' - skipping", keybuf);
317                                 break;
318                         case YP_BADDB:
319                         default:
320                                 err(1,"failed to write new record - exiting");
321                                 break;
322                         }
323                 }
324
325         }
326
327         (void)(dbp->close)(dbp);
328
329 doclear:
330
331         if (clear) {
332                 char in = 0;
333                 char *out = NULL;
334                 int stat;
335                 if ((stat = callrpc("localhost", YPPROG,YPVERS, YPPROC_CLEAR,
336                         (xdrproc_t)xdr_void, &in,
337                         (xdrproc_t)xdr_void, out)) != RPC_SUCCESS) {
338                         warnx("failed to send 'clear' to local ypserv: %s",
339                                 clnt_sperrno((enum clnt_stat) stat));
340                 }
341         }
342
343         exit(0);
344 }