root/lib/tdb/tools/tdbtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _start_timer
  2. _end_timer
  3. print_asc
  4. print_data
  5. help
  6. terror
  7. create_tdb
  8. open_tdb
  9. insert_tdb
  10. store_tdb
  11. show_tdb
  12. delete_tdb
  13. move_rec
  14. print_rec
  15. print_key
  16. print_hexkey
  17. traverse_fn
  18. info_tdb
  19. speed_tdb
  20. toggle_mmap
  21. tdb_getline
  22. do_delete_fn
  23. first_record
  24. next_record
  25. test_fn
  26. check_db
  27. do_command
  28. convert_string
  29. main

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

/* [<][>][^][v][top][bottom][index][help] */