Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / perl5 / 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(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         for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) {
165                 if (*s == '\\') {
166                         if (*++s == 'n')
167                                 *p = '\n';
168                         else if (*s == 'r')
169                                 *p = '\r';
170                         else if (*s == 'f')
171                                 *p = '\f';
172                         else if (*s == 't')
173                                 *p = '\t';
174                         else if (isdigit(*s) && isdigit(*(s + 1)) && isdigit(*(s + 2))) {
175                                 i = (*s++ - '0') << 6;
176                                 i |= (*s++ - '0') << 3;
177                                 i |= *s - '0';
178                                 *p = i;
179                         }
180                         else if (*s == '0')
181                                 *p = '\0';
182                         else
183                                 *p = *s;
184                 }
185                 else
186                         *p = *s;
187         }
188
189         return db;
190 }
191
192
193 char *
194 key2s(db)
195 datum db;
196 {
197         char *buf;
198         char *p1, *p2;
199
200         buf = (char *) malloc((db.dsize + 1) * sizeof(char));
201         for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
202         *p1 = '\0';
203         return buf;
204 }
205
206
207 main(argc, argv)
208 int argc;
209 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 }