1*44926Smckusick /*
2*44926Smckusick  * $Id: mk-amd-map.c,v 5.2 90/06/23 22:20:10 jsp Rel $
3*44926Smckusick  *
4*44926Smckusick  * Copyright (c) 1990 Jan-Simon Pendry
5*44926Smckusick  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6*44926Smckusick  * Copyright (c) 1990 The Regents of the University of California.
7*44926Smckusick  * All rights reserved.
8*44926Smckusick  *
9*44926Smckusick  * This code is derived from software contributed to Berkeley by
10*44926Smckusick  * Jan-Simon Pendry at Imperial College, London.
11*44926Smckusick  *
12*44926Smckusick  * %sccs.include.redist.c%
13*44926Smckusick  *
14*44926Smckusick  *	@(#)mk-amd-map.c	5.1 (Berkeley) 07/19/90
15*44926Smckusick  */
16*44926Smckusick 
17*44926Smckusick /*
18*44926Smckusick  * Convert a file map into an ndbm map
19*44926Smckusick  */
20*44926Smckusick 
21*44926Smckusick #ifndef lint
22*44926Smckusick char copyright[] = "\
23*44926Smckusick @(#)Copyright (c) 1990 Jan-Simon Pendry\n\
24*44926Smckusick @(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
25*44926Smckusick @(#)Copyright (c) 1990 The Regents of the University of California.\n\
26*44926Smckusick @(#)All rights reserved.\n";
27*44926Smckusick #endif /* not lint */
28*44926Smckusick 
29*44926Smckusick #ifndef lint
30*44926Smckusick static char rcsid[] = "$Id: mk-amd-map.c,v 5.2 90/06/23 22:20:10 jsp Rel $";
31*44926Smckusick static char sccsid[] = "@(#)mk-amd-map.c	5.1 (Berkeley) 07/19/90";
32*44926Smckusick #endif /* not lint */
33*44926Smckusick 
34*44926Smckusick #include "am.h"
35*44926Smckusick 
36*44926Smckusick #ifdef OS_HAS_GDBM
37*44926Smckusick #define HAS_DATABASE
38*44926Smckusick #include "gdbm.h"
39*44926Smckusick #endif /* OS_HAS_GDBM */
40*44926Smckusick 
41*44926Smckusick #ifndef HAS_DATABASE
42*44926Smckusick #ifdef OS_HAS_NDBM
43*44926Smckusick #define HAS_DATABASE
44*44926Smckusick #define	USE_NDBM
45*44926Smckusick #include <ndbm.h>
46*44926Smckusick 
47*44926Smckusick #define create_database(name) dbm_open(name, O_RDWR|O_CREAT, 0444)
48*44926Smckusick 
49*44926Smckusick static int store_data(db, k, v)
50*44926Smckusick voidp db;
51*44926Smckusick char *k, *v;
52*44926Smckusick {
53*44926Smckusick 	datum key, val;
54*44926Smckusick 
55*44926Smckusick 	key.dptr = k; val.dptr = v;
56*44926Smckusick 	key.dsize = strlen(k) + 1;
57*44926Smckusick 	val.dsize = strlen(v) + 1;
58*44926Smckusick 	return dbm_store((DBM *) db, key, val, DBM_INSERT);
59*44926Smckusick }
60*44926Smckusick 
61*44926Smckusick #endif /* OS_HAS_NDBM */
62*44926Smckusick #endif /* !OS_HAS_DATABASE */
63*44926Smckusick 
64*44926Smckusick #ifdef HAS_DATABASE
65*44926Smckusick #include <fcntl.h>
66*44926Smckusick #include <ctype.h>
67*44926Smckusick 
68*44926Smckusick static int read_line(buf, size, fp)
69*44926Smckusick char *buf;
70*44926Smckusick int size;
71*44926Smckusick FILE *fp;
72*44926Smckusick {
73*44926Smckusick 	int done = 0;
74*44926Smckusick 
75*44926Smckusick 	do {
76*44926Smckusick 		while (fgets(buf, size, fp)) {
77*44926Smckusick 			int len = strlen(buf);
78*44926Smckusick 			done += len;
79*44926Smckusick 			if (len > 1 && buf[len-2] == '\\' &&
80*44926Smckusick 					buf[len-1] == '\n') {
81*44926Smckusick 				int ch;
82*44926Smckusick 				buf += len - 2;
83*44926Smckusick 				size -= len - 2;
84*44926Smckusick 				/*
85*44926Smckusick 				 * Skip leading white space on next line
86*44926Smckusick 				 */
87*44926Smckusick 				while ((ch = getc(fp)) != EOF &&
88*44926Smckusick 					isascii(ch) && isspace(ch))
89*44926Smckusick 						;
90*44926Smckusick 				(void) ungetc(ch, fp);
91*44926Smckusick 			} else {
92*44926Smckusick 				return done;
93*44926Smckusick 			}
94*44926Smckusick 		}
95*44926Smckusick 	} while (size > 0 && !feof(fp));
96*44926Smckusick 
97*44926Smckusick 	return done;
98*44926Smckusick }
99*44926Smckusick 
100*44926Smckusick /*
101*44926Smckusick  * Read through a map
102*44926Smckusick  */
103*44926Smckusick static int read_file(fp, map, db)
104*44926Smckusick FILE *fp;
105*44926Smckusick char *map;
106*44926Smckusick voidp db;
107*44926Smckusick {
108*44926Smckusick 	char key_val[2048];
109*44926Smckusick 	int chuck = 0;
110*44926Smckusick 	int line_no = 0;
111*44926Smckusick 	int errs = 0;
112*44926Smckusick 
113*44926Smckusick 	while (read_line(key_val, sizeof(key_val), fp)) {
114*44926Smckusick 		char *kp;
115*44926Smckusick 		char *cp;
116*44926Smckusick 		char *hash;
117*44926Smckusick 		int len = strlen(key_val);
118*44926Smckusick 		line_no++;
119*44926Smckusick 
120*44926Smckusick 		/*
121*44926Smckusick 		 * Make sure we got the whole line
122*44926Smckusick 		 */
123*44926Smckusick 		if (key_val[len-1] != '\n') {
124*44926Smckusick 			fprintf(stderr, "line %d in \"%s\" is too long", line_no, map);
125*44926Smckusick 			chuck = 1;
126*44926Smckusick 		} else {
127*44926Smckusick 			key_val[len-1] = '\0';
128*44926Smckusick 		}
129*44926Smckusick 
130*44926Smckusick 		/*
131*44926Smckusick 		 * Strip comments
132*44926Smckusick 		 */
133*44926Smckusick 		hash = strchr(key_val, '#');
134*44926Smckusick 		if (hash)
135*44926Smckusick 			*hash = '\0';
136*44926Smckusick 
137*44926Smckusick 		/*
138*44926Smckusick 		 * Find start of key
139*44926Smckusick 		 */
140*44926Smckusick 		for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
141*44926Smckusick 			;
142*44926Smckusick 
143*44926Smckusick 		/*
144*44926Smckusick 		 * Ignore blank lines
145*44926Smckusick 		 */
146*44926Smckusick 		if (!*kp)
147*44926Smckusick 			goto again;
148*44926Smckusick 
149*44926Smckusick 		/*
150*44926Smckusick 		 * Find end of key
151*44926Smckusick 		 */
152*44926Smckusick 		for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
153*44926Smckusick 			;
154*44926Smckusick 
155*44926Smckusick 		/*
156*44926Smckusick 		 * Check whether key matches, or whether
157*44926Smckusick 		 * the entry is a wildcard entry.
158*44926Smckusick 		 */
159*44926Smckusick 		if (*cp)
160*44926Smckusick 			*cp++ = '\0';
161*44926Smckusick 		while (*cp && isascii(*cp) && isspace(*cp))
162*44926Smckusick 			cp++;
163*44926Smckusick 		if (*kp == '+') {
164*44926Smckusick 			fprintf(stderr, "Can't interpolate %s\n", kp);
165*44926Smckusick 			errs++;
166*44926Smckusick 		} else if (*cp) {
167*44926Smckusick #ifdef DEBUG
168*44926Smckusick 			printf("%s\t%s\n", kp, cp);
169*44926Smckusick #endif /* DEBUG */
170*44926Smckusick 			if (store_data(db, kp, cp) < 0) {
171*44926Smckusick 				fprintf(stderr, "Could store %s -> %s\n", kp, cp);
172*44926Smckusick 				errs++;
173*44926Smckusick 			}
174*44926Smckusick 		} else {
175*44926Smckusick 			fprintf(stderr, "%s: line %d has no value field", map, line_no);
176*44926Smckusick 			errs++;
177*44926Smckusick 		}
178*44926Smckusick 
179*44926Smckusick again:
180*44926Smckusick 		/*
181*44926Smckusick 		 * If the last read didn't get a whole line then
182*44926Smckusick 		 * throw away the remainder before continuing...
183*44926Smckusick 		 */
184*44926Smckusick 		if (chuck) {
185*44926Smckusick 			while (fgets(key_val, sizeof(key_val), fp) &&
186*44926Smckusick 				!strchr(key_val, '\n'))
187*44926Smckusick 					;
188*44926Smckusick 			chuck = 0;
189*44926Smckusick 		}
190*44926Smckusick 	}
191*44926Smckusick 	return errs;
192*44926Smckusick }
193*44926Smckusick 
194*44926Smckusick static int remove(f)
195*44926Smckusick char *f;
196*44926Smckusick {
197*44926Smckusick 	if (unlink(f) < 0 && errno != ENOENT)
198*44926Smckusick 		return -1;
199*44926Smckusick 	return 0;
200*44926Smckusick }
201*44926Smckusick 
202*44926Smckusick main(argc, argv)
203*44926Smckusick int argc;
204*44926Smckusick char *argv[];
205*44926Smckusick {
206*44926Smckusick 	FILE *mapf;
207*44926Smckusick 	char *map;
208*44926Smckusick 	int rc = 0;
209*44926Smckusick 	DBM *mapd;
210*44926Smckusick 	char *maptmp = "dbmXXXXXX";
211*44926Smckusick 	char maptpag[16], maptdir[16];
212*44926Smckusick 	char *mappag, *mapdir;
213*44926Smckusick 	int len;
214*44926Smckusick 	char *sl;
215*44926Smckusick 
216*44926Smckusick 	if (argc != 2) {
217*44926Smckusick 		fputs("Usage: mk-amd-map file-map\n", stderr);
218*44926Smckusick 		exit(1);
219*44926Smckusick 	}
220*44926Smckusick 
221*44926Smckusick 	map = argv[1];
222*44926Smckusick 	sl = strrchr(map, '/');
223*44926Smckusick 	if (sl) {
224*44926Smckusick 		*sl = '\0';
225*44926Smckusick 		if (chdir(map) < 0) {
226*44926Smckusick 			fputs("Can't chdir to ", stderr);
227*44926Smckusick 			perror(map);
228*44926Smckusick 			exit(1);
229*44926Smckusick 		}
230*44926Smckusick 		map = sl + 1;
231*44926Smckusick 	}
232*44926Smckusick #ifdef USE_NDBM
233*44926Smckusick 	len = strlen(map);
234*44926Smckusick 	mappag = (char *) malloc(len + 5);
235*44926Smckusick 	mapdir = (char *) malloc(len + 5);
236*44926Smckusick 	if (!mappag || !mapdir) {
237*44926Smckusick 		perror("malloc");
238*44926Smckusick 		exit(1);
239*44926Smckusick 	}
240*44926Smckusick 	mktemp(maptmp);
241*44926Smckusick 	sprintf(maptpag, "%s.pag", maptmp);
242*44926Smckusick 	sprintf(maptdir, "%s.dir", maptmp);
243*44926Smckusick 	if (remove(maptpag) < 0 || remove(maptdir) < 0) {
244*44926Smckusick 		fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag);
245*44926Smckusick 		perror(maptdir);
246*44926Smckusick 		exit(1);
247*44926Smckusick 	}
248*44926Smckusick #endif /* USE_NDBM */
249*44926Smckusick 	mapf =  fopen(map, "r");
250*44926Smckusick 	if (mapf)
251*44926Smckusick 		mapd = create_database(maptmp);
252*44926Smckusick 	else
253*44926Smckusick 		mapd = 0;
254*44926Smckusick #ifndef DEBUG
255*44926Smckusick 	signal(SIGINT, SIG_IGN);
256*44926Smckusick #endif /* DEBUG */
257*44926Smckusick 	if (mapd) {
258*44926Smckusick 		int error = read_file(mapf, map, mapd);
259*44926Smckusick 		(void) fclose(mapf);
260*44926Smckusick 		if (error) {
261*44926Smckusick 			fprintf(stderr, "Error creating ndbm map for %s\n", map);
262*44926Smckusick 			rc = 1;
263*44926Smckusick 		}
264*44926Smckusick #ifdef USE_NDBM
265*44926Smckusick 		sprintf(mappag, "%s.pag", map);
266*44926Smckusick 		sprintf(mapdir, "%s.dir", map);
267*44926Smckusick 		if (rename(maptpag, mappag) < 0) {
268*44926Smckusick 			fprintf(stderr, "Couldn't rename %s to ", maptpag);
269*44926Smckusick 			perror(mappag);
270*44926Smckusick 			/* Throw away the temporary map */
271*44926Smckusick 			unlink(maptpag);
272*44926Smckusick 			unlink(maptdir);
273*44926Smckusick 			rc = 1;
274*44926Smckusick 		} else if (rename(maptdir, mapdir) < 0) {
275*44926Smckusick 			fprintf(stderr, "Couldn't rename %s to ", maptdir);
276*44926Smckusick 			perror(mapdir);
277*44926Smckusick 			/* Put the .pag file back */
278*44926Smckusick 			rename(mappag, maptpag);
279*44926Smckusick 			/* Throw away remaining part of original map */
280*44926Smckusick 			unlink(mapdir);
281*44926Smckusick 			fprintf(stderr, "WARNING: existing map \"%s.{dir,pag}\" destroyed\n", map);
282*44926Smckusick 			rc = 1;
283*44926Smckusick 		}
284*44926Smckusick #endif /* USE_NDBM */
285*44926Smckusick 	} else {
286*44926Smckusick #ifdef USE_NDBM
287*44926Smckusick 		fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map);
288*44926Smckusick #endif /* USE_NDBM */
289*44926Smckusick 		perror("writing");
290*44926Smckusick 		rc = 1;
291*44926Smckusick 	}
292*44926Smckusick 	exit(rc);
293*44926Smckusick }
294*44926Smckusick #else
295*44926Smckusick main()
296*44926Smckusick {
297*44926Smckusick 	fputs("This system does not support hashed database files\n", stderr);
298*44926Smckusick 	exit(0);
299*44926Smckusick }
300*44926Smckusick #endif /* HAS_DATABASE */
301