1 #include <stdio.h> 2 #include <string.h> 3 #ifndef VMS 4 #include <sys/file.h> 5 #include <ndbm.h> 6 #else 7 #include "file.h" 8 #include "ndbm.h" 9 #endif 10 #include <ctype.h> 11 12 /***************************************************************************\ 13 ** ** 14 ** Function name: getopt() ** 15 ** Author: Henry Spencer, UofT ** 16 ** Coding date: 84/04/28 ** 17 ** ** 18 ** Description: ** 19 ** ** 20 ** Parses argv[] for arguments. ** 21 ** Works with Whitesmith's C compiler. ** 22 ** ** 23 ** Inputs - The number of arguments ** 24 ** - The base address of the array of arguments ** 25 ** - A string listing the valid options (':' indicates an ** 26 ** argument to the preceding option is required, a ';' ** 27 ** indicates an argument to the preceding option is optional) ** 28 ** ** 29 ** Outputs - Returns the next option character, ** 30 ** '?' for non '-' arguments ** 31 ** or ':' when there is no more arguments. ** 32 ** ** 33 ** Side Effects + The argument to an option is pointed to by 'optarg' ** 34 ** ** 35 ***************************************************************************** 36 ** ** 37 ** REVISION HISTORY: ** 38 ** ** 39 ** DATE NAME DESCRIPTION ** 40 ** YY/MM/DD ------------------ ------------------------------------ ** 41 ** 88/10/20 Janick Bergeron Returns '?' on unamed arguments ** 42 ** returns '!' on unknown options ** 43 ** and 'EOF' only when exhausted. ** 44 ** 88/11/18 Janick Bergeron Return ':' when no more arguments ** 45 ** 89/08/11 Janick Bergeron Optional optarg when ';' in optstring ** 46 ** ** 47 \***************************************************************************/ 48 49 char *optarg; /* Global argument pointer. */ 50 51 char 52 getopt(int argc, char **argv, char *optstring) 53 { 54 int c; 55 char *place; 56 static int optind = 0; 57 static char *scan = NULL; 58 59 optarg = NULL; 60 61 if (scan == NULL || *scan == '\0') { 62 63 if (optind == 0) 64 optind++; 65 if (optind >= argc) 66 return ':'; 67 68 optarg = place = argv[optind++]; 69 if (place[0] != '-' || place[1] == '\0') 70 return '?'; 71 if (place[1] == '-' && place[2] == '\0') 72 return '?'; 73 scan = place + 1; 74 } 75 76 c = *scan++; 77 place = strchr(optstring, c); 78 if (place == NULL || c == ':' || c == ';') { 79 80 (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); 81 scan = NULL; 82 return '!'; 83 } 84 if (*++place == ':') { 85 86 if (*scan != '\0') { 87 88 optarg = scan; 89 scan = NULL; 90 91 } 92 else { 93 94 if (optind >= argc) { 95 96 (void) fprintf(stderr, "%s: %c requires an argument\n", 97 argv[0], c); 98 return '!'; 99 } 100 optarg = argv[optind]; 101 optind++; 102 } 103 } 104 else if (*place == ';') { 105 106 if (*scan != '\0') { 107 108 optarg = scan; 109 scan = NULL; 110 111 } 112 else { 113 114 if (optind >= argc || *argv[optind] == '-') 115 optarg = NULL; 116 else { 117 optarg = argv[optind]; 118 optind++; 119 } 120 } 121 } 122 return c; 123 } 124 125 126 void 127 print_datum(datum db) 128 { 129 int i; 130 131 putchar('"'); 132 for (i = 0; i < db.dsize; i++) { 133 if (isprint((unsigned char)db.dptr[i])) 134 putchar(db.dptr[i]); 135 else { 136 putchar('\\'); 137 putchar('0' + ((db.dptr[i] >> 6) & 0x07)); 138 putchar('0' + ((db.dptr[i] >> 3) & 0x07)); 139 putchar('0' + (db.dptr[i] & 0x07)); 140 } 141 } 142 putchar('"'); 143 } 144 145 146 datum 147 read_datum(char *s) 148 { 149 datum db; 150 char *p; 151 int i; 152 153 db.dsize = 0; 154 db.dptr = (char *) malloc(strlen(s) * sizeof(char)); 155 if (!db.dptr) 156 oops("cannot get memory"); 157 158 for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) { 159 if (*s == '\\') { 160 if (*++s == 'n') 161 *p = '\n'; 162 else if (*s == 'r') 163 *p = '\r'; 164 else if (*s == 'f') 165 *p = '\f'; 166 else if (*s == 't') 167 *p = '\t'; 168 else if (isdigit((unsigned char)*s) 169 && isdigit((unsigned char)*(s + 1)) 170 && isdigit((unsigned char)*(s + 2))) 171 { 172 i = (*s++ - '0') << 6; 173 i |= (*s++ - '0') << 3; 174 i |= *s - '0'; 175 *p = i; 176 } 177 else if (*s == '0') 178 *p = '\0'; 179 else 180 *p = *s; 181 } 182 else 183 *p = *s; 184 } 185 186 return db; 187 } 188 189 190 char * 191 key2s(datum db) 192 { 193 char *buf; 194 char *p1, *p2; 195 196 buf = (char *) malloc((db.dsize + 1) * sizeof(char)); 197 if (!buf) 198 oops("cannot get memory"); 199 for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++); 200 *p1 = '\0'; 201 return buf; 202 } 203 204 int 205 main(int argc, char **argv) 206 { 207 typedef enum { 208 YOW, FETCH, STORE, DELETE, SCAN, REGEXP 209 } commands; 210 char opt; 211 int flags; 212 int giveusage = 0; 213 int verbose = 0; 214 commands what = YOW; 215 char *comarg[3]; 216 int st_flag = DBM_INSERT; 217 int argn; 218 DBM *db; 219 datum key; 220 datum content; 221 222 flags = O_RDWR; 223 argn = 0; 224 225 while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') { 226 switch (opt) { 227 case 'a': 228 what = SCAN; 229 break; 230 case 'c': 231 flags |= O_CREAT; 232 break; 233 case 'd': 234 what = DELETE; 235 break; 236 case 'f': 237 what = FETCH; 238 break; 239 case 'F': 240 what = REGEXP; 241 break; 242 case 'm': 243 flags &= ~(000007); 244 if (strcmp(optarg, "r") == 0) 245 flags |= O_RDONLY; 246 else if (strcmp(optarg, "w") == 0) 247 flags |= O_WRONLY; 248 else if (strcmp(optarg, "rw") == 0) 249 flags |= O_RDWR; 250 else { 251 fprintf(stderr, "Invalid mode: \"%s\"\n", optarg); 252 giveusage = 1; 253 } 254 break; 255 case 'r': 256 st_flag = DBM_REPLACE; 257 break; 258 case 's': 259 what = STORE; 260 break; 261 case 't': 262 flags |= O_TRUNC; 263 break; 264 case 'v': 265 verbose = 1; 266 break; 267 case 'x': 268 flags |= O_EXCL; 269 break; 270 case '!': 271 giveusage = 1; 272 break; 273 case '?': 274 if (argn < 3) 275 comarg[argn++] = optarg; 276 else { 277 fprintf(stderr, "Too many arguments.\n"); 278 giveusage = 1; 279 } 280 break; 281 } 282 } 283 284 if (giveusage || what == YOW || argn < 1) { 285 fprintf(stderr, "Usage: %s database [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]); 286 exit(-1); 287 } 288 289 if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) { 290 fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]); 291 exit(-1); 292 } 293 294 if (argn > 1) 295 key = read_datum(comarg[1]); 296 if (argn > 2) 297 content = read_datum(comarg[2]); 298 299 switch (what) { 300 301 case SCAN: 302 key = dbm_firstkey(db); 303 if (dbm_error(db)) { 304 fprintf(stderr, "Error when fetching first key\n"); 305 goto db_exit; 306 } 307 while (key.dptr != NULL) { 308 content = dbm_fetch(db, key); 309 if (dbm_error(db)) { 310 fprintf(stderr, "Error when fetching "); 311 print_datum(key); 312 printf("\n"); 313 goto db_exit; 314 } 315 print_datum(key); 316 printf(": "); 317 print_datum(content); 318 printf("\n"); 319 if (dbm_error(db)) { 320 fprintf(stderr, "Error when fetching next key\n"); 321 goto db_exit; 322 } 323 key = dbm_nextkey(db); 324 } 325 break; 326 327 case REGEXP: 328 if (argn < 2) { 329 fprintf(stderr, "Missing regular expression.\n"); 330 goto db_exit; 331 } 332 if (re_comp(comarg[1])) { 333 fprintf(stderr, "Invalid regular expression\n"); 334 goto db_exit; 335 } 336 key = dbm_firstkey(db); 337 if (dbm_error(db)) { 338 fprintf(stderr, "Error when fetching first key\n"); 339 goto db_exit; 340 } 341 while (key.dptr != NULL) { 342 if (re_exec(key2s(key))) { 343 content = dbm_fetch(db, key); 344 if (dbm_error(db)) { 345 fprintf(stderr, "Error when fetching "); 346 print_datum(key); 347 printf("\n"); 348 goto db_exit; 349 } 350 print_datum(key); 351 printf(": "); 352 print_datum(content); 353 printf("\n"); 354 if (dbm_error(db)) { 355 fprintf(stderr, "Error when fetching next key\n"); 356 goto db_exit; 357 } 358 } 359 key = dbm_nextkey(db); 360 } 361 break; 362 363 case FETCH: 364 if (argn < 2) { 365 fprintf(stderr, "Missing fetch key.\n"); 366 goto db_exit; 367 } 368 content = dbm_fetch(db, key); 369 if (dbm_error(db)) { 370 fprintf(stderr, "Error when fetching "); 371 print_datum(key); 372 printf("\n"); 373 goto db_exit; 374 } 375 if (content.dptr == NULL) { 376 fprintf(stderr, "Cannot find "); 377 print_datum(key); 378 printf("\n"); 379 goto db_exit; 380 } 381 print_datum(key); 382 printf(": "); 383 print_datum(content); 384 printf("\n"); 385 break; 386 387 case DELETE: 388 if (argn < 2) { 389 fprintf(stderr, "Missing delete key.\n"); 390 goto db_exit; 391 } 392 if (dbm_delete(db, key) || dbm_error(db)) { 393 fprintf(stderr, "Error when deleting "); 394 print_datum(key); 395 printf("\n"); 396 goto db_exit; 397 } 398 if (verbose) { 399 print_datum(key); 400 printf(": DELETED\n"); 401 } 402 break; 403 404 case STORE: 405 if (argn < 3) { 406 fprintf(stderr, "Missing key and/or content.\n"); 407 goto db_exit; 408 } 409 if (dbm_store(db, key, content, st_flag) || dbm_error(db)) { 410 fprintf(stderr, "Error when storing "); 411 print_datum(key); 412 printf("\n"); 413 goto db_exit; 414 } 415 if (verbose) { 416 print_datum(key); 417 printf(": "); 418 print_datum(content); 419 printf(" STORED\n"); 420 } 421 break; 422 } 423 424 db_exit: 425 dbm_clearerr(db); 426 dbm_close(db); 427 if (dbm_error(db)) { 428 fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]); 429 exit(-1); 430 } 431 } 432