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