| 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 2 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, write to the Free Software
|
|---|
| 21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|---|
| 22 | */
|
|---|
| 23 |
|
|---|
| 24 | #include <errno.h>
|
|---|
| 25 | #include <stdlib.h>
|
|---|
| 26 | #include <stdio.h>
|
|---|
| 27 | #include <fcntl.h>
|
|---|
| 28 | #include <unistd.h>
|
|---|
| 29 | #include <string.h>
|
|---|
| 30 | #include <fcntl.h>
|
|---|
| 31 | #include <time.h>
|
|---|
| 32 | #include <sys/mman.h>
|
|---|
| 33 | #include <sys/stat.h>
|
|---|
| 34 | #include <sys/time.h>
|
|---|
| 35 | #include <ctype.h>
|
|---|
| 36 | #include <signal.h>
|
|---|
| 37 | #include "tdb.h"
|
|---|
| 38 | #include "pstring.h"
|
|---|
| 39 |
|
|---|
| 40 | static int do_command(void);
|
|---|
| 41 | char *cmdname, *arg1, *arg2;
|
|---|
| 42 | size_t arg1len, arg2len;
|
|---|
| 43 | int do_connections;
|
|---|
| 44 | int bIterate = 0;
|
|---|
| 45 | char *line;
|
|---|
| 46 | TDB_DATA iterate_kbuf;
|
|---|
| 47 | char cmdline[1024];
|
|---|
| 48 |
|
|---|
| 49 | enum commands {
|
|---|
| 50 | CMD_CREATE_TDB,
|
|---|
| 51 | CMD_OPEN_TDB,
|
|---|
| 52 | CMD_ERASE,
|
|---|
| 53 | CMD_DUMP,
|
|---|
| 54 | CMD_CDUMP,
|
|---|
| 55 | CMD_INSERT,
|
|---|
| 56 | CMD_MOVE,
|
|---|
| 57 | CMD_STORE,
|
|---|
| 58 | CMD_SHOW,
|
|---|
| 59 | CMD_KEYS,
|
|---|
| 60 | CMD_HEXKEYS,
|
|---|
| 61 | CMD_DELETE,
|
|---|
| 62 | CMD_LIST_HASH_FREE,
|
|---|
| 63 | CMD_LIST_FREE,
|
|---|
| 64 | CMD_INFO,
|
|---|
| 65 | CMD_FIRST,
|
|---|
| 66 | CMD_NEXT,
|
|---|
| 67 | CMD_SYSTEM,
|
|---|
| 68 | CMD_QUIT,
|
|---|
| 69 | CMD_HELP
|
|---|
| 70 | };
|
|---|
| 71 |
|
|---|
| 72 | typedef struct {
|
|---|
| 73 | const char *name;
|
|---|
| 74 | enum commands cmd;
|
|---|
| 75 | } COMMAND_TABLE;
|
|---|
| 76 |
|
|---|
| 77 | COMMAND_TABLE cmd_table[] = {
|
|---|
| 78 | {"create", CMD_CREATE_TDB},
|
|---|
| 79 | {"open", CMD_OPEN_TDB},
|
|---|
| 80 | {"erase", CMD_ERASE},
|
|---|
| 81 | {"dump", CMD_DUMP},
|
|---|
| 82 | {"cdump", CMD_CDUMP},
|
|---|
| 83 | {"insert", CMD_INSERT},
|
|---|
| 84 | {"move", CMD_MOVE},
|
|---|
| 85 | {"store", CMD_STORE},
|
|---|
| 86 | {"show", CMD_SHOW},
|
|---|
| 87 | {"keys", CMD_KEYS},
|
|---|
| 88 | {"hexkeys", CMD_HEXKEYS},
|
|---|
| 89 | {"delete", CMD_DELETE},
|
|---|
| 90 | {"list", CMD_LIST_HASH_FREE},
|
|---|
| 91 | {"free", CMD_LIST_FREE},
|
|---|
| 92 | {"info", CMD_INFO},
|
|---|
| 93 | {"first", CMD_FIRST},
|
|---|
| 94 | {"1", CMD_FIRST},
|
|---|
| 95 | {"next", CMD_NEXT},
|
|---|
| 96 | {"n", CMD_NEXT},
|
|---|
| 97 | {"quit", CMD_QUIT},
|
|---|
| 98 | {"q", CMD_QUIT},
|
|---|
| 99 | {"!", CMD_SYSTEM},
|
|---|
| 100 | {NULL, CMD_HELP}
|
|---|
| 101 | };
|
|---|
| 102 |
|
|---|
| 103 | /* a tdb tool for manipulating a tdb database */
|
|---|
| 104 |
|
|---|
| 105 | /* these are taken from smb.h - make sure they are in sync */
|
|---|
| 106 |
|
|---|
| 107 | typedef struct connections_key {
|
|---|
| 108 | pid_t pid;
|
|---|
| 109 | int cnum;
|
|---|
| 110 | fstring name;
|
|---|
| 111 | } connections_key;
|
|---|
| 112 |
|
|---|
| 113 | typedef struct connections_data {
|
|---|
| 114 | int magic;
|
|---|
| 115 | pid_t pid;
|
|---|
| 116 | int cnum;
|
|---|
| 117 | uid_t uid;
|
|---|
| 118 | gid_t gid;
|
|---|
| 119 | char servicename[FSTRING_LEN];
|
|---|
| 120 | char addr[24];
|
|---|
| 121 | char machine[FSTRING_LEN];
|
|---|
| 122 | time_t start;
|
|---|
| 123 | unsigned bcast_msg_flags;
|
|---|
| 124 | } connections_data;
|
|---|
| 125 |
|
|---|
| 126 | static TDB_CONTEXT *tdb;
|
|---|
| 127 |
|
|---|
| 128 | static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 129 | static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 130 | static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 131 | static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 132 | static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 133 |
|
|---|
| 134 | static void print_asc(const char *buf,int len)
|
|---|
| 135 | {
|
|---|
| 136 | int i;
|
|---|
| 137 |
|
|---|
| 138 | /* We're probably printing ASCII strings so don't try to display
|
|---|
| 139 | the trailing NULL character. */
|
|---|
| 140 |
|
|---|
| 141 | if (buf[len - 1] == 0)
|
|---|
| 142 | len--;
|
|---|
| 143 |
|
|---|
| 144 | for (i=0;i<len;i++)
|
|---|
| 145 | printf("%c",isprint(buf[i])?buf[i]:'.');
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | static void print_data(const char *buf,int len)
|
|---|
| 149 | {
|
|---|
| 150 | int i=0;
|
|---|
| 151 | if (len<=0) return;
|
|---|
| 152 | printf("[%03X] ",i);
|
|---|
| 153 | for (i=0;i<len;) {
|
|---|
| 154 | printf("%02X ",(int)buf[i]);
|
|---|
| 155 | i++;
|
|---|
| 156 | if (i%8 == 0) printf(" ");
|
|---|
| 157 | if (i%16 == 0) {
|
|---|
| 158 | print_asc(&buf[i-16],8); printf(" ");
|
|---|
| 159 | print_asc(&buf[i-8],8); printf("\n");
|
|---|
| 160 | if (i<len) printf("[%03X] ",i);
|
|---|
| 161 | }
|
|---|
| 162 | }
|
|---|
| 163 | if (i%16) {
|
|---|
| 164 | int n;
|
|---|
| 165 |
|
|---|
| 166 | n = 16 - (i%16);
|
|---|
| 167 | printf(" ");
|
|---|
| 168 | if (n>8) printf(" ");
|
|---|
| 169 | while (n--) printf(" ");
|
|---|
| 170 |
|
|---|
| 171 | n = i%16;
|
|---|
| 172 | if (n > 8) n = 8;
|
|---|
| 173 | print_asc(&buf[i-(i%16)],n); printf(" ");
|
|---|
| 174 | n = (i%16) - n;
|
|---|
| 175 | if (n>0) print_asc(&buf[i-n],n);
|
|---|
| 176 | printf("\n");
|
|---|
| 177 | }
|
|---|
| 178 | }
|
|---|
| 179 |
|
|---|
| 180 | static void help(void)
|
|---|
| 181 | {
|
|---|
| 182 | printf("\n"
|
|---|
| 183 | "tdbtool: \n"
|
|---|
| 184 | " create dbname : create a database\n"
|
|---|
| 185 | " open dbname : open an existing database\n"
|
|---|
| 186 | " erase : erase the database\n"
|
|---|
| 187 | " dump : dump the database as strings\n"
|
|---|
| 188 | " cdump : dump the database as connection records\n"
|
|---|
| 189 | " keys : dump the database keys as strings\n"
|
|---|
| 190 | " hexkeys : dump the database keys as hex values\n"
|
|---|
| 191 | " info : print summary info about the database\n"
|
|---|
| 192 | " insert key data : insert a record\n"
|
|---|
| 193 | " move key file : move a record to a destination tdb\n"
|
|---|
| 194 | " store key data : store a record (replace)\n"
|
|---|
| 195 | " show key : show a record by key\n"
|
|---|
| 196 | " delete key : delete a record by key\n"
|
|---|
| 197 | " list : print the database hash table and freelist\n"
|
|---|
| 198 | " free : print the database freelist\n"
|
|---|
| 199 | " ! command : execute system command\n"
|
|---|
| 200 | " 1 | first : print the first record\n"
|
|---|
| 201 | " n | next : print the next record\n"
|
|---|
| 202 | " q | quit : terminate\n"
|
|---|
| 203 | " \\n : repeat 'next' command\n"
|
|---|
| 204 | "\n");
|
|---|
| 205 | }
|
|---|
| 206 |
|
|---|
| 207 | static void terror(const char *why)
|
|---|
| 208 | {
|
|---|
| 209 | printf("%s\n", why);
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | static void create_tdb(char * tdbname)
|
|---|
| 213 | {
|
|---|
| 214 | if (tdb) tdb_close(tdb);
|
|---|
| 215 | tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST,
|
|---|
| 216 | O_RDWR | O_CREAT | O_TRUNC, 0600);
|
|---|
| 217 | if (!tdb) {
|
|---|
| 218 | printf("Could not create %s: %s\n", tdbname, strerror(errno));
|
|---|
| 219 | }
|
|---|
| 220 | }
|
|---|
| 221 |
|
|---|
| 222 | static void open_tdb(char *tdbname)
|
|---|
| 223 | {
|
|---|
| 224 | if (tdb) tdb_close(tdb);
|
|---|
| 225 | tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
|
|---|
| 226 | if (!tdb) {
|
|---|
| 227 | printf("Could not open %s: %s\n", tdbname, strerror(errno));
|
|---|
| 228 | }
|
|---|
| 229 | }
|
|---|
| 230 |
|
|---|
| 231 | static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
|
|---|
| 232 | {
|
|---|
| 233 | TDB_DATA key, dbuf;
|
|---|
| 234 |
|
|---|
| 235 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 236 | terror("need key");
|
|---|
| 237 | return;
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | key.dptr = keyname;
|
|---|
| 241 | key.dsize = keylen;
|
|---|
| 242 | dbuf.dptr = data;
|
|---|
| 243 | dbuf.dsize = datalen;
|
|---|
| 244 |
|
|---|
| 245 | if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
|
|---|
| 246 | terror("insert failed");
|
|---|
| 247 | }
|
|---|
| 248 | }
|
|---|
| 249 |
|
|---|
| 250 | static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
|
|---|
| 251 | {
|
|---|
| 252 | TDB_DATA key, dbuf;
|
|---|
| 253 |
|
|---|
| 254 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 255 | terror("need key");
|
|---|
| 256 | return;
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|
| 259 | if ((data == NULL) || (datalen == 0)) {
|
|---|
| 260 | terror("need data");
|
|---|
| 261 | return;
|
|---|
| 262 | }
|
|---|
| 263 |
|
|---|
| 264 | key.dptr = keyname;
|
|---|
| 265 | key.dsize = keylen;
|
|---|
| 266 | dbuf.dptr = data;
|
|---|
| 267 | dbuf.dsize = datalen;
|
|---|
| 268 |
|
|---|
| 269 | printf("Storing key:\n");
|
|---|
| 270 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 271 |
|
|---|
| 272 | if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
|
|---|
| 273 | terror("store failed");
|
|---|
| 274 | }
|
|---|
| 275 | }
|
|---|
| 276 |
|
|---|
| 277 | static void show_tdb(char *keyname, size_t keylen)
|
|---|
| 278 | {
|
|---|
| 279 | TDB_DATA key, dbuf;
|
|---|
| 280 |
|
|---|
| 281 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 282 | terror("need key");
|
|---|
| 283 | return;
|
|---|
| 284 | }
|
|---|
| 285 |
|
|---|
| 286 | key.dptr = keyname;
|
|---|
| 287 | key.dsize = keylen;
|
|---|
| 288 |
|
|---|
| 289 | dbuf = tdb_fetch(tdb, key);
|
|---|
| 290 | if (!dbuf.dptr) {
|
|---|
| 291 | terror("fetch failed");
|
|---|
| 292 | return;
|
|---|
| 293 | }
|
|---|
| 294 |
|
|---|
| 295 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 296 |
|
|---|
| 297 | free( dbuf.dptr );
|
|---|
| 298 |
|
|---|
| 299 | return;
|
|---|
| 300 | }
|
|---|
| 301 |
|
|---|
| 302 | static void delete_tdb(char *keyname, size_t keylen)
|
|---|
| 303 | {
|
|---|
| 304 | TDB_DATA key;
|
|---|
| 305 |
|
|---|
| 306 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 307 | terror("need key");
|
|---|
| 308 | return;
|
|---|
| 309 | }
|
|---|
| 310 |
|
|---|
| 311 | key.dptr = keyname;
|
|---|
| 312 | key.dsize = keylen;
|
|---|
| 313 |
|
|---|
| 314 | if (tdb_delete(tdb, key) != 0) {
|
|---|
| 315 | terror("delete failed");
|
|---|
| 316 | }
|
|---|
| 317 | }
|
|---|
| 318 |
|
|---|
| 319 | static void move_rec(char *keyname, size_t keylen, char* tdbname)
|
|---|
| 320 | {
|
|---|
| 321 | TDB_DATA key, dbuf;
|
|---|
| 322 | TDB_CONTEXT *dst_tdb;
|
|---|
| 323 |
|
|---|
| 324 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 325 | terror("need key");
|
|---|
| 326 | return;
|
|---|
| 327 | }
|
|---|
| 328 |
|
|---|
| 329 | if ( !tdbname ) {
|
|---|
| 330 | terror("need destination tdb name");
|
|---|
| 331 | return;
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | key.dptr = keyname;
|
|---|
| 335 | key.dsize = keylen;
|
|---|
| 336 |
|
|---|
| 337 | dbuf = tdb_fetch(tdb, key);
|
|---|
| 338 | if (!dbuf.dptr) {
|
|---|
| 339 | terror("fetch failed");
|
|---|
| 340 | return;
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 344 |
|
|---|
| 345 | dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
|
|---|
| 346 | if ( !dst_tdb ) {
|
|---|
| 347 | terror("unable to open destination tdb");
|
|---|
| 348 | return;
|
|---|
| 349 | }
|
|---|
| 350 |
|
|---|
| 351 | if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
|
|---|
| 352 | terror("failed to move record");
|
|---|
| 353 | }
|
|---|
| 354 | else
|
|---|
| 355 | printf("record moved\n");
|
|---|
| 356 |
|
|---|
| 357 | tdb_close( dst_tdb );
|
|---|
| 358 |
|
|---|
| 359 | return;
|
|---|
| 360 | }
|
|---|
| 361 |
|
|---|
| 362 | static int print_conn_key(TDB_DATA key)
|
|---|
| 363 | {
|
|---|
| 364 | printf( "\nkey %d bytes\n", (int)key.dsize);
|
|---|
| 365 | printf( "pid =%5d ", ((connections_key*)key.dptr)->pid);
|
|---|
| 366 | printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum);
|
|---|
| 367 | printf( "name =[%s]\n", ((connections_key*)key.dptr)->name);
|
|---|
| 368 | return 0;
|
|---|
| 369 | }
|
|---|
| 370 |
|
|---|
| 371 | static int print_conn_data(TDB_DATA dbuf)
|
|---|
| 372 | {
|
|---|
| 373 | printf( "\ndata %d bytes\n", (int)dbuf.dsize);
|
|---|
| 374 | printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid);
|
|---|
| 375 | printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum);
|
|---|
| 376 | printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->servicename);
|
|---|
| 377 |
|
|---|
| 378 | printf( "uid =%5d ", ((connections_data*)dbuf.dptr)->uid);
|
|---|
| 379 | printf( "addr =[%s]\n", ((connections_data*)dbuf.dptr)->addr);
|
|---|
| 380 | printf( "gid =%5d ", ((connections_data*)dbuf.dptr)->gid);
|
|---|
| 381 | printf( "machine=[%s]\n", ((connections_data*)dbuf.dptr)->machine);
|
|---|
| 382 | printf( "start = %s\n", ctime(&((connections_data*)dbuf.dptr)->start));
|
|---|
| 383 | printf( "magic = 0x%x ", ((connections_data*)dbuf.dptr)->magic);
|
|---|
| 384 | printf( "flags = 0x%x\n", ((connections_data*)dbuf.dptr)->bcast_msg_flags);
|
|---|
| 385 | return 0;
|
|---|
| 386 | }
|
|---|
| 387 |
|
|---|
| 388 | static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 389 | {
|
|---|
| 390 | if (do_connections && (dbuf.dsize == sizeof(connections_data)))
|
|---|
| 391 | print_crec(the_tdb, key, dbuf, state);
|
|---|
| 392 | else
|
|---|
| 393 | print_arec(the_tdb, key, dbuf, state);
|
|---|
| 394 | return 0;
|
|---|
| 395 | }
|
|---|
| 396 |
|
|---|
| 397 | static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 398 | {
|
|---|
| 399 | print_conn_key(key);
|
|---|
| 400 | print_conn_data(dbuf);
|
|---|
| 401 | return 0;
|
|---|
| 402 | }
|
|---|
| 403 |
|
|---|
| 404 | static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 405 | {
|
|---|
| 406 | printf("\nkey %d bytes\n", (int)key.dsize);
|
|---|
| 407 | print_asc(key.dptr, key.dsize);
|
|---|
| 408 | printf("\ndata %d bytes\n", (int)dbuf.dsize);
|
|---|
| 409 | print_data(dbuf.dptr, dbuf.dsize);
|
|---|
| 410 | return 0;
|
|---|
| 411 | }
|
|---|
| 412 |
|
|---|
| 413 | static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 414 | {
|
|---|
| 415 | printf("key %d bytes: ", (int)key.dsize);
|
|---|
| 416 | print_asc(key.dptr, key.dsize);
|
|---|
| 417 | printf("\n");
|
|---|
| 418 | return 0;
|
|---|
| 419 | }
|
|---|
| 420 |
|
|---|
| 421 | static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 422 | {
|
|---|
| 423 | printf("key %d bytes\n", (int)key.dsize);
|
|---|
| 424 | print_data(key.dptr, key.dsize);
|
|---|
| 425 | printf("\n");
|
|---|
| 426 | return 0;
|
|---|
| 427 | }
|
|---|
| 428 |
|
|---|
| 429 | static int total_bytes;
|
|---|
| 430 |
|
|---|
| 431 | static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 432 | {
|
|---|
| 433 | total_bytes += dbuf.dsize;
|
|---|
| 434 | return 0;
|
|---|
| 435 | }
|
|---|
| 436 |
|
|---|
| 437 | static void info_tdb(void)
|
|---|
| 438 | {
|
|---|
| 439 | int count;
|
|---|
| 440 | total_bytes = 0;
|
|---|
| 441 | if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
|
|---|
| 442 | printf("Error = %s\n", tdb_errorstr(tdb));
|
|---|
| 443 | else
|
|---|
| 444 | printf("%d records totalling %d bytes\n", count, total_bytes);
|
|---|
| 445 | }
|
|---|
| 446 |
|
|---|
| 447 | static char *tdb_getline(const char *prompt)
|
|---|
| 448 | {
|
|---|
| 449 | static char thisline[1024];
|
|---|
| 450 | char *p;
|
|---|
| 451 | fputs(prompt, stdout);
|
|---|
| 452 | thisline[0] = 0;
|
|---|
| 453 | p = fgets(thisline, sizeof(thisline)-1, stdin);
|
|---|
| 454 | if (p) p = strchr(p, '\n');
|
|---|
| 455 | if (p) *p = 0;
|
|---|
| 456 | return p?thisline:NULL;
|
|---|
| 457 | }
|
|---|
| 458 |
|
|---|
| 459 | static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
|
|---|
| 460 | void *state)
|
|---|
| 461 | {
|
|---|
| 462 | return tdb_delete(the_tdb, key);
|
|---|
| 463 | }
|
|---|
| 464 |
|
|---|
| 465 | static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
|
|---|
| 466 | {
|
|---|
| 467 | TDB_DATA dbuf;
|
|---|
| 468 | *pkey = tdb_firstkey(the_tdb);
|
|---|
| 469 |
|
|---|
| 470 | dbuf = tdb_fetch(the_tdb, *pkey);
|
|---|
| 471 | if (!dbuf.dptr) terror("fetch failed");
|
|---|
| 472 | else {
|
|---|
| 473 | print_rec(the_tdb, *pkey, dbuf, NULL);
|
|---|
| 474 | }
|
|---|
| 475 | }
|
|---|
| 476 |
|
|---|
| 477 | static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
|
|---|
| 478 | {
|
|---|
| 479 | TDB_DATA dbuf;
|
|---|
| 480 | *pkey = tdb_nextkey(the_tdb, *pkey);
|
|---|
| 481 |
|
|---|
| 482 | dbuf = tdb_fetch(the_tdb, *pkey);
|
|---|
| 483 | if (!dbuf.dptr)
|
|---|
| 484 | terror("fetch failed");
|
|---|
| 485 | else
|
|---|
| 486 | print_rec(the_tdb, *pkey, dbuf, NULL);
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 | static int do_command(void)
|
|---|
| 490 | {
|
|---|
| 491 | COMMAND_TABLE *ctp = cmd_table;
|
|---|
| 492 | enum commands mycmd = CMD_HELP;
|
|---|
| 493 | int cmd_len;
|
|---|
| 494 |
|
|---|
| 495 | do_connections = 0;
|
|---|
| 496 |
|
|---|
| 497 | if (cmdname && strlen(cmdname) == 0) {
|
|---|
| 498 | mycmd = CMD_NEXT;
|
|---|
| 499 | } else {
|
|---|
| 500 | while (ctp->name) {
|
|---|
| 501 | cmd_len = strlen(ctp->name);
|
|---|
| 502 | if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
|
|---|
| 503 | mycmd = ctp->cmd;
|
|---|
| 504 | break;
|
|---|
| 505 | }
|
|---|
| 506 | ctp++;
|
|---|
| 507 | }
|
|---|
| 508 | }
|
|---|
| 509 |
|
|---|
| 510 | switch (mycmd) {
|
|---|
| 511 | case CMD_CREATE_TDB:
|
|---|
| 512 | bIterate = 0;
|
|---|
| 513 | create_tdb(arg1);
|
|---|
| 514 | return 0;
|
|---|
| 515 | case CMD_OPEN_TDB:
|
|---|
| 516 | bIterate = 0;
|
|---|
| 517 | open_tdb(arg1);
|
|---|
| 518 | return 0;
|
|---|
| 519 | case CMD_SYSTEM:
|
|---|
| 520 | /* Shell command */
|
|---|
| 521 | system(arg1);
|
|---|
| 522 | return 0;
|
|---|
| 523 | case CMD_QUIT:
|
|---|
| 524 | return 1;
|
|---|
| 525 | default:
|
|---|
| 526 | /* all the rest require a open database */
|
|---|
| 527 | if (!tdb) {
|
|---|
| 528 | bIterate = 0;
|
|---|
| 529 | terror("database not open");
|
|---|
| 530 | help();
|
|---|
| 531 | return 0;
|
|---|
| 532 | }
|
|---|
| 533 | switch (mycmd) {
|
|---|
| 534 | case CMD_ERASE:
|
|---|
| 535 | bIterate = 0;
|
|---|
| 536 | tdb_traverse(tdb, do_delete_fn, NULL);
|
|---|
| 537 | return 0;
|
|---|
| 538 | case CMD_DUMP:
|
|---|
| 539 | bIterate = 0;
|
|---|
| 540 | tdb_traverse(tdb, print_rec, NULL);
|
|---|
| 541 | return 0;
|
|---|
| 542 | case CMD_CDUMP:
|
|---|
| 543 | do_connections = 1;
|
|---|
| 544 | bIterate = 0;
|
|---|
| 545 | tdb_traverse(tdb, print_rec, NULL);
|
|---|
| 546 | return 0;
|
|---|
| 547 | case CMD_INSERT:
|
|---|
| 548 | bIterate = 0;
|
|---|
| 549 | insert_tdb(arg1, arg1len,arg2,arg2len);
|
|---|
| 550 | return 0;
|
|---|
| 551 | case CMD_MOVE:
|
|---|
| 552 | bIterate = 0;
|
|---|
| 553 | move_rec(arg1,arg1len,arg2);
|
|---|
| 554 | return 0;
|
|---|
| 555 | case CMD_STORE:
|
|---|
| 556 | bIterate = 0;
|
|---|
| 557 | store_tdb(arg1,arg1len,arg2,arg2len);
|
|---|
| 558 | return 0;
|
|---|
| 559 | case CMD_SHOW:
|
|---|
| 560 | bIterate = 0;
|
|---|
| 561 | show_tdb(arg1, arg1len);
|
|---|
| 562 | return 0;
|
|---|
| 563 | case CMD_KEYS:
|
|---|
| 564 | tdb_traverse(tdb, print_key, NULL);
|
|---|
| 565 | return 0;
|
|---|
| 566 | case CMD_HEXKEYS:
|
|---|
| 567 | tdb_traverse(tdb, print_hexkey, NULL);
|
|---|
| 568 | return 0;
|
|---|
| 569 | case CMD_DELETE:
|
|---|
| 570 | bIterate = 0;
|
|---|
| 571 | delete_tdb(arg1,arg1len);
|
|---|
| 572 | return 0;
|
|---|
| 573 | case CMD_LIST_HASH_FREE:
|
|---|
| 574 | tdb_dump_all(tdb);
|
|---|
| 575 | return 0;
|
|---|
| 576 | case CMD_LIST_FREE:
|
|---|
| 577 | tdb_printfreelist(tdb);
|
|---|
| 578 | return 0;
|
|---|
| 579 | case CMD_INFO:
|
|---|
| 580 | info_tdb();
|
|---|
| 581 | return 0;
|
|---|
| 582 | case CMD_FIRST:
|
|---|
| 583 | bIterate = 1;
|
|---|
| 584 | first_record(tdb, &iterate_kbuf);
|
|---|
| 585 | return 0;
|
|---|
| 586 | case CMD_NEXT:
|
|---|
| 587 | if (bIterate)
|
|---|
| 588 | next_record(tdb, &iterate_kbuf);
|
|---|
| 589 | return 0;
|
|---|
| 590 | case CMD_HELP:
|
|---|
| 591 | help();
|
|---|
| 592 | return 0;
|
|---|
| 593 | case CMD_CREATE_TDB:
|
|---|
| 594 | case CMD_OPEN_TDB:
|
|---|
| 595 | case CMD_SYSTEM:
|
|---|
| 596 | case CMD_QUIT:
|
|---|
| 597 | /*
|
|---|
| 598 | * unhandled commands. cases included here to avoid compiler
|
|---|
| 599 | * warnings.
|
|---|
| 600 | */
|
|---|
| 601 | return 0;
|
|---|
| 602 | }
|
|---|
| 603 | }
|
|---|
| 604 |
|
|---|
| 605 | return 0;
|
|---|
| 606 | }
|
|---|
| 607 |
|
|---|
| 608 | static char *convert_string(char *instring, size_t *sizep)
|
|---|
| 609 | {
|
|---|
| 610 | size_t length = 0;
|
|---|
| 611 | char *outp, *inp;
|
|---|
| 612 | char temp[3];
|
|---|
| 613 |
|
|---|
| 614 |
|
|---|
| 615 | outp = inp = instring;
|
|---|
| 616 |
|
|---|
| 617 | while (*inp) {
|
|---|
| 618 | if (*inp == '\\') {
|
|---|
| 619 | inp++;
|
|---|
| 620 | if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
|
|---|
| 621 | temp[0] = *inp++;
|
|---|
| 622 | temp[1] = '\0';
|
|---|
| 623 | if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
|
|---|
| 624 | temp[1] = *inp++;
|
|---|
| 625 | temp[2] = '\0';
|
|---|
| 626 | }
|
|---|
| 627 | *outp++ = (char)strtol((const char *)temp,NULL,16);
|
|---|
| 628 | } else {
|
|---|
| 629 | *outp++ = *inp++;
|
|---|
| 630 | }
|
|---|
| 631 | } else {
|
|---|
| 632 | *outp++ = *inp++;
|
|---|
| 633 | }
|
|---|
| 634 | length++;
|
|---|
| 635 | }
|
|---|
| 636 | *sizep = length;
|
|---|
| 637 | return instring;
|
|---|
| 638 | }
|
|---|
| 639 |
|
|---|
| 640 | int main(int argc, char *argv[])
|
|---|
| 641 | {
|
|---|
| 642 | cmdname = (char *) "";
|
|---|
| 643 | arg1 = NULL;
|
|---|
| 644 | arg1len = 0;
|
|---|
| 645 | arg2 = NULL;
|
|---|
| 646 | arg2len = 0;
|
|---|
| 647 |
|
|---|
| 648 | if (argv[1]) {
|
|---|
| 649 | cmdname = (char *) "open";
|
|---|
| 650 | arg1 = argv[1];
|
|---|
| 651 | do_command();
|
|---|
| 652 | cmdname = (char *) "";
|
|---|
| 653 | arg1 = NULL;
|
|---|
| 654 | }
|
|---|
| 655 |
|
|---|
| 656 | switch (argc) {
|
|---|
| 657 | case 1:
|
|---|
| 658 | case 2:
|
|---|
| 659 | /* Interactive mode */
|
|---|
| 660 | while ((cmdname = tdb_getline("tdb> "))) {
|
|---|
| 661 | arg2 = arg1 = NULL;
|
|---|
| 662 | if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
|
|---|
| 663 | arg1++;
|
|---|
| 664 | arg2 = arg1;
|
|---|
| 665 | while (*arg2) {
|
|---|
| 666 | if (*arg2 == ' ') {
|
|---|
| 667 | *arg2++ = '\0';
|
|---|
| 668 | break;
|
|---|
| 669 | }
|
|---|
| 670 | if ((*arg2++ == '\\') && (*arg2 == ' ')) {
|
|---|
| 671 | arg2++;
|
|---|
| 672 | }
|
|---|
| 673 | }
|
|---|
| 674 | }
|
|---|
| 675 | if (arg1) arg1 = convert_string(arg1,&arg1len);
|
|---|
| 676 | if (arg2) arg2 = convert_string(arg2,&arg2len);
|
|---|
| 677 | if (do_command()) break;
|
|---|
| 678 | }
|
|---|
| 679 | break;
|
|---|
| 680 | case 5:
|
|---|
| 681 | arg2 = convert_string(argv[4],&arg2len);
|
|---|
| 682 | case 4:
|
|---|
| 683 | arg1 = convert_string(argv[3],&arg1len);
|
|---|
| 684 | case 3:
|
|---|
| 685 | cmdname = argv[2];
|
|---|
| 686 | default:
|
|---|
| 687 | do_command();
|
|---|
| 688 | break;
|
|---|
| 689 | }
|
|---|
| 690 |
|
|---|
| 691 | if (tdb) tdb_close(tdb);
|
|---|
| 692 |
|
|---|
| 693 | return 0;
|
|---|
| 694 | }
|
|---|