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