00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <errno.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include <string.h>
00030 #include <fcntl.h>
00031 #include <time.h>
00032 #include <sys/mman.h>
00033 #include <sys/stat.h>
00034 #include <sys/time.h>
00035 #include <ctype.h>
00036 #include <signal.h>
00037 #include "tdb.h"
00038 #include "pstring.h"
00039
00040 static int do_command(void);
00041 char *cmdname, *arg1, *arg2;
00042 size_t arg1len, arg2len;
00043 int do_connections;
00044 int bIterate = 0;
00045 char *line;
00046 TDB_DATA iterate_kbuf;
00047 char cmdline[1024];
00048
00049 enum commands {
00050 CMD_CREATE_TDB,
00051 CMD_OPEN_TDB,
00052 CMD_ERASE,
00053 CMD_DUMP,
00054 CMD_CDUMP,
00055 CMD_INSERT,
00056 CMD_MOVE,
00057 CMD_STORE,
00058 CMD_SHOW,
00059 CMD_KEYS,
00060 CMD_HEXKEYS,
00061 CMD_DELETE,
00062 CMD_LIST_HASH_FREE,
00063 CMD_LIST_FREE,
00064 CMD_INFO,
00065 CMD_FIRST,
00066 CMD_NEXT,
00067 CMD_SYSTEM,
00068 CMD_QUIT,
00069 CMD_HELP
00070 };
00071
00072 typedef struct {
00073 const char *name;
00074 enum commands cmd;
00075 } COMMAND_TABLE;
00076
00077 COMMAND_TABLE cmd_table[] = {
00078 {"create", CMD_CREATE_TDB},
00079 {"open", CMD_OPEN_TDB},
00080 {"erase", CMD_ERASE},
00081 {"dump", CMD_DUMP},
00082 {"cdump", CMD_CDUMP},
00083 {"insert", CMD_INSERT},
00084 {"move", CMD_MOVE},
00085 {"store", CMD_STORE},
00086 {"show", CMD_SHOW},
00087 {"keys", CMD_KEYS},
00088 {"hexkeys", CMD_HEXKEYS},
00089 {"delete", CMD_DELETE},
00090 {"list", CMD_LIST_HASH_FREE},
00091 {"free", CMD_LIST_FREE},
00092 {"info", CMD_INFO},
00093 {"first", CMD_FIRST},
00094 {"1", CMD_FIRST},
00095 {"next", CMD_NEXT},
00096 {"n", CMD_NEXT},
00097 {"quit", CMD_QUIT},
00098 {"q", CMD_QUIT},
00099 {"!", CMD_SYSTEM},
00100 {NULL, CMD_HELP}
00101 };
00102
00103
00104
00105
00106
00107 typedef struct connections_key {
00108 pid_t pid;
00109 int cnum;
00110 fstring name;
00111 } connections_key;
00112
00113 typedef struct connections_data {
00114 int magic;
00115 pid_t pid;
00116 int cnum;
00117 uid_t uid;
00118 gid_t gid;
00119 char servicename[FSTRING_LEN];
00120 char addr[24];
00121 char machine[FSTRING_LEN];
00122 time_t start;
00123 unsigned bcast_msg_flags;
00124 } connections_data;
00125
00126 static TDB_CONTEXT *tdb;
00127
00128 static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00129 static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00130 static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00131 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00132 static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
00133
00134 static void print_asc(const char *buf,int len)
00135 {
00136 int i;
00137
00138
00139
00140
00141 if (buf[len - 1] == 0)
00142 len--;
00143
00144 for (i=0;i<len;i++)
00145 printf("%c",isprint(buf[i])?buf[i]:'.');
00146 }
00147
00148 static void print_data(const char *buf,int len)
00149 {
00150 int i=0;
00151 if (len<=0) return;
00152 printf("[%03X] ",i);
00153 for (i=0;i<len;) {
00154 printf("%02X ",(int)((unsigned char)buf[i]));
00155 i++;
00156 if (i%8 == 0) printf(" ");
00157 if (i%16 == 0) {
00158 print_asc(&buf[i-16],8); printf(" ");
00159 print_asc(&buf[i-8],8); printf("\n");
00160 if (i<len) printf("[%03X] ",i);
00161 }
00162 }
00163 if (i%16) {
00164 int n;
00165
00166 n = 16 - (i%16);
00167 printf(" ");
00168 if (n>8) printf(" ");
00169 while (n--) printf(" ");
00170
00171 n = i%16;
00172 if (n > 8) n = 8;
00173 print_asc(&buf[i-(i%16)],n); printf(" ");
00174 n = (i%16) - n;
00175 if (n>0) print_asc(&buf[i-n],n);
00176 printf("\n");
00177 }
00178 }
00179
00180 static void help(void)
00181 {
00182 printf("\n"
00183 "tdbtool: \n"
00184 " create dbname : create a database\n"
00185 " open dbname : open an existing database\n"
00186 " erase : erase the database\n"
00187 " dump : dump the database as strings\n"
00188 " cdump : dump the database as connection records\n"
00189 " keys : dump the database keys as strings\n"
00190 " hexkeys : dump the database keys as hex values\n"
00191 " info : print summary info about the database\n"
00192 " insert key data : insert a record\n"
00193 " move key file : move a record to a destination tdb\n"
00194 " store key data : store a record (replace)\n"
00195 " show key : show a record by key\n"
00196 " delete key : delete a record by key\n"
00197 " list : print the database hash table and freelist\n"
00198 " free : print the database freelist\n"
00199 " ! command : execute system command\n"
00200 " 1 | first : print the first record\n"
00201 " n | next : print the next record\n"
00202 " q | quit : terminate\n"
00203 " \\n : repeat 'next' command\n"
00204 "\n");
00205 }
00206
00207 static void terror(const char *why)
00208 {
00209 printf("%s\n", why);
00210 }
00211
00212 static void create_tdb(char * tdbname)
00213 {
00214 if (tdb) tdb_close(tdb);
00215 tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST,
00216 O_RDWR | O_CREAT | O_TRUNC, 0600);
00217 if (!tdb) {
00218 printf("Could not create %s: %s\n", tdbname, strerror(errno));
00219 }
00220 }
00221
00222 static void open_tdb(char *tdbname)
00223 {
00224 if (tdb) tdb_close(tdb);
00225 tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
00226 if (!tdb) {
00227 printf("Could not open %s: %s\n", tdbname, strerror(errno));
00228 }
00229 }
00230
00231 static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
00232 {
00233 TDB_DATA key, dbuf;
00234
00235 if ((keyname == NULL) || (keylen == 0)) {
00236 terror("need key");
00237 return;
00238 }
00239
00240 key.dptr = keyname;
00241 key.dsize = keylen;
00242 dbuf.dptr = data;
00243 dbuf.dsize = datalen;
00244
00245 if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
00246 terror("insert failed");
00247 }
00248 }
00249
00250 static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
00251 {
00252 TDB_DATA key, dbuf;
00253
00254 if ((keyname == NULL) || (keylen == 0)) {
00255 terror("need key");
00256 return;
00257 }
00258
00259 if ((data == NULL) || (datalen == 0)) {
00260 terror("need data");
00261 return;
00262 }
00263
00264 key.dptr = keyname;
00265 key.dsize = keylen;
00266 dbuf.dptr = data;
00267 dbuf.dsize = datalen;
00268
00269 printf("Storing key:\n");
00270 print_rec(tdb, key, dbuf, NULL);
00271
00272 if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
00273 terror("store failed");
00274 }
00275 }
00276
00277 static void show_tdb(char *keyname, size_t keylen)
00278 {
00279 TDB_DATA key, dbuf;
00280
00281 if ((keyname == NULL) || (keylen == 0)) {
00282 terror("need key");
00283 return;
00284 }
00285
00286 key.dptr = keyname;
00287 key.dsize = keylen;
00288
00289 dbuf = tdb_fetch(tdb, key);
00290 if (!dbuf.dptr) {
00291 terror("fetch failed");
00292 return;
00293 }
00294
00295 print_rec(tdb, key, dbuf, NULL);
00296
00297 free( dbuf.dptr );
00298
00299 return;
00300 }
00301
00302 static void delete_tdb(char *keyname, size_t keylen)
00303 {
00304 TDB_DATA key;
00305
00306 if ((keyname == NULL) || (keylen == 0)) {
00307 terror("need key");
00308 return;
00309 }
00310
00311 key.dptr = keyname;
00312 key.dsize = keylen;
00313
00314 if (tdb_delete(tdb, key) != 0) {
00315 terror("delete failed");
00316 }
00317 }
00318
00319 static void move_rec(char *keyname, size_t keylen, char* tdbname)
00320 {
00321 TDB_DATA key, dbuf;
00322 TDB_CONTEXT *dst_tdb;
00323
00324 if ((keyname == NULL) || (keylen == 0)) {
00325 terror("need key");
00326 return;
00327 }
00328
00329 if ( !tdbname ) {
00330 terror("need destination tdb name");
00331 return;
00332 }
00333
00334 key.dptr = keyname;
00335 key.dsize = keylen;
00336
00337 dbuf = tdb_fetch(tdb, key);
00338 if (!dbuf.dptr) {
00339 terror("fetch failed");
00340 return;
00341 }
00342
00343 print_rec(tdb, key, dbuf, NULL);
00344
00345 dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
00346 if ( !dst_tdb ) {
00347 terror("unable to open destination tdb");
00348 return;
00349 }
00350
00351 if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
00352 terror("failed to move record");
00353 }
00354 else
00355 printf("record moved\n");
00356
00357 tdb_close( dst_tdb );
00358
00359 return;
00360 }
00361
00362 static int print_conn_key(TDB_DATA key)
00363 {
00364 printf( "\nkey %d bytes\n", (int)key.dsize);
00365 printf( "pid =%5d ", ((connections_key*)key.dptr)->pid);
00366 printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum);
00367 printf( "name =[%s]\n", ((connections_key*)key.dptr)->name);
00368 return 0;
00369 }
00370
00371 static int print_conn_data(TDB_DATA dbuf)
00372 {
00373 printf( "\ndata %d bytes\n", (int)dbuf.dsize);
00374 printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid);
00375 printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum);
00376 printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->servicename);
00377
00378 printf( "uid =%5d ", ((connections_data*)dbuf.dptr)->uid);
00379 printf( "addr =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
00380 printf( "gid =%5d ", ((connections_data*)dbuf.dptr)->gid);
00381 printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
00382 printf( "start = %s\n", ctime(&((connections_data*)dbuf.dptr)->start));
00383 printf( "magic = 0x%x ", ((connections_data*)dbuf.dptr)->magic);
00384 printf( "flags = 0x%x\n", ((connections_data*)dbuf.dptr)->bcast_msg_flags);
00385 return 0;
00386 }
00387
00388 static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00389 {
00390 if (do_connections && (dbuf.dsize == sizeof(connections_data)))
00391 print_crec(the_tdb, key, dbuf, state);
00392 else
00393 print_arec(the_tdb, key, dbuf, state);
00394 return 0;
00395 }
00396
00397 static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00398 {
00399 print_conn_key(key);
00400 print_conn_data(dbuf);
00401 return 0;
00402 }
00403
00404 static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00405 {
00406 printf("\nkey %d bytes\n", (int)key.dsize);
00407 print_asc(key.dptr, key.dsize);
00408 printf("\ndata %d bytes\n", (int)dbuf.dsize);
00409 print_data(dbuf.dptr, dbuf.dsize);
00410 return 0;
00411 }
00412
00413 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00414 {
00415 printf("key %d bytes: ", (int)key.dsize);
00416 print_asc(key.dptr, key.dsize);
00417 printf("\n");
00418 return 0;
00419 }
00420
00421 static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00422 {
00423 printf("key %d bytes\n", (int)key.dsize);
00424 print_data(key.dptr, key.dsize);
00425 printf("\n");
00426 return 0;
00427 }
00428
00429 static int total_bytes;
00430
00431 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00432 {
00433 total_bytes += dbuf.dsize;
00434 return 0;
00435 }
00436
00437 static void info_tdb(void)
00438 {
00439 int count;
00440 total_bytes = 0;
00441 if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
00442 printf("Error = %s\n", tdb_errorstr(tdb));
00443 else
00444 printf("%d records totalling %d bytes\n", count, total_bytes);
00445 }
00446
00447 static char *tdb_getline(const char *prompt)
00448 {
00449 static char thisline[1024];
00450 char *p;
00451 fputs(prompt, stdout);
00452 thisline[0] = 0;
00453 p = fgets(thisline, sizeof(thisline)-1, stdin);
00454 if (p) p = strchr(p, '\n');
00455 if (p) *p = 0;
00456 return p?thisline:NULL;
00457 }
00458
00459 static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
00460 void *state)
00461 {
00462 return tdb_delete(the_tdb, key);
00463 }
00464
00465 static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
00466 {
00467 TDB_DATA dbuf;
00468 *pkey = tdb_firstkey(the_tdb);
00469
00470 dbuf = tdb_fetch(the_tdb, *pkey);
00471 if (!dbuf.dptr) terror("fetch failed");
00472 else {
00473 print_rec(the_tdb, *pkey, dbuf, NULL);
00474 }
00475 }
00476
00477 static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
00478 {
00479 TDB_DATA dbuf;
00480 *pkey = tdb_nextkey(the_tdb, *pkey);
00481
00482 dbuf = tdb_fetch(the_tdb, *pkey);
00483 if (!dbuf.dptr)
00484 terror("fetch failed");
00485 else
00486 print_rec(the_tdb, *pkey, dbuf, NULL);
00487 }
00488
00489 static int do_command(void)
00490 {
00491 COMMAND_TABLE *ctp = cmd_table;
00492 enum commands mycmd = CMD_HELP;
00493 int cmd_len;
00494
00495 do_connections = 0;
00496
00497 if (cmdname && strlen(cmdname) == 0) {
00498 mycmd = CMD_NEXT;
00499 } else {
00500 while (ctp->name) {
00501 cmd_len = strlen(ctp->name);
00502 if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
00503 mycmd = ctp->cmd;
00504 break;
00505 }
00506 ctp++;
00507 }
00508 }
00509
00510 switch (mycmd) {
00511 case CMD_CREATE_TDB:
00512 bIterate = 0;
00513 create_tdb(arg1);
00514 return 0;
00515 case CMD_OPEN_TDB:
00516 bIterate = 0;
00517 open_tdb(arg1);
00518 return 0;
00519 case CMD_SYSTEM:
00520
00521 system(arg1);
00522 return 0;
00523 case CMD_QUIT:
00524 return 1;
00525 default:
00526
00527 if (!tdb) {
00528 bIterate = 0;
00529 terror("database not open");
00530 help();
00531 return 0;
00532 }
00533 switch (mycmd) {
00534 case CMD_ERASE:
00535 bIterate = 0;
00536 tdb_traverse(tdb, do_delete_fn, NULL);
00537 return 0;
00538 case CMD_DUMP:
00539 bIterate = 0;
00540 tdb_traverse(tdb, print_rec, NULL);
00541 return 0;
00542 case CMD_CDUMP:
00543 do_connections = 1;
00544 bIterate = 0;
00545 tdb_traverse(tdb, print_rec, NULL);
00546 return 0;
00547 case CMD_INSERT:
00548 bIterate = 0;
00549 insert_tdb(arg1, arg1len,arg2,arg2len);
00550 return 0;
00551 case CMD_MOVE:
00552 bIterate = 0;
00553 move_rec(arg1,arg1len,arg2);
00554 return 0;
00555 case CMD_STORE:
00556 bIterate = 0;
00557 store_tdb(arg1,arg1len,arg2,arg2len);
00558 return 0;
00559 case CMD_SHOW:
00560 bIterate = 0;
00561 show_tdb(arg1, arg1len);
00562 return 0;
00563 case CMD_KEYS:
00564 tdb_traverse(tdb, print_key, NULL);
00565 return 0;
00566 case CMD_HEXKEYS:
00567 tdb_traverse(tdb, print_hexkey, NULL);
00568 return 0;
00569 case CMD_DELETE:
00570 bIterate = 0;
00571 delete_tdb(arg1,arg1len);
00572 return 0;
00573 case CMD_LIST_HASH_FREE:
00574 tdb_dump_all(tdb);
00575 return 0;
00576 case CMD_LIST_FREE:
00577 tdb_printfreelist(tdb);
00578 return 0;
00579 case CMD_INFO:
00580 info_tdb();
00581 return 0;
00582 case CMD_FIRST:
00583 bIterate = 1;
00584 first_record(tdb, &iterate_kbuf);
00585 return 0;
00586 case CMD_NEXT:
00587 if (bIterate)
00588 next_record(tdb, &iterate_kbuf);
00589 return 0;
00590 case CMD_HELP:
00591 help();
00592 return 0;
00593 case CMD_CREATE_TDB:
00594 case CMD_OPEN_TDB:
00595 case CMD_SYSTEM:
00596 case CMD_QUIT:
00597
00598
00599
00600
00601 return 0;
00602 }
00603 }
00604
00605 return 0;
00606 }
00607
00608 static char *convert_string(char *instring, size_t *sizep)
00609 {
00610 size_t length = 0;
00611 char *outp, *inp;
00612 char temp[3];
00613
00614
00615 outp = inp = instring;
00616
00617 while (*inp) {
00618 if (*inp == '\\') {
00619 inp++;
00620 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
00621 temp[0] = *inp++;
00622 temp[1] = '\0';
00623 if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
00624 temp[1] = *inp++;
00625 temp[2] = '\0';
00626 }
00627 *outp++ = (char)strtol((const char *)temp,NULL,16);
00628 } else {
00629 *outp++ = *inp++;
00630 }
00631 } else {
00632 *outp++ = *inp++;
00633 }
00634 length++;
00635 }
00636 *sizep = length;
00637 return instring;
00638 }
00639
00640 int main(int argc, char *argv[])
00641 {
00642 cmdname = (char *) "";
00643 arg1 = NULL;
00644 arg1len = 0;
00645 arg2 = NULL;
00646 arg2len = 0;
00647
00648 if (argv[1]) {
00649 cmdname = (char *) "open";
00650 arg1 = argv[1];
00651 do_command();
00652 cmdname = (char *) "";
00653 arg1 = NULL;
00654 }
00655
00656 switch (argc) {
00657 case 1:
00658 case 2:
00659
00660 while ((cmdname = tdb_getline("tdb> "))) {
00661 arg2 = arg1 = NULL;
00662 if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
00663 arg1++;
00664 arg2 = arg1;
00665 while (*arg2) {
00666 if (*arg2 == ' ') {
00667 *arg2++ = '\0';
00668 break;
00669 }
00670 if ((*arg2++ == '\\') && (*arg2 == ' ')) {
00671 arg2++;
00672 }
00673 }
00674 }
00675 if (arg1) arg1 = convert_string(arg1,&arg1len);
00676 if (arg2) arg2 = convert_string(arg2,&arg2len);
00677 if (do_command()) break;
00678 }
00679 break;
00680 case 5:
00681 arg2 = convert_string(argv[4],&arg2len);
00682 case 4:
00683 arg1 = convert_string(argv[3],&arg1len);
00684 case 3:
00685 cmdname = argv[2];
00686 default:
00687 do_command();
00688 break;
00689 }
00690
00691 if (tdb) tdb_close(tdb);
00692
00693 return 0;
00694 }