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