diff --git a/CheckResolv/Makefile b/CheckResolv/Makefile new file mode 100644 index 0000000..7701cd7 --- /dev/null +++ b/CheckResolv/Makefile @@ -0,0 +1,60 @@ +#------------------------------------------------------------------- +# +# CheckResolv +# +# editable configuration variables: + +DESTDIR = /usr/local +COPT = -g -ansi -Wall + +# +# you can now compile with "make checkresolv" and install it +# with "su -c 'make install'" +# +#------------------------------------------------------------------- + +VERSION=0.25 + +all: + @echo + @echo " may be you can read (and edit) the Makefile before" + @echo " trying to compile and run that kludge..." + @echo + @echo " for impatients: try \"make checkresolv\"" + @echo + +checkresolv.o: checkresolv.c Makefile fonctions.h + gcc $(COPT) -c -DVERSION=\"$(VERSION)\" -DTRACE=0 $< + +fonctions.o: fonctions.c Makefile fonctions.h + gcc $(COPT) -c -DVERSION=\"$(VERSION)\" -DTRACE=0 $< + +checkresolv: checkresolv.o fonctions.o + gcc $(COPT) $^ -o $@ + +#------------------------------------------------------------------- +# +# install procedure is _also_ quick and dirty +# +install: + install --strip checkresolv $(DESTDIR)/bin + install checkresolv.man $(DESTDIR)/man/man1/checkresolv.1 + +#------------------------------------------------------------------- + +FILES=*.c *.h Makefile CHANGELOG README TODO checkresolv.man *.html + +TARNAME=checkresolv-$(VERSION).tar.gz + +tarball: $(FILES) + @echo "Tarball is" $(TARNAME) + @ls $^ > MANIFEST ; \ + ( cd .. ; \ + tar zcvf $(TARNAME) `sed 's/^/CheckResolv\//' CheckResolv/MANIFEST` ) + @date >> tarball + @wc -c ../$(TARNAME) + +lines: $(FILES) + wc $(FILES) | sort -n + +#------------------------------------------------------------------- diff --git a/CheckResolv/README.md b/CheckResolv/README.md new file mode 100644 index 0000000..edf492d --- /dev/null +++ b/CheckResolv/README.md @@ -0,0 +1,21 @@ +``` + CheckResolv + =========== + + This is a quick and dirty hack, built for chasing + a LPRng latency problem. Usage is very simple: + you give a hostname or an IP addr, and the soft + try a few lookup and/or reverse lookup. + + + Options are: + -V display version + -r do a reverse lookup + -v increase verbosity + -e print relateds env vars + -t display time op operations + + + Have a good life, don't release CO2 in the Ternet... + +``` diff --git a/CheckResolv/TODO b/CheckResolv/TODO new file mode 100644 index 0000000..c4ccbaa --- /dev/null +++ b/CheckResolv/TODO @@ -0,0 +1,12 @@ + This is the TODO file for CheckResolv + ------------------------------------- + + - virer les GNUismes du Makefile + - check for potentials buffers overflows + - write a really cut manpage + + - add a function to analyze /etc/resolv.conf + - add a function to check /etc/hosts + + - build a fonction for detect DNS used by the resolver. + diff --git a/CheckResolv/checkresolv.c b/CheckResolv/checkresolv.c new file mode 100644 index 0000000..ab1ff16 --- /dev/null +++ b/CheckResolv/checkresolv.c @@ -0,0 +1,238 @@ +/* + * CheckResolv + * =========== + * + * quick and dirty debugging hack. + * + */ + +#include +#include +#include +#define __USE_BSD +#include +/* #undef __USE_BSD */ +#include +#include + +#define __USE_MISC +#include /* herror ? */ + +#include +#include +#include + +#include "fonctions.h" + +char * strdup(char *); /* DIRTY HACK */ + +/* ------------------------------------------------------------ */ +/* quick and dirty global variables */ + +int verbose = 0; +int do_reverse = 0; +int do_environ = 0; +int do_timing = 0; + +/* ------------------------------------------------------------ */ +/* parameter '*txt' is not used */ +int print_hostent(struct hostent *ph, char *txt) +{ +char *ptr, **pptr; + +printf("h_name: %s\n", ph->h_name); + +pptr = ph->h_aliases; +if (verbose) { + printf("h_aliases: %p -> %p\n", pptr, *pptr); + } + +while ( (ptr = *(pptr)) != NULL ) { + printf(" alias: %s\n", ptr); + pptr++; + } + +if (verbose) { + printf("h_addrtype: %d\n", ph->h_addrtype); + printf("h_length: %d\n", ph->h_length); + } + +print_ip((struct in_addr **)ph->h_addr_list); /* strange cast */ + +return 0; +} +/* ------------------------------------------------------------ */ +/* + * If we have a list of IP addr, we can try a + * reverse lookup, no ? + */ +int check_reverse(struct hostent *ph) +{ +struct in_addr **liste; +struct in_addr *addr; +struct in_addr l_addr; /* Jules */ +struct hostent *revph; +int nbre; +double t1 , t2; +char *ptmp; + +if (do_timing) t1 = chronometre(); + +nbre = 0; +liste = (struct in_addr **)ph->h_addr_list; + +while (NULL != (addr = *liste++)) { + l_addr = *addr; /* Jules */ +#if TRACE + fprintf(stderr, "---> %p %p\n", addr, l_addr); +#endif + revph = gethostbyaddr(&l_addr, ph->h_length, ph->h_addrtype); + if (NULL != revph) { + /* taking over hidden string vars */ + ptmp = strdup(inet_ntoa(l_addr)); + if (NULL == ptmp) { + fprintf(stderr, "no memory in %s, line %d\n", + __FILE__, __LINE__); + abort(); + } +#if TRACE + fprintf(stderr, "%s:%d %p %p\n", __func__, __LINE__, + ptmp, revph->h_name); +#endif + printf("reverse %-16s -> %s\n", ptmp, revph->h_name); + free(ptmp); + } + else { + /* fprintf(stderr, "reverse ? wtf ?\n"); */ + herror("reverse lookup"); /* this func is obsolete ! */ + } + nbre++; + } + +if (do_timing) { + t2 = chronometre(); + if (nbre > 1) + printf("reverse take %.3f s (%.3f s)\n", t2-t1, (t2-t1)/nbre); + else + printf("reverse take %.3f s.\n", t2-t1); + } + +return 0; +} +/* ------------------------------------------------------------ */ +struct hostent *direct_lookup(char *hostname) +{ +struct hostent *p_host; +double t1 , t2; +int foo; + +if (do_timing) t1 = chronometre(); +p_host = gethostbyname(hostname); +if (do_timing) t2 = chronometre(); + +if (p_host==NULL) + { + fprintf(stderr, "error %d on '%s'", h_errno, hostname); + herror(" "); + return NULL; + } + +foo = print_hostent(p_host, NULL); + +if (do_timing) printf("gethostbyname take %.3f s.\n", t2 - t1); + +return p_host; +} +/* ------------------------------------------------------------ */ +int analyse(char *nom, int flag) +{ +struct hostent *p_host; + +p_host = direct_lookup(nom); + +/* + * new, 31 jan 2005, v 0.19 + * if the requested 'hostname' seems to be an ip address, can we + * force a valid reverse lookup ? + */ +if (is_IP_addr(nom) && !do_reverse) + { + fprintf(stderr, "* if %s is a valid ip addr, try the '-r' switch.\n", + nom); + } + +if (do_reverse && (p_host!=NULL)) + check_reverse(p_host); + +return 0; +} +/* ------------------------------------------------------------ */ +/* + * Set some global flags, based on our environment + * variable. + */ +void analyze_environ(void) +{ +char *ptr; + +ptr = getenv("CHECKRESOLV"); +if (ptr == NULL) + return; +if ( ! strcmp("tech", ptr) ) { + do_reverse = 1; + do_timing = 1; + } +if ( ! strcmp("all", ptr) ) { + do_reverse = 1; + do_timing = 1; + verbose = 1; + do_environ = 1; + } +} +/* ------------------------------------------------------------ */ +int main (int argc, char *argv[]) +{ +int foo; + +char * liste_opt = "vrhteV"; +int option; + +if (argc == 1) help_options(); + +while ((option=getopt(argc, argv, liste_opt)) != -1) + { + switch(option) + { + case 'v': verbose++; break; + case 'r': do_reverse=1; break; + case 'e': do_environ=1; break; + case 't': do_timing=1; break; + case 'h': usage(); break; + case 'V': version(); break; + } + } + +#if TRACE +fprintf(stderr, "argc %d optind %d\n", argc, optind); +for (foo=optind; foo + +CheckResolv + + + + + +

CheckResolv

+ +

+This is a quick'n'dirty tool for checking the configuration +of your local resolver and/or DNS configuration. See the +included manpage and source code for more explanations. +

+ +

options

+ +
-V
display version number and exit. +
-h
brief help on the command-line options. +
-v
display various useless messages. +
-r
do reverse lookup on IP address discovered. +
-e
show content of a few environment var resolver-related. +
-t
compute elapsed time of operation, not really accurate. +
+ +
+

+This software use only basic functions like gethostbyname(3) +or gethostbyaddr(3). Checkresolv use the more low-level +of the resolver galaxy, so it works like any "lambda" +application. Really nice when you have to catch a mysterious +failure in a LAMBDA software. +

+ +

+The environmemt variable CHECKRESOLV control the verbosity. +A value of tech add the display of reverse lookup and timings. +And setting to all give you all the bells'n'whistles needed +by geeks. +

