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