1 /* 2 * Copyright (c) 1992 Eric P. Allman. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)makemap.c 8.7 (Berkeley) 07/24/94"; 11 #endif /* not lint */ 12 13 #include <stdio.h> 14 #include <sysexits.h> 15 #include <sys/types.h> 16 #include <sys/file.h> 17 #include <ctype.h> 18 #include <string.h> 19 #include "useful.h" 20 #include "conf.h" 21 22 #ifdef NDBM 23 #include <ndbm.h> 24 #endif 25 26 #ifdef NEWDB 27 #include <db.h> 28 #endif 29 30 enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN }; 31 32 union dbent 33 { 34 #ifdef NDBM 35 datum dbm; 36 #endif 37 #ifdef NEWDB 38 DBT db; 39 #endif 40 struct 41 { 42 char *data; 43 int size; 44 } xx; 45 }; 46 47 #define BUFSIZE 1024 48 49 main(argc, argv) 50 int argc; 51 char **argv; 52 { 53 char *progname; 54 bool inclnull = FALSE; 55 bool notrunc = FALSE; 56 bool allowreplace = FALSE; 57 bool allowdups = FALSE; 58 bool verbose = FALSE; 59 bool foldcase = TRUE; 60 int exitstat; 61 int opt; 62 char *typename; 63 char *mapname; 64 char *ext; 65 int lineno; 66 int st; 67 int mode; 68 enum type type; 69 union 70 { 71 #ifdef NDBM 72 DBM *dbm; 73 #endif 74 #ifdef NEWDB 75 DB *db; 76 #endif 77 void *dbx; 78 } dbp; 79 union dbent key, val; 80 #ifdef NEWDB 81 BTREEINFO bti; 82 #endif 83 char ibuf[BUFSIZE]; 84 char fbuf[MAXNAME]; 85 extern char *optarg; 86 extern int optind; 87 88 progname = argv[0]; 89 90 while ((opt = getopt(argc, argv, "Ndforv")) != EOF) 91 { 92 switch (opt) 93 { 94 case 'N': 95 inclnull = TRUE; 96 break; 97 98 case 'd': 99 allowdups = TRUE; 100 break; 101 102 case 'f': 103 foldcase = FALSE; 104 break; 105 106 case 'o': 107 notrunc = TRUE; 108 break; 109 110 case 'r': 111 allowreplace = TRUE; 112 break; 113 114 case 'v': 115 verbose = TRUE; 116 break; 117 118 default: 119 type = T_ERR; 120 break; 121 } 122 } 123 124 argc -= optind; 125 argv += optind; 126 if (argc != 2) 127 type = T_ERR; 128 else 129 { 130 typename = argv[0]; 131 mapname = argv[1]; 132 ext = NULL; 133 134 if (strcmp(typename, "dbm") == 0) 135 { 136 type = T_DBM; 137 } 138 else if (strcmp(typename, "btree") == 0) 139 { 140 type = T_BTREE; 141 ext = ".db"; 142 } 143 else if (strcmp(typename, "hash") == 0) 144 { 145 type = T_HASH; 146 ext = ".db"; 147 } 148 else 149 type = T_UNKNOWN; 150 } 151 152 switch (type) 153 { 154 case T_ERR: 155 fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname); 156 exit(EX_USAGE); 157 158 case T_UNKNOWN: 159 fprintf(stderr, "%s: Unknown database type %s\n", 160 progname, typename); 161 exit(EX_USAGE); 162 163 #ifndef NDBM 164 case T_DBM: 165 #endif 166 #ifndef NEWDB 167 case T_BTREE: 168 case T_HASH: 169 #endif 170 fprintf(stderr, "%s: Type %s not supported in this version\n", 171 progname, typename); 172 exit(EX_UNAVAILABLE); 173 174 #ifdef NEWDB 175 case T_BTREE: 176 bzero(&bti, sizeof bti); 177 if (allowdups) 178 bti.flags |= R_DUP; 179 break; 180 181 case T_HASH: 182 #endif 183 #ifdef NDBM 184 case T_DBM: 185 #endif 186 if (allowdups) 187 { 188 fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n", 189 progname, typename); 190 exit(EX_UNAVAILABLE); 191 } 192 break; 193 } 194 195 /* 196 ** Adjust file names. 197 */ 198 199 if (ext != NULL) 200 { 201 int el, fl; 202 203 el = strlen(ext); 204 fl = strlen(mapname); 205 if (fl < el || strcmp(&mapname[fl - el], ext) != 0) 206 { 207 strcpy(fbuf, mapname); 208 strcat(fbuf, ext); 209 mapname = fbuf; 210 } 211 } 212 213 /* 214 ** Create the database. 215 */ 216 217 mode = O_RDWR; 218 if (!notrunc) 219 mode |= O_CREAT|O_TRUNC; 220 switch (type) 221 { 222 #ifdef NDBM 223 case T_DBM: 224 dbp.dbm = dbm_open(mapname, mode, 0644); 225 break; 226 #endif 227 228 #ifdef NEWDB 229 case T_HASH: 230 dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); 231 break; 232 233 case T_BTREE: 234 dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti); 235 break; 236 #endif 237 238 default: 239 fprintf(stderr, "%s: internal error: type %d\n", progname, type); 240 exit(EX_SOFTWARE); 241 } 242 243 if (dbp.dbx == NULL) 244 { 245 fprintf(stderr, "%s: cannot create type %s map %s\n", 246 progname, typename, mapname); 247 exit(EX_CANTCREAT); 248 } 249 250 /* 251 ** Copy the data 252 */ 253 254 lineno = 0; 255 exitstat = EX_OK; 256 while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 257 { 258 register char *p; 259 260 lineno++; 261 262 /* 263 ** Parse the line. 264 */ 265 266 p = strchr(ibuf, '\n'); 267 if (p != NULL) 268 *p = '\0'; 269 else if (!feof(stdin)) 270 { 271 fprintf(stderr, "%s: %s: line %d: line too long (%d bytes max)\n", 272 progname, mapname, lineno, sizeof ibuf); 273 continue; 274 } 275 276 if (ibuf[0] == '\0' || ibuf[0] == '#') 277 continue; 278 if (isspace(ibuf[0])) 279 { 280 fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 281 progname, mapname, lineno); 282 continue; 283 } 284 key.xx.data = ibuf; 285 for (p = ibuf; *p != '\0' && !isspace(*p); p++) 286 { 287 if (foldcase && isupper(*p)) 288 *p = tolower(*p); 289 } 290 key.xx.size = p - key.xx.data; 291 if (inclnull) 292 key.xx.size++; 293 if (*p != '\0') 294 *p++ = '\0'; 295 while (isspace(*p)) 296 p++; 297 if (*p == '\0') 298 { 299 fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 300 progname, mapname, lineno, key.xx.data); 301 continue; 302 } 303 val.xx.data = p; 304 val.xx.size = strlen(p); 305 if (inclnull) 306 val.xx.size++; 307 308 /* 309 ** Do the database insert. 310 */ 311 312 if (verbose) 313 { 314 printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 315 } 316 317 switch (type) 318 { 319 #ifdef NDBM 320 case T_DBM: 321 st = dbm_store(dbp.dbm, key.dbm, val.dbm, 322 allowreplace ? DBM_REPLACE : DBM_INSERT); 323 break; 324 #endif 325 326 #ifdef NEWDB 327 case T_BTREE: 328 case T_HASH: 329 st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 330 allowreplace ? 0 : R_NOOVERWRITE); 331 break; 332 #endif 333 } 334 335 if (st < 0) 336 { 337 fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 338 progname, mapname, lineno, key.xx.data); 339 perror(mapname); 340 exitstat = EX_IOERR; 341 } 342 else if (st > 0) 343 { 344 fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 345 progname, mapname, lineno, key.xx.data); 346 } 347 } 348 349 /* 350 ** Now close the database. 351 */ 352 353 switch (type) 354 { 355 #ifdef NDBM 356 case T_DBM: 357 dbm_close(dbp.dbm); 358 break; 359 #endif 360 361 #ifdef NEWDB 362 case T_HASH: 363 case T_BTREE: 364 if ((*dbp.db->close)(dbp.db) < 0) 365 { 366 fprintf(stderr, "%s: %s: error on close\n", 367 progname, mapname); 368 perror(mapname); 369 exitstat = EX_IOERR; 370 } 371 #endif 372 } 373 374 exit (exitstat); 375 } 376