This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove another dead function in vms/vms.c.
[perl5.git] / ext / SDBM_File / 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(int argc, char **argv, char *optstring)
56 {
57         int c;
58         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
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
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 *
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
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 database [-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 }