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