/*****************************************************//**
* @brief Prmitive hexadecimal file viewer (pipe it to 'less' or 'more'
* to make it much less primitive... see Usage below).
* @file hexview.c
* @version 0.1A
* @date 21 Feb, 2012
* @author migf1 <mig_f1@hotmail.com>
* @par Language:
* C (ANSI C89)
* @par Usage:
* hexview [-raw] [filename]
* \n
* Use -raw as the 1st command-line argument to force raw output
* (useful for piping, e.g: hexview -raw file | less)
*
* @remark Feel free to experiment with the values of the pre-processor
* constants: FMT_NCOLS, FMT_PGBREAK and FMT_POS. They affect the
* appearance of the output.
*********************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXINPUT (1024+1)
#define FMT_FPOS 8 /* width in # of chars for the file-pos field */
#define FMT_NCOLS 16 /* # of columns in Bytes area(no more than 16)*/
#define FMT_PGBREAK 20 /* # of lines before page-break appears */
#define pressENTER() \
do{ \
char mYcHAr; \
printf( "press ENTER..." ); \
while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \
; \
}while(0)
typedef unsigned char Byte;
/*********************************************************//**
* Read a c-string from stdin.
*************************************************************
*/
char *s_read( char *s, size_t maxlen )
{
size_t len = 0U;
if ( !s
|| !fgets( s
, maxlen
, stdin
) ) return NULL;
if ( maxlen > MAXINPUT)
maxlen = MAXINPUT;
if ( s
[ (len
=strlen(s
))-1 ] == '\n') s[ len-1 ] = '\0';
return s;
}
/*********************************************************//**
* Return user selection on page-breaks
*************************************************************
*/
char on_pagebreak(void)
{
char input[ MAXINPUT ] = {'\0'};
printf("--- Q to quit, ENTER to continue --- ");
if ( !fgets( input
, MAXINPUT
, stdin
) ) return '\0';
}
/*********************************************************//**
* Display text labels and other info on the currently displayed page.
*************************************************************
*/
void show_header( const char *fname, unsigned long int pg )
{
unsigned short int i;
const unsigned short totalcols = (FMT_FPOS + 1) + (3*FMT_NCOLS) + FMT_NCOLS;
if ( !fname || !*fname )
return;
/* text labels for Bytes & Chars areas */
printf( "%*s | page %lu\n", totalcols
/2,fname
, pg
); printf( "%-*c %-*s%-*s\n", FMT_FPOS
,' ', (3*FMT_NCOLS
),"Bytes area", FMT_NCOLS
,"Chars area" );
/* text label for file-position */
printf("%-*s ", FMT_FPOS
,"Pos");
/* hex indicies for Bytes */
for (i=0; i < FMT_NCOLS; i++)
/* hex indicies for Characters */
for (i=0; i < FMT_NCOLS; i++)
/* separating line */
for (i=0; i < totalcols; i++)
return;
}
/*********************************************************//**
* List the contents of a file in hex/char tabular format.
*************************************************************
*/
int file_hexlist( const char *fname, const unsigned short int israw )
{
Byte buffer[ FMT_NCOLS ] = {0}; /* for reading file chunks into memory*/
unsigned long int i, row, pg; /* byte, row and page counters */
FILE *fp = NULL; /* file pointer */
if ( !fname
|| !*fname
|| NULL
== (fp
=fopen(fname
, "rb")) ) return 0; /* FALSE */
pg = 0;
for (i
=0,row
=0; !feof(fp
); row
++,i
+=FMT_NCOLS
) {
unsigned int j;
size_t n;
/* on page break */
if ( !israw && row % FMT_PGBREAK == 0 ) {
if ( row != 0 )
if ( 'q' == on_pagebreak() )
break;
show_header(fname, pg+1);
pg++;
}
memset( buffer
, 0, FMT_NCOLS
* sizeof(Byte
) ); n
= fread(buffer
, sizeof(Byte
), FMT_NCOLS
, fp
);
for (j=0; j < n; j++)
for (; j < FMT_NCOLS; j++)
for (j=0; j < n; j++)
for (; j < FMT_NCOLS; j++)
}
return 1; /* TRUE */
}
/*********************************************************//**
*
*************************************************************
*/
int main( int argc, char *argv[] )
{
char fname[ MAXINPUT ] = {'\0'}; /* name of the file to be viewed */
unsigned short int israw = 0; /* FALSE */
/* parse the command line */
if ( 1 == argc ) /* no arguments in the command line */
{
printf("Enter name of the file: "); s_read( fname, MAXINPUT );
}
else /* command line contains arguments */
{
if ( !strcmp(argv
[1], "-raw") ) israw = 1; /* TRUE */
else
strncpy( fname
, argv
[1], MAXINPUT
-1 );
if ( israw && argc > 2 )
strncpy( fname
, argv
[2], MAXINPUT
-1 ); else if ( israw && argc == 2 ) {
printf("Enter name of the file: "); s_read( fname, MAXINPUT );
}
}
/* list the file contents */
if ( !file_hexlist(fname, israw) ) {
goto exit_failure;
}
if ( !israw )
pressENTER();
exit_failure:
if ( !israw )
pressENTER();
}
LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBAYnJpZWYJUHJtaXRpdmUgaGV4YWRlY2ltYWwgZmlsZSB2aWV3ZXIgKHBpcGUgaXQgdG8gJ2xlc3MnIG9yICdtb3JlJwogKgkJdG8gbWFrZSBpdCBtdWNoIGxlc3MgcHJpbWl0aXZlLi4uIHNlZSBVc2FnZSBiZWxvdykuCiAqIEBmaWxlCWhleHZpZXcuYwogKiBAdmVyc2lvbgkwLjFBCiAqIEBkYXRlCTIxIEZlYiwgMjAxMgogKiBAYXV0aG9yIAltaWdmMSA8bWlnX2YxQGhvdG1haWwuY29tPgogKiBAcGFyIExhbmd1YWdlOgogKgkJQyAoQU5TSSBDODkpCiAqIEBwYXIgVXNhZ2U6CiAqCQloZXh2aWV3IFstcmF3XSBbZmlsZW5hbWVdCiAqCQlcbgogKgkJVXNlIC1yYXcgYXMgdGhlIDFzdCBjb21tYW5kLWxpbmUgYXJndW1lbnQgdG8gZm9yY2UgcmF3IG91dHB1dAogKgkJKHVzZWZ1bCBmb3IgcGlwaW5nLCBlLmc6IGhleHZpZXcgLXJhdyBmaWxlIHwgbGVzcykKICoKICogQHJlbWFyawlGZWVsIGZyZWUgdG8gZXhwZXJpbWVudCB3aXRoIHRoZSB2YWx1ZXMgb2YgdGhlIHByZS1wcm9jZXNzb3IKICogCQljb25zdGFudHM6IEZNVF9OQ09MUywgRk1UX1BHQlJFQUsgYW5kIEZNVF9QT1MuIFRoZXkgYWZmZWN0IHRoZQogKgkJYXBwZWFyYW5jZSBvZiB0aGUgb3V0cHV0LgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KCiNkZWZpbmUgTUFYSU5QVVQJKDEwMjQrMSkKCiNkZWZpbmUgRk1UX0ZQT1MJOAkJLyogd2lkdGggaW4gIyBvZiBjaGFycyBmb3IgdGhlIGZpbGUtcG9zIGZpZWxkICovCiNkZWZpbmUgRk1UX05DT0xTCTE2CQkvKiAjIG9mIGNvbHVtbnMgaW4gQnl0ZXMgYXJlYShubyBtb3JlIHRoYW4gMTYpKi8KI2RlZmluZSBGTVRfUEdCUkVBSwkyMAkJLyogIyBvZiBsaW5lcyBiZWZvcmUgcGFnZS1icmVhayBhcHBlYXJzICAgICAgICovCgojZGVmaW5lIHByZXNzRU5URVIoKQkJCQkJCQlcCmRvewkJCQkJCQkJCVwKCWNoYXIgbVljSEFyOwkJCQkJCQlcCglwcmludGYoICJwcmVzcyBFTlRFUi4uLiIgKTsJCQkJCVwKCXdoaWxlICggKG1ZY0hBcj1nZXRjaGFyKCkpICE9ICdcbicgJiYgbVljSEFyICE9IEVPRiApCQlcCgkJOwkJCQkJCQlcCn13aGlsZSgwKQoKdHlwZWRlZiB1bnNpZ25lZCBjaGFyIEJ5dGU7CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBSZWFkIGEgYy1zdHJpbmcgZnJvbSBzdGRpbi4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmNoYXIgKnNfcmVhZCggY2hhciAqcywgc2l6ZV90IG1heGxlbiApCnsKCXNpemVfdCBsZW4gPSAwVTsKCglpZiAoICFzIHx8ICFmZ2V0cyggcywgbWF4bGVuLCBzdGRpbikgKQoJCXJldHVybiBOVUxMOwoKCWlmICggbWF4bGVuID4gTUFYSU5QVVQpCgkJbWF4bGVuID0gTUFYSU5QVVQ7CgoJaWYgKCBzWyAobGVuPXN0cmxlbihzKSktMSBdID09ICdcbicpCgkJc1sgbGVuLTEgXSA9ICdcMCc7CgoJcmV0dXJuIHM7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovLyoqCiAqIFJldHVybiB1c2VyIHNlbGVjdGlvbiBvbiBwYWdlLWJyZWFrcwogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKi8KY2hhciBvbl9wYWdlYnJlYWsodm9pZCkKewoJY2hhciBpbnB1dFsgTUFYSU5QVVQgXSA9IHsnXDAnfTsKCglwcmludGYoIi0tLSBRIHRvIHF1aXQsIEVOVEVSIHRvIGNvbnRpbnVlIC0tLSAiKTsKCWZmbHVzaCggc3Rkb3V0ICk7CgoJaWYgKCAhZmdldHMoIGlucHV0LCBNQVhJTlBVVCwgc3RkaW4gKSApCgkJcmV0dXJuICdcMCc7CgoJcmV0dXJuIHRvbG93ZXIoICppbnB1dCApOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBEaXNwbGF5IHRleHQgbGFiZWxzIGFuZCBvdGhlciBpbmZvIG9uIHRoZSBjdXJyZW50bHkgZGlzcGxheWVkIHBhZ2UuCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwp2b2lkIHNob3dfaGVhZGVyKCBjb25zdCBjaGFyICpmbmFtZSwgdW5zaWduZWQgbG9uZyBpbnQgcGcgKQp7Cgl1bnNpZ25lZCBzaG9ydCBpbnQgaTsKCWNvbnN0IHVuc2lnbmVkIHNob3J0IHRvdGFsY29scyA9IChGTVRfRlBPUyArIDEpICsgKDMqRk1UX05DT0xTKSArIEZNVF9OQ09MUzsKCglpZiAoICFmbmFtZSB8fCAhKmZuYW1lICkKCQlyZXR1cm47CgoJLyogdGV4dCBsYWJlbHMgZm9yIEJ5dGVzICYgQ2hhcnMgYXJlYXMgKi8KCXByaW50ZiggIiUqcyB8IHBhZ2UgJWx1XG4iLCB0b3RhbGNvbHMvMixmbmFtZSwgcGcpOwoJcHJpbnRmKCAiJS0qYyAlLSpzJS0qc1xuIiwgRk1UX0ZQT1MsJyAnLCAoMypGTVRfTkNPTFMpLCJCeXRlcyBhcmVhIiwgRk1UX05DT0xTLCJDaGFycyBhcmVhIiApOwoKCS8qIHRleHQgbGFiZWwgZm9yIGZpbGUtcG9zaXRpb24gKi8KCXByaW50ZigiJS0qcyAiLCBGTVRfRlBPUywiUG9zIik7CgoJLyogaGV4IGluZGljaWVzIGZvciBCeXRlcyAqLwoJZm9yIChpPTA7IGkgPCBGTVRfTkNPTFM7IGkrKykKCQlwcmludGYoICIlLTJoWCAiLCBpKTsKCgkvKiBoZXggaW5kaWNpZXMgZm9yIENoYXJhY3RlcnMgKi8KCWZvciAoaT0wOyBpIDwgRk1UX05DT0xTOyBpKyspCgkJcHJpbnRmKCAiJWhYIiwgaSk7CglwdXRjaGFyKCdcbicpOwoKCS8qIHNlcGFyYXRpbmcgbGluZSAqLwoJZm9yIChpPTA7IGkgPCB0b3RhbGNvbHM7IGkrKykKCQlwdXRjaGFyKCctJyk7CglwdXRjaGFyKCdcbicpOwoKCglyZXR1cm47Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovLyoqCiAqIExpc3QgdGhlIGNvbnRlbnRzIG9mIGEgZmlsZSBpbiBoZXgvY2hhciB0YWJ1bGFyIGZvcm1hdC4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmludCBmaWxlX2hleGxpc3QoIGNvbnN0IGNoYXIgKmZuYW1lLCBjb25zdCB1bnNpZ25lZCBzaG9ydCBpbnQgaXNyYXcgKQp7CglCeXRlIGJ1ZmZlclsgRk1UX05DT0xTIF0gPSB7MH07CQkvKiBmb3IgcmVhZGluZyBmaWxlIGNodW5rcyBpbnRvIG1lbW9yeSovCgl1bnNpZ25lZCBsb25nIGludCBpLCByb3csIHBnOwkJLyogYnl0ZSwgcm93IGFuZCBwYWdlIGNvdW50ZXJzICAgICAgICAqLwoJRklMRSAqZnAgPSBOVUxMOwkJCS8qIGZpbGUgcG9pbnRlciAgICAgICAgICAgICAgICAgICAgICAgKi8KCglpZiAoICFmbmFtZSB8fCAhKmZuYW1lIHx8IE5VTEwgPT0gKGZwPWZvcGVuKGZuYW1lLCAicmIiKSkgKQoJCXJldHVybiAwOwkvKiBGQUxTRSAqLwoKCXBnID0gMDsKCWZvciAoaT0wLHJvdz0wOyAhZmVvZihmcCk7IHJvdysrLGkrPUZNVF9OQ09MUyApCgl7CgkJdW5zaWduZWQgaW50IAlqOwoJCXNpemVfdCAJCW47CgoJCS8qIG9uIHBhZ2UgYnJlYWsgKi8KCQlpZiAoICFpc3JhdyAmJiByb3cgJSBGTVRfUEdCUkVBSyA9PSAwICkgewoJCQlpZiAoIHJvdyAhPSAwICkKCQkJCWlmICggJ3EnID09IG9uX3BhZ2VicmVhaygpICkKCQkJCQlicmVhazsKCQkJc2hvd19oZWFkZXIoZm5hbWUsIHBnKzEpOwoJCQlwZysrOwoJCX0KCgkJbWVtc2V0KCBidWZmZXIsIDAsIEZNVF9OQ09MUyAqIHNpemVvZihCeXRlKSApOwoJCW4gPSBmcmVhZChidWZmZXIsIHNpemVvZihCeXRlKSwgRk1UX05DT0xTLCBmcCk7CgoJCXByaW50ZiggIiUwOGxYICIsIGkpOwoKCQlmb3IgKGo9MDsgaiA8IG47IGorKykKCQkJcHJpbnRmKCIlMDJoWCAiLCBidWZmZXJbal0gKTsKCQlmb3IgKDsgaiA8IEZNVF9OQ09MUzsgaisrKQoJCQlwcmludGYoIiAgICIpOwoKCQlmb3IgKGo9MDsgaiA8IG47IGorKykKCQkJcHV0Y2hhciggaXNwcmludChidWZmZXJbal0pID8gYnVmZmVyW2pdIDogJy4nICk7CgkJZm9yICg7IGogPCBGTVRfTkNPTFM7IGorKykKCQkJcHV0Y2hhcignICcpOwoJCXB1dGNoYXIoJ1xuJyk7Cgl9CglwdXRjaGFyKCdcbicpOwoKCWZjbG9zZShmcCk7CglyZXR1cm4gMTsJCS8qIFRSVUUgKi8KfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmludCBtYWluKCBpbnQgYXJnYywgY2hhciAqYXJndltdICkKewoJY2hhciBmbmFtZVsgTUFYSU5QVVQgXSA9IHsnXDAnfTsJLyogbmFtZSBvZiB0aGUgZmlsZSB0byBiZSB2aWV3ZWQgICAgKi8KCXVuc2lnbmVkIHNob3J0IGludCBpc3JhdyA9IDA7CQkvKiBGQUxTRSAqLwoKCS8qIHBhcnNlIHRoZSBjb21tYW5kIGxpbmUgKi8KCWlmICggMSA9PSBhcmdjICkJCQkvKiBubyBhcmd1bWVudHMgaW4gdGhlIGNvbW1hbmQgbGluZSAqLwoJewoJCXByaW50ZigiRW50ZXIgbmFtZSBvZiB0aGUgZmlsZTogIik7CgkJc19yZWFkKCBmbmFtZSwgTUFYSU5QVVQgKTsKCX0KCWVsc2UJCQkJCS8qIGNvbW1hbmQgbGluZSBjb250YWlucyBhcmd1bWVudHMgKi8KCXsKCQlpZiAoICFzdHJjbXAoYXJndlsxXSwgIi1yYXciKSApCgkJCWlzcmF3ID0gMTsJCS8qIFRSVUUgKi8KCQllbHNlCgkJCXN0cm5jcHkoIGZuYW1lLCBhcmd2WzFdLCBNQVhJTlBVVC0xICk7CgoJCWlmICggaXNyYXcgJiYgYXJnYyA+IDIgKQoJCQlzdHJuY3B5KCBmbmFtZSwgYXJndlsyXSwgTUFYSU5QVVQtMSApOwoJCWVsc2UgaWYgKCBpc3JhdyAmJiBhcmdjID09IDIgICkgewoJCQlwcmludGYoIkVudGVyIG5hbWUgb2YgdGhlIGZpbGU6ICIpOwoJCQlzX3JlYWQoIGZuYW1lLCBNQVhJTlBVVCApOwoJCX0KCX0KCgkvKiBsaXN0IHRoZSBmaWxlIGNvbnRlbnRzICovCglpZiAoICFmaWxlX2hleGxpc3QoZm5hbWUsIGlzcmF3KSApIHsKCQlwZXJyb3IoTlVMTCk7CgkJZ290byBleGl0X2ZhaWx1cmU7Cgl9CgoJaWYgKCAhaXNyYXcgKQoJCXByZXNzRU5URVIoKTsKCWV4aXQoIEVYSVRfU1VDQ0VTUyApOwoKZXhpdF9mYWlsdXJlOgoJaWYgKCAhaXNyYXcgKQoJCXByZXNzRU5URVIoKTsKCWV4aXQoIEVYSVRfRkFJTFVSRSApOwp9Cg==