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.1 (Berkeley) 07/19/90 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.1 (Berkeley) 07/19/90"; 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 remove(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 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 (remove(maptpag) < 0 || remove(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