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