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