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*64557Seric static char sccsid[] = "@(#)makemap.c 8.5 (Berkeley) 09/22/93"; 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; 5756811Seric bool verbose = FALSE; 58*64557Seric bool foldcase = TRUE; 5956811Seric int exitstat; 6056811Seric int opt; 6156811Seric char *typename; 6256811Seric char *mapname; 6364152Seric char *ext; 6456811Seric int lineno; 6556811Seric int st; 6656811Seric int mode; 6756811Seric enum type type; 6856811Seric union 6956811Seric { 7060558Seric #ifdef NDBM 7156811Seric DBM *dbm; 7256811Seric #endif 7360558Seric #ifdef NEWDB 7456811Seric DB *db; 7556811Seric #endif 7656811Seric void *dbx; 7756811Seric } dbp; 7856811Seric union dbent key, val; 7956811Seric char ibuf[BUFSIZE]; 8064151Seric char fbuf[MAXNAME]; 8156811Seric extern char *optarg; 8256811Seric extern int optind; 8356811Seric 8456811Seric progname = argv[0]; 8556811Seric 8657078Seric while ((opt = getopt(argc, argv, "Nforv")) != EOF) 8756811Seric { 8856811Seric switch (opt) 8956811Seric { 9056811Seric case 'N': 9156811Seric inclnull = TRUE; 9256811Seric break; 9356811Seric 9457078Seric case 'f': 95*64557Seric foldcase = FALSE; 9657078Seric break; 9757078Seric 9856811Seric case 'o': 9956811Seric notrunc = TRUE; 10056811Seric break; 10156811Seric 10256811Seric case 'r': 10356811Seric allowreplace = TRUE; 10456811Seric break; 10556811Seric 10656811Seric case 'v': 10756811Seric verbose = TRUE; 10856811Seric break; 10956811Seric 11056811Seric default: 11156811Seric type = T_ERR; 11256811Seric break; 11356811Seric } 11456811Seric } 11556811Seric 11656811Seric argc -= optind; 11756811Seric argv += optind; 11856811Seric if (argc != 2) 11956811Seric type = T_ERR; 12056811Seric else 12156811Seric { 12256811Seric typename = argv[0]; 12356811Seric mapname = argv[1]; 12464151Seric ext = NULL; 12556811Seric 12656811Seric if (strcmp(typename, "dbm") == 0) 12764151Seric { 12856811Seric type = T_DBM; 12964151Seric } 13056811Seric else if (strcmp(typename, "btree") == 0) 13164151Seric { 13256811Seric type = T_BTREE; 13364151Seric ext = ".db"; 13464151Seric } 13556811Seric else if (strcmp(typename, "hash") == 0) 13664151Seric { 13756811Seric type = T_HASH; 13864151Seric ext = ".db"; 13964151Seric } 14056811Seric else 14156811Seric type = T_UNKNOWN; 14256811Seric } 14356811Seric 14456811Seric switch (type) 14556811Seric { 14656811Seric case T_ERR: 14756811Seric fprintf(stderr, "Usage: %s [-N] [-o] [-v] type mapname\n", progname); 14856811Seric exit(EX_USAGE); 14956811Seric 15056811Seric case T_UNKNOWN: 15156811Seric fprintf(stderr, "%s: Unknown database type %s\n", 15256811Seric progname, typename); 15356811Seric exit(EX_USAGE); 15456811Seric 15560558Seric #ifndef NDBM 15656811Seric case T_DBM: 15756811Seric #endif 15860558Seric #ifndef NEWDB 15956811Seric case T_BTREE: 16056811Seric case T_HASH: 16156811Seric #endif 16256811Seric fprintf(stderr, "%s: Type %s not supported in this version\n", 16356811Seric progname, typename); 16456811Seric exit(EX_UNAVAILABLE); 16556811Seric } 16656811Seric 16756811Seric /* 16864151Seric ** Adjust file names. 16964151Seric */ 17064151Seric 17164151Seric if (ext != NULL) 17264151Seric { 17364151Seric int el, fl; 17464151Seric 17564151Seric el = strlen(ext); 17664151Seric fl = strlen(mapname); 17764151Seric if (fl < el || strcmp(&mapname[fl - el], ext) != 0) 17864151Seric { 17964151Seric strcpy(fbuf, mapname); 18064151Seric strcat(fbuf, ext); 18164151Seric mapname = fbuf; 18264151Seric } 18364151Seric } 18464151Seric 18564151Seric /* 18656811Seric ** Create the database. 18756811Seric */ 18856811Seric 18956811Seric mode = O_RDWR; 19056811Seric if (!notrunc) 19156811Seric mode |= O_CREAT|O_TRUNC; 19256811Seric switch (type) 19356811Seric { 19460558Seric #ifdef NDBM 19556811Seric case T_DBM: 19656811Seric dbp.dbm = dbm_open(mapname, mode, 0644); 19756811Seric break; 19856811Seric #endif 19956811Seric 20060558Seric #ifdef NEWDB 20156811Seric case T_HASH: 20256811Seric dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); 20356811Seric break; 20456811Seric 20556811Seric case T_BTREE: 20656811Seric dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL); 20756811Seric break; 20856811Seric #endif 20956811Seric 21056811Seric default: 21156811Seric fprintf(stderr, "%s: internal error: type %d\n", progname, type); 21256811Seric exit(EX_SOFTWARE); 21356811Seric } 21456811Seric 21556811Seric if (dbp.dbx == NULL) 21656811Seric { 21756811Seric fprintf(stderr, "%s: cannot create type %s map %s\n", 21856811Seric progname, typename, mapname); 21956811Seric exit(EX_CANTCREAT); 22056811Seric } 22156811Seric 22256811Seric /* 22356811Seric ** Copy the data 22456811Seric */ 22556811Seric 22656811Seric lineno = 0; 22756811Seric exitstat = EX_OK; 22856811Seric while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 22956811Seric { 23056811Seric register char *p; 23156811Seric 23256811Seric lineno++; 23356811Seric 23456811Seric /* 23556811Seric ** Parse the line. 23656811Seric */ 23756811Seric 23856811Seric p = strchr(ibuf, '\n'); 23956811Seric if (*p != '\0') 24056811Seric *p = '\0'; 24156811Seric if (ibuf[0] == '\0' || ibuf[0] == '#') 24256811Seric continue; 24356811Seric if (isspace(ibuf[0])) 24456811Seric { 24556811Seric fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 24656811Seric progname, mapname, lineno); 24756811Seric continue; 24856811Seric } 24956811Seric key.xx.data = ibuf; 25056811Seric for (p = ibuf; *p != '\0' && !isspace(*p); p++) 25157078Seric { 25257078Seric if (foldcase && isupper(*p)) 25357078Seric *p = tolower(*p); 25457078Seric } 25556811Seric key.xx.size = p - key.xx.data; 25656811Seric if (inclnull) 25756811Seric key.xx.size++; 25856811Seric if (*p != '\0') 25956811Seric *p++ = '\0'; 26056811Seric while (isspace(*p)) 26156811Seric p++; 26256811Seric if (*p == '\0') 26356811Seric { 26456811Seric fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 26556811Seric progname, mapname, lineno, key.xx.data); 26656811Seric continue; 26756811Seric } 26856811Seric val.xx.data = p; 26956811Seric val.xx.size = strlen(p); 27056811Seric if (inclnull) 27156811Seric val.xx.size++; 27256811Seric 27356811Seric /* 27456811Seric ** Do the database insert. 27556811Seric */ 27656811Seric 27756811Seric if (verbose) 27856811Seric { 27956811Seric printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 28056811Seric } 28156811Seric 28256811Seric switch (type) 28356811Seric { 28460558Seric #ifdef NDBM 28556811Seric case T_DBM: 28656811Seric st = dbm_store(dbp.dbm, key.dbm, val.dbm, 28756811Seric allowreplace ? DBM_REPLACE : DBM_INSERT); 28856811Seric break; 28956811Seric #endif 29056811Seric 29160558Seric #ifdef NEWDB 29256811Seric case T_BTREE: 29356811Seric case T_HASH: 29456811Seric st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 29556811Seric allowreplace ? 0 : R_NOOVERWRITE); 29656811Seric break; 29756811Seric #endif 29856811Seric } 29956811Seric 30056811Seric if (st < 0) 30156811Seric { 30256811Seric fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 30356811Seric progname, mapname, lineno, key.xx.data); 30456811Seric perror(mapname); 30556811Seric exitstat = EX_IOERR; 30656811Seric } 30756811Seric else if (st > 0) 30856811Seric { 30956811Seric fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 31056811Seric progname, mapname, lineno, key.xx.data); 31156811Seric } 31256811Seric } 31356811Seric 31456811Seric /* 31556811Seric ** Now close the database. 31656811Seric */ 31756811Seric 31856811Seric switch (type) 31956811Seric { 32060558Seric #ifdef NDBM 32156811Seric case T_DBM: 32256811Seric dbm_close(dbp.dbm); 32356811Seric break; 32456811Seric #endif 32556811Seric 32660558Seric #ifdef NEWDB 32756811Seric case T_HASH: 32856811Seric case T_BTREE: 32956811Seric if ((*dbp.db->close)(dbp.db) < 0) 33056811Seric { 33156811Seric fprintf(stderr, "%s: %s: error on close\n", 33256811Seric progname, mapname); 33356811Seric perror(mapname); 33456811Seric exitstat = EX_IOERR; 33556811Seric } 33656811Seric #endif 33756811Seric } 33856811Seric 33956811Seric exit (exitstat); 34056811Seric } 341