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