/* dumpgdbm.c ========== Very old Homepage = http://tboudet.free.fr/dumpgdbm/ (g) 2003 Thierry Boudet - aka TontonTh */ #include #include #include #include #include #include #include #include #include #define MAIN 1 #include "dumpgdbm.h" /* --------------------------------------------------------------------- */ /* global variables */ int warn_if_key_empty = 0; int found_an_empty_key = 0; int interactive = 0; int leading_zero = 1; #define MAX_FILENAME_LENGTH 4242 /* 63 bytes for a filename is enough for all. -imaginary BG- */ char filename[MAX_FILENAME_LENGTH+2]; /* --------------------------------------------------------------------- */ static void dump_entry(datum key, datum data, int maxsize) { #if TRACE printf("@,L: %p,%d %p,%d\n", key.dptr, key.dsize, data.dptr, data.dsize); #endif printf("K: "); if (hexadecimal) hexadump(key.dptr, key.dsize); else if (octal) octaldump(key.dptr, key.dsize); else asciidump(key.dptr, key.dsize); printf("D: "); if (hexadecimal) hexadump(data.dptr, data.dsize); else if (octal) octaldump(data.dptr, data.dsize); else asciidump(data.dptr, data.dsize); free(data.dptr); /* XXX XXX */ printf("\n"); } /* --------------------------------------------------------------------- */ /* * here we have the main loop for batches dumps. */ static int dump_gdbm_file(char *name) { GDBM_FILE file; datum entry, datas; file = gdbm_open(name, 512, GDBM_READER, 0444, NULL); #if TRACE fprintf(stderr, "retour gdbm_open = %08lx\n", (unsigned long)file); #endif if (file == NULL) { fprintf(stderr, "can't open %s\n", name); return -1; } entry = gdbm_firstkey(file); if (entry.dptr == NULL) { fprintf(stderr, "database %s is empty\n", name); exit(2); } do { datas = gdbm_fetch(file, entry); if (entry.dsize == 0) { found_an_empty_key = 1; } dump_entry(entry, datas, maxoctets); /* * XXX may be we must free the data memory here ? */ entry = gdbm_nextkey(file, entry); } while ( entry.dptr != NULL); gdbm_close(file); return 0; } /* --------------------------------------------------------------------- */ /* * Oct 17 2002: use of regular expressions. */ int search_key(GDBM_FILE gf, char * pattern) { datum entry, datas; char *bufptr, *cptr; int foo; regex_t reg; regmatch_t match[1]; if (pattern == NULL) { fprintf(stderr, "no pattern ??\n"); return -1; } foo = strlen(pattern); if (pattern[foo-1] == '\n') pattern[foo-1] = '\0'; #if TRACE fprintf(stderr, "Search Key: cleaned pattern [%s]\n", pattern); #endif foo = regcomp(®, pattern, REG_EXTENDED); #if TRACE printf("regcomp ---> %d\n", foo); #endif entry = gdbm_firstkey(gf); if (entry.dptr == NULL) { fprintf(stderr, "database is empty or bugged\n"); exit(2); } do { bufptr = (char *)malloc(entry.dsize+2); if (bufptr == NULL) { fprintf(stderr, "in Search Key: no memory, sorry\n"); exit(5); } strncpy(bufptr, entry.dptr, entry.dsize); bufptr[entry.dsize] = '\0'; #if TRACE fprintf(stderr, "Search Key: bufptr is [%s]\n", bufptr); #endif foo = regexec(®, bufptr, 1, match, 0); if (foo==0) { datas = gdbm_fetch(gf, entry); dump_entry(entry, datas, maxoctets); } free(bufptr); /* 26 Jul 2002 */ entry = gdbm_nextkey(gf, entry); } while ( entry.dptr != NULL); regfree(®); return 0; } /* --------------------------------------------------------------------- */ /* * Oct 16 2002: use of regular expressions. */ int search_data(GDBM_FILE gf, char * pattern) { datum entry, datas; char *bufptr; int foo; regex_t reg; regmatch_t match[1]; if (pattern == NULL) { fprintf(stderr, "no pattern ??\n"); return -1; } foo = strlen(pattern); if (pattern[foo-1] == '\n') pattern[foo-1] = '\0'; #if TRACE fprintf(stderr, "\nSearch Data: cleaned pattern [%s]\n", pattern); #endif foo = regcomp(®, pattern, REG_EXTENDED); #if TRACE printf("regcomp ---> %d\n", foo); #endif entry = gdbm_firstkey(gf); if (entry.dptr == NULL) { fprintf(stderr, "database is empty or bugged\n"); exit(2); } do { datas = gdbm_fetch(gf, entry); if (datas.dsize > 0) { bufptr = (char *)malloc(datas.dsize+2); if (bufptr == NULL) { fprintf(stderr, "in Search Data: no memory, sorry\n"); exit(5); } strncpy(bufptr, datas.dptr, datas.dsize); bufptr[datas.dsize] = '\0'; #if TRACE // fprintf(stderr, "Search Data: bufptr [%s]\n", bufptr); #endif foo = regexec(®, bufptr, 1, match, 0); if (foo==0) { dump_entry(entry, datas, maxoctets); } } else { fprintf(stderr, "data size is 0 ?\n"); } entry = gdbm_nextkey(gf, entry); } while ( entry.dptr != NULL); regfree(®); return 0; } /* --------------------------------------------------------------------- */ #define CMDLINE_LENGTH 80 #define CMD_QUIT 1 #define CMD_HEX 2 #define CMD_ASCII 3 #define CMD_OCTAL 4 #define CMD_FIRST 5 #define CMD_NEXT 6 #define CMD_SEVEN 7 #define CMD_HEIGHT 8 #define CMD_PRINT 10 #define CMD_KEYSEARCH 12 #define CMD_DATASEARCH 13 #define CMD_MAXOCT 14 #define CMD_FMBL 15 #define CMD_EMPTY 16 #define CMD_HELP 42 #define CMD_LISTCOM 43 #define CMD_VERSION 51 typedef struct { char *keyw; int code; } Commande; Commande commandes[] = { { "q", CMD_QUIT }, { "ZZ", CMD_QUIT }, { ":q", CMD_QUIT }, { ":q!", CMD_QUIT }, { "exit", CMD_QUIT }, { "quit", CMD_QUIT }, { "bye", CMD_QUIT }, { "x", CMD_HEX }, { "hex", CMD_HEX }, { "hexa", CMD_HEX }, { "a", CMD_ASCII }, { "ascii", CMD_ASCII }, { "o", CMD_OCTAL }, { "octal", CMD_OCTAL }, { "h", CMD_HELP }, { "help", CMD_HELP }, { "?", CMD_HELP }, { "f", CMD_FIRST }, { "first", CMD_FIRST }, { "m", CMD_MAXOCT }, { "maxoctets", CMD_MAXOCT }, { "maxbytes", CMD_MAXOCT }, { "n", CMD_NEXT }, { "next", CMD_NEXT }, { "p", CMD_PRINT }, { "print", CMD_PRINT }, { "ks", CMD_KEYSEARCH }, { "keysearch", CMD_KEYSEARCH }, { "ds", CMD_DATASEARCH }, { "datasearch", CMD_DATASEARCH }, { "empty", CMD_EMPTY }, { "7", CMD_SEVEN }, { "8", CMD_HEIGHT }, { "V", CMD_VERSION }, { "version", CMD_VERSION }, { "commands", CMD_LISTCOM }, { "listcom", CMD_LISTCOM }, { "sux", 0 } }; #define NBRE_CMD (sizeof(commandes)/sizeof(Commande)) typedef struct { int number; char *text; } Help; char Help_version[] = "If you send me a bug report at , you must give me\n" " this information, with the output of 'uname -a' command."; char Help_maxoctet[] = "change the number of bytes displayed for key & data field.\n" " can be modified with the -m NN command line option."; char Help_print[] = "re-print the current record, so you can see it with different 'base':\n" " ascii, hexadecimal or octal. use '? [a|x|o]' for more info."; char Help_first[] = "JUMPTO the first record. you have to understand this. man gdbm."; char Help_next[] = "GOTO the next record. you have to understand this. 'man gdbm' is a must."; char Help_seven[] = "only true ASCII chars are printed. others are displayed as '.'"; char Help_height[] = "display all chars. beware of differences in charset between Os !"; char Help_KS[] = "Search a posix regex pattern in all the key fields."; char Help_DS[] = "POSIX extended regex search in all the data fields."; char No_Help_Text[] = "this help text need to be written..."; Help help[] = { { 0, "just a joke for my friend tnemeth :)" }, { CMD_QUIT, "good bye, cruel world." }, { CMD_VERSION, Help_version }, { CMD_HEX, "switch to hexadecimal display." }, { CMD_OCTAL, "switch to octal display, you own a pdp11 ???" }, { CMD_ASCII, "switch to ascii display, see 7 & 8 commands." }, { CMD_MAXOCT, Help_maxoctet }, { CMD_PRINT, Help_print }, { CMD_FIRST, Help_first }, { CMD_NEXT, Help_next }, { CMD_SEVEN, Help_seven }, { CMD_HEIGHT, Help_height }, { CMD_KEYSEARCH, Help_KS }, { CMD_DATASEARCH, Help_DS }, { CMD_HELP, "sure, 42 is the ultimate answer !" } }; #define NBRE_HELP (sizeof(help)/sizeof(Help)) // ------------------------- static int lookup_cmd(char *cmd) { int foo; /* * bon, la, c'est un hack un peu crade... mais je pense * que c'est qu'on rec,oit un parametre foireux... */ if ( cmd[strlen(cmd)-1] == '\n') cmd[strlen(cmd)-1] = '\0'; #if TRACE printf("lookup cmd [%s]\n", cmd); #endif for (foo=0; foo 69) /* sex number ? */ { bar = 0; puts(""); } } printf("\n-----------( use '? command' for details )----------\n"); } static void full_help(char *keyword) { int num_keyword, foo; num_keyword = lookup_cmd(keyword); #if TRACE fprintf(stderr, "%s -> %d\n", keyword, num_keyword); #endif if (num_keyword == -1) { printf("%s: no such command\n", keyword); return; } for (foo=0; foo "); if (pline == NULL) { printf("\nEOF ?\n"); break; } /* * if the line is not empty, add it to the history */ if ( pline && *pline ) add_history(pline); #if TRACE printf("[%s]\n", pligne); #endif /* * search the first token on the line */ cptr = strtok(pline, " \t"); #if TRACE fprintf(stderr, "pline %p cptr %p\n", pline, cptr); #endif /* * is there a text on this command-line ? */ if ( cptr==NULL || !strcmp("\n", cptr) ) continue; #if TRACE printf("token = %s\n", cptr); #endif /* * Ok, la commande est pointee par cptr, on va tenter * de la comprendre... */ code_cmd = lookup_cmd(cptr); switch (code_cmd) { case CMD_QUIT: flag_exit = 1; break; case CMD_HEX: hexadecimal = 1; octal = 0; break; case CMD_OCTAL: octal = 1; hexadecimal = 0; break; case CMD_ASCII: octal = hexadecimal = 0; break; case CMD_HELP: cptr = strtok(NULL, " \t"); if (cptr == NULL || *cptr == '\0') help_cli(); else full_help(cptr); break; case CMD_VERSION: print_version(1); break; case CMD_FIRST: entry = gdbm_firstkey(gdbm_file); if (entry.dptr == NULL) { fprintf(stderr, "database is empty\n"); break; } datas = gdbm_fetch(gdbm_file, entry); dump_entry(entry, datas, maxoctets); first_ok = 1; break; case CMD_NEXT: if (first_ok) entry = gdbm_nextkey(gdbm_file, entry); else entry = gdbm_firstkey(gdbm_file); first_ok = 1; if (entry.dptr == NULL) { fprintf(stderr, "end of database\n"); break; } datas = gdbm_fetch(gdbm_file, entry); dump_entry(entry, datas, maxoctets); break; case CMD_PRINT: if ( ! first_ok ) entry = gdbm_firstkey(gdbm_file); first_ok = 42; if (entry.dptr == NULL) { fprintf(stderr, "Print: no entry\n"); break; } datas = gdbm_fetch(gdbm_file, entry); dump_entry(entry, datas, maxoctets); break; case CMD_KEYSEARCH: cptr = strtok(NULL, " \t"); if (cptr != NULL) { search_key(gdbm_file, cptr); } else { fprintf(stderr, "keysearch need an argument\n"); } break; case CMD_DATASEARCH: #if TRACE fprintf(stderr, "==== DATA SEARCH ====\n"); #endif search_data(gdbm_file, strtok(NULL, " \t")); break; case CMD_MAXOCT: cptr = strtok(NULL, " \t"); if (cptr != NULL) { #if TRACE fprintf(stderr, "MAXOCT: cptr %s\n", cptr); #endif if ( sscanf(cptr, "%d", &value) == 1 ) { printf("maxoctets = %d\n", value); maxoctets = value; } } else { fprintf(stderr, "need a numeric argument\n"); } break; case CMD_SEVEN: ok_for_8_bits = 0; break; case CMD_HEIGHT: ok_for_8_bits = 1; break; case CMD_LISTCOM: list_commands(0); break; case 0: fprintf(stderr, "\t\tChimera roulaize grave a donf\n"); fprintf(stderr, "\t\tAthena widgets are so nice !!\n"); break; default: fprintf(stderr, "command %s : huho ?\n", cptr); break; } #if TRACE fprintf(stderr, "freeing command line %p\n", pline); #endif free(pline); } while ( ! flag_exit ); } /* --------------------------------------------------------------------- */ static char *optstring = "VvxohwW8m:ia"; int main(int argc, char *argv[]) { int option_retour; int foo; init_global_vars(); while ( (option_retour = getopt(argc, argv, optstring)) >= 0) { #if TRACE fprintf(stderr, "getopt = %d, argc = %d, optind = %d\n", option_retour, argc, optind); #endif switch (option_retour) { case 'V': print_version(1); exit(1); break; case 'v': verbosity++; if (verbosity > 5) { fprintf(stderr, "Higher verbosity !\n"); fprintf(stderr, "now dumping kernel...\n"); sleep(5); exit(1); } break; case 'a': hexadecimal = octal = 0; break; case 'x': hexadecimal = 1; octal = 0; break; case 'o': octal = 1; hexadecimal = 0; break; case 'h': print_version(0); print_options(); exit(2); break; case 'w': warn_if_key_empty = 1; break; case '8': ok_for_8_bits = 1; break; case 'i': interactive = 1; break; case 'm': if (sscanf(optarg, "%d", &foo) == 1) { maxoctets = foo; } else { fprintf(stderr,"opt 'm' need a numeric arg\n"); exit(5); } break; } } #if TRACE fprintf(stderr, "fin traitement options argc=%d, optind=%d\n", argc, optind); #endif /* * a cet endroit il est probable qu'on puisse memoriser * le nom du fichier GDBM dans une variable globale. */ if (optind != argc) { strncpy(filename, argv[optind], MAX_FILENAME_LENGTH); } else { fprintf(stderr, "WARNING: dumpgdbm: missing filename\n"); print_options(); exit(1); } if (interactive) { shell(); } else { dump_gdbm_file(argv[optind]); } if (found_an_empty_key && warn_if_key_empty) { fprintf(stderr, "YO! A KEY IS EMPTY\n"); } return 0; } /* ------------------------------------------------------- the end ----- */