Home | History | Annotate | Line # | Download | only in makedbm
makedbm.c revision 1.16
      1 /*	$NetBSD: makedbm.c,v 1.16 1999/07/25 07:59:48 lukem 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.16 1999/07/25 07:59:48 lukem 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 <time.h>
     50 #include <unistd.h>
     51 #include <util.h>
     52 
     53 #include <rpc/rpc.h>
     54 #include <rpc/xdr.h>
     55 
     56 #include "protos.h"
     57 #include "ypdb.h"
     58 #include "ypdef.h"
     59 
     60 extern	char *__progname;		/* from crt0.o */
     61 
     62 int	main __P((int, char *[]));
     63 void	usage __P((void));
     64 int	add_record __P((DBM *, char *, char *, int));
     65 char	*file_date __P((char *));
     66 void	list_database __P((char *));
     67 void	create_database __P((char *, char *, char *, char *,
     68 	    char *, char *, int, int, int));
     69 
     70 int
     71 main(argc, argv)
     72 	int argc;
     73 	char *argv[];
     74 {
     75 	int aflag, uflag, bflag, lflag, sflag;
     76 	char *yp_input_file, *yp_output_file;
     77 	char *yp_master_name, *yp_domain_name;
     78 	char *infile, *outfile;
     79 	int ch;
     80 
     81 	yp_input_file = yp_output_file = NULL;
     82 	yp_master_name = yp_domain_name = NULL;
     83 	aflag = uflag = bflag = lflag = sflag = 0;
     84 	infile = outfile = NULL;
     85 
     86 	while ((ch = getopt(argc, argv, "blsui:o:m:d:")) != -1) {
     87 		switch (ch) {
     88 		case 'b':
     89 			bflag = aflag = 1;
     90 			break;
     91 
     92 		case 'l':
     93 			lflag = aflag = 1;
     94 			break;
     95 
     96 		case 's':
     97 			sflag = aflag = 1;
     98 			break;
     99 
    100 		case 'i':
    101 			yp_input_file = optarg;
    102 			aflag = 1;
    103 			break;
    104 
    105 		case 'o':
    106 			yp_output_file = optarg;
    107 			aflag = 1;
    108 			break;
    109 
    110 		case 'm':
    111 			yp_master_name = optarg;
    112 			aflag = 1;
    113 			break;
    114 
    115 		case 'd':
    116 			yp_domain_name = optarg;
    117 			aflag = 1;
    118 			break;
    119 
    120 		case 'u':
    121 			uflag = 1;
    122 			break;
    123 
    124 		default:
    125 			usage();
    126 		}
    127 	}
    128 	argc -= optind; argv += optind;
    129 
    130 	if ((uflag != 0) && (aflag != 0))
    131 		usage();
    132 	else {
    133 		if (uflag != 0) {
    134 			if (argc == 1)
    135 				infile = argv[0];
    136 			else
    137 				usage();
    138 		} else {
    139 			if (argc == 2) {
    140 				infile = argv[0];
    141 				outfile = argv[1];
    142 			} else
    143 				usage();
    144 		}
    145 	}
    146 
    147 	if (uflag != 0)
    148 		list_database(infile);
    149 	else
    150 		create_database(infile, outfile,
    151 		    yp_input_file, yp_output_file, yp_master_name,
    152 		    yp_domain_name, bflag, lflag, sflag);
    153 
    154 	exit(0);
    155 }
    156 
    157 int
    158 add_record(db, str1, str2, check)
    159 	DBM *db;
    160 	char *str1, *str2;
    161 	int check;
    162 {
    163 	datum key, val;
    164 	int status;
    165 
    166 	key.dptr = str1;
    167 	key.dsize = strlen(str1);
    168 
    169 	if (check) {
    170 		val = ypdb_fetch(db, key);
    171 
    172 		if (val.dptr != NULL)
    173 			return 0;	/* already there */
    174 	}
    175 	val.dptr = str2;
    176 	val.dsize = strlen(str2);
    177 	status = ypdb_store(db, key, val, YPDB_INSERT);
    178 
    179 	if (status != 0) {
    180 		warnx("can't store `%s %s'", str1, str2);
    181 		return -1;
    182 	}
    183 	return 0;
    184 }
    185 
    186 char *
    187 file_date(filename)
    188 	char *filename;
    189 {
    190 	struct stat finfo;
    191 	static char datestr[11];
    192 
    193 	memset(datestr, 0, sizeof(datestr));
    194 
    195 	if (strcmp(filename, "-") == 0)
    196 		snprintf(datestr, sizeof(datestr), "%010d",
    197 		    (int)time(NULL));
    198 	else {
    199 		if (stat(filename, &finfo) != 0)
    200 			err(1, "can't stat %s", filename);
    201 		snprintf(datestr, sizeof(datestr), "%010d",
    202 		    (int)finfo.st_mtime);
    203 	}
    204 
    205 	return datestr;
    206 }
    207 
    208 void
    209 list_database(database)
    210 	char *database;
    211 {
    212 	DBM *db;
    213 	datum key, val;
    214 
    215 	db = ypdb_open(database, O_RDONLY, 0444);
    216 	if (db == NULL)
    217 		err(1, "can't open database `%s'", database);
    218 
    219 	key = ypdb_firstkey(db);
    220 
    221 	while (key.dptr != NULL) {
    222 		val = ypdb_fetch(db, key);
    223 				/* workround trailing \0 in aliases.db */
    224 		if (key.dptr[key.dsize - 1] == '\0')
    225 			key.dsize--;
    226 		printf("%*.*s", key.dsize, key.dsize, key.dptr);
    227 		if (val.dsize > 0) {
    228 			if (val.dptr[val.dsize - 1] == '\0')
    229 				val.dsize--;
    230 			printf(" %*.*s", val.dsize, val.dsize, val.dptr);
    231 		}
    232 		printf("\n");
    233 		key = ypdb_nextkey(db);
    234 	}
    235 
    236 	ypdb_close(db);
    237 }
    238 
    239 void
    240 create_database(infile, database, yp_input_file, yp_output_file,
    241     yp_master_name, yp_domain_name, bflag, lflag, sflag)
    242 	char *infile, *database, *yp_input_file, *yp_output_file;
    243 	char *yp_master_name, *yp_domain_name;
    244 	int bflag, lflag, sflag;
    245 {
    246 	FILE *data_file;
    247 	char myname[MAXHOSTNAMELEN];
    248 	size_t line_no = 0;
    249 	size_t len;
    250 	char *p, *k, *v, *slash;
    251 	DBM *new_db;
    252 	static char mapname[] = "ypdbXXXXXX";
    253 	char db_mapname[MAXPATHLEN + 1], db_outfile[MAXPATHLEN + 1];
    254 	char db_tempname[MAXPATHLEN + 1];
    255 	char empty_str[] = "";
    256 
    257 	memset(db_mapname, 0, sizeof(db_mapname));
    258 	memset(db_outfile, 0, sizeof(db_outfile));
    259 	memset(db_tempname, 0, sizeof(db_tempname));
    260 
    261 	if (strcmp(infile, "-") == 0)
    262 		data_file = stdin;
    263 	else {
    264 		data_file = fopen(infile, "r");
    265 		if (data_file == NULL)
    266 			err(1, "can't open `%s'", infile);
    267 	}
    268 
    269 	if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN)
    270 		errx(1, "file name `%s' too long", database);
    271 
    272 	snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX);
    273 
    274 	slash = strrchr(database, '/');
    275 	if (slash != NULL)
    276 		slash[1] = '\0';	/* truncate to dir */
    277 	else
    278 		*database = '\0';	/* eliminate */
    279 
    280 	/* NOTE: database is now directory where map goes ! */
    281 
    282 	if (strlen(database) + strlen(mapname) +
    283 	    strlen(YPDB_SUFFIX) > MAXPATHLEN)
    284 		errx(1, "directory name `%s' too long", database);
    285 
    286 	snprintf(db_tempname, sizeof(db_tempname), "%s%s",
    287 	    database, mapname);
    288 	mktemp(db_tempname);	/* OK */
    289 	snprintf(db_mapname, sizeof(db_mapname), "%s%s",
    290 	    db_tempname, YPDB_SUFFIX);
    291 
    292 	new_db = ypdb_open(db_tempname, O_RDWR | O_CREAT | O_EXCL, 0644);
    293 	if (new_db == NULL)
    294 		err(1, "can't create temp database `%s'", db_tempname);
    295 
    296 	for (;
    297 	    (p = fparseln(data_file, &len, &line_no, NULL, FPARSELN_UNESCALL));
    298 	    free(p)) {
    299 		k = p;				/* set start of key */
    300 		while (*k && isspace(*k))	/* skip leading whitespace */
    301 			k++;
    302 
    303 		if (! *k)
    304 			continue;
    305 
    306 		v = k;
    307 		while (*v && !isspace(*v)) {	/* find leading whitespace */
    308 				/* convert key to lower case if forcing. */
    309 			if (lflag && isupper(*v))
    310 				*v = tolower(*v);
    311 			v++;
    312 		}
    313 		while (*v && isspace(*v))	/* replace space with <NUL> */
    314 			*v++ = '\0';
    315 
    316 		if (add_record(new_db, k, v, TRUE)) {    /* save record */
    317 bad_record:
    318 			ypdb_close(new_db);
    319 			unlink(db_mapname);
    320 			errx(1, "error adding record for line %lu",
    321 			    (unsigned long)line_no);
    322 		}
    323 	}
    324 
    325 	if (strcmp(infile, "-") != 0)
    326 		(void) fclose(data_file);
    327 
    328 	if (add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE))
    329 		goto bad_record;
    330 
    331 	if (yp_input_file) {
    332 		if (add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE))
    333 			goto bad_record;
    334 	}
    335 
    336 	if (yp_output_file) {
    337 		if (add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE))
    338 			goto bad_record;
    339 	}
    340 
    341 	if (yp_master_name) {
    342 		if (add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE))
    343 			goto bad_record;
    344 	} else {
    345 		localhostname(myname, sizeof(myname) - 1);
    346 		if (add_record(new_db, YP_MASTER_KEY, myname, FALSE))
    347 			goto bad_record;
    348 	}
    349 
    350 	if (yp_domain_name) {
    351 		if (add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE))
    352 			goto bad_record;
    353 	}
    354 
    355 	if (bflag) {
    356 		if (add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE))
    357 			goto bad_record;
    358 	}
    359 
    360 	if (sflag) {
    361 		if (add_record(new_db, YP_SECURE_KEY, empty_str, FALSE))
    362 			goto bad_record;
    363 	}
    364 
    365 	ypdb_close(new_db);
    366 	if (rename(db_mapname, db_outfile) < 0) {
    367 		unlink(db_mapname);
    368 		err(1, "rename `%s' -> `%s'", db_mapname, db_outfile);
    369 	}
    370 }
    371 
    372 void
    373 usage()
    374 {
    375 
    376 	fprintf(stderr, "usage: %s -u file\n", __progname);
    377 	fprintf(stderr, "       %s [-lbs] %s\n", __progname,
    378 	    "[-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]");
    379 	fprintf(stderr, "          %s infile outfile\n",
    380 	    "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME]");
    381 	exit(1);
    382 }
    383