1#include <stdio.h>
2#include <sys/file.h>
3#ifdef SDBM
4#include "EXTERN.h"
5#include "sdbm.h"
6#else
7#include <ndbm.h>
8#endif
9#include <string.h>
10
11extern int	getopt();
12extern void	oops();
13
14char *progname;
15
16static int rflag;
17static char *usage = "%s [-R] cat | look |... dbmname";
18
19#define DERROR	0
20#define DLOOK	1
21#define DINSERT	2
22#define DDELETE 3
23#define DCAT    4
24#define DBUILD	5
25#define DPRESS	6
26#define DCREAT	7
27
28#define LINEMAX	8192
29
30typedef struct {
31        char *sname;
32        int scode;
33        int flags;
34} cmd;
35
36static cmd cmds[] = {
37
38        "fetch", DLOOK, 	O_RDONLY,
39        "get", DLOOK,		O_RDONLY,
40        "look", DLOOK,		O_RDONLY,
41        "add", DINSERT,		O_RDWR,
42        "insert", DINSERT,	O_RDWR,
43        "store", DINSERT,	O_RDWR,
44        "delete", DDELETE,	O_RDWR,
45        "remove", DDELETE,	O_RDWR,
46        "dump", DCAT,		O_RDONLY,
47        "list", DCAT, 		O_RDONLY,
48        "cat", DCAT,		O_RDONLY,
49        "creat", DCREAT,	O_RDWR | O_CREAT | O_TRUNC,
50        "new", DCREAT,		O_RDWR | O_CREAT | O_TRUNC,
51        "build", DBUILD,	O_RDWR | O_CREAT,
52        "squash", DPRESS,	O_RDWR,
53        "compact", DPRESS,	O_RDWR,
54        "compress", DPRESS,	O_RDWR
55};
56
57#define CTABSIZ (sizeof (cmds)/sizeof (cmd))
58
59static cmd *parse();
60static void badk(), doit(), prdatum();
61
62int
63main(int argc, char **argv)
64{
65        int c;
66        cmd *act;
67        extern int optind;
68        extern char *optarg;
69
70        progname = argv[0];
71
72        while ((c = getopt(argc, argv, "R")) != EOF)
73                switch (c) {
74                case 'R':	       /* raw processing  */
75                        rflag++;
76                        break;
77
78                default:
79                        oops("usage: %s", usage);
80                        break;
81                }
82
83        if ((argc -= optind) < 2)
84                oops("usage: %s", usage);
85
86        if ((act = parse(argv[optind])) == NULL)
87                badk(argv[optind]);
88        optind++;
89        doit(act, argv[optind]);
90        return 0;
91}
92
93static void
94doit(cmd *act, char *file)
95{
96        datum key;
97        datum val;
98        DBM *db;
99        char *op;
100        int n;
101        char *line;
102#ifdef TIME
103        long start;
104        extern long time();
105#endif
106
107        if ((db = dbm_open(file, act->flags, 0644)) == NULL)
108                oops("cannot open: %s", file);
109
110        if ((line = (char *) malloc(LINEMAX)) == NULL)
111                oops("%s: cannot get memory", "line alloc");
112
113        switch (act->scode) {
114
115        case DLOOK:
116                while (fgets(line, LINEMAX, stdin) != NULL) {
117                        n = strlen(line) - 1;
118                        line[n] = 0;
119                        key.dptr = line;
120                        key.dsize = n;
121                        val = dbm_fetch(db, key);
122                        if (val.dptr != NULL) {
123                                prdatum(stdout, val);
124                                putchar('\n');
125                                continue;
126                        }
127                        prdatum(stderr, key);
128                        fprintf(stderr, ": not found.\n");
129                }
130                break;
131        case DINSERT:
132                break;
133        case DDELETE:
134                while (fgets(line, LINEMAX, stdin) != NULL) {
135                        n = strlen(line) - 1;
136                        line[n] = 0;
137                        key.dptr = line;
138                        key.dsize = n;
139                        if (dbm_delete(db, key) == -1) {
140                                prdatum(stderr, key);
141                                fprintf(stderr, ": not found.\n");
142                        }
143                }
144                break;
145        case DCAT:
146                for (key = dbm_firstkey(db); key.dptr != 0;
147                     key = dbm_nextkey(db)) {
148                        prdatum(stdout, key);
149                        putchar('\t');
150                        prdatum(stdout, dbm_fetch(db, key));
151                        putchar('\n');
152                }
153                break;
154        case DBUILD:
155#ifdef TIME
156                start = time(0);
157#endif
158                while (fgets(line, LINEMAX, stdin) != NULL) {
159                        n = strlen(line) - 1;
160                        line[n] = 0;
161                        key.dptr = line;
162                        if ((op = strchr(line, '\t')) != 0) {
163                                key.dsize = op - line;
164                                *op++ = 0;
165                                val.dptr = op;
166                                val.dsize = line + n - op;
167                        }
168                        else
169                                oops("bad input; %s", line);
170
171                        if (dbm_store(db, key, val, DBM_REPLACE) < 0) {
172                                prdatum(stderr, key);
173                                fprintf(stderr, ": ");
174                                oops("store: %s", "failed");
175                        }
176                }
177#ifdef TIME
178                printf("done: %d seconds.\n", time(0) - start);
179#endif
180                break;
181        case DPRESS:
182                break;
183        case DCREAT:
184                break;
185        }
186
187        dbm_close(db);
188}
189
190static void
191badk(char *word)
192{
193        int i;
194
195        if (progname)
196                fprintf(stderr, "%s: ", progname);
197        fprintf(stderr, "bad keywd %s. use one of\n", word);
198        for (i = 0; i < (int)CTABSIZ; i++)
199                fprintf(stderr, "%-8s%c", cmds[i].sname,
200                        ((i + 1) % 6 == 0) ? '\n' : ' ');
201        fprintf(stderr, "\n");
202        exit(1);
203        /*NOTREACHED*/
204}
205
206static cmd *
207parse(char *str)
208{
209        int i = CTABSIZ;
210        cmd *p;
211
212        for (p = cmds; i--; p++)
213                if (strcmp(p->sname, str) == 0)
214                        return p;
215        return NULL;
216}
217
218static void
219prdatum(FILE *stream, datum d)
220{
221        int c;
222        U8 *p = (U8 *) d.dptr;
223        int n = d.dsize;
224
225        while (n--) {
226                c = *p++;
227#ifndef EBCDIC /* Meta notation doesn't make sense on EBCDIC systems*/
228                if (c & 0200) {
229                    fprintf(stream, "M-");
230                    c &= 0177;
231                }
232#endif
233                /* \c notation applies for \0 . \x1f, plus \c? */
234                if (c <= 0x1F || c == QUESTION_MARK_CTRL) {
235                    fprintf(stream, "^%c", toCTRL(c));
236                }
237#ifdef EBCDIC   /* Instead of meta, use \x{} for non-printables */
238                else if (! isPRINT_A(c)) {
239                    fprintf(stream, "\\x{%02x}", c);
240                }
241#endif
242                else { /* must be an ASCII printable */
243                    putc(c, stream);
244                }
245        }
246}
247
248
249