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