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
getopt(int argc,char ** argv,char * optstring)55 getopt(int argc, char **argv, char *optstring)
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
print_datum(datum db)131 print_datum(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(char * s)151 read_datum(char *s)
152 {
153 	datum db;
154 	char *p;
155 	int i;
156 
157 	db.dsize = 0;
158 	db.dptr = (char *) malloc(strlen(s) * sizeof(char));
159 	if (!db.dptr)
160 	    oops("cannot get memory");
161 
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';
172 			else if (isdigit((unsigned char)*s)
173 				 && isdigit((unsigned char)*(s + 1))
174 				 && isdigit((unsigned char)*(s + 2)))
175 			{
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 *
key2s(datum db)195 key2s(datum db)
196 {
197 	char *buf;
198 	char *p1, *p2;
199 
200 	buf = (char *) malloc((db.dsize + 1) * sizeof(char));
201 	if (!buf)
202 	    oops("cannot get memory");
203 	for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
204 	*p1 = '\0';
205 	return buf;
206 }
207 
208 int
main(int argc,char ** argv)209 main(int argc, 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 }
436