makedbm.c revision 1.13 1 /* $NetBSD: makedbm.c,v 1.13 1998/06/10 21:15:41 kleink Exp $ */
2
3 /*
4 * Copyright (c) 1994 Mats O Jansson <moj (at) stacken.kth.se>
5 * 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 Mats O Jansson
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 #ifndef lint
36 __RCSID("$NetBSD: makedbm.c,v 1.13 1998/06/10 21:15:41 kleink Exp $");
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/stat.h>
41
42 #include <ctype.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <util.h>
51
52 #include <rpc/rpc.h>
53 #include <rpc/xdr.h>
54
55 #include "protos.h"
56 #include "ypdb.h"
57 #include "ypdef.h"
58
59 extern char *__progname; /* from crt0.o */
60
61 int main __P((int, char *[]));
62 void usage __P((void));
63 int add_record __P((DBM *, char *, char *, int));
64 char *file_date __P((char *));
65 void list_database __P((char *));
66 void create_database __P((char *, char *, char *, char *,
67 char *, char *, int, int, int));
68
69 int
70 main(argc, argv)
71 int argc;
72 char *argv[];
73 {
74 int aflag, uflag, bflag, lflag, sflag;
75 char *yp_input_file, *yp_output_file;
76 char *yp_master_name, *yp_domain_name;
77 char *infile, *outfile;
78 int ch;
79
80 yp_input_file = yp_output_file = NULL;
81 yp_master_name = yp_domain_name = NULL;
82 aflag = uflag = bflag = lflag = sflag = 0;
83 infile = outfile = NULL;
84
85 while ((ch = getopt(argc, argv, "blsui:o:m:d:")) != -1) {
86 switch (ch) {
87 case 'b':
88 bflag = aflag = 1;
89 break;
90
91 case 'l':
92 lflag = aflag = 1;
93 break;
94
95 case 's':
96 sflag = aflag = 1;
97 break;
98
99 case 'i':
100 yp_input_file = optarg;
101 aflag = 1;
102 break;
103
104 case 'o':
105 yp_output_file = optarg;
106 aflag = 1;
107 break;
108
109 case 'm':
110 yp_master_name = optarg;
111 aflag = 1;
112 break;
113
114 case 'd':
115 yp_domain_name = optarg;
116 aflag = 1;
117 break;
118
119 case 'u':
120 uflag = 1;
121 break;
122
123 default:
124 usage();
125 }
126 }
127 argc -= optind; argv += optind;
128
129 if ((uflag != 0) && (aflag != 0))
130 usage();
131 else {
132 if (uflag != 0) {
133 if (argc == 1)
134 infile = argv[0];
135 else
136 usage();
137 } else {
138 if (argc == 2) {
139 infile = argv[0];
140 outfile = argv[1];
141 } else
142 usage();
143 }
144 }
145
146 if (uflag != 0)
147 list_database(infile);
148 else
149 create_database(infile, outfile,
150 yp_input_file, yp_output_file, yp_master_name,
151 yp_domain_name, bflag, lflag, sflag);
152
153 exit(0);
154 }
155
156 int
157 add_record(db, str1, str2, check)
158 DBM *db;
159 char *str1, *str2;
160 int check;
161 {
162 datum key, val;
163 int status;
164
165 key.dptr = str1;
166 key.dsize = strlen(str1);
167
168 if (check) {
169 val = ypdb_fetch(db, key);
170
171 if (val.dptr != NULL)
172 return 0; /* already there */
173 }
174 val.dptr = str2;
175 val.dsize = strlen(str2);
176 status = ypdb_store(db, key, val, YPDB_INSERT);
177
178 if (status != 0) {
179 warnx("can't store `%s %s'", str1, str2);
180 return -1;
181 }
182 return 0;
183 }
184
185 char *
186 file_date(filename)
187 char *filename;
188 {
189 struct stat finfo;
190 static char datestr[11];
191
192 memset(datestr, 0, sizeof(datestr));
193
194 if (strcmp(filename, "-") == 0)
195 snprintf(datestr, sizeof(datestr), "%010d",
196 (int)time(NULL));
197 else {
198 if (stat(filename, &finfo) != 0)
199 err(1, "can't stat %s", filename);
200 snprintf(datestr, sizeof(datestr), "%010d",
201 (int)finfo.st_mtime);
202 }
203
204 return datestr;
205 }
206
207 void
208 list_database(database)
209 char *database;
210 {
211 DBM *db;
212 datum key, val;
213
214 db = ypdb_open(database, O_RDONLY, 0444);
215 if (db == NULL)
216 err(1, "can't open database `%s'", database);
217
218 key = ypdb_firstkey(db);
219
220 while (key.dptr != NULL) {
221 val = ypdb_fetch(db, key);
222 /* workround trailing \0 in aliases.db */
223 if (key.dptr[key.dsize - 1] == '\0')
224 key.dsize--;
225 printf("%*.*s", key.dsize, key.dsize, key.dptr);
226 if (val.dsize > 0) {
227 if (val.dptr[val.dsize - 1] == '\0')
228 val.dsize--;
229 printf(" %*.*s", val.dsize, val.dsize, val.dptr);
230 }
231 printf("\n");
232 key = ypdb_nextkey(db);
233 }
234
235 ypdb_close(db);
236 }
237
238 void
239 create_database(infile, database, yp_input_file, yp_output_file,
240 yp_master_name, yp_domain_name, bflag, lflag, sflag)
241 char *infile, *database, *yp_input_file, *yp_output_file;
242 char *yp_master_name, *yp_domain_name;
243 int bflag, lflag, sflag;
244 {
245 FILE *data_file;
246 char myname[MAXHOSTNAMELEN];
247 size_t line_no = 0;
248 size_t len;
249 char *p, *k, *v, *slash;
250 DBM *new_db;
251 static char mapname[] = "ypdbXXXXXX";
252 char db_mapname[MAXPATHLEN + 1], db_outfile[MAXPATHLEN + 1];
253 char db_tempname[MAXPATHLEN + 1];
254 char empty_str[] = "";
255
256 memset(db_mapname, 0, sizeof(db_mapname));
257 memset(db_outfile, 0, sizeof(db_outfile));
258 memset(db_tempname, 0, sizeof(db_tempname));
259
260 if (strcmp(infile, "-") == 0)
261 data_file = stdin;
262 else {
263 data_file = fopen(infile, "r");
264 if (data_file == NULL)
265 err(1, "can't open `%s'", infile);
266 }
267
268 if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN)
269 errx(1, "file name `%s' too long", database);
270
271 snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX);
272
273 slash = strrchr(database, '/');
274 if (slash != NULL)
275 slash[1] = '\0'; /* truncate to dir */
276 else
277 *database = '\0'; /* eliminate */
278
279 /* NOTE: database is now directory where map goes ! */
280
281 if (strlen(database) + strlen(mapname) +
282 strlen(YPDB_SUFFIX) > MAXPATHLEN)
283 errx(1, "directory name `%s' too long", database);
284
285 snprintf(db_tempname, sizeof(db_tempname), "%s%s",
286 database, mapname);
287 mktemp(db_tempname);
288 snprintf(db_mapname, sizeof(db_mapname), "%s%s",
289 db_tempname, YPDB_SUFFIX);
290
291 new_db = ypdb_open(db_tempname, O_RDWR | O_CREAT | O_EXCL, 0644);
292 if (new_db == NULL)
293 err(1, "can't create temp database `%s'", db_tempname);
294
295 for (;
296 (p = fparseln(data_file, &len, &line_no, NULL, FPARSELN_UNESCALL));
297 free(p)) {
298 while (*p && isspace(*p)) /* skip leading whitespace */
299 p++;
300
301 if (! *p)
302 continue;
303
304 k = p; /* save start of key */
305 while (*p && !isspace(*p)) { /* find whitespace */
306 /* Convert to lower case if forcing. */
307 if (lflag && isupper(*p))
308 *p = tolower(*p);
309 p++;
310 }
311 if (! *p)
312 v = ""; /* no value found - use "" */
313 else {
314 while (isspace(*p)) /* replace space with <NUL> */
315 *p++ = '\0';
316 v = p; /* save start of value */
317 }
318
319 if (add_record(new_db, k, v, TRUE)) { /* save record */
320 bad_record:
321 ypdb_close(new_db);
322 unlink(db_mapname);
323 errx(1, "error adding record for line %lu",
324 (unsigned long)line_no);
325 }
326 }
327
328 if (strcmp(infile, "-") != 0)
329 (void) fclose(data_file);
330
331 if (add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE))
332 goto bad_record;
333
334 if (yp_input_file) {
335 if (add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE))
336 goto bad_record;
337 }
338
339 if (yp_output_file) {
340 if (add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE))
341 goto bad_record;
342 }
343
344 if (yp_master_name) {
345 if (add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE))
346 goto bad_record;
347 } else {
348 localhostname(myname, sizeof(myname) - 1);
349 if (add_record(new_db, YP_MASTER_KEY, myname, FALSE))
350 goto bad_record;
351 }
352
353 if (yp_domain_name) {
354 if (add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE))
355 goto bad_record;
356 }
357
358 if (bflag) {
359 if (add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE))
360 goto bad_record;
361 }
362
363 if (sflag) {
364 if (add_record(new_db, YP_SECURE_KEY, empty_str, FALSE))
365 goto bad_record;
366 }
367
368 ypdb_close(new_db);
369 if (rename(db_mapname, db_outfile) < 0) {
370 unlink(db_mapname);
371 err(1, "rename `%s' -> `%s'", db_mapname, db_outfile);
372 }
373 }
374
375 void
376 usage()
377 {
378
379 fprintf(stderr, "usage: %s -u file\n", __progname);
380 fprintf(stderr, " %s [-lbs] %s\n", __progname,
381 "[-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]");
382 fprintf(stderr, " %s infile outfile\n",
383 "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME]");
384 exit(1);
385 }
386