source: branches/samba-3.5.x/lib/tdb/tools/tdbtool.c

Last change on this file was 456, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: changes from 3.3

File size: 17.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Samba database functions
4 Copyright (C) Andrew Tridgell 1999-2000
5 Copyright (C) Paul `Rusty' Russell 2000
6 Copyright (C) Jeremy Allison 2000
7 Copyright (C) Andrew Esh 2001
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "replace.h"
24#include "system/locale.h"
25#include "system/time.h"
26#include "system/filesys.h"
27#include "system/wait.h"
28#include "tdb.h"
29
30static int do_command(void);
31const char *cmdname;
32char *arg1, *arg2;
33size_t arg1len, arg2len;
34int bIterate = 0;
35char *line;
36TDB_DATA iterate_kbuf;
37char cmdline[1024];
38static int disable_mmap;
39
40#ifdef __OS2__
41static bool createDbCmd;
42#endif
43
44enum commands {
45 CMD_CREATE_TDB,
46 CMD_OPEN_TDB,
47 CMD_TRANSACTION_START,
48 CMD_TRANSACTION_COMMIT,
49 CMD_TRANSACTION_CANCEL,
50 CMD_ERASE,
51 CMD_DUMP,
52 CMD_INSERT,
53 CMD_MOVE,
54 CMD_STORE,
55 CMD_SHOW,
56 CMD_KEYS,
57 CMD_HEXKEYS,
58 CMD_DELETE,
59 CMD_LIST_HASH_FREE,
60 CMD_LIST_FREE,
61 CMD_INFO,
62 CMD_MMAP,
63 CMD_SPEED,
64 CMD_FIRST,
65 CMD_NEXT,
66 CMD_SYSTEM,
67 CMD_CHECK,
68 CMD_QUIT,
69 CMD_HELP
70};
71
72typedef struct {
73 const char *name;
74 enum commands cmd;
75} COMMAND_TABLE;
76
77COMMAND_TABLE cmd_table[] = {
78 {"create", CMD_CREATE_TDB},
79 {"open", CMD_OPEN_TDB},
80 {"transaction_start", CMD_TRANSACTION_START},
81 {"transaction_commit", CMD_TRANSACTION_COMMIT},
82 {"transaction_cancel", CMD_TRANSACTION_CANCEL},
83 {"erase", CMD_ERASE},
84 {"dump", CMD_DUMP},
85 {"insert", CMD_INSERT},
86 {"move", CMD_MOVE},
87 {"store", CMD_STORE},
88 {"show", CMD_SHOW},
89 {"keys", CMD_KEYS},
90 {"hexkeys", CMD_HEXKEYS},
91 {"delete", CMD_DELETE},
92 {"list", CMD_LIST_HASH_FREE},
93 {"free", CMD_LIST_FREE},
94 {"info", CMD_INFO},
95 {"speed", CMD_SPEED},
96 {"mmap", CMD_MMAP},
97 {"first", CMD_FIRST},
98 {"1", CMD_FIRST},
99 {"next", CMD_NEXT},
100 {"n", CMD_NEXT},
101 {"check", CMD_CHECK},
102 {"quit", CMD_QUIT},
103 {"q", CMD_QUIT},
104 {"!", CMD_SYSTEM},
105 {NULL, CMD_HELP}
106};
107
108struct timeval tp1,tp2;
109
110static void _start_timer(void)
111{
112 gettimeofday(&tp1,NULL);
113}
114
115static double _end_timer(void)
116{
117 gettimeofday(&tp2,NULL);
118 return((tp2.tv_sec - tp1.tv_sec) +
119 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
120}
121
122#ifdef PRINTF_ATTRIBUTE
123static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
124#endif
125static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...)
126{
127 va_list ap;
128
129 va_start(ap, format);
130 vfprintf(stderr, format, ap);
131 va_end(ap);
132}
133
134/* a tdb tool for manipulating a tdb database */
135
136static TDB_CONTEXT *tdb;
137
138static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
139static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
140static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
141
142static void print_asc(const char *buf,int len)
143{
144 int i;
145
146 /* We're probably printing ASCII strings so don't try to display
147 the trailing NULL character. */
148
149 if (buf[len - 1] == 0)
150 len--;
151
152 for (i=0;i<len;i++)
153 printf("%c",isprint(buf[i])?buf[i]:'.');
154}
155
156static void print_data(const char *buf,int len)
157{
158 int i=0;
159 if (len<=0) return;
160 printf("[%03X] ",i);
161 for (i=0;i<len;) {
162 printf("%02X ",(int)((unsigned char)buf[i]));
163 i++;
164 if (i%8 == 0) printf(" ");
165 if (i%16 == 0) {
166 print_asc(&buf[i-16],8); printf(" ");
167 print_asc(&buf[i-8],8); printf("\n");
168 if (i<len) printf("[%03X] ",i);
169 }
170 }
171 if (i%16) {
172 int n;
173
174 n = 16 - (i%16);
175 printf(" ");
176 if (n>8) printf(" ");
177 while (n--) printf(" ");
178
179 n = i%16;
180 if (n > 8) n = 8;
181 print_asc(&buf[i-(i%16)],n); printf(" ");
182 n = (i%16) - n;
183 if (n>0) print_asc(&buf[i-n],n);
184 printf("\n");
185 }
186}
187
188static void help(void)
189{
190 printf("\n"
191"tdbtool: \n"
192" create dbname : create a database\n"
193" open dbname : open an existing database\n"
194" transaction_start : start a transaction\n"
195" transaction_commit : commit a transaction\n"
196" transaction_cancel : cancel a transaction\n"
197" erase : erase the database\n"
198" dump : dump the database as strings\n"
199" keys : dump the database keys as strings\n"
200" hexkeys : dump the database keys as hex values\n"
201" info : print summary info about the database\n"
202" insert key data : insert a record\n"
203" move key file : move a record to a destination tdb\n"
204" store key data : store a record (replace)\n"
205" show key : show a record by key\n"
206" delete key : delete a record by key\n"
207" list : print the database hash table and freelist\n"
208" free : print the database freelist\n"
209" check : check the integrity of an opened database\n"
210" speed : perform speed tests on the database\n"
211" ! command : execute system command\n"
212" 1 | first : print the first record\n"
213" n | next : print the next record\n"
214" q | quit : terminate\n"
215" \\n : repeat 'next' command\n"
216"\n");
217}
218
219static void terror(const char *why)
220{
221 printf("%s\n", why);
222}
223
224static void create_tdb(const char *tdbname)
225{
226 struct tdb_logging_context log_ctx;
227 log_ctx.log_fn = tdb_log;
228
229 if (tdb) tdb_close(tdb);
230 tdb = tdb_open_ex(tdbname, 0, TDB_CLEAR_IF_FIRST | (disable_mmap?TDB_NOMMAP:0),
231 O_RDWR | O_CREAT | O_TRUNC, 0600, &log_ctx, NULL);
232 if (!tdb) {
233 printf("Could not create %s: %s\n", tdbname, strerror(errno));
234 }
235}
236
237static void open_tdb(const char *tdbname)
238{
239 struct tdb_logging_context log_ctx;
240 log_ctx.log_fn = tdb_log;
241
242 if (tdb) tdb_close(tdb);
243 tdb = tdb_open_ex(tdbname, 0, disable_mmap?TDB_NOMMAP:0, O_RDWR, 0600,
244 &log_ctx, NULL);
245#ifdef __OS2__
246 if (!tdb && !createDbCmd) {
247#else
248 if (!tdb) {
249#endif
250 printf("Could not open %s: %s\n", tdbname, strerror(errno));
251 }
252}
253
254static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
255{
256 TDB_DATA key, dbuf;
257
258 if ((keyname == NULL) || (keylen == 0)) {
259 terror("need key");
260 return;
261 }
262
263 key.dptr = (unsigned char *)keyname;
264 key.dsize = keylen;
265 dbuf.dptr = (unsigned char *)data;
266 dbuf.dsize = datalen;
267
268 if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
269 terror("insert failed");
270 }
271}
272
273static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
274{
275 TDB_DATA key, dbuf;
276
277 if ((keyname == NULL) || (keylen == 0)) {
278 terror("need key");
279 return;
280 }
281
282 if ((data == NULL) || (datalen == 0)) {
283 terror("need data");
284 return;
285 }
286
287 key.dptr = (unsigned char *)keyname;
288 key.dsize = keylen;
289 dbuf.dptr = (unsigned char *)data;
290 dbuf.dsize = datalen;
291
292 printf("Storing key:\n");
293 print_rec(tdb, key, dbuf, NULL);
294
295 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
296 terror("store failed");
297 }
298}
299
300static void show_tdb(char *keyname, size_t keylen)
301{
302 TDB_DATA key, dbuf;
303
304 if ((keyname == NULL) || (keylen == 0)) {
305 terror("need key");
306 return;
307 }
308
309 key.dptr = (unsigned char *)keyname;
310 key.dsize = keylen;
311
312 dbuf = tdb_fetch(tdb, key);
313 if (!dbuf.dptr) {
314 terror("fetch failed");
315 return;
316 }
317
318 print_rec(tdb, key, dbuf, NULL);
319
320 free( dbuf.dptr );
321
322 return;
323}
324
325static void delete_tdb(char *keyname, size_t keylen)
326{
327 TDB_DATA key;
328
329 if ((keyname == NULL) || (keylen == 0)) {
330 terror("need key");
331 return;
332 }
333
334 key.dptr = (unsigned char *)keyname;
335 key.dsize = keylen;
336
337 if (tdb_delete(tdb, key) != 0) {
338 terror("delete failed");
339 }
340}
341
342static void move_rec(char *keyname, size_t keylen, char* tdbname)
343{
344 TDB_DATA key, dbuf;
345 TDB_CONTEXT *dst_tdb;
346
347 if ((keyname == NULL) || (keylen == 0)) {
348 terror("need key");
349 return;
350 }
351
352 if ( !tdbname ) {
353 terror("need destination tdb name");
354 return;
355 }
356
357 key.dptr = (unsigned char *)keyname;
358 key.dsize = keylen;
359
360 dbuf = tdb_fetch(tdb, key);
361 if (!dbuf.dptr) {
362 terror("fetch failed");
363 return;
364 }
365
366 print_rec(tdb, key, dbuf, NULL);
367
368 dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
369 if ( !dst_tdb ) {
370 terror("unable to open destination tdb");
371 return;
372 }
373
374 if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
375 terror("failed to move record");
376 }
377 else
378 printf("record moved\n");
379
380 tdb_close( dst_tdb );
381
382 return;
383}
384
385static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
386{
387 printf("\nkey %d bytes\n", (int)key.dsize);
388 print_asc((const char *)key.dptr, key.dsize);
389 printf("\ndata %d bytes\n", (int)dbuf.dsize);
390 print_data((const char *)dbuf.dptr, dbuf.dsize);
391 return 0;
392}
393
394static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
395{
396 printf("key %d bytes: ", (int)key.dsize);
397 print_asc((const char *)key.dptr, key.dsize);
398 printf("\n");
399 return 0;
400}
401
402static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
403{
404 printf("key %d bytes\n", (int)key.dsize);
405 print_data((const char *)key.dptr, key.dsize);
406 printf("\n");
407 return 0;
408}
409
410static int total_bytes;
411
412static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
413{
414 total_bytes += dbuf.dsize;
415 return 0;
416}
417
418static void info_tdb(void)
419{
420 int count;
421 total_bytes = 0;
422 if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
423 printf("Error = %s\n", tdb_errorstr(tdb));
424 else
425 printf("%d records totalling %d bytes\n", count, total_bytes);
426}
427
428static void speed_tdb(const char *tlimit)
429{
430 const char *str = "store test", *str2 = "transaction test";
431 unsigned timelimit = tlimit?atoi(tlimit):0;
432 double t;
433 int ops;
434 if (timelimit == 0) timelimit = 5;
435
436 ops = 0;
437 printf("Testing store speed for %u seconds\n", timelimit);
438 _start_timer();
439 do {
440 long int r = random();
441 TDB_DATA key, dbuf;
442 key.dptr = discard_const_p(uint8_t, str);
443 key.dsize = strlen((char *)key.dptr);
444 dbuf.dptr = (uint8_t *) &r;
445 dbuf.dsize = sizeof(r);
446 tdb_store(tdb, key, dbuf, TDB_REPLACE);
447 t = _end_timer();
448 ops++;
449 } while (t < timelimit);
450 printf("%10.3f ops/sec\n", ops/t);
451
452 ops = 0;
453 printf("Testing fetch speed for %u seconds\n", timelimit);
454 _start_timer();
455 do {
456 long int r = random();
457 TDB_DATA key, dbuf;
458 key.dptr = discard_const_p(uint8_t, str);
459 key.dsize = strlen((char *)key.dptr);
460 dbuf.dptr = (uint8_t *) &r;
461 dbuf.dsize = sizeof(r);
462 tdb_fetch(tdb, key);
463 t = _end_timer();
464 ops++;
465 } while (t < timelimit);
466 printf("%10.3f ops/sec\n", ops/t);
467
468 ops = 0;
469 printf("Testing transaction speed for %u seconds\n", timelimit);
470 _start_timer();
471 do {
472 long int r = random();
473 TDB_DATA key, dbuf;
474 key.dptr = discard_const_p(uint8_t, str2);
475 key.dsize = strlen((char *)key.dptr);
476 dbuf.dptr = (uint8_t *) &r;
477 dbuf.dsize = sizeof(r);
478 tdb_transaction_start(tdb);
479 tdb_store(tdb, key, dbuf, TDB_REPLACE);
480 tdb_transaction_commit(tdb);
481 t = _end_timer();
482 ops++;
483 } while (t < timelimit);
484 printf("%10.3f ops/sec\n", ops/t);
485
486 ops = 0;
487 printf("Testing traverse speed for %u seconds\n", timelimit);
488 _start_timer();
489 do {
490 tdb_traverse(tdb, traverse_fn, NULL);
491 t = _end_timer();
492 ops++;
493 } while (t < timelimit);
494 printf("%10.3f ops/sec\n", ops/t);
495}
496
497static void toggle_mmap(void)
498{
499 disable_mmap = !disable_mmap;
500 if (disable_mmap) {
501 printf("mmap is disabled\n");
502 } else {
503 printf("mmap is enabled\n");
504 }
505}
506
507static char *tdb_getline(const char *prompt)
508{
509 static char thisline[1024];
510 char *p;
511 fputs(prompt, stdout);
512 thisline[0] = 0;
513 p = fgets(thisline, sizeof(thisline)-1, stdin);
514 if (p) p = strchr(p, '\n');
515 if (p) *p = 0;
516 return p?thisline:NULL;
517}
518
519static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
520 void *state)
521{
522 return tdb_delete(the_tdb, key);
523}
524
525static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
526{
527 TDB_DATA dbuf;
528 *pkey = tdb_firstkey(the_tdb);
529
530 dbuf = tdb_fetch(the_tdb, *pkey);
531 if (!dbuf.dptr) terror("fetch failed");
532 else {
533 print_rec(the_tdb, *pkey, dbuf, NULL);
534 }
535}
536
537static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
538{
539 TDB_DATA dbuf;
540 *pkey = tdb_nextkey(the_tdb, *pkey);
541
542 dbuf = tdb_fetch(the_tdb, *pkey);
543 if (!dbuf.dptr)
544 terror("fetch failed");
545 else
546 print_rec(the_tdb, *pkey, dbuf, NULL);
547}
548
549static int count(TDB_DATA key, TDB_DATA data, void *private_data)
550{
551 (*(unsigned int *)private_data)++;
552 return 0;
553}
554
555static void check_db(TDB_CONTEXT *the_tdb)
556{
557 int tdbcount = 0;
558 if (!the_tdb)
559 printf("Error: No database opened!\n");
560 else if (tdb_check(the_tdb, count, &tdbcount) == -1)
561 printf("Integrity check for the opened database failed.\n");
562 else
563 printf("Database integrity is OK and has %d records.\n",
564 tdbcount);
565}
566
567static int do_command(void)
568{
569 COMMAND_TABLE *ctp = cmd_table;
570 enum commands mycmd = CMD_HELP;
571 int cmd_len;
572
573#ifdef __OS2__
574 if (cmdname) {
575#endif
576
577 if (cmdname && strlen(cmdname) == 0) {
578 mycmd = CMD_NEXT;
579 } else {
580 while (ctp->name) {
581 cmd_len = strlen(ctp->name);
582 if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
583 mycmd = ctp->cmd;
584 break;
585 }
586 ctp++;
587 }
588 }
589#ifdef __OS2__
590 }
591#endif
592
593 switch (mycmd) {
594 case CMD_CREATE_TDB:
595 bIterate = 0;
596 create_tdb(arg1);
597 return 0;
598 case CMD_OPEN_TDB:
599 bIterate = 0;
600 open_tdb(arg1);
601 return 0;
602 case CMD_SYSTEM:
603 /* Shell command */
604 if (system(arg1) == -1) {
605 terror("system() call failed\n");
606 }
607 return 0;
608 case CMD_QUIT:
609 return 1;
610 default:
611 /* all the rest require a open database */
612 if (!tdb) {
613 bIterate = 0;
614 terror("database not open");
615 help();
616 return 0;
617 }
618 switch (mycmd) {
619 case CMD_TRANSACTION_START:
620 bIterate = 0;
621 tdb_transaction_start(tdb);
622 return 0;
623 case CMD_TRANSACTION_COMMIT:
624 bIterate = 0;
625 tdb_transaction_commit(tdb);
626 return 0;
627 case CMD_TRANSACTION_CANCEL:
628 bIterate = 0;
629 tdb_transaction_cancel(tdb);
630 return 0;
631 case CMD_ERASE:
632 bIterate = 0;
633 tdb_traverse(tdb, do_delete_fn, NULL);
634 return 0;
635 case CMD_DUMP:
636 bIterate = 0;
637 tdb_traverse(tdb, print_rec, NULL);
638 return 0;
639 case CMD_INSERT:
640 bIterate = 0;
641 insert_tdb(arg1, arg1len,arg2,arg2len);
642 return 0;
643 case CMD_MOVE:
644 bIterate = 0;
645 move_rec(arg1,arg1len,arg2);
646 return 0;
647 case CMD_STORE:
648 bIterate = 0;
649 store_tdb(arg1,arg1len,arg2,arg2len);
650 return 0;
651 case CMD_SHOW:
652 bIterate = 0;
653 show_tdb(arg1, arg1len);
654 return 0;
655 case CMD_KEYS:
656 tdb_traverse(tdb, print_key, NULL);
657 return 0;
658 case CMD_HEXKEYS:
659 tdb_traverse(tdb, print_hexkey, NULL);
660 return 0;
661 case CMD_DELETE:
662 bIterate = 0;
663 delete_tdb(arg1,arg1len);
664 return 0;
665 case CMD_LIST_HASH_FREE:
666 tdb_dump_all(tdb);
667 return 0;
668 case CMD_LIST_FREE:
669 tdb_printfreelist(tdb);
670 return 0;
671 case CMD_INFO:
672 info_tdb();
673 return 0;
674 case CMD_SPEED:
675 speed_tdb(arg1);
676 return 0;
677 case CMD_MMAP:
678 toggle_mmap();
679 return 0;
680 case CMD_FIRST:
681 bIterate = 1;
682 first_record(tdb, &iterate_kbuf);
683 return 0;
684 case CMD_NEXT:
685 if (bIterate)
686 next_record(tdb, &iterate_kbuf);
687 return 0;
688 case CMD_CHECK:
689 check_db(tdb);
690 return 0;
691 case CMD_HELP:
692 help();
693 return 0;
694 case CMD_CREATE_TDB:
695 case CMD_OPEN_TDB:
696 case CMD_SYSTEM:
697 case CMD_QUIT:
698 /*
699 * unhandled commands. cases included here to avoid compiler
700 * warnings.
701 */
702 return 0;
703 }
704 }
705
706 return 0;
707}
708
709static char *convert_string(char *instring, size_t *sizep)
710{
711 size_t length = 0;
712 char *outp, *inp;
713 char temp[3];
714
715 outp = inp = instring;
716
717 while (*inp) {
718 if (*inp == '\\') {
719 inp++;
720 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
721 temp[0] = *inp++;
722 temp[1] = '\0';
723 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
724 temp[1] = *inp++;
725 temp[2] = '\0';
726 }
727 *outp++ = (char)strtol((const char *)temp,NULL,16);
728 } else {
729 *outp++ = *inp++;
730 }
731 } else {
732 *outp++ = *inp++;
733 }
734 length++;
735 }
736 *sizep = length;
737 return instring;
738}
739
740int main(int argc, char *argv[])
741{
742 cmdname = "";
743 arg1 = NULL;
744 arg1len = 0;
745 arg2 = NULL;
746 arg2len = 0;
747
748#ifdef __OS2__
749 int cnt = 1;
750 createDbCmd = false;
751 while (argv[cnt]) {
752 if (strncmp("create",argv[cnt],6) == 0) {
753 createDbCmd = true;
754 break;
755 }
756 cnt++;
757 }
758#endif
759
760 if (argv[1]) {
761 cmdname = "open";
762 arg1 = argv[1];
763 do_command();
764 cmdname = "";
765 arg1 = NULL;
766 }
767
768 switch (argc) {
769 case 1:
770 case 2:
771 /* Interactive mode */
772 while ((cmdname = tdb_getline("tdb> "))) {
773 arg2 = arg1 = NULL;
774 if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
775 arg1++;
776 arg2 = arg1;
777 while (*arg2) {
778 if (*arg2 == ' ') {
779 *arg2++ = '\0';
780 break;
781 }
782 if ((*arg2++ == '\\') && (*arg2 == ' ')) {
783 arg2++;
784 }
785 }
786 }
787 if (arg1) arg1 = convert_string(arg1,&arg1len);
788 if (arg2) arg2 = convert_string(arg2,&arg2len);
789 if (do_command()) break;
790 }
791 break;
792 case 5:
793 arg2 = convert_string(argv[4],&arg2len);
794 case 4:
795 arg1 = convert_string(argv[3],&arg1len);
796 case 3:
797 cmdname = argv[2];
798 default:
799#ifdef __OS2__
800 if (argc == 3) {
801 arg1 = convert_string(argv[1], &arg1len);
802 }
803#endif
804 do_command();
805 break;
806 }
807
808 if (tdb) tdb_close(tdb);
809
810 return 0;
811}
Note: See TracBrowser for help on using the repository browser.