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(int argc,char ** argv,char * optstring)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
print_datum(datum db)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
read_datum(char * s)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 *
key2s(datum db)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
main(int argc,char ** argv)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