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