144926Smckusick /*
263601Sbostic  * Copyright (c) 1990, 1993 Jan-Simon Pendry
344926Smckusick  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
463601Sbostic  * Copyright (c) 1990, 1993
563601Sbostic  *	The Regents of the University of California.  All rights reserved.
644926Smckusick  *
744926Smckusick  * This code is derived from software contributed to Berkeley by
844926Smckusick  * Jan-Simon Pendry at Imperial College, London.
944926Smckusick  *
1044926Smckusick  * %sccs.include.redist.c%
1144926Smckusick  *
12*63613Sbostic  *	@(#)mk-amd-map.c	8.1 (Berkeley) 06/28/93
1349687Spendry  *
1452458Spendry  * $Id: mk-amd-map.c,v 5.2.2.1 1992/02/09 15:09:18 jsp beta $
1544926Smckusick  */
1644926Smckusick 
1744926Smckusick /*
1844926Smckusick  * Convert a file map into an ndbm map
1944926Smckusick  */
2044926Smckusick 
2144926Smckusick #ifndef lint
2244926Smckusick char copyright[] = "\
2363601Sbostic @(#)Copyright (c) 1990, 1993 Jan-Simon Pendry\n\
2444926Smckusick @(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
2563601Sbostic @(#)Copyright (c) 1990, 1993\n\
2663601Sbostic 	The Regents of the University of California.  All rights reserved.\n";
2744926Smckusick #endif /* not lint */
2844926Smckusick 
2944926Smckusick #ifndef lint
3052458Spendry static char rcsid[] = "$Id: mk-amd-map.c,v 5.2.2.1 1992/02/09 15:09:18 jsp beta $";
31*63613Sbostic static char sccsid[] = "@(#)mk-amd-map.c	8.1 (Berkeley) 06/28/93";
3244926Smckusick #endif /* not lint */
3344926Smckusick 
3444926Smckusick #include "am.h"
3544926Smckusick 
3647533Spendry #ifndef SIGINT
3747533Spendry #include <signal.h>
3847533Spendry #endif
3944926Smckusick 
4044926Smckusick #ifdef OS_HAS_NDBM
4144926Smckusick #define HAS_DATABASE
4244926Smckusick #include <ndbm.h>
4344926Smckusick 
4463601Sbostic #ifdef DBM_SUFFIX
4563601Sbostic #define USING_DB
4663601Sbostic #endif
4744926Smckusick 
4863601Sbostic #define create_database(name) dbm_open(name, O_RDWR|O_CREAT, 0644)
4963601Sbostic 
store_data(db,k,v)5044926Smckusick static int store_data(db, k, v)
5144926Smckusick voidp db;
5244926Smckusick char *k, *v;
5344926Smckusick {
5444926Smckusick 	datum key, val;
5544926Smckusick 
5644926Smckusick 	key.dptr = k; val.dptr = v;
5744926Smckusick 	key.dsize = strlen(k) + 1;
5844926Smckusick 	val.dsize = strlen(v) + 1;
5944926Smckusick 	return dbm_store((DBM *) db, key, val, DBM_INSERT);
6044926Smckusick }
6144926Smckusick 
6244926Smckusick #endif /* OS_HAS_NDBM */
6344926Smckusick 
6444926Smckusick #ifdef HAS_DATABASE
6544926Smckusick #include <fcntl.h>
6644926Smckusick #include <ctype.h>
6744926Smckusick 
read_line(buf,size,fp)6844926Smckusick static int read_line(buf, size, fp)
6944926Smckusick char *buf;
7044926Smckusick int size;
7144926Smckusick FILE *fp;
7244926Smckusick {
7344926Smckusick 	int done = 0;
7444926Smckusick 
7544926Smckusick 	do {
7644926Smckusick 		while (fgets(buf, size, fp)) {
7744926Smckusick 			int len = strlen(buf);
7844926Smckusick 			done += len;
7944926Smckusick 			if (len > 1 && buf[len-2] == '\\' &&
8044926Smckusick 					buf[len-1] == '\n') {
8144926Smckusick 				int ch;
8244926Smckusick 				buf += len - 2;
8344926Smckusick 				size -= len - 2;
8449687Spendry 				*buf = '\n'; buf[1] = '\0';
8544926Smckusick 				/*
8644926Smckusick 				 * Skip leading white space on next line
8744926Smckusick 				 */
8844926Smckusick 				while ((ch = getc(fp)) != EOF &&
8944926Smckusick 					isascii(ch) && isspace(ch))
9044926Smckusick 						;
9144926Smckusick 				(void) ungetc(ch, fp);
9244926Smckusick 			} else {
9344926Smckusick 				return done;
9444926Smckusick 			}
9544926Smckusick 		}
9644926Smckusick 	} while (size > 0 && !feof(fp));
9744926Smckusick 
9844926Smckusick 	return done;
9944926Smckusick }
10044926Smckusick 
10144926Smckusick /*
10244926Smckusick  * Read through a map
10344926Smckusick  */
read_file(fp,map,db)10444926Smckusick static int read_file(fp, map, db)
10544926Smckusick FILE *fp;
10644926Smckusick char *map;
10744926Smckusick voidp db;
10844926Smckusick {
10944926Smckusick 	char key_val[2048];
11044926Smckusick 	int chuck = 0;
11144926Smckusick 	int line_no = 0;
11244926Smckusick 	int errs = 0;
11344926Smckusick 
11444926Smckusick 	while (read_line(key_val, sizeof(key_val), fp)) {
11544926Smckusick 		char *kp;
11644926Smckusick 		char *cp;
11744926Smckusick 		char *hash;
11844926Smckusick 		int len = strlen(key_val);
11944926Smckusick 		line_no++;
12044926Smckusick 
12144926Smckusick 		/*
12244926Smckusick 		 * Make sure we got the whole line
12344926Smckusick 		 */
12444926Smckusick 		if (key_val[len-1] != '\n') {
12544926Smckusick 			fprintf(stderr, "line %d in \"%s\" is too long", line_no, map);
12644926Smckusick 			chuck = 1;
12744926Smckusick 		} else {
12844926Smckusick 			key_val[len-1] = '\0';
12944926Smckusick 		}
13044926Smckusick 
13144926Smckusick 		/*
13244926Smckusick 		 * Strip comments
13344926Smckusick 		 */
13444926Smckusick 		hash = strchr(key_val, '#');
13544926Smckusick 		if (hash)
13644926Smckusick 			*hash = '\0';
13744926Smckusick 
13844926Smckusick 		/*
13944926Smckusick 		 * Find start of key
14044926Smckusick 		 */
14144926Smckusick 		for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
14244926Smckusick 			;
14344926Smckusick 
14444926Smckusick 		/*
14544926Smckusick 		 * Ignore blank lines
14644926Smckusick 		 */
14744926Smckusick 		if (!*kp)
14844926Smckusick 			goto again;
14944926Smckusick 
15044926Smckusick 		/*
15144926Smckusick 		 * Find end of key
15244926Smckusick 		 */
15344926Smckusick 		for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
15444926Smckusick 			;
15544926Smckusick 
15644926Smckusick 		/*
15744926Smckusick 		 * Check whether key matches, or whether
15844926Smckusick 		 * the entry is a wildcard entry.
15944926Smckusick 		 */
16044926Smckusick 		if (*cp)
16144926Smckusick 			*cp++ = '\0';
16244926Smckusick 		while (*cp && isascii(*cp) && isspace(*cp))
16344926Smckusick 			cp++;
16444926Smckusick 		if (*kp == '+') {
16544926Smckusick 			fprintf(stderr, "Can't interpolate %s\n", kp);
16644926Smckusick 			errs++;
16744926Smckusick 		} else if (*cp) {
16847533Spendry 			if (db) {
16947533Spendry 				if (store_data(db, kp, cp) < 0) {
17047533Spendry 					fprintf(stderr, "Could store %s -> %s\n", kp, cp);
17147533Spendry 					errs++;
17247533Spendry 				}
17347533Spendry 			} else {
17447533Spendry 				printf("%s\t%s\n", kp, cp);
17544926Smckusick 			}
17644926Smckusick 		} else {
17744926Smckusick 			fprintf(stderr, "%s: line %d has no value field", map, line_no);
17844926Smckusick 			errs++;
17944926Smckusick 		}
18044926Smckusick 
18144926Smckusick again:
18244926Smckusick 		/*
18344926Smckusick 		 * If the last read didn't get a whole line then
18444926Smckusick 		 * throw away the remainder before continuing...
18544926Smckusick 		 */
18644926Smckusick 		if (chuck) {
18744926Smckusick 			while (fgets(key_val, sizeof(key_val), fp) &&
18844926Smckusick 				!strchr(key_val, '\n'))
18944926Smckusick 					;
19044926Smckusick 			chuck = 0;
19144926Smckusick 		}
19244926Smckusick 	}
19344926Smckusick 	return errs;
19444926Smckusick }
19544926Smckusick 
remove_file(f)19647533Spendry static int remove_file(f)
19744926Smckusick char *f;
19844926Smckusick {
19944926Smckusick 	if (unlink(f) < 0 && errno != ENOENT)
20044926Smckusick 		return -1;
20144926Smckusick 	return 0;
20244926Smckusick }
20344926Smckusick 
main(argc,argv)20444926Smckusick main(argc, argv)
20544926Smckusick int argc;
20644926Smckusick char *argv[];
20744926Smckusick {
20844926Smckusick 	FILE *mapf;
20944926Smckusick 	char *map;
21044926Smckusick 	int rc = 0;
21144926Smckusick 	DBM *mapd;
21249687Spendry 	static char maptmp[] = "dbmXXXXXX";
21363601Sbostic 	char maptpag[16];
21463601Sbostic 	char *mappag;
21563601Sbostic #ifndef USING_DB
21663601Sbostic 	char maptdir[16];
21763601Sbostic 	char *mapdir;
21863601Sbostic #endif
21944926Smckusick 	int len;
22044926Smckusick 	char *sl;
22147533Spendry 	int printit = 0;
22247533Spendry 	int usage = 0;
22347533Spendry 	int ch;
22447533Spendry 	extern int optind;
22544926Smckusick 
22647533Spendry 	while ((ch = getopt(argc, argv, "p")) != EOF)
22747533Spendry 	switch (ch) {
22847533Spendry 	case 'p':
22947533Spendry 		printit = 1;
23047533Spendry 		break;
23147533Spendry 	default:
23247533Spendry 		usage++;
23347533Spendry 		break;
23447533Spendry 	}
23547533Spendry 
23647533Spendry 	if (usage || optind != (argc - 1)) {
23747533Spendry 		fputs("Usage: mk-amd-map [-p] file-map\n", stderr);
23844926Smckusick 		exit(1);
23944926Smckusick 	}
24044926Smckusick 
24147533Spendry 	map = argv[optind];
24244926Smckusick 	sl = strrchr(map, '/');
24344926Smckusick 	if (sl) {
24444926Smckusick 		*sl = '\0';
24544926Smckusick 		if (chdir(map) < 0) {
24644926Smckusick 			fputs("Can't chdir to ", stderr);
24744926Smckusick 			perror(map);
24844926Smckusick 			exit(1);
24944926Smckusick 		}
25044926Smckusick 		map = sl + 1;
25144926Smckusick 	}
25247533Spendry 
25347533Spendry 	if (!printit) {
25447533Spendry 		len = strlen(map);
25563601Sbostic #ifdef USING_DB
25647533Spendry 		mappag = (char *) malloc(len + 5);
25763601Sbostic 		if (!mappag) {
25863601Sbostic 			perror("mk-amd-map: malloc");
25963601Sbostic 			exit(1);
26063601Sbostic 		}
26163601Sbostic 		mktemp(maptmp);
26263601Sbostic 		sprintf(maptpag, "%s%s", maptmp, DBM_SUFFIX);
26363601Sbostic 		if (remove_file(maptpag) < 0) {
26463601Sbostic 			fprintf(stderr, "Can't remove existing temporary file");
26563601Sbostic 			perror(maptpag);
26663601Sbostic 			exit(1);
26763601Sbostic 		}
26863601Sbostic #else
26963601Sbostic 		mappag = (char *) malloc(len + 5);
27047533Spendry 		mapdir = (char *) malloc(len + 5);
27147533Spendry 		if (!mappag || !mapdir) {
27247533Spendry 			perror("mk-amd-map: malloc");
27347533Spendry 			exit(1);
27447533Spendry 		}
27547533Spendry 		mktemp(maptmp);
27647533Spendry 		sprintf(maptpag, "%s.pag", maptmp);
27747533Spendry 		sprintf(maptdir, "%s.dir", maptmp);
27847533Spendry 		if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) {
27947533Spendry 			fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag);
28047533Spendry 			perror(maptdir);
28147533Spendry 			exit(1);
28247533Spendry 		}
28363601Sbostic #endif
28444926Smckusick 	}
28547533Spendry 
28644926Smckusick 	mapf =  fopen(map, "r");
28747533Spendry 	if (mapf && !printit)
28844926Smckusick 		mapd = create_database(maptmp);
28944926Smckusick 	else
29044926Smckusick 		mapd = 0;
29147533Spendry 
29244926Smckusick #ifndef DEBUG
29344926Smckusick 	signal(SIGINT, SIG_IGN);
29447533Spendry #endif
29547533Spendry 
29647533Spendry 	if (mapd || printit) {
29744926Smckusick 		int error = read_file(mapf, map, mapd);
29863612Sbostic 		if (mapd)
29963612Sbostic 			dbm_close(mapd);
30044926Smckusick 		(void) fclose(mapf);
30147533Spendry 		if (printit) {
30247533Spendry 			if (error) {
30347533Spendry 				fprintf(stderr, "Error creating ndbm map for %s\n", map);
30447533Spendry 				rc = 1;
30547533Spendry 			}
30647533Spendry 		} else {
30747533Spendry 			if (error) {
30847533Spendry 				fprintf(stderr, "Error reading source file  %s\n", map);
30947533Spendry 				rc = 1;
31047533Spendry 			} else {
31163601Sbostic #ifdef USING_DB
31263601Sbostic 				sprintf(mappag, "%s%s", map, DBM_SUFFIX);
31363601Sbostic 				if (rename(maptpag, mappag) < 0) {
31463601Sbostic 					fprintf(stderr, "Couldn't rename %s to ", maptpag);
31563601Sbostic 					perror(mappag);
31663601Sbostic 					/* Throw away the temporary map */
31763601Sbostic 					unlink(maptpag);
31863601Sbostic 					rc = 1;
31963601Sbostic 				}
32063601Sbostic #else
32147533Spendry 				sprintf(mappag, "%s.pag", map);
32247533Spendry 				sprintf(mapdir, "%s.dir", map);
32347533Spendry 				if (rename(maptpag, mappag) < 0) {
32447533Spendry 					fprintf(stderr, "Couldn't rename %s to ", maptpag);
32547533Spendry 					perror(mappag);
32647533Spendry 					/* Throw away the temporary map */
32747533Spendry 					unlink(maptpag);
32847533Spendry 					unlink(maptdir);
32947533Spendry 					rc = 1;
33047533Spendry 				} else if (rename(maptdir, mapdir) < 0) {
33147533Spendry 					fprintf(stderr, "Couldn't rename %s to ", maptdir);
33247533Spendry 					perror(mapdir);
33347533Spendry 					/* Put the .pag file back */
33447533Spendry 					rename(mappag, maptpag);
33547533Spendry 					/* Throw away remaining part of original map */
33647533Spendry 					unlink(mapdir);
33747533Spendry 					fprintf(stderr,
33847533Spendry 						"WARNING: existing map \"%s.{dir,pag}\" destroyed\n",
33947533Spendry 						map);
34047533Spendry 					rc = 1;
34147533Spendry 				}
34263601Sbostic #endif
34347533Spendry 			}
34444926Smckusick 		}
34544926Smckusick 	} else {
34644926Smckusick 		fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map);
34744926Smckusick 		perror("writing");
34844926Smckusick 		rc = 1;
34944926Smckusick 	}
35044926Smckusick 	exit(rc);
35144926Smckusick }
35244926Smckusick #else
main()35344926Smckusick main()
35444926Smckusick {
35547533Spendry 	fputs("mk-amd-map: This system does not support hashed database files\n", stderr);
35647533Spendry 	exit(1);
35744926Smckusick }
35844926Smckusick #endif /* HAS_DATABASE */
359