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