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