xref: /openbsd/gnu/usr.bin/perl/ext/SDBM_File/dbe.c (revision d89ec533)
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
52 getopt(int argc, char **argv, char *optstring)
53 {
54 	int c;
55 	char *place;
56 	static int optind = 0;
57 	static char *scan = NULL;
58 
59 	optarg = NULL;
60 
61 	if (scan == NULL || *scan == '\0') {
62 
63 		if (optind == 0)
64 			optind++;
65 		if (optind >= argc)
66 			return ':';
67 
68 		optarg = place = argv[optind++];
69 		if (place[0] != '-' || place[1] == '\0')
70 			return '?';
71 		if (place[1] == '-' && place[2] == '\0')
72 			return '?';
73 		scan = place + 1;
74 	}
75 
76 	c = *scan++;
77 	place = strchr(optstring, c);
78 	if (place == NULL || c == ':' || c == ';') {
79 
80 		(void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
81 		scan = NULL;
82 		return '!';
83 	}
84 	if (*++place == ':') {
85 
86 		if (*scan != '\0') {
87 
88 			optarg = scan;
89 			scan = NULL;
90 
91 		}
92 		else {
93 
94 			if (optind >= argc) {
95 
96 				(void) fprintf(stderr, "%s: %c requires an argument\n",
97 					       argv[0], c);
98 				return '!';
99 			}
100 			optarg = argv[optind];
101 			optind++;
102 		}
103 	}
104 	else if (*place == ';') {
105 
106 		if (*scan != '\0') {
107 
108 			optarg = scan;
109 			scan = NULL;
110 
111 		}
112 		else {
113 
114 			if (optind >= argc || *argv[optind] == '-')
115 				optarg = NULL;
116 			else {
117 				optarg = argv[optind];
118 				optind++;
119 			}
120 		}
121 	}
122 	return c;
123 }
124 
125 
126 void
127 print_datum(datum db)
128 {
129 	int i;
130 
131 	putchar('"');
132 	for (i = 0; i < db.dsize; i++) {
133 		if (isprint((unsigned char)db.dptr[i]))
134 			putchar(db.dptr[i]);
135 		else {
136 			putchar('\\');
137 			putchar('0' + ((db.dptr[i] >> 6) & 0x07));
138 			putchar('0' + ((db.dptr[i] >> 3) & 0x07));
139 			putchar('0' + (db.dptr[i] & 0x07));
140 		}
141 	}
142 	putchar('"');
143 }
144 
145 
146 datum
147 read_datum(char *s)
148 {
149 	datum db;
150 	char *p;
151 	int i;
152 
153 	db.dsize = 0;
154 	db.dptr = (char *) malloc(strlen(s) * sizeof(char));
155 	if (!db.dptr)
156 	    oops("cannot get memory");
157 
158 	for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) {
159 		if (*s == '\\') {
160 			if (*++s == 'n')
161 				*p = '\n';
162 			else if (*s == 'r')
163 				*p = '\r';
164 			else if (*s == 'f')
165 				*p = '\f';
166 			else if (*s == 't')
167 				*p = '\t';
168 			else if (isdigit((unsigned char)*s)
169 				 && isdigit((unsigned char)*(s + 1))
170 				 && isdigit((unsigned char)*(s + 2)))
171 			{
172 				i = (*s++ - '0') << 6;
173 				i |= (*s++ - '0') << 3;
174 				i |= *s - '0';
175 				*p = i;
176 			}
177 			else if (*s == '0')
178 				*p = '\0';
179 			else
180 				*p = *s;
181 		}
182 		else
183 			*p = *s;
184 	}
185 
186 	return db;
187 }
188 
189 
190 char *
191 key2s(datum db)
192 {
193 	char *buf;
194 	char *p1, *p2;
195 
196 	buf = (char *) malloc((db.dsize + 1) * sizeof(char));
197 	if (!buf)
198 	    oops("cannot get memory");
199 	for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
200 	*p1 = '\0';
201 	return buf;
202 }
203 
204 int
205 main(int argc, char **argv)
206 {
207 	typedef enum {
208 		YOW, FETCH, STORE, DELETE, SCAN, REGEXP
209 	} commands;
210 	char opt;
211 	int flags;
212 	int giveusage = 0;
213 	int verbose = 0;
214 	commands what = YOW;
215 	char *comarg[3];
216 	int st_flag = DBM_INSERT;
217 	int argn;
218 	DBM *db;
219 	datum key;
220 	datum content;
221 
222 	flags = O_RDWR;
223 	argn = 0;
224 
225 	while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') {
226 		switch (opt) {
227 		case 'a':
228 			what = SCAN;
229 			break;
230 		case 'c':
231 			flags |= O_CREAT;
232 			break;
233 		case 'd':
234 			what = DELETE;
235 			break;
236 		case 'f':
237 			what = FETCH;
238 			break;
239 		case 'F':
240 			what = REGEXP;
241 			break;
242 		case 'm':
243 			flags &= ~(000007);
244 			if (strcmp(optarg, "r") == 0)
245 				flags |= O_RDONLY;
246 			else if (strcmp(optarg, "w") == 0)
247 				flags |= O_WRONLY;
248 			else if (strcmp(optarg, "rw") == 0)
249 				flags |= O_RDWR;
250 			else {
251 				fprintf(stderr, "Invalid mode: \"%s\"\n", optarg);
252 				giveusage = 1;
253 			}
254 			break;
255 		case 'r':
256 			st_flag = DBM_REPLACE;
257 			break;
258 		case 's':
259 			what = STORE;
260 			break;
261 		case 't':
262 			flags |= O_TRUNC;
263 			break;
264 		case 'v':
265 			verbose = 1;
266 			break;
267 		case 'x':
268 			flags |= O_EXCL;
269 			break;
270 		case '!':
271 			giveusage = 1;
272 			break;
273 		case '?':
274 			if (argn < 3)
275 				comarg[argn++] = optarg;
276 			else {
277 				fprintf(stderr, "Too many arguments.\n");
278 				giveusage = 1;
279 			}
280 			break;
281 		}
282 	}
283 
284 	if (giveusage || what == YOW || argn < 1) {
285 		fprintf(stderr, "Usage: %s database [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]);
286 		exit(-1);
287 	}
288 
289 	if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) {
290 		fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]);
291 		exit(-1);
292 	}
293 
294 	if (argn > 1)
295 		key = read_datum(comarg[1]);
296 	if (argn > 2)
297 		content = read_datum(comarg[2]);
298 
299 	switch (what) {
300 
301 	case SCAN:
302 		key = dbm_firstkey(db);
303 		if (dbm_error(db)) {
304 			fprintf(stderr, "Error when fetching first key\n");
305 			goto db_exit;
306 		}
307 		while (key.dptr != NULL) {
308 			content = dbm_fetch(db, key);
309 			if (dbm_error(db)) {
310 				fprintf(stderr, "Error when fetching ");
311 				print_datum(key);
312 				printf("\n");
313 				goto db_exit;
314 			}
315 			print_datum(key);
316 			printf(": ");
317 			print_datum(content);
318 			printf("\n");
319 			if (dbm_error(db)) {
320 				fprintf(stderr, "Error when fetching next key\n");
321 				goto db_exit;
322 			}
323 			key = dbm_nextkey(db);
324 		}
325 		break;
326 
327 	case REGEXP:
328 		if (argn < 2) {
329 			fprintf(stderr, "Missing regular expression.\n");
330 			goto db_exit;
331 		}
332 		if (re_comp(comarg[1])) {
333 			fprintf(stderr, "Invalid regular expression\n");
334 			goto db_exit;
335 		}
336 		key = dbm_firstkey(db);
337 		if (dbm_error(db)) {
338 			fprintf(stderr, "Error when fetching first key\n");
339 			goto db_exit;
340 		}
341 		while (key.dptr != NULL) {
342 			if (re_exec(key2s(key))) {
343 				content = dbm_fetch(db, key);
344 				if (dbm_error(db)) {
345 					fprintf(stderr, "Error when fetching ");
346 					print_datum(key);
347 					printf("\n");
348 					goto db_exit;
349 				}
350 				print_datum(key);
351 				printf(": ");
352 				print_datum(content);
353 				printf("\n");
354 				if (dbm_error(db)) {
355 					fprintf(stderr, "Error when fetching next key\n");
356 					goto db_exit;
357 				}
358 			}
359 			key = dbm_nextkey(db);
360 		}
361 		break;
362 
363 	case FETCH:
364 		if (argn < 2) {
365 			fprintf(stderr, "Missing fetch key.\n");
366 			goto db_exit;
367 		}
368 		content = dbm_fetch(db, key);
369 		if (dbm_error(db)) {
370 			fprintf(stderr, "Error when fetching ");
371 			print_datum(key);
372 			printf("\n");
373 			goto db_exit;
374 		}
375 		if (content.dptr == NULL) {
376 			fprintf(stderr, "Cannot find ");
377 			print_datum(key);
378 			printf("\n");
379 			goto db_exit;
380 		}
381 		print_datum(key);
382 		printf(": ");
383 		print_datum(content);
384 		printf("\n");
385 		break;
386 
387 	case DELETE:
388 		if (argn < 2) {
389 			fprintf(stderr, "Missing delete key.\n");
390 			goto db_exit;
391 		}
392 		if (dbm_delete(db, key) || dbm_error(db)) {
393 			fprintf(stderr, "Error when deleting ");
394 			print_datum(key);
395 			printf("\n");
396 			goto db_exit;
397 		}
398 		if (verbose) {
399 			print_datum(key);
400 			printf(": DELETED\n");
401 		}
402 		break;
403 
404 	case STORE:
405 		if (argn < 3) {
406 			fprintf(stderr, "Missing key and/or content.\n");
407 			goto db_exit;
408 		}
409 		if (dbm_store(db, key, content, st_flag) || dbm_error(db)) {
410 			fprintf(stderr, "Error when storing ");
411 			print_datum(key);
412 			printf("\n");
413 			goto db_exit;
414 		}
415 		if (verbose) {
416 			print_datum(key);
417 			printf(": ");
418 			print_datum(content);
419 			printf(" STORED\n");
420 		}
421 		break;
422 	}
423 
424 db_exit:
425 	dbm_clearerr(db);
426 	dbm_close(db);
427 	if (dbm_error(db)) {
428 		fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]);
429 		exit(-1);
430 	}
431 }
432