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 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 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 */ 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 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 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 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