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++) { |
141 | if (isprint(db.dptr[i])) |
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)); |
164 | for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) { |
165 | if (*s == '\\') { |
166 | if (*++s == 'n') |
167 | *p = '\n'; |
168 | else if (*s == 'r') |
169 | *p = '\r'; |
170 | else if (*s == 'f') |
171 | *p = '\f'; |
172 | else if (*s == 't') |
173 | *p = '\t'; |
174 | else if (isdigit(*s) && isdigit(*(s + 1)) && isdigit(*(s + 2))) { |
175 | i = (*s++ - '0') << 6; |
176 | i |= (*s++ - '0') << 3; |
177 | i |= *s - '0'; |
178 | *p = i; |
179 | } |
180 | else if (*s == '0') |
181 | *p = '\0'; |
182 | else |
183 | *p = *s; |
184 | } |
185 | else |
186 | *p = *s; |
187 | } |
188 | |
189 | return db; |
190 | } |
191 | |
192 | |
193 | char * |
194 | key2s(db) |
195 | datum db; |
196 | { |
197 | char *buf; |
198 | char *p1, *p2; |
199 | |
200 | buf = (char *) malloc((db.dsize + 1) * sizeof(char)); |
201 | for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++); |
202 | *p1 = '\0'; |
203 | return buf; |
204 | } |
205 | |
206 | |
207 | main(argc, argv) |
208 | int argc; |
209 | char **argv; |
210 | { |
211 | typedef enum { |
212 | YOW, FETCH, STORE, DELETE, SCAN, REGEXP |
213 | } commands; |
214 | char opt; |
215 | int flags; |
216 | int giveusage = 0; |
217 | int verbose = 0; |
218 | commands what = YOW; |
219 | char *comarg[3]; |
220 | int st_flag = DBM_INSERT; |
221 | int argn; |
222 | DBM *db; |
223 | datum key; |
224 | datum content; |
225 | |
226 | flags = O_RDWR; |
227 | argn = 0; |
228 | |
229 | while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') { |
230 | switch (opt) { |
231 | case 'a': |
232 | what = SCAN; |
233 | break; |
234 | case 'c': |
235 | flags |= O_CREAT; |
236 | break; |
237 | case 'd': |
238 | what = DELETE; |
239 | break; |
240 | case 'f': |
241 | what = FETCH; |
242 | break; |
243 | case 'F': |
244 | what = REGEXP; |
245 | break; |
246 | case 'm': |
247 | flags &= ~(000007); |
248 | if (strcmp(optarg, "r") == 0) |
249 | flags |= O_RDONLY; |
250 | else if (strcmp(optarg, "w") == 0) |
251 | flags |= O_WRONLY; |
252 | else if (strcmp(optarg, "rw") == 0) |
253 | flags |= O_RDWR; |
254 | else { |
255 | fprintf(stderr, "Invalid mode: \"%s\"\n", optarg); |
256 | giveusage = 1; |
257 | } |
258 | break; |
259 | case 'r': |
260 | st_flag = DBM_REPLACE; |
261 | break; |
262 | case 's': |
263 | what = STORE; |
264 | break; |
265 | case 't': |
266 | flags |= O_TRUNC; |
267 | break; |
268 | case 'v': |
269 | verbose = 1; |
270 | break; |
271 | case 'x': |
272 | flags |= O_EXCL; |
273 | break; |
274 | case '!': |
275 | giveusage = 1; |
276 | break; |
277 | case '?': |
278 | if (argn < 3) |
279 | comarg[argn++] = optarg; |
280 | else { |
281 | fprintf(stderr, "Too many arguments.\n"); |
282 | giveusage = 1; |
283 | } |
284 | break; |
285 | } |
286 | } |
287 | |
288 | if (giveusage | what == YOW | argn < 1) { |
289 | fprintf(stderr, "Usage: %s databse [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]); |
290 | exit(-1); |
291 | } |
292 | |
293 | if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) { |
294 | fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]); |
295 | exit(-1); |
296 | } |
297 | |
298 | if (argn > 1) |
299 | key = read_datum(comarg[1]); |
300 | if (argn > 2) |
301 | content = read_datum(comarg[2]); |
302 | |
303 | switch (what) { |
304 | |
305 | case SCAN: |
306 | key = dbm_firstkey(db); |
307 | if (dbm_error(db)) { |
308 | fprintf(stderr, "Error when fetching first key\n"); |
309 | goto db_exit; |
310 | } |
311 | while (key.dptr != NULL) { |
312 | content = dbm_fetch(db, key); |
313 | if (dbm_error(db)) { |
314 | fprintf(stderr, "Error when fetching "); |
315 | print_datum(key); |
316 | printf("\n"); |
317 | goto db_exit; |
318 | } |
319 | print_datum(key); |
320 | printf(": "); |
321 | print_datum(content); |
322 | printf("\n"); |
323 | if (dbm_error(db)) { |
324 | fprintf(stderr, "Error when fetching next key\n"); |
325 | goto db_exit; |
326 | } |
327 | key = dbm_nextkey(db); |
328 | } |
329 | break; |
330 | |
331 | case REGEXP: |
332 | if (argn < 2) { |
333 | fprintf(stderr, "Missing regular expression.\n"); |
334 | goto db_exit; |
335 | } |
336 | if (re_comp(comarg[1])) { |
337 | fprintf(stderr, "Invalid regular expression\n"); |
338 | goto db_exit; |
339 | } |
340 | key = dbm_firstkey(db); |
341 | if (dbm_error(db)) { |
342 | fprintf(stderr, "Error when fetching first key\n"); |
343 | goto db_exit; |
344 | } |
345 | while (key.dptr != NULL) { |
346 | if (re_exec(key2s(key))) { |
347 | content = dbm_fetch(db, key); |
348 | if (dbm_error(db)) { |
349 | fprintf(stderr, "Error when fetching "); |
350 | print_datum(key); |
351 | printf("\n"); |
352 | goto db_exit; |
353 | } |
354 | print_datum(key); |
355 | printf(": "); |
356 | print_datum(content); |
357 | printf("\n"); |
358 | if (dbm_error(db)) { |
359 | fprintf(stderr, "Error when fetching next key\n"); |
360 | goto db_exit; |
361 | } |
362 | } |
363 | key = dbm_nextkey(db); |
364 | } |
365 | break; |
366 | |
367 | case FETCH: |
368 | if (argn < 2) { |
369 | fprintf(stderr, "Missing fetch key.\n"); |
370 | goto db_exit; |
371 | } |
372 | content = dbm_fetch(db, key); |
373 | if (dbm_error(db)) { |
374 | fprintf(stderr, "Error when fetching "); |
375 | print_datum(key); |
376 | printf("\n"); |
377 | goto db_exit; |
378 | } |
379 | if (content.dptr == NULL) { |
380 | fprintf(stderr, "Cannot find "); |
381 | print_datum(key); |
382 | printf("\n"); |
383 | goto db_exit; |
384 | } |
385 | print_datum(key); |
386 | printf(": "); |
387 | print_datum(content); |
388 | printf("\n"); |
389 | break; |
390 | |
391 | case DELETE: |
392 | if (argn < 2) { |
393 | fprintf(stderr, "Missing delete key.\n"); |
394 | goto db_exit; |
395 | } |
396 | if (dbm_delete(db, key) || dbm_error(db)) { |
397 | fprintf(stderr, "Error when deleting "); |
398 | print_datum(key); |
399 | printf("\n"); |
400 | goto db_exit; |
401 | } |
402 | if (verbose) { |
403 | print_datum(key); |
404 | printf(": DELETED\n"); |
405 | } |
406 | break; |
407 | |
408 | case STORE: |
409 | if (argn < 3) { |
410 | fprintf(stderr, "Missing key and/or content.\n"); |
411 | goto db_exit; |
412 | } |
413 | if (dbm_store(db, key, content, st_flag) || dbm_error(db)) { |
414 | fprintf(stderr, "Error when storing "); |
415 | print_datum(key); |
416 | printf("\n"); |
417 | goto db_exit; |
418 | } |
419 | if (verbose) { |
420 | print_datum(key); |
421 | printf(": "); |
422 | print_datum(content); |
423 | printf(" STORED\n"); |
424 | } |
425 | break; |
426 | } |
427 | |
428 | db_exit: |
429 | dbm_clearerr(db); |
430 | dbm_close(db); |
431 | if (dbm_error(db)) { |
432 | fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]); |
433 | exit(-1); |
434 | } |
435 | } |