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