156811Seric /* 256811Seric * Copyright (c) 1992 Eric P. Allman. 362514Sbostic * Copyright (c) 1992, 1993 462514Sbostic * The Regents of the University of California. All rights reserved. 556811Seric * 656811Seric * %sccs.include.redist.c% 756811Seric */ 856811Seric 956811Seric #ifndef lint 10*64151Seric static char sccsid[] = "@(#)makemap.c 8.2 (Berkeley) 08/08/93"; 1156811Seric #endif /* not lint */ 1256811Seric 1356811Seric #include <stdio.h> 1456811Seric #include <sysexits.h> 1556811Seric #include <sys/file.h> 1656811Seric #include <ctype.h> 1756811Seric #include <string.h> 1856811Seric #include "useful.h" 1956811Seric #include "conf.h" 2056811Seric 2160558Seric #ifdef NDBM 2256811Seric #include <ndbm.h> 2356811Seric #endif 2456811Seric 2560558Seric #ifdef NEWDB 2656811Seric #include <db.h> 2756811Seric #endif 2856811Seric 2956811Seric enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN }; 3056811Seric 3156811Seric union dbent 3256811Seric { 3360558Seric #ifdef NDBM 3456811Seric datum dbm; 3556811Seric #endif 3660558Seric #ifdef NEWDB 3756811Seric DBT db; 3856811Seric #endif 3956811Seric struct 4056811Seric { 4156811Seric char *data; 4256811Seric int size; 4356811Seric } xx; 4456811Seric }; 4556811Seric 4656811Seric #define BUFSIZE 1024 4756811Seric 4856811Seric main(argc, argv) 4956811Seric int argc; 5056811Seric char **argv; 5156811Seric { 5256811Seric char *progname; 5356811Seric bool inclnull = FALSE; 5456811Seric bool notrunc = FALSE; 5556811Seric bool allowreplace = FALSE; 5656811Seric bool verbose = FALSE; 5757078Seric bool foldcase = FALSE; 5856811Seric int exitstat; 5956811Seric int opt; 6056811Seric char *typename; 6156811Seric char *mapname; 6256811Seric int lineno; 6356811Seric int st; 6456811Seric int mode; 6556811Seric enum type type; 6656811Seric union 6756811Seric { 6860558Seric #ifdef NDBM 6956811Seric DBM *dbm; 7056811Seric #endif 7160558Seric #ifdef NEWDB 7256811Seric DB *db; 7356811Seric #endif 7456811Seric void *dbx; 7556811Seric } dbp; 7656811Seric union dbent key, val; 7756811Seric char ibuf[BUFSIZE]; 78*64151Seric char fbuf[MAXNAME]; 7956811Seric extern char *optarg; 8056811Seric extern int optind; 8156811Seric 8256811Seric progname = argv[0]; 8356811Seric 8457078Seric while ((opt = getopt(argc, argv, "Nforv")) != EOF) 8556811Seric { 8656811Seric switch (opt) 8756811Seric { 8856811Seric case 'N': 8956811Seric inclnull = TRUE; 9056811Seric break; 9156811Seric 9257078Seric case 'f': 9357078Seric foldcase = TRUE; 9457078Seric break; 9557078Seric 9656811Seric case 'o': 9756811Seric notrunc = TRUE; 9856811Seric break; 9956811Seric 10056811Seric case 'r': 10156811Seric allowreplace = TRUE; 10256811Seric break; 10356811Seric 10456811Seric case 'v': 10556811Seric verbose = TRUE; 10656811Seric break; 10756811Seric 10856811Seric default: 10956811Seric type = T_ERR; 11056811Seric break; 11156811Seric } 11256811Seric } 11356811Seric 11456811Seric argc -= optind; 11556811Seric argv += optind; 11656811Seric if (argc != 2) 11756811Seric type = T_ERR; 11856811Seric else 11956811Seric { 12056811Seric typename = argv[0]; 12156811Seric mapname = argv[1]; 122*64151Seric ext = NULL; 12356811Seric 12456811Seric if (strcmp(typename, "dbm") == 0) 125*64151Seric { 12656811Seric type = T_DBM; 127*64151Seric } 12856811Seric else if (strcmp(typename, "btree") == 0) 129*64151Seric { 13056811Seric type = T_BTREE; 131*64151Seric ext = ".db"; 132*64151Seric } 13356811Seric else if (strcmp(typename, "hash") == 0) 134*64151Seric { 13556811Seric type = T_HASH; 136*64151Seric ext = ".db"; 137*64151Seric } 13856811Seric else 13956811Seric type = T_UNKNOWN; 14056811Seric } 14156811Seric 14256811Seric switch (type) 14356811Seric { 14456811Seric case T_ERR: 14556811Seric fprintf(stderr, "Usage: %s [-N] [-o] [-v] type mapname\n", progname); 14656811Seric exit(EX_USAGE); 14756811Seric 14856811Seric case T_UNKNOWN: 14956811Seric fprintf(stderr, "%s: Unknown database type %s\n", 15056811Seric progname, typename); 15156811Seric exit(EX_USAGE); 15256811Seric 15360558Seric #ifndef NDBM 15456811Seric case T_DBM: 15556811Seric #endif 15660558Seric #ifndef NEWDB 15756811Seric case T_BTREE: 15856811Seric case T_HASH: 15956811Seric #endif 16056811Seric fprintf(stderr, "%s: Type %s not supported in this version\n", 16156811Seric progname, typename); 16256811Seric exit(EX_UNAVAILABLE); 16356811Seric } 16456811Seric 16556811Seric /* 166*64151Seric ** Adjust file names. 167*64151Seric */ 168*64151Seric 169*64151Seric if (ext != NULL) 170*64151Seric { 171*64151Seric int el, fl; 172*64151Seric 173*64151Seric el = strlen(ext); 174*64151Seric fl = strlen(mapname); 175*64151Seric if (fl < el || strcmp(&mapname[fl - el], ext) != 0) 176*64151Seric { 177*64151Seric strcpy(fbuf, mapname); 178*64151Seric strcat(fbuf, ext); 179*64151Seric mapname = fbuf; 180*64151Seric } 181*64151Seric } 182*64151Seric 183*64151Seric /* 18456811Seric ** Create the database. 18556811Seric */ 18656811Seric 18756811Seric mode = O_RDWR; 18856811Seric if (!notrunc) 18956811Seric mode |= O_CREAT|O_TRUNC; 19056811Seric switch (type) 19156811Seric { 19260558Seric #ifdef NDBM 19356811Seric case T_DBM: 19456811Seric dbp.dbm = dbm_open(mapname, mode, 0644); 19556811Seric break; 19656811Seric #endif 19756811Seric 19860558Seric #ifdef NEWDB 19956811Seric case T_HASH: 20056811Seric dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); 20156811Seric break; 20256811Seric 20356811Seric case T_BTREE: 20456811Seric dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL); 20556811Seric break; 20656811Seric #endif 20756811Seric 20856811Seric default: 20956811Seric fprintf(stderr, "%s: internal error: type %d\n", progname, type); 21056811Seric exit(EX_SOFTWARE); 21156811Seric } 21256811Seric 21356811Seric if (dbp.dbx == NULL) 21456811Seric { 21556811Seric fprintf(stderr, "%s: cannot create type %s map %s\n", 21656811Seric progname, typename, mapname); 21756811Seric exit(EX_CANTCREAT); 21856811Seric } 21956811Seric 22056811Seric /* 22156811Seric ** Copy the data 22256811Seric */ 22356811Seric 22456811Seric lineno = 0; 22556811Seric exitstat = EX_OK; 22656811Seric while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 22756811Seric { 22856811Seric register char *p; 22956811Seric 23056811Seric lineno++; 23156811Seric 23256811Seric /* 23356811Seric ** Parse the line. 23456811Seric */ 23556811Seric 23656811Seric p = strchr(ibuf, '\n'); 23756811Seric if (*p != '\0') 23856811Seric *p = '\0'; 23956811Seric if (ibuf[0] == '\0' || ibuf[0] == '#') 24056811Seric continue; 24156811Seric if (isspace(ibuf[0])) 24256811Seric { 24356811Seric fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 24456811Seric progname, mapname, lineno); 24556811Seric continue; 24656811Seric } 24756811Seric key.xx.data = ibuf; 24856811Seric for (p = ibuf; *p != '\0' && !isspace(*p); p++) 24957078Seric { 25057078Seric if (foldcase && isupper(*p)) 25157078Seric *p = tolower(*p); 25257078Seric } 25356811Seric key.xx.size = p - key.xx.data; 25456811Seric if (inclnull) 25556811Seric key.xx.size++; 25656811Seric if (*p != '\0') 25756811Seric *p++ = '\0'; 25856811Seric while (isspace(*p)) 25956811Seric p++; 26056811Seric if (*p == '\0') 26156811Seric { 26256811Seric fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 26356811Seric progname, mapname, lineno, key.xx.data); 26456811Seric continue; 26556811Seric } 26656811Seric val.xx.data = p; 26756811Seric val.xx.size = strlen(p); 26856811Seric if (inclnull) 26956811Seric val.xx.size++; 27056811Seric 27156811Seric /* 27256811Seric ** Do the database insert. 27356811Seric */ 27456811Seric 27556811Seric if (verbose) 27656811Seric { 27756811Seric printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 27856811Seric } 27956811Seric 28056811Seric switch (type) 28156811Seric { 28260558Seric #ifdef NDBM 28356811Seric case T_DBM: 28456811Seric st = dbm_store(dbp.dbm, key.dbm, val.dbm, 28556811Seric allowreplace ? DBM_REPLACE : DBM_INSERT); 28656811Seric break; 28756811Seric #endif 28856811Seric 28960558Seric #ifdef NEWDB 29056811Seric case T_BTREE: 29156811Seric case T_HASH: 29256811Seric st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 29356811Seric allowreplace ? 0 : R_NOOVERWRITE); 29456811Seric break; 29556811Seric #endif 29656811Seric } 29756811Seric 29856811Seric if (st < 0) 29956811Seric { 30056811Seric fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 30156811Seric progname, mapname, lineno, key.xx.data); 30256811Seric perror(mapname); 30356811Seric exitstat = EX_IOERR; 30456811Seric } 30556811Seric else if (st > 0) 30656811Seric { 30756811Seric fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 30856811Seric progname, mapname, lineno, key.xx.data); 30956811Seric } 31056811Seric } 31156811Seric 31256811Seric /* 31356811Seric ** Now close the database. 31456811Seric */ 31556811Seric 31656811Seric switch (type) 31756811Seric { 31860558Seric #ifdef NDBM 31956811Seric case T_DBM: 32056811Seric dbm_close(dbp.dbm); 32156811Seric break; 32256811Seric #endif 32356811Seric 32460558Seric #ifdef NEWDB 32556811Seric case T_HASH: 32656811Seric case T_BTREE: 32756811Seric if ((*dbp.db->close)(dbp.db) < 0) 32856811Seric { 32956811Seric fprintf(stderr, "%s: %s: error on close\n", 33056811Seric progname, mapname); 33156811Seric perror(mapname); 33256811Seric exitstat = EX_IOERR; 33356811Seric } 33456811Seric #endif 33556811Seric } 33656811Seric 33756811Seric exit (exitstat); 33856811Seric } 339