156811Seric /* 256811Seric * Copyright (c) 1992 Eric P. Allman. 356811Seric * Copyright (c) 1992 Regents of the University of California. 456811Seric * All rights reserved. 556811Seric * 656811Seric * %sccs.include.redist.c% 756811Seric */ 856811Seric 956811Seric #ifndef lint 10*57078Seric static char sccsid[] = "@(#)makemap.c 5.2 (Berkeley) 12/12/92"; 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 2156811Seric #ifdef DBM_MAP 2256811Seric #include <ndbm.h> 2356811Seric #endif 2456811Seric 2556811Seric #if defined(HASH_MAP) || defined(BTREE_MAP) 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 { 3356811Seric #ifdef DBM_MAP 3456811Seric datum dbm; 3556811Seric #endif 3656811Seric #if defined(HASH_MAP) || defined(BTREE_MAP) 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; 57*57078Seric 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 { 6856811Seric #ifdef DBM_MAP 6956811Seric DBM *dbm; 7056811Seric #endif 7156811Seric #if defined(HASH_MAP) || defined(BTREE_MAP) 7256811Seric DB *db; 7356811Seric #endif 7456811Seric void *dbx; 7556811Seric } dbp; 7656811Seric union dbent key, val; 7756811Seric char ibuf[BUFSIZE]; 7856811Seric extern char *optarg; 7956811Seric extern int optind; 8056811Seric 8156811Seric progname = argv[0]; 8256811Seric 83*57078Seric while ((opt = getopt(argc, argv, "Nforv")) != EOF) 8456811Seric { 8556811Seric switch (opt) 8656811Seric { 8756811Seric case 'N': 8856811Seric inclnull = TRUE; 8956811Seric break; 9056811Seric 91*57078Seric case 'f': 92*57078Seric foldcase = TRUE; 93*57078Seric break; 94*57078Seric 9556811Seric case 'o': 9656811Seric notrunc = TRUE; 9756811Seric break; 9856811Seric 9956811Seric case 'r': 10056811Seric allowreplace = TRUE; 10156811Seric break; 10256811Seric 10356811Seric case 'v': 10456811Seric verbose = TRUE; 10556811Seric break; 10656811Seric 10756811Seric default: 10856811Seric type = T_ERR; 10956811Seric break; 11056811Seric } 11156811Seric } 11256811Seric 11356811Seric argc -= optind; 11456811Seric argv += optind; 11556811Seric if (argc != 2) 11656811Seric type = T_ERR; 11756811Seric else 11856811Seric { 11956811Seric typename = argv[0]; 12056811Seric mapname = argv[1]; 12156811Seric 12256811Seric if (strcmp(typename, "dbm") == 0) 12356811Seric type = T_DBM; 12456811Seric else if (strcmp(typename, "btree") == 0) 12556811Seric type = T_BTREE; 12656811Seric else if (strcmp(typename, "hash") == 0) 12756811Seric type = T_HASH; 12856811Seric else 12956811Seric type = T_UNKNOWN; 13056811Seric } 13156811Seric 13256811Seric switch (type) 13356811Seric { 13456811Seric case T_ERR: 13556811Seric fprintf(stderr, "Usage: %s [-N] [-o] [-v] type mapname\n", progname); 13656811Seric exit(EX_USAGE); 13756811Seric 13856811Seric case T_UNKNOWN: 13956811Seric fprintf(stderr, "%s: Unknown database type %s\n", 14056811Seric progname, typename); 14156811Seric exit(EX_USAGE); 14256811Seric 14356811Seric #ifndef DBM_MAP 14456811Seric case T_DBM: 14556811Seric #endif 14656811Seric #ifndef BTREE_MAP 14756811Seric case T_BTREE: 14856811Seric #endif 14956811Seric #ifndef HASH_MAP 15056811Seric case T_HASH: 15156811Seric #endif 15256811Seric fprintf(stderr, "%s: Type %s not supported in this version\n", 15356811Seric progname, typename); 15456811Seric exit(EX_UNAVAILABLE); 15556811Seric } 15656811Seric 15756811Seric /* 15856811Seric ** Create the database. 15956811Seric */ 16056811Seric 16156811Seric mode = O_RDWR; 16256811Seric if (!notrunc) 16356811Seric mode |= O_CREAT|O_TRUNC; 16456811Seric switch (type) 16556811Seric { 16656811Seric #ifdef DBM_MAP 16756811Seric case T_DBM: 16856811Seric dbp.dbm = dbm_open(mapname, mode, 0644); 16956811Seric break; 17056811Seric #endif 17156811Seric 17256811Seric #ifdef HASH_MAP 17356811Seric case T_HASH: 17456811Seric dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); 17556811Seric break; 17656811Seric #endif 17756811Seric 17856811Seric #ifdef BTREE_MAP 17956811Seric case T_BTREE: 18056811Seric dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL); 18156811Seric break; 18256811Seric #endif 18356811Seric 18456811Seric default: 18556811Seric fprintf(stderr, "%s: internal error: type %d\n", progname, type); 18656811Seric exit(EX_SOFTWARE); 18756811Seric } 18856811Seric 18956811Seric if (dbp.dbx == NULL) 19056811Seric { 19156811Seric fprintf(stderr, "%s: cannot create type %s map %s\n", 19256811Seric progname, typename, mapname); 19356811Seric exit(EX_CANTCREAT); 19456811Seric } 19556811Seric 19656811Seric /* 19756811Seric ** Copy the data 19856811Seric */ 19956811Seric 20056811Seric lineno = 0; 20156811Seric exitstat = EX_OK; 20256811Seric while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 20356811Seric { 20456811Seric register char *p; 20556811Seric 20656811Seric lineno++; 20756811Seric 20856811Seric /* 20956811Seric ** Parse the line. 21056811Seric */ 21156811Seric 21256811Seric p = strchr(ibuf, '\n'); 21356811Seric if (*p != '\0') 21456811Seric *p = '\0'; 21556811Seric if (ibuf[0] == '\0' || ibuf[0] == '#') 21656811Seric continue; 21756811Seric if (isspace(ibuf[0])) 21856811Seric { 21956811Seric fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 22056811Seric progname, mapname, lineno); 22156811Seric continue; 22256811Seric } 22356811Seric key.xx.data = ibuf; 22456811Seric for (p = ibuf; *p != '\0' && !isspace(*p); p++) 225*57078Seric { 226*57078Seric if (foldcase && isupper(*p)) 227*57078Seric *p = tolower(*p); 228*57078Seric } 22956811Seric key.xx.size = p - key.xx.data; 23056811Seric if (inclnull) 23156811Seric key.xx.size++; 23256811Seric if (*p != '\0') 23356811Seric *p++ = '\0'; 23456811Seric while (isspace(*p)) 23556811Seric p++; 23656811Seric if (*p == '\0') 23756811Seric { 23856811Seric fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 23956811Seric progname, mapname, lineno, key.xx.data); 24056811Seric continue; 24156811Seric } 24256811Seric val.xx.data = p; 24356811Seric val.xx.size = strlen(p); 24456811Seric if (inclnull) 24556811Seric val.xx.size++; 24656811Seric 24756811Seric /* 24856811Seric ** Do the database insert. 24956811Seric */ 25056811Seric 25156811Seric if (verbose) 25256811Seric { 25356811Seric printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 25456811Seric } 25556811Seric 25656811Seric switch (type) 25756811Seric { 25856811Seric #ifdef DBM_MAP 25956811Seric case T_DBM: 26056811Seric st = dbm_store(dbp.dbm, key.dbm, val.dbm, 26156811Seric allowreplace ? DBM_REPLACE : DBM_INSERT); 26256811Seric break; 26356811Seric #endif 26456811Seric 26556811Seric #if defined(BTREE_MAP) || defined(HASH_MAP) 26656811Seric case T_BTREE: 26756811Seric case T_HASH: 26856811Seric st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 26956811Seric allowreplace ? 0 : R_NOOVERWRITE); 27056811Seric break; 27156811Seric #endif 27256811Seric } 27356811Seric 27456811Seric if (st < 0) 27556811Seric { 27656811Seric fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 27756811Seric progname, mapname, lineno, key.xx.data); 27856811Seric perror(mapname); 27956811Seric exitstat = EX_IOERR; 28056811Seric } 28156811Seric else if (st > 0) 28256811Seric { 28356811Seric fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 28456811Seric progname, mapname, lineno, key.xx.data); 28556811Seric } 28656811Seric } 28756811Seric 28856811Seric /* 28956811Seric ** Now close the database. 29056811Seric */ 29156811Seric 29256811Seric switch (type) 29356811Seric { 29456811Seric #ifdef DBM_MAP 29556811Seric case T_DBM: 29656811Seric dbm_close(dbp.dbm); 29756811Seric break; 29856811Seric #endif 29956811Seric 30056811Seric #if defined(HASH_MAP) || defined(BTREE_MAP) 30156811Seric case T_HASH: 30256811Seric case T_BTREE: 30356811Seric if ((*dbp.db->close)(dbp.db) < 0) 30456811Seric { 30556811Seric fprintf(stderr, "%s: %s: error on close\n", 30656811Seric progname, mapname); 30756811Seric perror(mapname); 30856811Seric exitstat = EX_IOERR; 30956811Seric } 31056811Seric #endif 31156811Seric } 31256811Seric 31356811Seric exit (exitstat); 31456811Seric } 315