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*67557Seric static char sccsid[] = "@(#)makemap.c 8.7 (Berkeley) 07/24/94"; 1156811Seric #endif /* not lint */ 1256811Seric 1356811Seric #include <stdio.h> 1456811Seric #include <sysexits.h> 1564343Seric #include <sys/types.h> 1656811Seric #include <sys/file.h> 1756811Seric #include <ctype.h> 1856811Seric #include <string.h> 1956811Seric #include "useful.h" 2056811Seric #include "conf.h" 2156811Seric 2260558Seric #ifdef NDBM 2356811Seric #include <ndbm.h> 2456811Seric #endif 2556811Seric 2660558Seric #ifdef NEWDB 2756811Seric #include <db.h> 2856811Seric #endif 2956811Seric 3056811Seric enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN }; 3156811Seric 3256811Seric union dbent 3356811Seric { 3460558Seric #ifdef NDBM 3556811Seric datum dbm; 3656811Seric #endif 3760558Seric #ifdef NEWDB 3856811Seric DBT db; 3956811Seric #endif 4056811Seric struct 4156811Seric { 4256811Seric char *data; 4356811Seric int size; 4456811Seric } xx; 4556811Seric }; 4656811Seric 4756811Seric #define BUFSIZE 1024 4856811Seric 4956811Seric main(argc, argv) 5056811Seric int argc; 5156811Seric char **argv; 5256811Seric { 5356811Seric char *progname; 5456811Seric bool inclnull = FALSE; 5556811Seric bool notrunc = FALSE; 5656811Seric bool allowreplace = FALSE; 57*67557Seric bool allowdups = FALSE; 5856811Seric bool verbose = FALSE; 5964557Seric bool foldcase = TRUE; 6056811Seric int exitstat; 6156811Seric int opt; 6256811Seric char *typename; 6356811Seric char *mapname; 6464152Seric char *ext; 6556811Seric int lineno; 6656811Seric int st; 6756811Seric int mode; 6856811Seric enum type type; 6956811Seric union 7056811Seric { 7160558Seric #ifdef NDBM 7256811Seric DBM *dbm; 7356811Seric #endif 7460558Seric #ifdef NEWDB 7556811Seric DB *db; 7656811Seric #endif 7756811Seric void *dbx; 7856811Seric } dbp; 7956811Seric union dbent key, val; 80*67557Seric #ifdef NEWDB 81*67557Seric BTREEINFO bti; 82*67557Seric #endif 8356811Seric char ibuf[BUFSIZE]; 8464151Seric char fbuf[MAXNAME]; 8556811Seric extern char *optarg; 8656811Seric extern int optind; 8756811Seric 8856811Seric progname = argv[0]; 8956811Seric 90*67557Seric while ((opt = getopt(argc, argv, "Ndforv")) != EOF) 9156811Seric { 9256811Seric switch (opt) 9356811Seric { 9456811Seric case 'N': 9556811Seric inclnull = TRUE; 9656811Seric break; 9756811Seric 98*67557Seric case 'd': 99*67557Seric allowdups = TRUE; 100*67557Seric break; 101*67557Seric 10257078Seric case 'f': 10364557Seric foldcase = FALSE; 10457078Seric break; 10557078Seric 10656811Seric case 'o': 10756811Seric notrunc = TRUE; 10856811Seric break; 10956811Seric 11056811Seric case 'r': 11156811Seric allowreplace = TRUE; 11256811Seric break; 11356811Seric 11456811Seric case 'v': 11556811Seric verbose = TRUE; 11656811Seric break; 11756811Seric 11856811Seric default: 11956811Seric type = T_ERR; 12056811Seric break; 12156811Seric } 12256811Seric } 12356811Seric 12456811Seric argc -= optind; 12556811Seric argv += optind; 12656811Seric if (argc != 2) 12756811Seric type = T_ERR; 12856811Seric else 12956811Seric { 13056811Seric typename = argv[0]; 13156811Seric mapname = argv[1]; 13264151Seric ext = NULL; 13356811Seric 13456811Seric if (strcmp(typename, "dbm") == 0) 13564151Seric { 13656811Seric type = T_DBM; 13764151Seric } 13856811Seric else if (strcmp(typename, "btree") == 0) 13964151Seric { 14056811Seric type = T_BTREE; 14164151Seric ext = ".db"; 14264151Seric } 14356811Seric else if (strcmp(typename, "hash") == 0) 14464151Seric { 14556811Seric type = T_HASH; 14664151Seric ext = ".db"; 14764151Seric } 14856811Seric else 14956811Seric type = T_UNKNOWN; 15056811Seric } 15156811Seric 15256811Seric switch (type) 15356811Seric { 15456811Seric case T_ERR: 155*67557Seric fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname); 15656811Seric exit(EX_USAGE); 15756811Seric 15856811Seric case T_UNKNOWN: 15956811Seric fprintf(stderr, "%s: Unknown database type %s\n", 16056811Seric progname, typename); 16156811Seric exit(EX_USAGE); 16256811Seric 16360558Seric #ifndef NDBM 16456811Seric case T_DBM: 16556811Seric #endif 16660558Seric #ifndef NEWDB 16756811Seric case T_BTREE: 16856811Seric case T_HASH: 16956811Seric #endif 17056811Seric fprintf(stderr, "%s: Type %s not supported in this version\n", 17156811Seric progname, typename); 17256811Seric exit(EX_UNAVAILABLE); 173*67557Seric 174*67557Seric #ifdef NEWDB 175*67557Seric case T_BTREE: 176*67557Seric bzero(&bti, sizeof bti); 177*67557Seric if (allowdups) 178*67557Seric bti.flags |= R_DUP; 179*67557Seric break; 180*67557Seric 181*67557Seric case T_HASH: 182*67557Seric #endif 183*67557Seric #ifdef NDBM 184*67557Seric case T_DBM: 185*67557Seric #endif 186*67557Seric if (allowdups) 187*67557Seric { 188*67557Seric fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n", 189*67557Seric progname, typename); 190*67557Seric exit(EX_UNAVAILABLE); 191*67557Seric } 192*67557Seric break; 19356811Seric } 19456811Seric 19556811Seric /* 19664151Seric ** Adjust file names. 19764151Seric */ 19864151Seric 19964151Seric if (ext != NULL) 20064151Seric { 20164151Seric int el, fl; 20264151Seric 20364151Seric el = strlen(ext); 20464151Seric fl = strlen(mapname); 20564151Seric if (fl < el || strcmp(&mapname[fl - el], ext) != 0) 20664151Seric { 20764151Seric strcpy(fbuf, mapname); 20864151Seric strcat(fbuf, ext); 20964151Seric mapname = fbuf; 21064151Seric } 21164151Seric } 21264151Seric 21364151Seric /* 21456811Seric ** Create the database. 21556811Seric */ 21656811Seric 21756811Seric mode = O_RDWR; 21856811Seric if (!notrunc) 21956811Seric mode |= O_CREAT|O_TRUNC; 22056811Seric switch (type) 22156811Seric { 22260558Seric #ifdef NDBM 22356811Seric case T_DBM: 22456811Seric dbp.dbm = dbm_open(mapname, mode, 0644); 22556811Seric break; 22656811Seric #endif 22756811Seric 22860558Seric #ifdef NEWDB 22956811Seric case T_HASH: 23056811Seric dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); 23156811Seric break; 23256811Seric 23356811Seric case T_BTREE: 234*67557Seric dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti); 23556811Seric break; 23656811Seric #endif 23756811Seric 23856811Seric default: 23956811Seric fprintf(stderr, "%s: internal error: type %d\n", progname, type); 24056811Seric exit(EX_SOFTWARE); 24156811Seric } 24256811Seric 24356811Seric if (dbp.dbx == NULL) 24456811Seric { 24556811Seric fprintf(stderr, "%s: cannot create type %s map %s\n", 24656811Seric progname, typename, mapname); 24756811Seric exit(EX_CANTCREAT); 24856811Seric } 24956811Seric 25056811Seric /* 25156811Seric ** Copy the data 25256811Seric */ 25356811Seric 25456811Seric lineno = 0; 25556811Seric exitstat = EX_OK; 25656811Seric while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 25756811Seric { 25856811Seric register char *p; 25956811Seric 26056811Seric lineno++; 26156811Seric 26256811Seric /* 26356811Seric ** Parse the line. 26456811Seric */ 26556811Seric 26656811Seric p = strchr(ibuf, '\n'); 26764934Seric if (p != NULL) 26856811Seric *p = '\0'; 26964934Seric else if (!feof(stdin)) 27064934Seric { 27164934Seric fprintf(stderr, "%s: %s: line %d: line too long (%d bytes max)\n", 27264934Seric progname, mapname, lineno, sizeof ibuf); 27364934Seric continue; 27464934Seric } 27564934Seric 27656811Seric if (ibuf[0] == '\0' || ibuf[0] == '#') 27756811Seric continue; 27856811Seric if (isspace(ibuf[0])) 27956811Seric { 28056811Seric fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 28156811Seric progname, mapname, lineno); 28256811Seric continue; 28356811Seric } 28456811Seric key.xx.data = ibuf; 28556811Seric for (p = ibuf; *p != '\0' && !isspace(*p); p++) 28657078Seric { 28757078Seric if (foldcase && isupper(*p)) 28857078Seric *p = tolower(*p); 28957078Seric } 29056811Seric key.xx.size = p - key.xx.data; 29156811Seric if (inclnull) 29256811Seric key.xx.size++; 29356811Seric if (*p != '\0') 29456811Seric *p++ = '\0'; 29556811Seric while (isspace(*p)) 29656811Seric p++; 29756811Seric if (*p == '\0') 29856811Seric { 29956811Seric fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 30056811Seric progname, mapname, lineno, key.xx.data); 30156811Seric continue; 30256811Seric } 30356811Seric val.xx.data = p; 30456811Seric val.xx.size = strlen(p); 30556811Seric if (inclnull) 30656811Seric val.xx.size++; 30756811Seric 30856811Seric /* 30956811Seric ** Do the database insert. 31056811Seric */ 31156811Seric 31256811Seric if (verbose) 31356811Seric { 31456811Seric printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 31556811Seric } 31656811Seric 31756811Seric switch (type) 31856811Seric { 31960558Seric #ifdef NDBM 32056811Seric case T_DBM: 32156811Seric st = dbm_store(dbp.dbm, key.dbm, val.dbm, 32256811Seric allowreplace ? DBM_REPLACE : DBM_INSERT); 32356811Seric break; 32456811Seric #endif 32556811Seric 32660558Seric #ifdef NEWDB 32756811Seric case T_BTREE: 32856811Seric case T_HASH: 32956811Seric st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 33056811Seric allowreplace ? 0 : R_NOOVERWRITE); 33156811Seric break; 33256811Seric #endif 33356811Seric } 33456811Seric 33556811Seric if (st < 0) 33656811Seric { 33756811Seric fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 33856811Seric progname, mapname, lineno, key.xx.data); 33956811Seric perror(mapname); 34056811Seric exitstat = EX_IOERR; 34156811Seric } 34256811Seric else if (st > 0) 34356811Seric { 34456811Seric fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 34556811Seric progname, mapname, lineno, key.xx.data); 34656811Seric } 34756811Seric } 34856811Seric 34956811Seric /* 35056811Seric ** Now close the database. 35156811Seric */ 35256811Seric 35356811Seric switch (type) 35456811Seric { 35560558Seric #ifdef NDBM 35656811Seric case T_DBM: 35756811Seric dbm_close(dbp.dbm); 35856811Seric break; 35956811Seric #endif 36056811Seric 36160558Seric #ifdef NEWDB 36256811Seric case T_HASH: 36356811Seric case T_BTREE: 36456811Seric if ((*dbp.db->close)(dbp.db) < 0) 36556811Seric { 36656811Seric fprintf(stderr, "%s: %s: error on close\n", 36756811Seric progname, mapname); 36856811Seric perror(mapname); 36956811Seric exitstat = EX_IOERR; 37056811Seric } 37156811Seric #endif 37256811Seric } 37356811Seric 37456811Seric exit (exitstat); 37556811Seric } 376