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 |
ba106d47 |
55 | getopt(int argc, char **argv, char *optstring) |
463ee0b2 |
56 | { |
57 | register int c; |
58 | register char *place; |
59 | extern char *index(); |
60 | static int optind = 0; |
61 | static char *scan = NULL; |
62 | |
63 | optarg = NULL; |
64 | |
65 | if (scan == NULL || *scan == '\0') { |
66 | |
67 | if (optind == 0) |
68 | optind++; |
69 | if (optind >= argc) |
70 | return ':'; |
71 | |
72 | optarg = place = argv[optind++]; |
73 | if (place[0] != '-' || place[1] == '\0') |
74 | return '?'; |
75 | if (place[1] == '-' && place[2] == '\0') |
76 | return '?'; |
77 | scan = place + 1; |
78 | } |
79 | |
80 | c = *scan++; |
81 | place = index(optstring, c); |
82 | if (place == NULL || c == ':' || c == ';') { |
83 | |
84 | (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); |
85 | scan = NULL; |
86 | return '!'; |
87 | } |
88 | if (*++place == ':') { |
89 | |
90 | if (*scan != '\0') { |
91 | |
92 | optarg = scan; |
93 | scan = NULL; |
94 | |
95 | } |
96 | else { |
97 | |
98 | if (optind >= argc) { |
99 | |
100 | (void) fprintf(stderr, "%s: %c requires an argument\n", |
101 | argv[0], c); |
102 | return '!'; |
103 | } |
104 | optarg = argv[optind]; |
105 | optind++; |
106 | } |
107 | } |
108 | else if (*place == ';') { |
109 | |
110 | if (*scan != '\0') { |
111 | |
112 | optarg = scan; |
113 | scan = NULL; |
114 | |
115 | } |
116 | else { |
117 | |
118 | if (optind >= argc || *argv[optind] == '-') |
119 | optarg = NULL; |
120 | else { |
121 | optarg = argv[optind]; |
122 | optind++; |
123 | } |
124 | } |
125 | } |
126 | return c; |
127 | } |
128 | |
129 | |
130 | void |
ba106d47 |
131 | print_datum(datum db) |
463ee0b2 |
132 | { |
133 | int i; |
134 | |
135 | putchar('"'); |
136 | for (i = 0; i < db.dsize; i++) { |
de030af3 |
137 | if (isprint((unsigned char)db.dptr[i])) |
463ee0b2 |
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 |
ba106d47 |
151 | read_datum(char *s) |
463ee0b2 |
152 | { |
153 | datum db; |
154 | char *p; |
155 | int i; |
156 | |
157 | db.dsize = 0; |
158 | db.dptr = (char *) malloc(strlen(s) * sizeof(char)); |
db7c17d7 |
159 | if (!db.dptr) |
160 | oops("cannot get memory"); |
161 | |
463ee0b2 |
162 | for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) { |
163 | if (*s == '\\') { |
164 | if (*++s == 'n') |
165 | *p = '\n'; |
166 | else if (*s == 'r') |
167 | *p = '\r'; |
168 | else if (*s == 'f') |
169 | *p = '\f'; |
170 | else if (*s == 't') |
171 | *p = '\t'; |
de030af3 |
172 | else if (isdigit((unsigned char)*s) |
173 | && isdigit((unsigned char)*(s + 1)) |
174 | && isdigit((unsigned char)*(s + 2))) |
175 | { |
463ee0b2 |
176 | i = (*s++ - '0') << 6; |
177 | i |= (*s++ - '0') << 3; |
178 | i |= *s - '0'; |
179 | *p = i; |
180 | } |
181 | else if (*s == '0') |
182 | *p = '\0'; |
183 | else |
184 | *p = *s; |
185 | } |
186 | else |
187 | *p = *s; |
188 | } |
189 | |
190 | return db; |
191 | } |
192 | |
193 | |
194 | char * |
ba106d47 |
195 | key2s(datum db) |
463ee0b2 |
196 | { |
197 | char *buf; |
198 | char *p1, *p2; |
199 | |
200 | buf = (char *) malloc((db.dsize + 1) * sizeof(char)); |
db7c17d7 |
201 | if (!buf) |
202 | oops("cannot get memory"); |
463ee0b2 |
203 | for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++); |
204 | *p1 = '\0'; |
205 | return buf; |
206 | } |
207 | |
ba106d47 |
208 | int |
209 | main(int argc, char **argv) |
463ee0b2 |
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 | |
db7c17d7 |
288 | if (giveusage || what == YOW || argn < 1) { |
463ee0b2 |
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 | } |