mk-amd-map.c revision 38500
1/* 2 * Copyright (c) 1997-1998 Erez Zadok 3 * Copyright (c) 1990 Jan-Simon Pendry 4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry at Imperial College, London. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * %W% (Berkeley) %G% 40 * 41 * $Id: mk-amd-map.c,v 1.1.1.1 1998/08/23 22:07:21 obrien Exp $ 42 */ 43 44/* 45 * Convert a file map into an ndbm map 46 */ 47 48#ifdef HAVE_CONFIG_H 49# include <config.h> 50#endif /* HAVE_CONFIG_H */ 51#include <am_defs.h> 52 53/* dummy variables */ 54char *progname; 55char hostname[MAXHOSTNAMELEN]; 56int orig_umask, foreground, debug_flags; 57pid_t mypid; 58serv_state amd_state; 59 60 61#ifdef HAVE_MAP_NDBM 62 63static int 64store_data(voidp db, char *k, char *v) 65{ 66 datum key, val; 67 68 key.dptr = k; 69 val.dptr = v; 70 key.dsize = strlen(k) + 1; 71 val.dsize = strlen(v) + 1; 72 return dbm_store((DBM *) db, key, val, DBM_INSERT); 73} 74 75 76/* 77 * Read one line from file. 78 */ 79static int 80read_line(char *buf, int size, FILE *fp) 81{ 82 int done = 0; 83 84 do { 85 while (fgets(buf, size, fp)) { 86 int len = strlen(buf); 87 88 done += len; 89 if (len > 1 && buf[len - 2] == '\\' && buf[len - 1] == '\n') { 90 int ch; 91 buf += len - 2; 92 size -= len - 2; 93 *buf = '\n'; 94 buf[1] = '\0'; 95 96 /* 97 * Skip leading white space on next line 98 */ 99 while ((ch = getc(fp)) != EOF && isascii(ch) && isspace(ch)) ; 100 (void) ungetc(ch, fp); 101 } else { 102 return done; 103 } 104 } 105 } while (size > 0 && !feof(fp)); 106 107 return done; 108} 109 110 111/* 112 * Read through a map. 113 */ 114static int 115read_file(FILE *fp, char *map, voidp db) 116{ 117 char key_val[2048]; 118 int chuck = 0; 119 int line_no = 0; 120 int errs = 0; 121 122 while (read_line(key_val, sizeof(key_val), fp)) { 123 char *kp; 124 char *cp; 125 char *hash; 126 int len = strlen(key_val); 127 128 line_no++; 129 130 /* 131 * Make sure we got the whole line 132 */ 133 if (key_val[len - 1] != '\n') { 134 fprintf(stderr, "line %d in \"%s\" is too long", line_no, map); 135 chuck = 1; 136 } else { 137 key_val[len - 1] = '\0'; 138 } 139 140 /* 141 * Strip comments 142 */ 143 hash = strchr(key_val, '#'); 144 if (hash) 145 *hash = '\0'; 146 147 /* 148 * Find start of key 149 */ 150 for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; 151 152 /* 153 * Ignore blank lines 154 */ 155 if (!*kp) 156 goto again; 157 158 /* 159 * Find end of key 160 */ 161 for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; 162 163 /* 164 * Check whether key matches, or whether 165 * the entry is a wildcard entry. 166 */ 167 if (*cp) 168 *cp++ = '\0'; 169 while (*cp && isascii(*cp) && isspace((int)*cp)) 170 cp++; 171 if (*kp == '+') { 172 fprintf(stderr, "Can't interpolate %s\n", kp); 173 errs++; 174 } else if (*cp) { 175 if (db) { 176 if (store_data(db, kp, cp) < 0) { 177 fprintf(stderr, "Could store %s -> %s\n", kp, cp); 178 errs++; 179 } 180 } else { 181 printf("%s\t%s\n", kp, cp); 182 } 183 } else { 184 fprintf(stderr, "%s: line %d has no value field", map, line_no); 185 errs++; 186 } 187 188 again: 189 /* 190 * If the last read didn't get a whole line then 191 * throw away the remainder before continuing... 192 */ 193 if (chuck) { 194 while (fgets(key_val, sizeof(key_val), fp) && 195 !strchr(key_val, '\n')) ; 196 chuck = 0; 197 } 198 } 199 return errs; 200} 201 202 203static int 204remove_file(char *f) 205{ 206 if (unlink(f) < 0 && errno != ENOENT) 207 return -1; 208 209 return 0; 210} 211 212 213int 214main(int argc, char *argv[]) 215{ 216 FILE *mapf; 217 int mapfd = -1; 218 char *map; 219 int rc = 0; 220 DBM *mapd = NULL; 221 static char maptmp[] = "dbmXXXXXX"; 222 char maptpag[16], maptdir[16]; 223 char *mappag = (char *) NULL, *mapdir = (char *) NULL; 224 int len; 225 char *sl; 226 int printit = 0; 227 int usage = 0; 228 int ch; 229 extern int optind; 230 231 /* test options */ 232 while ((ch = getopt(argc, argv, "p")) != -1) 233 switch (ch) { 234 case 'p': 235 printit = 1; 236 break; 237 default: 238 usage++; 239 break; 240 } 241 242 if (usage || optind != (argc - 1)) { 243 fputs("Usage: mk-amd-map [-p] file-map\n", stderr); 244 exit(1); 245 } 246 map = argv[optind]; 247 248 /* test if can get to the map directory */ 249 sl = strrchr(map, '/'); 250 if (sl) { 251 *sl = '\0'; 252 if (chdir(map) < 0) { 253 fputs("Can't chdir to ", stderr); 254 perror(map); 255 exit(1); 256 } 257 map = sl + 1; 258 } 259 260 if (!printit) { 261 len = strlen(map); 262 mappag = (char *) malloc(len + 5); 263 mapdir = (char *) malloc(len + 5); 264 if (!mappag || !mapdir) { 265 perror("mk-amd-map: malloc"); 266 exit(1); 267 } 268#ifdef HAVE_MKSTEMP 269 mapfd = mkstemp(maptmp); 270#else /* not HAVE_MKSTEMP */ 271 map = mktemp(maptmp); 272 if (!maptmp) { 273 fprintf(stderr, "cannot create temporary file\n"); 274 exit(1); 275 } 276 mapfd = open(map, O_RDONLY); 277#endif /* not HAVE_MKSTEMP */ 278 279 /* open DBM files */ 280 sprintf(maptpag, "%s.pag", maptmp); 281 sprintf(maptdir, "%s.dir", maptmp); 282 if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) { 283 fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag); 284 perror(maptdir); 285 exit(1); 286 } 287 } 288 /* open and check if map file was opened OK */ 289 mapf = fdopen(mapfd, "r"); 290 if (mapf && !printit) 291 mapd = dbm_open(maptmp, O_RDWR|O_CREAT, 0444); 292 else 293 mapd = 0; 294 295#ifndef DEBUG 296 /* ignore ^C if debuggung is on (but why?) */ 297 signal(SIGINT, SIG_IGN); 298#endif /* not DEBUG */ 299 300 if (mapd || printit) { 301 int error = read_file(mapf, map, mapd); 302 (void) close(mapfd); 303 (void) fclose(mapf); 304 dbm_close(mapd); 305 if (printit) { 306 if (error) { 307 fprintf(stderr, "Error creating ndbm map for %s\n", map); 308 rc = 1; 309 } 310 } else { 311 312 if (error) { 313 fprintf(stderr, "Error reading source file %s\n", map); 314 rc = 1; 315 } else { 316 sprintf(mappag, "%s.pag", map); 317 sprintf(mapdir, "%s.dir", map); 318 if (rename(maptpag, mappag) < 0) { 319 fprintf(stderr, "Couldn't rename %s to ", maptpag); 320 perror(mappag); 321 /* Throw away the temporary map */ 322 unlink(maptpag); 323 unlink(maptdir); 324 rc = 1; 325 326 } else if (rename(maptdir, mapdir) < 0) { 327 fprintf(stderr, "Couldn't rename %s to ", maptdir); 328 perror(mapdir); 329 /* Put the .pag file back */ 330 rename(mappag, maptpag); 331 /* Throw away remaining part of original map */ 332 unlink(mapdir); 333 fprintf(stderr, 334 "WARNING: existing map \"%s.{dir,pag}\" destroyed\n", 335 map); 336 rc = 1; 337 } 338 } 339 } 340 341 } else { 342 fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map); 343 perror("writing"); 344 rc = 1; 345 } 346 exit(rc); 347} 348 349#else /* not HAVE_MAP_NDBM */ 350 351main() 352{ 353 fputs("mk-amd-map: This system does not support hashed database files\n", stderr); 354 exit(1); 355} 356 357#endif /* not HAVE_MAP_NDBM */ 358