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
11 extern int getopt();
12 extern void oops();
13
14 char *progname;
15
16 static int rflag;
17 static 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
30 typedef struct {
31 char *sname;
32 int scode;
33 int flags;
34 } cmd;
35
36 static 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
59 static cmd *parse();
60 static void badk(), doit(), prdatum();
61
62 int
main(int argc,char ** argv)63 main(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
93 static void
doit(cmd * act,char * file)94 doit(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
190 static void
badk(char * word)191 badk(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
206 static cmd *
parse(char * str)207 parse(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
218 static void
prdatum(FILE * stream,datum d)219 prdatum(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