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.5 (Berkeley) 09/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 != '\0') 240 *p = '\0'; 241 if (ibuf[0] == '\0' || ibuf[0] == '#') 242 continue; 243 if (isspace(ibuf[0])) 244 { 245 fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n", 246 progname, mapname, lineno); 247 continue; 248 } 249 key.xx.data = ibuf; 250 for (p = ibuf; *p != '\0' && !isspace(*p); p++) 251 { 252 if (foldcase && isupper(*p)) 253 *p = tolower(*p); 254 } 255 key.xx.size = p - key.xx.data; 256 if (inclnull) 257 key.xx.size++; 258 if (*p != '\0') 259 *p++ = '\0'; 260 while (isspace(*p)) 261 p++; 262 if (*p == '\0') 263 { 264 fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", 265 progname, mapname, lineno, key.xx.data); 266 continue; 267 } 268 val.xx.data = p; 269 val.xx.size = strlen(p); 270 if (inclnull) 271 val.xx.size++; 272 273 /* 274 ** Do the database insert. 275 */ 276 277 if (verbose) 278 { 279 printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data); 280 } 281 282 switch (type) 283 { 284 #ifdef NDBM 285 case T_DBM: 286 st = dbm_store(dbp.dbm, key.dbm, val.dbm, 287 allowreplace ? DBM_REPLACE : DBM_INSERT); 288 break; 289 #endif 290 291 #ifdef NEWDB 292 case T_BTREE: 293 case T_HASH: 294 st = (*dbp.db->put)(dbp.db, &key.db, &val.db, 295 allowreplace ? 0 : R_NOOVERWRITE); 296 break; 297 #endif 298 } 299 300 if (st < 0) 301 { 302 fprintf(stderr, "%s: %s: line %d: key %s: put error\n", 303 progname, mapname, lineno, key.xx.data); 304 perror(mapname); 305 exitstat = EX_IOERR; 306 } 307 else if (st > 0) 308 { 309 fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", 310 progname, mapname, lineno, key.xx.data); 311 } 312 } 313 314 /* 315 ** Now close the database. 316 */ 317 318 switch (type) 319 { 320 #ifdef NDBM 321 case T_DBM: 322 dbm_close(dbp.dbm); 323 break; 324 #endif 325 326 #ifdef NEWDB 327 case T_HASH: 328 case T_BTREE: 329 if ((*dbp.db->close)(dbp.db) < 0) 330 { 331 fprintf(stderr, "%s: %s: error on close\n", 332 progname, mapname); 333 perror(mapname); 334 exitstat = EX_IOERR; 335 } 336 #endif 337 } 338 339 exit (exitstat); 340 } 341