144926Smckusick /*
2*47533Spendry  * $Id: mk-amd-map.c,v 5.2.1.2 91/03/17 17:37:27 jsp Alpha $
344926Smckusick  *
444926Smckusick  * Copyright (c) 1990 Jan-Simon Pendry
544926Smckusick  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
644926Smckusick  * Copyright (c) 1990 The Regents of the University of California.
744926Smckusick  * All rights reserved.
844926Smckusick  *
944926Smckusick  * This code is derived from software contributed to Berkeley by
1044926Smckusick  * Jan-Simon Pendry at Imperial College, London.
1144926Smckusick  *
1244926Smckusick  * %sccs.include.redist.c%
1344926Smckusick  *
14*47533Spendry  *	@(#)mk-amd-map.c	5.3 (Berkeley) 03/17/91
1544926Smckusick  */
1644926Smckusick 
1744926Smckusick /*
1844926Smckusick  * Convert a file map into an ndbm map
1944926Smckusick  */
2044926Smckusick 
2144926Smckusick #ifndef lint
2244926Smckusick char copyright[] = "\
2344926Smckusick @(#)Copyright (c) 1990 Jan-Simon Pendry\n\
2444926Smckusick @(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
2544926Smckusick @(#)Copyright (c) 1990 The Regents of the University of California.\n\
2644926Smckusick @(#)All rights reserved.\n";
2744926Smckusick #endif /* not lint */
2844926Smckusick 
2944926Smckusick #ifndef lint
30*47533Spendry static char rcsid[] = "$Id: mk-amd-map.c,v 5.2.1.2 91/03/17 17:37:27 jsp Alpha $";
31*47533Spendry static char sccsid[] = "@(#)mk-amd-map.c	5.3 (Berkeley) 03/17/91";
3244926Smckusick #endif /* not lint */
3344926Smckusick 
3444926Smckusick #include "am.h"
3544926Smckusick 
36*47533Spendry #ifndef SIGINT
37*47533Spendry #include <signal.h>
38*47533Spendry #endif
3944926Smckusick 
4044926Smckusick #ifdef OS_HAS_NDBM
4144926Smckusick #define HAS_DATABASE
4244926Smckusick #include <ndbm.h>
4344926Smckusick 
4444926Smckusick #define create_database(name) dbm_open(name, O_RDWR|O_CREAT, 0444)
4544926Smckusick 
4644926Smckusick static int store_data(db, k, v)
4744926Smckusick voidp db;
4844926Smckusick char *k, *v;
4944926Smckusick {
5044926Smckusick 	datum key, val;
5144926Smckusick 
5244926Smckusick 	key.dptr = k; val.dptr = v;
5344926Smckusick 	key.dsize = strlen(k) + 1;
5444926Smckusick 	val.dsize = strlen(v) + 1;
5544926Smckusick 	return dbm_store((DBM *) db, key, val, DBM_INSERT);
5644926Smckusick }
5744926Smckusick 
5844926Smckusick #endif /* OS_HAS_NDBM */
5944926Smckusick 
6044926Smckusick #ifdef HAS_DATABASE
6144926Smckusick #include <fcntl.h>
6244926Smckusick #include <ctype.h>
6344926Smckusick 
6444926Smckusick static int read_line(buf, size, fp)
6544926Smckusick char *buf;
6644926Smckusick int size;
6744926Smckusick FILE *fp;
6844926Smckusick {
6944926Smckusick 	int done = 0;
7044926Smckusick 
7144926Smckusick 	do {
7244926Smckusick 		while (fgets(buf, size, fp)) {
7344926Smckusick 			int len = strlen(buf);
7444926Smckusick 			done += len;
7544926Smckusick 			if (len > 1 && buf[len-2] == '\\' &&
7644926Smckusick 					buf[len-1] == '\n') {
7744926Smckusick 				int ch;
7844926Smckusick 				buf += len - 2;
7944926Smckusick 				size -= len - 2;
8044926Smckusick 				/*
8144926Smckusick 				 * Skip leading white space on next line
8244926Smckusick 				 */
8344926Smckusick 				while ((ch = getc(fp)) != EOF &&
8444926Smckusick 					isascii(ch) && isspace(ch))
8544926Smckusick 						;
8644926Smckusick 				(void) ungetc(ch, fp);
8744926Smckusick 			} else {
8844926Smckusick 				return done;
8944926Smckusick 			}
9044926Smckusick 		}
9144926Smckusick 	} while (size > 0 && !feof(fp));
9244926Smckusick 
9344926Smckusick 	return done;
9444926Smckusick }
9544926Smckusick 
9644926Smckusick /*
9744926Smckusick  * Read through a map
9844926Smckusick  */
9944926Smckusick static int read_file(fp, map, db)
10044926Smckusick FILE *fp;
10144926Smckusick char *map;
10244926Smckusick voidp db;
10344926Smckusick {
10444926Smckusick 	char key_val[2048];
10544926Smckusick 	int chuck = 0;
10644926Smckusick 	int line_no = 0;
10744926Smckusick 	int errs = 0;
10844926Smckusick 
10944926Smckusick 	while (read_line(key_val, sizeof(key_val), fp)) {
11044926Smckusick 		char *kp;
11144926Smckusick 		char *cp;
11244926Smckusick 		char *hash;
11344926Smckusick 		int len = strlen(key_val);
11444926Smckusick 		line_no++;
11544926Smckusick 
11644926Smckusick 		/*
11744926Smckusick 		 * Make sure we got the whole line
11844926Smckusick 		 */
11944926Smckusick 		if (key_val[len-1] != '\n') {
12044926Smckusick 			fprintf(stderr, "line %d in \"%s\" is too long", line_no, map);
12144926Smckusick 			chuck = 1;
12244926Smckusick 		} else {
12344926Smckusick 			key_val[len-1] = '\0';
12444926Smckusick 		}
12544926Smckusick 
12644926Smckusick 		/*
12744926Smckusick 		 * Strip comments
12844926Smckusick 		 */
12944926Smckusick 		hash = strchr(key_val, '#');
13044926Smckusick 		if (hash)
13144926Smckusick 			*hash = '\0';
13244926Smckusick 
13344926Smckusick 		/*
13444926Smckusick 		 * Find start of key
13544926Smckusick 		 */
13644926Smckusick 		for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
13744926Smckusick 			;
13844926Smckusick 
13944926Smckusick 		/*
14044926Smckusick 		 * Ignore blank lines
14144926Smckusick 		 */
14244926Smckusick 		if (!*kp)
14344926Smckusick 			goto again;
14444926Smckusick 
14544926Smckusick 		/*
14644926Smckusick 		 * Find end of key
14744926Smckusick 		 */
14844926Smckusick 		for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
14944926Smckusick 			;
15044926Smckusick 
15144926Smckusick 		/*
15244926Smckusick 		 * Check whether key matches, or whether
15344926Smckusick 		 * the entry is a wildcard entry.
15444926Smckusick 		 */
15544926Smckusick 		if (*cp)
15644926Smckusick 			*cp++ = '\0';
15744926Smckusick 		while (*cp && isascii(*cp) && isspace(*cp))
15844926Smckusick 			cp++;
15944926Smckusick 		if (*kp == '+') {
16044926Smckusick 			fprintf(stderr, "Can't interpolate %s\n", kp);
16144926Smckusick 			errs++;
16244926Smckusick 		} else if (*cp) {
163*47533Spendry 			if (db) {
164*47533Spendry 				if (store_data(db, kp, cp) < 0) {
165*47533Spendry 					fprintf(stderr, "Could store %s -> %s\n", kp, cp);
166*47533Spendry 					errs++;
167*47533Spendry 				}
168*47533Spendry 			} else {
169*47533Spendry 				printf("%s\t%s\n", kp, cp);
17044926Smckusick 			}
17144926Smckusick 		} else {
17244926Smckusick 			fprintf(stderr, "%s: line %d has no value field", map, line_no);
17344926Smckusick 			errs++;
17444926Smckusick 		}
17544926Smckusick 
17644926Smckusick again:
17744926Smckusick 		/*
17844926Smckusick 		 * If the last read didn't get a whole line then
17944926Smckusick 		 * throw away the remainder before continuing...
18044926Smckusick 		 */
18144926Smckusick 		if (chuck) {
18244926Smckusick 			while (fgets(key_val, sizeof(key_val), fp) &&
18344926Smckusick 				!strchr(key_val, '\n'))
18444926Smckusick 					;
18544926Smckusick 			chuck = 0;
18644926Smckusick 		}
18744926Smckusick 	}
18844926Smckusick 	return errs;
18944926Smckusick }
19044926Smckusick 
191*47533Spendry static int remove_file(f)
19244926Smckusick char *f;
19344926Smckusick {
19444926Smckusick 	if (unlink(f) < 0 && errno != ENOENT)
19544926Smckusick 		return -1;
19644926Smckusick 	return 0;
19744926Smckusick }
19844926Smckusick 
19944926Smckusick main(argc, argv)
20044926Smckusick int argc;
20144926Smckusick char *argv[];
20244926Smckusick {
20344926Smckusick 	FILE *mapf;
20444926Smckusick 	char *map;
20544926Smckusick 	int rc = 0;
20644926Smckusick 	DBM *mapd;
207*47533Spendry 	char *maptmp = "dbmXXXXXX";
20844926Smckusick 	char maptpag[16], maptdir[16];
20944926Smckusick 	char *mappag, *mapdir;
21044926Smckusick 	int len;
21144926Smckusick 	char *sl;
212*47533Spendry 	int printit = 0;
213*47533Spendry 	int usage = 0;
214*47533Spendry 	int ch;
215*47533Spendry 	extern int optind;
21644926Smckusick 
217*47533Spendry 	while ((ch = getopt(argc, argv, "p")) != EOF)
218*47533Spendry 	switch (ch) {
219*47533Spendry 	case 'p':
220*47533Spendry 		printit = 1;
221*47533Spendry 		break;
222*47533Spendry 	default:
223*47533Spendry 		usage++;
224*47533Spendry 		break;
225*47533Spendry 	}
226*47533Spendry 
227*47533Spendry 	if (usage || optind != (argc - 1)) {
228*47533Spendry 		fputs("Usage: mk-amd-map [-p] file-map\n", stderr);
22944926Smckusick 		exit(1);
23044926Smckusick 	}
23144926Smckusick 
232*47533Spendry 	map = argv[optind];
23344926Smckusick 	sl = strrchr(map, '/');
23444926Smckusick 	if (sl) {
23544926Smckusick 		*sl = '\0';
23644926Smckusick 		if (chdir(map) < 0) {
23744926Smckusick 			fputs("Can't chdir to ", stderr);
23844926Smckusick 			perror(map);
23944926Smckusick 			exit(1);
24044926Smckusick 		}
24144926Smckusick 		map = sl + 1;
24244926Smckusick 	}
243*47533Spendry 
244*47533Spendry 	if (!printit) {
245*47533Spendry 		len = strlen(map);
246*47533Spendry 		mappag = (char *) malloc(len + 5);
247*47533Spendry 		mapdir = (char *) malloc(len + 5);
248*47533Spendry 		if (!mappag || !mapdir) {
249*47533Spendry 			perror("mk-amd-map: malloc");
250*47533Spendry 			exit(1);
251*47533Spendry 		}
252*47533Spendry 		mktemp(maptmp);
253*47533Spendry 		sprintf(maptpag, "%s.pag", maptmp);
254*47533Spendry 		sprintf(maptdir, "%s.dir", maptmp);
255*47533Spendry 		if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) {
256*47533Spendry 			fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag);
257*47533Spendry 			perror(maptdir);
258*47533Spendry 			exit(1);
259*47533Spendry 		}
26044926Smckusick 	}
261*47533Spendry 
26244926Smckusick 	mapf =  fopen(map, "r");
263*47533Spendry 	if (mapf && !printit)
26444926Smckusick 		mapd = create_database(maptmp);
26544926Smckusick 	else
26644926Smckusick 		mapd = 0;
267*47533Spendry 
26844926Smckusick #ifndef DEBUG
26944926Smckusick 	signal(SIGINT, SIG_IGN);
270*47533Spendry #endif
271*47533Spendry 
272*47533Spendry 	if (mapd || printit) {
27344926Smckusick 		int error = read_file(mapf, map, mapd);
27444926Smckusick 		(void) fclose(mapf);
275*47533Spendry 		if (printit) {
276*47533Spendry 			if (error) {
277*47533Spendry 				fprintf(stderr, "Error creating ndbm map for %s\n", map);
278*47533Spendry 				rc = 1;
279*47533Spendry 			}
280*47533Spendry 		} else {
281*47533Spendry 			if (error) {
282*47533Spendry 				fprintf(stderr, "Error reading source file  %s\n", map);
283*47533Spendry 				rc = 1;
284*47533Spendry 			} else {
285*47533Spendry 				sprintf(mappag, "%s.pag", map);
286*47533Spendry 				sprintf(mapdir, "%s.dir", map);
287*47533Spendry 				if (rename(maptpag, mappag) < 0) {
288*47533Spendry 					fprintf(stderr, "Couldn't rename %s to ", maptpag);
289*47533Spendry 					perror(mappag);
290*47533Spendry 					/* Throw away the temporary map */
291*47533Spendry 					unlink(maptpag);
292*47533Spendry 					unlink(maptdir);
293*47533Spendry 					rc = 1;
294*47533Spendry 				} else if (rename(maptdir, mapdir) < 0) {
295*47533Spendry 					fprintf(stderr, "Couldn't rename %s to ", maptdir);
296*47533Spendry 					perror(mapdir);
297*47533Spendry 					/* Put the .pag file back */
298*47533Spendry 					rename(mappag, maptpag);
299*47533Spendry 					/* Throw away remaining part of original map */
300*47533Spendry 					unlink(mapdir);
301*47533Spendry 					fprintf(stderr,
302*47533Spendry 						"WARNING: existing map \"%s.{dir,pag}\" destroyed\n",
303*47533Spendry 						map);
304*47533Spendry 					rc = 1;
305*47533Spendry 				}
306*47533Spendry 			}
30744926Smckusick 		}
30844926Smckusick 	} else {
30944926Smckusick 		fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map);
31044926Smckusick 		perror("writing");
31144926Smckusick 		rc = 1;
31244926Smckusick 	}
31344926Smckusick 	exit(rc);
31444926Smckusick }
31544926Smckusick #else
31644926Smckusick main()
31744926Smckusick {
318*47533Spendry 	fputs("mk-amd-map: This system does not support hashed database files\n", stderr);
319*47533Spendry 	exit(1);
32044926Smckusick }
321*47533Spendry  * %sccs.include.redist.c%
32244926Smckusick #endif /* HAS_DATABASE */
323