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.1.1 (Berkeley) 03/06/95"; 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 size_t 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 if (dbp.db != NULL) 204 (void) (*dbp.db->sync)(dbp.db, 0); 205 break; 206 207 case T_BTREE: 208 dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL); 209 if (dbp.db != NULL) 210 (void) (*dbp.db->sync)(dbp.db, 0); 211 break; 212 #endif 213 214 default: 215 fprintf(stderr, "%s: internal error: type %d\n", progname, type); 216 exit(EX_SOFTWARE); 217 } 218 219 if (dbp.dbx == NULL) 220 { 221 fprintf(stderr, "%s: cannot create type %s map %s\n", 222 progname, typename, mapname); 223 exit(EX_CANTCREAT); 224 } 225 226 /* 227 ** Copy the data 228 */ 229 230 lineno = 0; 231 exitstat = EX_OK; 232 while (fgets(ibuf, sizeof ibuf, stdin) != NULL) 233 { 234 register char *p; 235 236 lineno++; 237 238 /* 239 ** Parse the line. 240 */ 241 242 p = strchr(ibuf, '\n'); 243 if (p != NULL) 244 *p = '\0'; 245 else if (!feof(stdin)) 246 { 247 fprintf(stderr, "%s: %s: line %d: line too long (%d bytes max)\n", 248 progname, mapname, lineno, sizeof ibuf); 249 continue; 250 } 251 252 if (ibuf[0] == '\0' || ibuf[0] == '#') 253 continue; 254 if (isspace(ibuf[0])) 255 { 256 fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 257 progname, mapname, lineno); 258 continue; 259 } 260 key.xx.data = ibuf; 261 for (p = ibuf; *p != '\0' && !isspace(*p); p++) 262 { 263 if (foldcase && isupper(*p)) 264 *p = tolower(*p); 265 } 266 key.xx.size = p - key.xx.data; 267 if (inclnull) 268 key.xx.size++; 269 if (*p != '\0') 270 *p++ = '\0'; 271 while (isspace(*p)) 272 p++; 273 if (*p == '\0') 274 { 275 fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 276 progname, mapname, lineno, key.xx.data); 277 continue; 278 } 279 val.xx.data = p; 280 val.xx.size = strlen(p); 281 if (inclnull) 282 val.xx.size++; 283 284 /* 285 ** Do the database insert. 286 */ 287 288 if (verbose) 289 { 290 printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 291 } 292 293 switch (type) 294 { 295 #ifdef NDBM 296 case T_DBM: 297 st = dbm_store(dbp.dbm, key.dbm, val.dbm, 298 allowreplace ? DBM_REPLACE : DBM_INSERT); 299 break; 300 #endif 301 302 #ifdef NEWDB 303 case T_BTREE: 304 case T_HASH: 305 st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 306 allowreplace ? 0 : R_NOOVERWRITE); 307 break; 308 #endif 309 } 310 311 if (st < 0) 312 { 313 fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 314 progname, mapname, lineno, key.xx.data); 315 perror(mapname); 316 exitstat = EX_IOERR; 317 } 318 else if (st > 0) 319 { 320 fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 321 progname, mapname, lineno, key.xx.data); 322 } 323 } 324 325 /* 326 ** Now close the database. 327 */ 328 329 switch (type) 330 { 331 #ifdef NDBM 332 case T_DBM: 333 dbm_close(dbp.dbm); 334 break; 335 #endif 336 337 #ifdef NEWDB 338 case T_HASH: 339 case T_BTREE: 340 if ((*dbp.db->close)(dbp.db) < 0) 341 { 342 fprintf(stderr, "%s: %s: error on close\n", 343 progname, mapname); 344 perror(mapname); 345 exitstat = EX_IOERR; 346 } 347 #endif 348 } 349 350 exit (exitstat); 351 } 352