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