+ + + diff --git a/CheckResolv/checkresolv.man b/CheckResolv/checkresolv.man new file mode 100644 index 0000000..e705011 --- /dev/null +++ b/CheckResolv/checkresolv.man @@ -0,0 +1,80 @@ +.TH CheckResolv 1 "2005 September" "various OS" "Tonton Th" + +.SH NAME +checkresolv \- quick & dirty tool for checking sanity of resolver. + +.SH SYNOPSIS +\fBcheckresolv\fP -V +.br +\fBcheckresolv\fP [options] host.name +.br +\fBcheckresolv\fP [options] 42.51.69.406 + +.SH DESCRIPTION +CheckResolv is a (not so) q'n'd tool for checking basic capacities and +potentials bugs of your resolver configuration. +I have started the dev of this thing when I was working hard on a remote +nasty printing problems. +It use only \fBgethostbyname\fP and \fBgethostbyaddr\fP functions, +like any lambda applications. +CheckResolv can also display environment variables who can modify the behaviour +of this damned resolver, or give you some problems. + +.SH OPTIONS +.B -V +display version number and exit. +.br +.B -h +brief help on the command-line options. +.br +.B -v +display various useless messages. +.br +.B -r +do reverse lookup on IP address discovered. +.br +.B -e +show content of a few environment vars resolver-related. +.br +.B -t +compute elapsed time of operation, not really accurate. + +.SH TIPS +If you have a strange problem between two hosts, "don't panic". Take the time +to compil CheckResolv on the two hosts, and run it with the -r option, first +with the hostname, and after that, with the IP address. +And do this two runs on the two hosts. So, you get four results. +Now, use your brain... + +.SH CONFIG FILE +All your config files are belong to us. In the futur, may be you can +put a list of env vars to display in a file. + +.SH ENV VARS +If the environment variable CHECKRESOLV is set to "tech", reverse lookup +and timing are activated, very nice when your pop3 server take 42 seconds +before you can get some silly answer. +And "all" give you all the bells & whistles. +This variable override command lines options. + +.SH SEE ALSO +.BR resolver (5), +.BR host (1), +.BR dig (1), +.BR nslookup (1) + +.SH BUGS +Some are here, some are waiting in the dark. Hidden static storage is a pain. +No IPv6 support. No Slackware package, no Debian package... + +.SH COMPILATION +Currently (2005 march), this software was only tested on Slackware 10.0 and +Debian Sarge, but it can +compile 'fine' on others Linux or *BSD flavors. IRIX is also a valuable target, +because my troll-master use it... + +.SH AUTHOR(S) +Thierry (aka tth) Boudet, with help from @donis, Miod, Reynerie... + + + diff --git a/CheckResolv/fonctions.c b/CheckResolv/fonctions.c new file mode 100644 index 0000000..59ea04a --- /dev/null +++ b/CheckResolv/fonctions.c @@ -0,0 +1,167 @@ +/* + * CheckResolv + * =========== + * quick and dirty debugging hack. + * + * a bunch of various undocumented functions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fonctions.h" + +/* ------------------------------------------------------------ */ +/* + * return !0 if str seems to be a quadnumber ip address. + */ +int is_IP_addr(char *str) +{ +int nbrdots, length, foo, flag; +/* int o[4]; */ + +length = strlen(str); +flag = nbrdots = 0; +for (foo=0; fooname != NULL) + { + print_onevar(pev->name); + pev++; + } + +return 0; +} +/* ------------------------------------------------------------ */ +void help_options(void) +{ +fputs("checkresolv [-v] [-r] [-e] [-t] hostname|ipaddr\n", stderr); +fputs("checkresolv -h : more help\n", stderr); +fputs("checkresolv -V : print version\n", stderr); +} +/* ------------------------------------------------------------ */ +void usage(void) +{ +fprintf(stderr, "*** CheckResolv v %s *** by tth ***\n", VERSION); +fputs("Usage:\n", stderr); +fputs("\tcheckresolv [options] hostname | @ip\n", stderr); +fputs("\n", stderr); +fputs("options:\n", stderr); +fputs("\t-V: display version number\n", stderr); +fputs("\t-v: increase verbosity\n", stderr); +fputs("\t-r: try a reverse lookup\n", stderr); +fputs("\t-e: print some env vars\n", stderr); +fputs("\t-t: print elapsed time\n", stderr); +fputs("\n", stderr); +fputs("environmemt variable:\n", stderr); +fputs("\tname: CHECKRESOLV\n", stderr); +fputs("\tvalue: \"tech\" reverse-lookup and timing\n", stderr); +fputs("\tvalue: \"all\" all the bells & whistles\n", stderr); +fputs("\n", stderr); +exit(0); +} +/* ------------------------------------------------------------ */ +void version(void) +{ +printf("CheckResolv v %s by tth\n", VERSION); +} +/* ------------------------------------------------------------ */ diff --git a/CheckResolv/fonctions.h b/CheckResolv/fonctions.h new file mode 100644 index 0000000..82dbdfe --- /dev/null +++ b/CheckResolv/fonctions.h @@ -0,0 +1,17 @@ +/* + * CheckResolv + * =========== + * quick and dirty debugging hack. + * + */ + +int is_IP_addr(char *str); +double chronometre(void); + +int print_ip(struct in_addr **liste); + +void help_options(void); +void usage(void); +void version(void); + +int print_envvars(int flag); diff --git a/DumpGDBM/.gitignore b/DumpGDBM/.gitignore new file mode 100644 index 0000000..551698e --- /dev/null +++ b/DumpGDBM/.gitignore @@ -0,0 +1 @@ +MANIFEST diff --git a/DumpGDBM/Makefile b/DumpGDBM/Makefile new file mode 100644 index 0000000..d5650ac --- /dev/null +++ b/DumpGDBM/Makefile @@ -0,0 +1,91 @@ +# ---------------------------------------------------- +# this is the Makefile for the 'dumpgdbm' utility +# ---------------------------------------------------- +# +# Pour plus d'information, le mieux, c'est de m'ecrire +# ou de me faire parvenir une caisse +# de vin australien. Ou chilien, ils font du bon vin +# au Chili: du Cabernet-Sauvignon de premiere bourre. +# +# ---------------------------------------------------- +# + +OU_LE_METTRE = /usr/local + +# +# Positionner TRACE a 42 pour avoir un binaire +# qui raconte sa vie, son oeuvre, ses trolls... +# +# you can safely remove the -g (debug) options. +# + +TRACE = 0 +C_OPT = -Wall -DTRACE=$(TRACE) + +# ---------------------------------------------------- + +all: dumpgdbm cleargdbm + +dump_funcs.o: dump_funcs.c dumpgdbm.h Makefile + cc $(C_OPT) -c dump_funcs.c + +dumpgdbm.o: dumpgdbm.c dumpgdbm.h Makefile + cc $(C_OPT) -c dumpgdbm.c + +dumpgdbm: dumpgdbm.o dump_funcs.o Makefile + cc $(C_OPT) dumpgdbm.o dump_funcs.o -lgdbm -lreadline -ltermcap -o dumpgdbm + +exemple.gdbm: exemple.pl Makefile + -rm exemple.gdbm + perl ./exemple.pl + +cleargdbm: cleargdbm.c Makefile + cc $(C_OPT) cleargdbm.c -lgdbm -o cleargdbm + +love: + @echo "--------- No War --------" + @echo "install -> " $(OU_LE_METTRE)/ + @echo "trace -> " $(TRACE) + +# +# Bon, OK, ma methode d'installation est rudimentaire, +# mais fallait lire la doc avant, si votre systeme est +# tout detruit, c'est pas de ma faute. Ymmv. +# + +install: + cp dumpgdbm dumpgdbm.install + strip dumpgdbm.install + cp dumpgdbm.install $(OU_LE_METTRE)/bin/dumpgdbm + rm dumpgdbm.install + cp dumpgdbm.1 $(OU_LE_METTRE)/man/man1/dumpgdbm.1 + cp cleargdbm.1 $(OU_LE_METTRE)/man/man1/cleargdbm.1 + @echo + @echo "configuration modified, you have to reboot now." + @echo " [YES] [NO] [MAY BE] [DON'T KNOW]" + @echo + @sleep 1 + @echo "arf, arf, trop drole, on s'y croirait..." + @echo + +# +# Rah, mais qu'est ce qu'est Gruiik, ce truc ! +# + +tarball: dumpgdbm.c dumpgdbm.1 Makefile README TODO MANIFEST BUGS \ + cleargdbm.c cleargdbm.1 INSTALL dump_funcs.c \ + dumpgdbm.h exemple.pl + ( cd .. ; \ + tar zcvf dumpgdbm.tar.gz `sed 's/^/DumpGDBM\//' DumpGDBM/MANIFEST` ) + date >> tarball + + +# +# merci de votre attention. +# +# http://la.buvette.org/ego/ +# http://krabulator.free.fr/devel/ +# +# +#-- end of Makefile -- + diff --git a/DumpGDBM/README.md b/DumpGDBM/README.md new file mode 100644 index 0000000..ecc29a7 --- /dev/null +++ b/DumpGDBM/README.md @@ -0,0 +1,2 @@ +# DumpGDBM + diff --git a/DumpGDBM/cleargdbm b/DumpGDBM/cleargdbm new file mode 100755 index 0000000..e70f7a6 Binary files /dev/null and b/DumpGDBM/cleargdbm differ diff --git a/DumpGDBM/cleargdbm.1 b/DumpGDBM/cleargdbm.1 new file mode 100644 index 0000000..1514eb5 --- /dev/null +++ b/DumpGDBM/cleargdbm.1 @@ -0,0 +1,59 @@ +.TH ClearGDBM 1 "Juillet 2002" "GNU/Linux" "tontonTh tools" + +.SH NAME +cleargdbm \- Videur de fichiers GDBM + +.SH SYNOPSYS +\fBcleargdbm\fP -V +.br +\fBcleargdbm\fP -h|-? +.br +\fBcleargdbm\fP [-v] fichier.gdbm + +.SH DESCRIPTION +Les fichiers GDBM permettent de stocker des 'tables associatives' +sur mémoire permanente. La rapidité de lecture de ces tables est +impressionante. Je les utilise parfois comme cache de bases de +données dans des applications Web. +.br + +\fBcleargdbm\fP permet de 'vider' une table gdbm, en fait de l'effacer +physiquement du disque, puis de la re-créer sans rien y mettre dedans. +Accessoirement, on peut aussi mesurer la vitesse d'utilisation, de +manière totalement arbitraire (à la BogoMIPS, en fait). +.br + +Le programme tente de préserver certaines caractéristiques du fichier +destroyé: les droits d'accès uniquement à l'heure actuelle. + + +.SH OPTIONS +.B -V +pour connaitre la version du machin-bidule. +.br +.B -v +pour avoir du bavardage (fmbl roulaize) sur ce que fait ce kludge. +.br +.B -h -? +Ah, il y a un peu de l'aide. On va en avoir besoin. +.br + +.SH SEE ALSO +.BR gdbm (3) +.BR GDBM_File (3pm) +.BR dumpgdbm (1) + +.SH BUGS +Il y en a probablement quelques uns qui trainent... +Au lieu de raler, il faut signaler les problêmes à l'auteur. +Toutes les idées d'amélioration sont les bienvenues. +De bonnes bouteilles aussi. +Bières anglo/saxonnes (Guinness roulaize) ou vins languedociens. + +.SH AUTHOR +Thierry Boudet (oulala@chez.com) depuis Juillet 1999. +Pour en savoir plus: http://krabulator.free.fr/devel/ ou La.Buvette.Org. + +.SH DEDICACE +Ce logiciel est dédié à Florence D. qui est le soleil de ma vie. + diff --git a/DumpGDBM/cleargdbm.c b/DumpGDBM/cleargdbm.c new file mode 100644 index 0000000..273ac10 --- /dev/null +++ b/DumpGDBM/cleargdbm.c @@ -0,0 +1,167 @@ +/* + cleargdbm.c + =========== + + very old homepage = http://krabulator.free.fr/devel/ + + ===================================================== + WARNING! this program is _not_ secure! don't use it + with a setuid root setting. + ===================================================== + + (g) 2003 Thierry Boudet - aka TontonTh +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "0.0.12" + +#define MAX_FILENAME_LENGTH 4242 // 63 bytes for a filename is enough + // for all. -imaginary BG- + +char filename[MAX_FILENAME_LENGTH+2]; +int verbosity = 0; +int block_size = 512; + +/* --------------------------------------------------------------------- */ +static void +print_version(int totale) +{ +printf ("\n"); +printf ("*** ClearGDBM version %s (g) 2003 TontonTh Useless Soft.\n", VERSION); +printf ("\n"); +if (totale) + { + printf (" file " __FILE__ " compiled " __DATE__ " at " __TIME__ "\n"); + printf (" %s\n", gdbm_version); + printf ("\n"); + } +#if TRACE +printf (" WARNING: compiled with TRACE option. May be _bogus_ !\n\n"); +#endif +} +/* --------------------------------------------------------------------- */ +static void +help(void) +{ + +} +/* --------------------------------------------------------------------- */ +static int +clear_gdbm(char *name, int flag) +{ +int foo; +GDBM_FILE file; +struct stat infos; +int mode; + +#if TRACE +fprintf(stderr, "TRACE: try to clear gdbm file '%s', flag=%d\n", name, flag); +#endif + +/* + * on va vérifier si c'est bien un fichier GDBM qu'on va niquer, là. + */ +file = gdbm_open(name, 512, GDBM_READER, 0444, NULL); +if (file == NULL) + { + fprintf(stderr, "Hu, Ho, '%s' is not a GDBM file, err: %s\n", + name, gdbm_strerror(gdbm_errno)); + exit(1); + } +gdbm_close(file); + +/* + * nous allons récuperer quelques infos sur le fichier à n*q**r. + */ +foo = stat(name, &infos); +#if TRACE +fprintf(stderr, "TRACE: retour stat = %d\n", foo); +#endif +mode = infos.st_mode & 0777; +fprintf(stderr, "protection = 0%03o\n", mode); + +/* + * bon, maintenant, on y va --force + */ +foo = unlink(name); +if (foo) + { + perror ("unlink file"); + exit(1); + } + +file = gdbm_open(name, 512, GDBM_WRCREAT, mode, NULL); +if (file == NULL) + { + fprintf(stderr, "Ho, désolé, pas pu créer %s (%s)\n", + name, gdbm_strerror(gdbm_errno)); + exit(1); + } +gdbm_close(file); + +return 0; +} +/* --------------------------------------------------------------------- */ +/* + * let's go for the destroy :) + */ + +static char *optstring = "Vvhb:?"; + +int main(int argc, char *argv[]) +{ +int option_retour; +int foo; +char *nomfichier; + +while ( (option_retour = getopt(argc, argv, optstring)) >= 0) + { +#if TRACE + fprintf(stderr, "TRACE: getopt = %d, argc = %d, optind = %d\n", + option_retour, argc, optind); +#endif + switch (option_retour) + { + case 'V': + print_version(1); + break; + + case 'v': + verbosity++; + break; + + case 'h': case '?': + help(); + break; + + } + } + +#if TRACE +fprintf(stderr, "TRACE: fin traitement options argc=%d, optind=%d\n", + argc, optind); +fprintf(stderr, "TRACE: next arg %s\n", argv[argc-1]); +#endif + +nomfichier = argv[argc-1]; + +/* + * WARNING! + * + * this programme is not secure. carefully read the sources + * before use. you have be warned. + */ + +clear_gdbm(nomfichier, 0); + +return 0; +} + +/* --------------------------------------------------------------------- */ diff --git a/DumpGDBM/dump_funcs.c b/DumpGDBM/dump_funcs.c new file mode 100644 index 0000000..188b8d2 --- /dev/null +++ b/DumpGDBM/dump_funcs.c @@ -0,0 +1,165 @@ +/* + various functions for dumpgdbm + ============================== + + -------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + -------------------------------------------------------------------- + + (g) 2003 Thierry Boudet - aka TontonTh + +*/ + +#include +#include +#include + +#include + +#include "dumpgdbm.h" + +/* --------------------------------------------------------------------- */ +void +print_version(int totale) +{ +printf ("\n"); +printf ("*** DumpGDBM version %s (g) 2003 TontonTh Useless Soft.\n", VERSION); +printf ("\n"); +if (totale) + { + printf (" more info -> http://krabulator.free.fr/devel/\n"); + printf (" this software is released under the 'Gnu Public License'\n"); + printf (" %s\n", gdbm_version); + printf ("\n"); + } +#if TRACE +printf (" WARNING: compiled with TRACE option. May be _bogus_ !\n\n"); +#endif +} +/* --------------------------------------------------------------------- */ +void +print_options(void) +{ +printf ("command-line options:\n"); +printf ("\t-V\tprint version and infos.\n"); +printf ("\t-x\thexadecimal display.\n"); +printf ("\t-o\toctal display.\n"); +printf ("\t-a\tascii display.\n"); +printf ("\t-v\tbe verbose. more tchatche.\n"); +printf ("\t-w\twarn if key empty. [todo]\n"); +printf ("\t-W\tsilent search empty key. [todo]\n"); +printf ("\t-m 42\tset the qty of bytes displayed.\n"); +printf ("\t-8\tdisplay chars with ascii>127\n"); +printf ("\t-i\tstart in interactive mode\n"); +printf ("\n"); +} +/* --------------------------------------------------------------------- */ +void init_global_vars(void) +{ +verbosity = 0; +maxoctets = 75; +hexadecimal = 0; +octal = 0; +ok_for_8_bits = 0; +} +/* --------------------------------------------------------------------- */ +int +hexadump(void *ptr, int count) +{ +int i, j; +unsigned char *cptr; + +cptr = (unsigned char *)ptr; +if (count > maxoctets) count = maxoctets; + +j = 0; + +for (i=0; i 22 && i!=(count-1)) + { + printf("\n "); + j = 0; + } + } +printf("\n"); +return 0; +} +/* --------------------------------------------------------------------- */ +int +octaldump(void *ptr, int count) +{ +int i, j; +unsigned char *cptr; + +cptr = (unsigned char *)ptr; +if (count > maxoctets) count = maxoctets; + +j = 0; + +for (i=0; i 16 && i!=(count-1)) + { + printf("\n "); + j = 0; + } + } +printf("\n"); +return 0; +} +/* --------------------------------------------------------------------- */ +int +asciidump(void *ptr, int count) +{ +int i, j; +unsigned char *cptr; + +cptr = (unsigned char *)ptr; +if (count > maxoctets) count = maxoctets; + +#if TRACE +fprintf(stderr, "ok_for_8_bits %d\n", ok_for_8_bits); +#endif + +j = 0; +for (i=0; i127) + printf("%c", cptr[i]); + else + printf("."); + } + else + { + if (isprint(cptr[i])) + printf("%c", cptr[i]); + else + printf("."); + } + if (j++ > 70 && i!=(count-1)) + { + printf("\n "); + j = 0; + } + } +printf("\n"); +return 0; +} +/* --------------------------------------------------------------------- */ diff --git a/DumpGDBM/dumpgdbm b/DumpGDBM/dumpgdbm new file mode 100755 index 0000000..a621fc5 Binary files /dev/null and b/DumpGDBM/dumpgdbm differ diff --git a/DumpGDBM/dumpgdbm.1 b/DumpGDBM/dumpgdbm.1 new file mode 100644 index 0000000..077ed91 --- /dev/null +++ b/DumpGDBM/dumpgdbm.1 @@ -0,0 +1,110 @@ +.TH DumpGDBM 1 "Fevrier 2003" "GNU/Linux" "Oulala tools" + +.SH NAME +dumpgdbm \- Dumpeur de fichiers GDBM + +.SH SYNOPSYS +\fBdumpgdbm\fP -V +.br +\fBdumpgdbm\fP -h +.br +\fBdumpgdbm\fP [-vxoa8] [-m 42] [-i] fichier.gdbm + +.SH DESCRIPTION +Les fichiers GDBM permettent de stocker des 'tables associatives' +sur mémoire permanente. La rapidité de lecture de ces tables est +impressionante. Mais leur utilisation est parfois surprenante. +Par exemple, la présence ou non d'un '\\0' en fin de chaine... +.br + +\fBdumpgdbm\fP affiche en ascii, en octal, ou en hexadécimal les +couples (clef/valeur) contenus dans un fichier GDBM. +Il devrait contenir bientôt (ymmv) un mécanisme de détection des clefs nulles, +réputées pour créer des problèmes dans des langages à typage faible, +comme Perl ou PHP. Suggestions attendues... + +.SH OPTIONS +.B -V +pour connaitre la version du machin-bidule. +.br +.B -x +affichage des octets en hexadecimal. +.br +.B -o +affichage en octal (pdp11 roulaize). +.br +.B -a +affichage en ascii (voir aussi -8) +.br +.B -v +pour avoir du bavardage (fmbl roulaize) +.br +.B -h +ah, il y a un peu de l'aide. +.br +.B -8 +C'est OK pour afficher les caractères dont le code ascii > 128. +.br +.B -m 42 +détermine le nombre maximum d'octets affichés. +.br +.B -i +démarrage en mode interactif. + +Les options -x, -a et -o sont exclusives et c'est la dernière rencontrée +sur la ligne de commande qui a la priorité. +L'option -8 n'a de sens qu'en mode ascii. + +.SH INTERACTIF +Pour le mettre en oeuvre, c'est l'option +.B -i +au lancement, et ensuite, au prompt, un +.B ? +pour une liste abrégée des commandes. Puis taper: +.B help command +ou +.B listcom +pour en savoir un peu plus. Désolé, mais mon interpréteur de commandes n'est +pas (encore) parfait. Il utilise readline, mais ne sauvegarde pas (encore) +l'historique des commandes. + +Les commandes de recherche, +.B ds +et +.B ks +, utilisent les expressions régulières POSIX. + + +.SH SEE ALSO +.BR gdbm (3) +.BR GDBM_File (3pm) +.BR cleargdbm (1) +.BR regex(3) + +.SH BUGS +Il y en a probablement quelques uns qui trainent... +Par exemple, rien n'est encore prévu pour l'EBCDIC (Flo?). +Mais bon, au lieu de raler, il faut signaler les problêmes à l'auteur. +Toutes les idées d'amélioration sont les bienvenues. +De bonnes bouteilles aussi. +Bières anglo/saxonnes (Guinness roulaize) ou vins languedociens. + +.SH SORRY +I have to rewrite this man page in english, but my english is very poor. + +.SH LICENSE +Ce logiciel est distribué sous la bienveillante protection de la +GNU GENERAL PUBLIC LICENSE, version 2. J'en profite pour remercier +.B RMS +sans qui rien de tout ça ne serait arrivé. + +.SH AUTHOR +Thierry Boudet (oulala@chez.com) depuis Juillet 1999. +Pour en savoir plus: http://krabulator.free.fr/devel/ ou +http://tboudet.free.fr/ + +.SH DEDICACE +Euh, donc ce logiciel est dédié à Jennifer Mack, dont je suis un fervent +admirateur depuis très longtemps. Merci également à Joshua, qui m'a fait +découvrir que tout cela n'est qu'un jeu. + diff --git a/DumpGDBM/dumpgdbm.c b/DumpGDBM/dumpgdbm.c new file mode 100644 index 0000000..9b6892e --- /dev/null +++ b/DumpGDBM/dumpgdbm.c @@ -0,0 +1,808 @@ +/* + 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 ----- */ diff --git a/DumpGDBM/dumpgdbm.h b/DumpGDBM/dumpgdbm.h new file mode 100644 index 0000000..bb1f7c7 --- /dev/null +++ b/DumpGDBM/dumpgdbm.h @@ -0,0 +1,26 @@ +#ifdef MAIN + #define EXTERN +#else + #define EXTERN extern +#endif + +#define VERSION "0.2.27" + +/* --------------------------------------------------------------------- */ +/* global variables */ + +EXTERN int verbosity; +EXTERN int maxoctets; +EXTERN int hexadecimal; +EXTERN int octal; +EXTERN int ok_for_8_bits; + +/* --------------------------------------------------------------------- */ + +void print_version(int); +void print_options(void); +void init_global_vars(void); + +int hexadump(void *ptr, int count); +int octaldump(void *ptr, int count); +int asciidump(void *ptr, int count); diff --git a/DumpGDBM/exemple.pl b/DumpGDBM/exemple.pl new file mode 100755 index 0000000..430d9ad --- /dev/null +++ b/DumpGDBM/exemple.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl -w + +use strict; +use GDBM_File; + +my $nomdb = "exemple.gdbm"; +my (%DB, @champs); +my ($user, $gecos); + +open(SOURCE, "< /etc/passwd") or die "source $!"; +tie(%DB, "GDBM_File", $nomdb, GDBM_WRCREAT, 0666) or die "gdbm $!"; + +while () + { + @champs = split ":", $_; + $user = $champs[0]."\0"; + $gecos = $champs[4]."\0"; + $DB{$user} = $gecos; + } + +untie %DB; +close SOURCE; +0; diff --git a/Hexdiff/.gitignore b/Hexdiff/.gitignore new file mode 100644 index 0000000..46d4973 --- /dev/null +++ b/Hexdiff/.gitignore @@ -0,0 +1,3 @@ + +hexdiff + diff --git a/Hexdiff/Makefile b/Hexdiff/Makefile new file mode 100644 index 0000000..7967d97 --- /dev/null +++ b/Hexdiff/Makefile @@ -0,0 +1,71 @@ +# +# VISUEL HEXDIFF +# -------------- +# +# old site : http://tboudet.free.fr/hexdiff/ +# + +OU_LE_METTRE = /usr/local +VERSION=0.0.50 + +TARNAME="hexdiff-$(VERSION).tar.gz" + +all: hexdiff + +# +# if you define TRACE to a non zero value, you get a +# lot of debugging trace on _stderr_ +# + +COMP=gcc +COPT=-g -DVERSION=\"$(VERSION)\" -DTRACE=0 -ansi +LOPT=-lncurses + +hexdiff.o: hexdiff.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c hexdiff.c + +fonctions.o: fonctions.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c fonctions.c + +parse_rc.o: parse_rc.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c parse_rc.c + +fileinfo.o: fileinfo.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c fileinfo.c + +sel_file.o: sel_file.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c sel_file.c + +asciiview.o: asciiview.c Makefile hexdiff.h + $(COMP) $(COPT) -Wall -O2 -c asciiview.c + +OBJECTS=hexdiff.o fonctions.o fileinfo.o parse_rc.o sel_file.o \ + asciiview.o + +hexdiff: Makefile $(OBJECTS) + $(COMP) $(OBJECTS) -o $@ $(LOPT) + +# +# this install procedure is very crude. +# +install: + cp hexdiff hexdiff.install + strip hexdiff.install + cp hexdiff.install $(OU_LE_METTRE)/bin/hexdiff + rm hexdiff.install + cp hexdiff.1 $(OU_LE_METTRE)/man/man1/hexdiff.1 + @echo "you can copy hexdiff.rc in your HOME as .hexdiffrc" + +FILES=hexdiff.c hexdiff.1 Makefile README TODO BUGS fonctions.c CHANGES \ + hexdiff.h parse_rc.c hexdiff.rc fileinfo.c sel_file.c \ + asciiview.c memcheck.sh + +tarball: $(FILES) + @echo $(TARNAME) + ls $^ > MANIFEST ; \ + ( cd .. ; \ + tar zcvf $(TARNAME) `sed 's/^/HexDiff\//' HexDiff/MANIFEST` ) + date >> tarball + +lines: $(FILES) + wc $(FILES) | sort -n diff --git a/Hexdiff/README.md b/Hexdiff/README.md new file mode 100644 index 0000000..6762b7b --- /dev/null +++ b/Hexdiff/README.md @@ -0,0 +1,19 @@ +# Hexdiff + +Un truc en ncurses pour voir les différences entre deux fichiers binaires. + +``` + look at: + - the Makefile + - the man page + - the source code + + old website: + http://tboudet.free.fr/hexdiff/ + + installation: + 1) run make + 2) patch + 3) goto 1 + +``` \ No newline at end of file diff --git a/Hexdiff/TODO b/Hexdiff/TODO new file mode 100644 index 0000000..0948a1c --- /dev/null +++ b/Hexdiff/TODO @@ -0,0 +1,14 @@ + + add a '/' keystroke for searching a byte sequence in + the current file. + + drink a beer ? or, better, eat a Guinness ? + + write a better english. write a better doc. write a + better manpage. write a better code. + + make a Slackware package. Mmmeee. + + move the config file from $HOME/.hexdiffrc to + $HOME/.tth/hexdiff.rc + diff --git a/Hexdiff/asciiview.c b/Hexdiff/asciiview.c new file mode 100644 index 0000000..0042267 --- /dev/null +++ b/Hexdiff/asciiview.c @@ -0,0 +1,202 @@ +/* + +----------------+ + | Ascii View | + +----------------+ +*/ +#include +#include + +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +static void av_sauve_contexte(void) +{ /* code to be defined ? */ } +/*----------------------------------------------------------------*/ +static void av_restaure_contexte(void) +{ /* code to be defined ? */ } +/*----------------------------------------------------------------*/ +static char * ascii_name(int code) +{ +static char static_buffer[20]; + +/* XXX this big switch must be audited.... */ + +switch (code) + { + case 0: return "NUL"; + case 1: return "SOH ^a"; + case 2: return "STX ^b"; + case 3: return "ETX ^c"; + case 4: return "EOT ^d"; + case 5: return "ENQ ^e"; + case 6: return "ACQ ^f"; + case 7: return "BEL ^g"; + case 8: return "BS ^h"; + case 9: return "HT ^i"; + case 10: return "LF ^j"; + case 11: return "VT ^k"; + case 12: return "FF ^l"; + case 13: return "CR ^m"; + case 14: return "SO ^n"; + case 15: return "SI ^o"; + case 16: return "DLE ^p"; + case 17: return "DC1 ^q"; + case 18: return "DC2 ^r"; + case 19: return "DC3 ^s"; + case 20: return "DC4 ^t"; + case 21: return "NAK ^u"; + case 22: return "SYN ^v"; + case 23: return "ETB ^w"; + case 24: return "CAN ^x"; + case 25: return "EM ^y"; + case 26: return "SUB ^z"; + case 27: return "ESC"; + case 28: return "FS "; + case 29: return "GS "; + case 30: return "RS "; + case 31: return "US "; + case 32: return "SPACE"; + case 127: return "DEL"; + } + +if (code < 128) + { + sprintf(static_buffer, "'%c'", code); + return static_buffer; + } + +/* may be for code > 127, we can put the "html" code &blabla; ? */ + +return ""; +} +/*----------------------------------------------------------------*/ +#define ASCV_I2LIG(idx) ((idx)>>6) +#define ASCV_I2COL(idx) ((idx)&63) + +static int av_affiche(Fichier *fic, WINDOW *pop, int clig, int ccol) +{ +int foo, lig, col, car; +char chaine[100]; +long depl; +unsigned char octet; + +wstandout(pop); +for (foo=1; foo<65; foo++) + mvwaddch(pop, 1, foo, ' '); +mvwaddstr(pop, 1, 2, fic->nom); + +depl = (clig*64)+ccol; +octet = fic->buffer[depl]; +sprintf(chaine, "%7ld : %3d 0x%02x 0%03o", + fic->offset+depl, octet, octet, octet); +mvwaddstr(pop, 18, 1, chaine); +mvwaddstr(pop, 18, 33, " "); +mvwaddstr(pop, 18, 33, ascii_name(fic->buffer[depl])); +wstandend(pop); + +for (foo=0; foo<16*64; foo++) + { + lig = ASCV_I2LIG(foo); + col = ASCV_I2COL(foo); + car = fic->buffer[foo]; + car = is_printable(car) ? car : ' '; + if (clig==lig && ccol==col) + wstandout(pop); + mvwaddch(pop, lig+2, col+1, car); + if (clig==lig && ccol==col) + wstandend(pop); + } + +/* put the cursor at the current location */ +/* this was a really bad idea for Xterm users, because + * current pos char was written in "standout", and the + * text cursor of xterm re-reverse it. + * XXX wmove(pop, clig+2, ccol+1); + */ +wmove(pop,1,64); + +wrefresh(pop); +return 0; +} +/*----------------------------------------------------------------*/ +/* new: 2004 Nov. + * still in developement. + */ +int asciiview(void) +{ +WINDOW * popup; +int foo, key, flag_exit; +int clig, ccol; /* position du curseur */ +Fichier * fic; + +av_sauve_contexte(); + +popup = newwin(21, 66, 3, 5); +bordure(popup); + +wstandout(popup); +for (foo=1; foo<65; foo++) + mvwaddch(popup, 19, foo, ' '); +mvwaddstr(popup, 19, 1, " 'Q' quit, see other file"); +for (foo=1; foo<65; foo++) + mvwaddch(popup, 18, foo, ' '); +wstandend(popup); +wrefresh(popup); + +flag_exit = 0; +clig = ccol = 0; +do + { + if (fenetre_active==0) fic = &f1; + else fic = &f2; + + av_affiche(fic, popup, clig, ccol); + key = getch(); + + switch (key) + { + case 'q': case 'Q': + flag_exit = 1; + break; + case '\t': + fenetre_active ^= 1; + break; + case KEY_UP: + if (clig>0) clig--; break; + case KEY_DOWN: + if (clig<15) clig++; break; + case KEY_LEFT: + if (ccol>0) ccol--; + else if (clig>0) + { + /* go to the previous line */ + ccol=63; clig--; + } + break; + case KEY_RIGHT: + if (ccol<63) ccol++; + else if (clig<15) + { + /* go to the next line */ + ccol=0; clig++; + } + break; + case KEY_HOME: + ccol = clig = 0; break; + case KEY_END: + ccol = 63; clig = 15; break; + default: + flash(); + break; + } + + } while ( ! flag_exit ); + +delwin(popup); + +av_restaure_contexte(); +return 42; +} +/*----------------------------------------------------------------*/ +/*----------------------------------------------------------------*/ + diff --git a/Hexdiff/fileinfo.c b/Hexdiff/fileinfo.c new file mode 100644 index 0000000..6cbc9e4 --- /dev/null +++ b/Hexdiff/fileinfo.c @@ -0,0 +1,138 @@ +/* + fileinfo.c + ---------- + + More infos --> http://tboudet.free.fr/hexdiff/ + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +/* private vars of this module */ + +/*----------------------------------------------------------------*/ +/* + * this func need more "configurability" + */ +static void prtime(time_t t, char *pstr) +{ +struct tm *ptm; +int foo; +ptm = gmtime(&t); +foo = strftime(pstr, 99, "%Y-%m-%d %H:%M:%S", ptm); +} +/*----------------------------------------------------------------*/ +#define W_FILEINFO 48 +WINDOW * do_fileinfo(int fd, int ligne) +{ +WINDOW * popup; +int foo, lig, hpopup; +struct stat stat_buf; +char buffer[100]; +struct passwd *pass; +struct group *grp; + +if (config.ext_fileinfo) hpopup = 13; +else hpopup = 12; + +popup = newwin(hpopup, W_FILEINFO, ligne, 15); +if ( popup==NULL ) return NULL; +bordure(popup); + +#if TRACE +sprintf(buffer, " fileinfos fd %d ", fd); +mvwaddstr(popup, 0, 10, buffer); +#endif + +foo = fstat(fd, &stat_buf); +if (foo==0) + { + lig = 2; + sprintf(buffer, "dev: %ld", (long)(stat_buf.st_dev)); + mvwaddstr(popup, lig, 2, buffer); + sprintf(buffer, "inode: %ld", stat_buf.st_ino); + mvwaddstr(popup, lig, 22, buffer); + lig += 2; + + sprintf(buffer, "uid: %d", stat_buf.st_uid); + mvwaddstr(popup, lig, 2, buffer); + sprintf(buffer, "gid: %d", stat_buf.st_gid); + mvwaddstr(popup, lig, 22, buffer); + if (config.ext_fileinfo) + { + lig++; + + pass = getpwuid(stat_buf.st_uid); + if (pass==NULL) strcpy(buffer, "unknow user"); + else sprintf(buffer, "user: %s", pass->pw_name); + mvwaddstr(popup, lig, 2, buffer); + + grp = getgrgid(stat_buf.st_gid); + if (grp==NULL) strcpy(buffer, "unknow group"); + else sprintf(buffer, "group: %s", grp->gr_name); + mvwaddstr(popup, lig, 22, buffer); + } + lig+=2; + + /* Nov 2004: may be, here, we need a 'ls-like' display , + with "-rwxr-x---" look'n'feel ? */ + sprintf(buffer, "rwx: %05o", stat_buf.st_mode & 01777); + mvwaddstr(popup, lig, 2, buffer); + sprintf(buffer, "size: %ld", stat_buf.st_size); + mvwaddstr(popup, lig, 22, buffer); + lig+=2; + + /* we don't display the atime, because, after all, + hexdiff _is_ reading the file :) */ + prtime(stat_buf.st_mtime, buffer); + mvwaddstr(popup, lig, 4, "mtime:"); + mvwaddstr(popup, lig, 14, buffer); + lig++; + + prtime(stat_buf.st_ctime, buffer); + mvwaddstr(popup, lig, 4, "ctime:"); + mvwaddstr(popup, lig, 14, buffer); + } +else + { + sprintf(buffer, "fstat error = %d", foo); + mvwaddstr(popup, 6, 2, buffer); + } + +wrefresh(popup); +return popup; +} +/*----------------------------------------------------------------*/ +int fileinfo(int fd, int ligne) +{ +WINDOW * pop; + +pop = do_fileinfo(fd, ligne); +getch(); +delwin(pop); +return 0; +} +/*----------------------------------------------------------------*/ +int double_fileinfo(int fd1, int ligne1, int fd2, int ligne2) +{ +WINDOW * pop1, * pop2; + +pop1 = do_fileinfo(fd1, ligne1); +pop2 = do_fileinfo(fd2, ligne2); +getch(); +delwin(pop1); +delwin(pop2); +return 0; +} +/*----------------------------------------------------------------*/ diff --git a/Hexdiff/fonctions.c b/Hexdiff/fonctions.c new file mode 100644 index 0000000..17bc013 --- /dev/null +++ b/Hexdiff/fonctions.c @@ -0,0 +1,331 @@ +/* + fonctions.c + ----------- + + Old site --> http://tboudet.free.fr/hexdiff/ + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +int is_printable(int octet) +{ +if (config.show_8bits) + return isprint(octet & 0x7f); + +return isprint(octet); +} +/*----------------------------------------------------------------*/ +int ouvre_fichier(char *nom) +{ +int fd, foo; +struct stat statbuf; +Fichier *fichier; +long offset; + +if ( (fd=open(nom, O_RDONLY)) < 0) + { + return 0; + } + +if (fenetre_active==0) + { + fichier = &f1; offset = f2.offset; + } +else + { + fichier = &f2; offset = f1.offset; + } + +/* + * close the old file + */ +close(fichier->fd); + +/* + * store information on newly open file + */ +strncpy(fichier->nom, nom, T_NOM); +foo = fstat(fd, &statbuf); +fichier->fd = fd; +fichier->taille = statbuf.st_size; +fichier->offset = offset; +fichier->lus = 0; + +return 1; +} +/*----------------------------------------------------------------*/ +void barre_inverse(char c, int ligne) +{ +int foo; +standout(); +for (foo=0; foo<80; foo++) + mvaddch(ligne, foo, c); +standend(); +/* refresh(); */ +} +/*----------------------------------------------------------------*/ +/* new 28 juillet 2007 */ +static int calcul_pourcent(Fichier *f) +{ +float foo; +if (f->taille < 16) return 0; +foo = ((float)f->offset * 100.0) / (float)f->taille; +return (int)foo; +} +/*----------------------------------------------------------------*/ +int +ecrire_barres_fichiers(void) +{ +char buffer[150]; +int pourcent; + +barre_inverse(' ', BARRE_1); +barre_inverse(' ', BARRE_2); + +standout(); + +mvaddstr(BARRE_1, 0, fenetre_active ? " " : "**"); +mvaddstr(BARRE_1, 3, f1.nom); +pourcent = calcul_pourcent(&f1); +sprintf(buffer, "%8ld %8ld %3d%%", f1.taille, f1.offset, pourcent); +/*sprintf(buffer, "%8ld %8ld %8ld", f1.taille, f1.offset, f1.lus);*/ +mvaddstr(BARRE_1, 52, buffer); + +mvaddstr(BARRE_2, 0, fenetre_active ? "**" : " "); +mvaddstr(BARRE_2, 3, f2.nom); +pourcent = calcul_pourcent(&f2); +sprintf(buffer, "%8ld %8ld %3d%%", f2.taille, f2.offset, pourcent); +mvaddstr(BARRE_2, 52, buffer); + +if (config.show_8bits) mvaddstr(0, 72, " 8bits "); +else mvaddstr(0, 72, " 7bits "); +if (config.offsets_in_hex) mvaddstr(0, 66, " hex "); +else mvaddstr(0, 66, " dec "); +standend(); + +return 0; +} +/*----------------------------------------------------------------*/ +int +fond_ecran(void) +{ +#if TRACE +int foo; +char buffer[200]; +#endif + +barre_inverse(' ', 0); +standout(); +mvaddstr(0, 2, " Visuel HexDiff v " VERSION " by tTh 2007 "); +#if TRACE +sprintf(buffer, " screen size %dx%d ", COLS, LINES); +foo = strlen(buffer); +mvaddstr(0, COLS-2-foo, buffer); +#endif +standend(); +refresh(); + +#if TRACE +fprintf(stderr, "HAUT %3d\n", HAUT); +fprintf(stderr, "HAUT_1 %3d BARRE_1 %3d\n", HAUT_1, BARRE_1); +fprintf(stderr, "HAUT_2 %3d BARRE_2 %3d\n", HAUT_2, BARRE_2); +#endif + +return 0; +} +/*----------------------------------------------------------------*/ +void bordure(WINDOW * w) +{ +if (config.nice_border) + box(w, 0, 0); +else + wborder(w, '|', '|', '-', '-', '+', '+', '+', '+'); +} +/*----------------------------------------------------------------*/ +typedef struct + { + int ligne; + char * texte; + } ligne_aide; + +ligne_aide lignes[] = + { + { 2, "x q : quit now, 'tfatf'" }, + { 4, "u j (U) : go up one (4) lines" }, + { 5, "d k (D) : go down one (4) lines" }, + { 6, " : go down one full page" }, + { 7, "0 : back to begin of files" }, + { 8, "$ : goto end of shortest file" }, + { 9, " : toggle the active window" }, + { 10, "g : input a new file offset" }, +/* { 11, "= : synchronize the two offsets" }, */ + { 12, "H : 'toogle' hex/dec offset display" }, + { 13, "7 8 : display control of bit 7" }, + { 14, "i (I) : info about file(s)" }, + { 15, "n : jump to the next difference" }, + { 16, "^O : open new file in current win" }, + { 17, "A : Ascii View (new feature :)" } + }; + +#define NB_LIG (sizeof(lignes)/sizeof(ligne_aide)) + +#define L_POPUP 2 +#define C_POPUP 11 + +void popup_aide(void) +{ +WINDOW * popup; +int foo, bar, ligmax, largmax; + +ligmax = largmax = 0; +for (foo=0; foo ligmax) ligmax = bar; + if ((bar=strlen(lignes[foo].texte)) > largmax) largmax = bar; + } + +ligmax += 3; +largmax += 7; +popup = newwin(ligmax, largmax, L_POPUP, C_POPUP); +bordure(popup); + +for (foo=0; foo +Descend de plusieurs lignes dans les deux fichiers. Ce nombre étant calculé +selon la taille de l'écran, je ne peux le révéler ici. +.br +.B 0 +Reprend au début des deux fichiers. +.br +.B $ +Vous emmène aux environs de juste avant la fin du plus petit des deux fichiers. +.br +.B g +Propose de saisir un nouvel offset pour les deux fichiers. Attention, cette +fonctions a été écrite à la 'Gruik' et n'est donc pas fiable. +.br +.B H +Bascule l'affichage des offsets entre le décimal et l'hexadécimal. Le mode +initial est configurable. +.br +.B i +Affichage des informations 'fstat' sur le fichier sélectionné. +.br +.B I +Affiche les mêmes informations, mais pour les deux fichiers simultanément. +.br +.B A +Open the (currently) experimental AsciiViewer. +Maybe coredump with no request. switch as usual. +.br +.B ^O +Ouverture d'un nouveau fichier dans la fenêtre courante. Le "selecteur de +fichier" est encore rudimentaire. Utiliser 'Q' pour annuler, pour +valider, et '?' pour l'aide. +.br +.B n +Part à la recherche de la prochaine différence entre les deux fichiers. +.br +.B +Change la fenètre active. Pour le moment, ça ne sert presque à rien. +Ah, non, il parait que ça joue sur le contexte d'autres fonctions. +Personne ne m'en a parlé, je ne suis au courant de rien, alors +je --->[] +.br +.B ? +"Popupe" une fenètre d'aide reprenant les principales commandes. Pour +les autres commandes: un seul slogan, Utsl. + +.SH CONFIG FILE +Le fichier de configuration est +.B .hexdiffrc +et doit se trouver dans le +.B $HOME +de l'utilisateur. +Une ligne commençant par un +.B '#' +est un commentaire. Les lignes vides sont ignorées. Pour plus de détails, +consulter le fichier 'hexdiff.rc' qui devrait se trouver dans l'archive. + +.SH SEE ALSO +.BR diff (1), +.BR cmp (1) + +.SH BUGS +Si vous redimensionnez votre xterm, \fBhexdiff\fP se prend un SIGWINCH, +et s'en va probablement visiter le pays des Slashies. Dans la pratique, +il en revient très vite. +.br +L'affichage en fin de fichier, si les tailles sont différentes, est +parfois un peu déglingué. Mais je vais réparer ça. +.br +Cette page de man n'est pas synchrone avec la réalité virtuelle du code. +Car le code évolue plus vite que la réalité. Parfois. + +.SH AUTHOR +Thierry Boudet aka +.B tTh +qui 'spleytise' avec vigueur ce petit programme depuis Mars 2002. +Pour en savoir un peu plus sur ce logiciel: +http://tboudet.free.fr/hexdiff/ et sur moi: http://tontonth.free.fr/plop/ + +.SH DEDICACE +Ce logiciel est dédié aux kamarades trolleurs de l'équipe HardStory du +CULTe, sans qui rien n'est pas faisable. + diff --git a/Hexdiff/hexdiff.c b/Hexdiff/hexdiff.c new file mode 100644 index 0000000..6cdbae8 --- /dev/null +++ b/Hexdiff/hexdiff.c @@ -0,0 +1,394 @@ +/* + Visuel Hexdiff + -------------- + + More infos --> http://tboudet.free.fr/hexdiff/ + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAIN + +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +static void finish(int signal) +{ +endwin(); exit(0); +} +/*----------------------------------------------------------------*/ +int +affiche_les_dumps(void) +{ +int foo, bar, idx, flag; +char buff[50]; +char *format_offset; + +memset(f1.buffer, 0, T_BUFF); +memset(f2.buffer, 0, T_BUFF); + +/* + * lire les deux fichiers... + */ +lseek(f1.fd, f1.offset, SEEK_SET); +f1.lus = read(f1.fd, f1.buffer, T_BUFF); +lseek(f2.fd, f2.offset, SEEK_SET); +f2.lus = read(f2.fd, f2.buffer, T_BUFF); + +ecrire_barres_fichiers(); + +/* + * afficher les offsets + */ +format_offset = config.offsets_in_hex ? "%08lx" : "%8ld"; + +for (foo=0; foo15) f1.offset -= 16; + if (f2.offset>15) f2.offset -= 16; + break; + + case 'U': + f1.offset -= 64; + if (f1.offset<0) f1.offset=0; + f2.offset -= 64; + if (f2.offset<0) f2.offset=0; + break; + + + case 'd': case 'k': + case KEY_DOWN: + if (pas_a_la_fin) + { + f1.offset += 16; + f2.offset += 16; + } + break; + + case 'D': + if (pas_a_la_fin) + { + f1.offset += 64; + f2.offset += 64; + } + break; + + case 'H': + config.offsets_in_hex ^= 1; + break; + + case ' ': + case KEY_NPAGE: + if (pas_a_la_fin) + { + f1.offset += (HAUT-1)*16; + f2.offset += (HAUT-1)*16; + } + break; + + case KEY_PPAGE: + lfoo = f1.offset - (HAUT-1)*16; + if (lfoo<0) lfoo = 0; + f1.offset = f2.offset = lfoo; + break; + + case '0': + case KEY_HOME: + f1.offset = f2.offset = 0; + break; + + case '7': + config.show_8bits = 0; + break; + + case '8': + config.show_8bits = 1; + break; + + case '$': + /* jump to the end of the smallest file */ + lfoo = (f1.taille + +/* "#define VERSION" is now in the Makefile */ + +#define T_BUFF 4242 +#define T_NOM 360 + +typedef struct + { + int fd; + long taille; + long offset; + long lus; + char nom[T_NOM+1]; /* buffer overflow ? */ + unsigned char buffer[T_BUFF]; + } Fichier; + +typedef struct + { + int nice_border; + int show_8bits; + char *language; + int offsets_in_hex; + int ext_fileinfo; + int show_hidden; + int sf_flag; + int explique; /* not used */ + int zoom; + int asciiview; /* not used */ + } configuration; + +/* + * declaration of globals vars + */ + +#ifdef MAIN + #define EXTERN +#else + #define EXTERN extern +#endif + +EXTERN Fichier f1, f2; +EXTERN int fenetre_active; +EXTERN configuration config; + +/* + * macros de positionnement en hauteur + */ +#define HAUT ((LINES-3)/2) +#define HAUT_1 1 +#define BARRE_1 (HAUT_1+HAUT) +#define HAUT_2 (HAUT_1+(HAUT)+1) +#define BARRE_2 (HAUT_2+HAUT) + +/* + * prototype des fonctions + */ +void barre_inverse(char c, int ligne); +int ecrire_barres_fichiers(void); +int fond_ecran(void); +void about(void); +void aide_cl(int flag); +void bordure(WINDOW * w); +void popup_aide(void); +long saisir_un_long(char *txt); +void version(void); +int is_printable(int octet); +int ouvre_fichier(char *nom); + +/* + * file parse_rc.c + */ +#define HEXDIFF_RC ".hexdiffrc" +int init_configuration(void); +int lire_configuration(int flag); + +/* + * file fileinfo.c + */ +int fileinfo(int fd, int ligne); +int double_fileinfo(int, int, int, int); + +/* + * file sel_file.c + */ +int select_new_file(char *, int, int); +int select_set_opt(int flg); + +/* + * file asciiview.c + */ +int asciiview(void); +int octalview(void); /* not urgent */ + diff --git a/Hexdiff/hexdiff.rc b/Hexdiff/hexdiff.rc new file mode 100644 index 0000000..00a49e4 --- /dev/null +++ b/Hexdiff/hexdiff.rc @@ -0,0 +1,31 @@ +# +# fichier de configuration pour Hexdiff +# http://tboudet.free.fr/hexdiff/ +# + +# enable (1) or disable (0) display of chars +# with a code > 127. charset dependant. +# you can toogle this flag with the 7 and 8 keys +show_8bits 1 + +# enable or disable usage of semi-graphic chars +# around the various popup windows. +nice_border 0 + +# select decimal or hexa display of file offset. +# the key 'H' switch interactively beetwen the two modes. +offsets_in_hex 0 +# sorry, at this time, no octal offset display... + +# if set to 1, display the id of user and group +# in the fileinfo popup (access by 'i' or 'I' key +ext_fileinfo 1 + +# those flags is not yet used... +language fr +asciiview 0 + +# is the file selector display hidden file ? +show_hidden 0 + + diff --git a/Hexdiff/memcheck.sh b/Hexdiff/memcheck.sh new file mode 100644 index 0000000..beab024 --- /dev/null +++ b/Hexdiff/memcheck.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# +# seek for memory leaks +# --------------------- +# you need a recent version of http://www.valgrind.org/ +# +make hexdiff + +rm valgr-plop* + +valgrind --tool=memcheck --log-file=valgr-plop \ + --leak-check=yes --show-reachable=yes \ + ./hexdiff hexdiff.o fonctions.o + diff --git a/Hexdiff/parse_rc.c b/Hexdiff/parse_rc.c new file mode 100644 index 0000000..08305e8 --- /dev/null +++ b/Hexdiff/parse_rc.c @@ -0,0 +1,259 @@ +/* + + HEXDIFF - lecture du fichier de configuration + --------------------------------------------- + + Attention, programmation a la "Gruiik" !-) + Il y a plein de GOTO dans cette fonction, mais je + les daguisent habilement en fortranisme. + -- tTh -- + +*/ + +#include +#include +#include /* pour strtok */ + /* certaines mauvaises langues pratendent + * que 'strtok' est obsolete, insecure et + * pas elegant. moi, je veux bien, mais + * alors,il faut me montrer par quoi le + * remplacer... + */ +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +/* + * positionner a des valeurs connues toutes les options de + * configuration. + * + * 18juin2002: euh, on ne pourrait pas faire ce truc a la + * declaration de la variable ? + */ +int +init_configuration(void) +{ +config.nice_border = 0; +config.show_8bits = 0; +config.language = "fr"; +config.offsets_in_hex = 0; +config.ext_fileinfo = 0; +config.show_hidden = 1; +config.sf_flag = 0; +config.explique = 0; +config.zoom = 0; +config.asciiview = 0; + +return 51; /* have a Pastis ? */ +} +/*----------------------------------------------------------------*/ + +#define DO_NICE_BORDER 1 +#define DO_LANGUAGE 2 +#define DO_SHOW_8BITS 3 +#define DO_OFFSET_HEX 4 +#define DO_EXT_FILEINFO 5 +#define DO_SHOW_HIDDEN 20 +#define DO_FS_FLAG 21 +#define DO_EXPLIQUE 24 +#define DO_START_ZOOM 25 +#define DO_ASCIIVIEW 26 + +#define FLAG 1 +#define TEXTE 2 +#define NOMBRE 3 +#define KEY_ALIAS 4 + +struct conf_var + { + char *nom; + int code; + int type; + }; + +struct conf_var conf_vars[] = + { + { "nice_border", DO_NICE_BORDER, FLAG }, + { "language", DO_LANGUAGE, TEXTE }, + { "show_8bits", DO_SHOW_8BITS, FLAG }, + { "offsets_in_hex", DO_OFFSET_HEX, FLAG }, + { "ext_fileinfo", DO_EXT_FILEINFO, FLAG }, + { "show_hidden", DO_SHOW_HIDDEN, FLAG }, + { "fs_flag", DO_FS_FLAG, NOMBRE }, + { "explique", DO_EXPLIQUE, FLAG }, + { "start_zoom", DO_START_ZOOM, FLAG }, + { "asciiview", DO_ASCIIVIEW, NOMBRE } + } ; + +#define NB_TOKEN ( sizeof(conf_vars) / sizeof(struct conf_var) ) + +/*----------------------------------------------------------------*/ +static int lookup_token(char *token) +{ +int foo; + +for (foo=0; foo LIGNE_RC) + { + fprintf(stderr, ".hexdiffrc buff overflow %d, bad $HOME ?\n", + foo); + exit(1); + } + strcpy(ligne, home); strcat(ligne, "/"); + strcat(ligne, HEXDIFF_RC); + } +else + /* + * oui, bon, c'est pas trop coherent, mais je ne + * savais pas trop quoi faire en cas de 'homeless', + * alors je me suis permis de supposer un contexte + * msdos/djgpp ... + */ + { + strcpy(ligne, "c:\\hexdiff.rc"); + } + +#if TRACE +if (flag) /* we are in .rc debug context */ + { + strcpy(ligne, "hexdiff.rc"); + } +#endif + +if ( (fp = fopen(ligne, "r")) == NULL ) + { + perror("hexdiff config file"); + return -1; + } + +line_number = 1; + +while ( fgets(ligne, LIGNE_RC, fp) != NULL ) + { + /* + * virer le caractere de fin de ligne (Gruiikage) + */ + foo=strlen(ligne); + if (foo>0) + ligne[foo-1] = '\0'; +#if TRACE + fprintf(stderr, "%4d %4d : %s\n", + line_number, foo, ligne); +#endif + line_number++; + + /* + * decomposition de la ligne en machins + */ + machin = strtok(ligne, delim); + + if (machin == NULL) /* ya pas de token */ + { + continue; + } + + if ( machin[0] == '#' ) /* c'est un commentaire */ + { + continue; + } + + numtok = lookup_token(machin); + + if (flag) + fprintf(stderr, "TOKEN = [%s] code=%d\n", machin, numtok); + + if ( numtok < 0 ) { continue; } + + valeur = strtok(NULL, delim); /* is strtok() usable in 2007 ? */ + + if ( valeur != NULL ) + { + if (flag) + fprintf(stderr, "VALUE = [%s]\n", valeur); + + switch(conf_vars[numtok].code) + { + case DO_NICE_BORDER: + config.nice_border = atoi(valeur); + break; + + case DO_SHOW_8BITS: + config.show_8bits = atoi(valeur); + break; + + case DO_LANGUAGE: +#if TRACE + fprintf(stderr, "lang=%s\n", valeur); +#endif + break; + + case DO_OFFSET_HEX: + config.offsets_in_hex = atoi(valeur); + break; + + case DO_EXT_FILEINFO: + config.ext_fileinfo = atoi(valeur); + break; + + case DO_SHOW_HIDDEN: + config.show_hidden = atoi(valeur); + break; + + case DO_FS_FLAG: + break; + + case DO_EXPLIQUE: + break; + + } + } + else /* valeur == NULL */ + { +#if TRACE + fprintf(stderr, "null value ?\n"); +#endif + continue; + } + + } +fclose(fp); + +return 42; /* thx for all the fishes, Douglas */ +} +/*----------------------------------------------------------------*/ + diff --git a/Hexdiff/sel_file.c b/Hexdiff/sel_file.c new file mode 100644 index 0000000..3d3016f --- /dev/null +++ b/Hexdiff/sel_file.c @@ -0,0 +1,352 @@ +/* + sel_file.c + ---------- + + old site --> http://tboudet.free.fr/hexdiff/ + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +/* nasty hack */ +char *strdup(char *); +/* end of hack */ +#include +#include + +#include "hexdiff.h" + +/*----------------------------------------------------------------*/ +/* private vars of this module */ + +typedef struct { + long taille; + char *nom; + int idx; + } FICH; + +static FICH *liste; +static int taille; /* taille de la liste */ +static int nombre; /* nbre d'entrees dans la liste */ + +#define TCHONK 42 + +/*----------------------------------------------------------------*/ +static int teste_dirent(const struct dirent *de, struct stat *pstat) +{ +int foo; + +foo = stat(de->d_name, pstat); + +if (S_ISDIR(pstat->st_mode)) + return 0; + +if (config.show_hidden==0 && de->d_name[0]=='.') + return 0; + +return 1; +} +/*----------------------------------------------------------------*/ +static int compare_nom_asc(const void *pa, const void *pb) +{ +return strcmp( ((FICH *)pa)->nom, ((FICH *)pb)->nom); +} +static int compare_nom_desc(const void *pa, const void *pb) +{ +return strcmp( ((FICH *)pb)->nom, ((FICH *)pa)->nom); +} +static int compare_taille_asc(const void *pa, const void *pb) +{ +return ((FICH *)pa)->taille - ((FICH *)pb)->taille; +} +static int compare_taille_desc(const void *pa, const void *pb) +{ +return ((FICH *)pb)->taille - ((FICH *)pa)->taille; +} +static int compare_idx(const void *pa, const void *pb) +{ +return ((FICH *)pa)->idx - ((FICH *)pb)->idx; +} +#define PAR_NOM_ASC 1 +#define PAR_NOM_DESC 2 +#define PAR_TAILLE_ASC 3 +#define PAR_TAILLE_DESC 4 +#define PAR_IDX 5 +#define PAR_PLOP 6 +static int trier_la_liste(int comment) +{ +switch (comment) + { + case PAR_NOM_ASC: + qsort(liste, nombre, sizeof(FICH), compare_nom_asc); + break; + case PAR_NOM_DESC: + qsort(liste, nombre, sizeof(FICH), compare_nom_desc); + break; + case PAR_TAILLE_ASC: + qsort(liste, nombre, sizeof(FICH), compare_taille_asc); + break; + case PAR_TAILLE_DESC: + qsort(liste, nombre, sizeof(FICH), compare_taille_desc); + break; + case PAR_IDX: + qsort(liste, nombre, sizeof(FICH), compare_idx); + break; + } +return 0; +} +/*----------------------------------------------------------------*/ +static int liste_fichiers(WINDOW *win, int flag) +{ +DIR *dir; +struct dirent *de; +struct stat statbuf; +int foo; + +/* + * initializing local vars, for list-of-files + */ +if ( NULL == (liste = malloc(TCHONK*sizeof(FICH))) ) + { + wprintw(win, "no mem for file list"); + wrefresh(win); + return 1; + } +taille = TCHONK; + +dir = opendir("."); +if (dir == NULL) + { + wprintw(win, "error on 'opendir'"); + wrefresh(win); + return 1; + } + +nombre = 0; +while ( (de=readdir(dir)) != NULL) + { + if ( ! teste_dirent(de, &statbuf) ) + { + continue; + } + /* strdup is a 'non-portable' function ? */ + liste[nombre].nom = strdup(de->d_name); + liste[nombre].taille = statbuf.st_size; + liste[nombre].idx = nombre; + nombre++; + wrefresh(win); + + /* + * if needed, increase the size of the list + */ + if (nombre >= taille) + { + liste = realloc(liste, sizeof(FICH)*(taille+TCHONK)); + taille += TCHONK; + } + } + +foo = closedir(dir); + +return nombre; +} +/*----------------------------------------------------------------*/ +char *txt_aide_fs[] = + { + "\n WARNING !\n\n", + " this file selector is a 'quick and dirty' hack\n", + " and code was written with a 'Spleyt' spirit :)\n\n", + "\n", + " smart keys are:\n\n", + " a -> sort by name ascending\n", + " A -> sort by name reversing\n", + " s -> sort by size\n", + " S -> sort reverse by size\n", + " n -> no sort\n", + "", + "sort by date is a work in progress..." + }; +int help_on_file_selector(WINDOW *win, int flag) +{ +int foo; + +werase(win); +for (foo=0; foo<(sizeof(txt_aide_fs)/sizeof(char *)); foo++) + { + wprintw(win, txt_aide_fs[foo]); + wrefresh(win); + } +foo = getch(); +return 0; +} +/*----------------------------------------------------------------*/ +/* + * new, 2005 June: now, we get the max usable length for *nomfich. + */ +int select_new_file(char *nomfich, int t_nom, int flags) +{ +int ligmax, largmax, affh, idx = -1; +WINDOW *fen_1, *fen_2; +int foo, first, curseur, flag_exit, key; +char chaine[T_NOM]; + +/* + * quick'n'dirty security check, need more work. + */ +if (t_nom > T_NOM) + { + fprintf(stderr, "\n%s:%d possible buffer overflow\n", __FILE__, __LINE__); + exit(1); + } + +ligmax = LINES-8; /* taille verticale de la popup */ +largmax = 62; + +fen_1 = newwin(ligmax, largmax, 2, 12); +bordure(fen_1); wrefresh(fen_1); + +/* + * first line of popup display active win number + * and current win directory. as this time, we can't + * select another directory ;-( + */ +wstandout(fen_1); +for (foo=1; foo", fenetre_active); +mvwaddstr(fen_1, 1, 2, chaine); +*/ + +if (getcwd(chaine,99)!=NULL) + mvwaddstr(fen_1, 1, 3, chaine); +else + mvwaddstr(fen_1, 1, 9, " can't get cwd, sorry... "); + +mvwaddstr(fen_1, ligmax-2, 4, "'Q' to abort, to select, '?' for help"); +wstandend(fen_1); +wrefresh(fen_1); + +/* + * create a subwindow for the scrolling selector + */ +fen_2 = derwin(fen_1, ligmax-4, largmax-2, 2, 1); +scrollok(fen_2, 1); + +affh = ligmax-4; /* XXX need a valid value :) */ + +foo = liste_fichiers(fen_2, 0); +#if TRACE +wprintw(fen_2, "ret liste fichiers = %d\n", foo); +wrefresh(fen_2); +getch(); +#endif + +trier_la_liste(PAR_NOM_ASC); + +/* + * now, the file list is built, so display the selector. + */ +first = curseur = 0; +flag_exit = 0; + +do + { + werase(fen_2); + for (foo=0; foo= nombre) + break; + + if (curseur==foo) wstandout(fen_2); + mvwprintw(fen_2, foo, 1, " %-46s %9ld ", + liste[idx].nom, liste[idx].taille); + if (curseur==foo) wstandend(fen_2); + } + wrefresh(fen_2); + +#if TRACE + mvwprintw(fen_1, 1, 2, "curs %3d first %3d ", curseur, first); + wrefresh(fen_1); +#endif + + /* + * user interaction + */ + key = getch(); + switch (key) + { + case KEY_UP: + if (curseur) curseur--; + else if (first>0) first--; + break; + + case KEY_DOWN: + if ((curseur+first) >= (nombre-1)) break; + + if (curseur < affh-1) curseur++; + else if (first<(nombre-affh)) first++; + break; + + /* SORT operations */ + case 'a': + trier_la_liste(PAR_NOM_ASC); break; + case 'A': + trier_la_liste(PAR_NOM_DESC); break; + case 's': + trier_la_liste(PAR_TAILLE_ASC); break; + case 'S': + trier_la_liste(PAR_TAILLE_DESC); break; + + case '?': + help_on_file_selector(fen_2, 0); + break; + + case '\r': + idx = curseur+first; + flag_exit = 1; + break; + + case 'Q': flag_exit = -1; break; + } + } while ( ! flag_exit ); + +delwin(fen_1); + +if (flag_exit == 1) + { + strcpy(nomfich, liste[idx].nom); + } + +/* + * free the memory used by our list + */ +for (foo=0; foo