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