home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
forum16.lzh
/
SOFTWARE
/
C
/
HEXED
/
hexed.c
< prev
next >
Wrap
Text File
|
1991-03-25
|
13KB
|
502 lines
/*
hexeditor made up of three parts:
- creating hexdump
- editing hexdump using standard texteditor
- retransforming hexdump to binary file
(C) Helmut Hoheisel-Zimmermann, D-2300 Kiel
03/91
*/
/* includes : */
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
/* externals : */
extern char *_prgname () ;
/* constants : */
#define TEMPDIR_DEFAULT "/r0" /* dir for temporary files */
#define EDITOR_DEFAULT "vi" /* texteditor's name */
#define EDOPTS_DEFAULT "" /* options for texteditor */
#define EDGOTO_DEFAULT "+" /* goto option for texteditor */
#define FORMAT_ERROR -2 /* wrong retransform format */
#define END_OF_LINE -1 /* normal end of line */
/* globals : */
char *tempdir = TEMPDIR_DEFAULT ;
char *editor = EDITOR_DEFAULT ;
char *edit_opts = EDOPTS_DEFAULT ;
char *edit_goto = EDGOTO_DEFAULT ;
/****************************************************************/
/* usage-message and exit : */
void usage ()
{
fprintf ( stderr, "Syntax: %s [<opts>] <path> {[<opts>] | [<path>]}\n", _prgname () ) ;
fprintf ( stderr, "Function: dump, edit and retransform file(s) with binary data\n" ) ;
fprintf ( stderr, "Options:\n" ) ;
fprintf ( stderr, " -t=<dir> use <dir> for temporary files (default: '%s')\n", tempdir ) ;
fprintf ( stderr, " -e=<editor> use <editor> as the texteditor (default: '%s')\n", editor ) ;
fprintf ( stderr, " -eo=<opts> use editor-<opts> (default: '%s')\n", edit_opts ) ;
fprintf ( stderr, " -eg=<opts> use editor-<opts> to go to specified line (default: '%s')\n", edit_goto ) ;
fprintf ( stderr, " -? show this message\n\n" ) ;
fprintf ( stderr, "Format for dumped lines as generated by '%s':\n", _prgname () ) ;
fprintf ( stderr, " bytecount (optional) will not be interpreted by retransformation\n" ) ;
fprintf ( stderr, " blank(s) (at least one blank, obligatory) as separator\n" ) ;
fprintf ( stderr, " hexdata bytes (an arbitrary number) each of it consisting of one or two\n" ) ;
fprintf ( stderr, " hex-digits; the bytes are separated by blank(s)\n" ) ;
fprintf ( stderr, " blank & ; & ASCII (optional) arbitrary comment or ASCII-representation\n\n" ) ;
fprintf ( stderr, "Alternatively the following line format can be retransformed:\n" ) ;
fprintf ( stderr, " .a inits ASCII-line\n" ) ;
fprintf ( stderr, " blank(s) (optional) as separator\n" ) ;
fprintf ( stderr, " delimiter arbitrary ASCII-character except blank as delimiter\n" ) ;
fprintf ( stderr, " ASCII-data text without delimiter\n" ) ;
fprintf ( stderr, " delimiter & ASCII (optional, delimiter as defined above) arbitrary comment\n" ) ;
exit ( 0 ) ;
}
/****************************************************************/
/* scan for options : */
void getargs ( ac, av )
int *ac ;
char *av [] ;
{
register int i ;
int maxac ;
char **avfilenames ;
for ( i = 1, maxac = *ac, avfilenames = av + 1 ; i < maxac ; i ++ )
{
if ( *av [i] == '-' )
{ /* parameter is option : */
switch ( *( av [i] + 1 ) )
{
case 't' :
if ( *( av [i] + 2 ) != '=' )
{
usage () ;
}
tempdir = av [i] + 3 ;
break ;
case 'e' :
switch ( *( av [i] + 2 ) )
{
case '=' :
editor = av [i] + 3 ;
break ;
case 'o' :
if ( *( av [i] + 3 ) != '=' )
{
usage () ;
}
edit_opts = av [i] + 4 ;
break ;
case 'g' :
if ( *( av [i] + 3 ) != '=' )
{
usage () ;
}
edit_goto = av [i] + 4 ;
break ;
default : /* illegal 2. option letter */
usage () ;
break ;
}
break ;
default : /* illegal option letter */
usage () ;
break ;
} /* end switch ( option letter */
( *ac ) -- ;
} /* end if ( option */
else
{ /* filename */
* avfilenames ++ = av [i] ;
}
} /* end for ( i ... */
if ( *ac < 2 )
{
usage () ;
}
}
/****************************************************************/
/* return pointer to pure filename without directories : */
char *get_filename ( path )
char *path ;
{
register char *cp ;
for ( cp = path + strlen ( path ) - 1 ; cp >= path ; cp -- )
{
if ( *cp == '/' )
{
break ;
}
}
return ( cp + 1 ) ;
}
/****************************************************************/
/* get hexdump filename from binary data filename : */
char *hd_filename ( path )
char *path ;
{
static char namebuf [160] ;
sprintf ( namebuf, "%s/%s.hd", tempdir, get_filename ( path ) ) ;
return ( namebuf ) ;
}
/****************************************************************/
/* create one dump file : */
void gen_dump ( source_path )
char *source_path ; /* name of sourcefile */
{
char *hd_path ; /* dump file name */
FILE *hdfile ; /* dump file pointer */
FILE *srcfile ; /* source file pointer */
register int current = 0 ; /* current byte number */
char ascii [16] ; /* buffer for ASCII represent. */
register int ch ; /* character read from input */
register int index ; /* column index */
hd_path = hd_filename ( source_path ) ;
fprintf ( stderr, "Creating '%s' from '%s'.\n", hd_path, source_path ) ;
if ( ( hdfile = fopen ( hd_path, "w" ) ) == (FILE*) 0 )
{
fprintf ( stderr, "error: can't create '%s' !\n", hd_path ) ;
exit ( 1 ) ;
}
if ( ( srcfile = fopen ( source_path, "r" ) ) != (FILE*) 0 )
{ /* source is available : */
while ( ( ch = getc ( srcfile ) ) != EOF )
{
switch ( index = current % 16 )
{
case 0 : /* start of dump line : */
memset ( ascii, ' ', 16 ) ;
ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
fprintf ( hdfile, "%06X %02x", current, ch ) ;
break ;
case 15 : /* last byte of this line : */
ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
fprintf ( hdfile, " %02x ; %.16s\n", ch, ascii ) ;
break ;
case 4 : /* quarters of the line : */
case 8 :
case 12 :
putc ( ' ', hdfile ) ;
default : /* else : */
ascii [ index ] = ch < 127 && isprint ( ch ) ? ch : '.' ;
fprintf ( hdfile, " %02x", ch ) ;
break ;
}
current ++ ;
}
if ( current % 16 )
{
if ( index < 4 )
{
putc ( ' ', hdfile ) ;
}
if ( index < 8 )
{
putc ( ' ', hdfile ) ;
}
if ( index < 12 )
{
putc ( ' ', hdfile ) ;
}
fprintf ( hdfile, "%*s ; %.*s\n", ( 15 - index ) * 3, "", index + 1 , ascii ) ;
}
fclose ( srcfile ) ;
}
fprintf ( hdfile, "%06X\n", current ) ;
fclose ( hdfile ) ;
}
/****************************************************************/
/* retransform one dump file : */
int dedump ( source_path )
char *source_path ; /* name of sourcefile */
{
char *hd_path ; /* dump file name */
FILE *hdfile ; /* dump file pointer */
FILE *srcfile ; /* source file pointer */
char line [512] ; /* one dump line */
register char *akt ; /* actual char ptr */
register int ch ; /* actual char */
int lnr ; /* line number */
register int phase ; /* status */
char *errtext ; /* error text for format errors */
int delimiter ; /* delimiter for ASCII text */
char *bytestart ; /* pointer to begin of hexbyte */
hd_path = hd_filename ( source_path ) ;
fprintf ( stderr, "Generating '%s' from '%s'.\n", source_path, hd_path ) ;
if ( ( hdfile = fopen ( hd_path, "r" ) ) == (FILE*) 0 )
{
fprintf ( stderr, "error: can't open '%s' !\n", hd_path ) ;
return ( -1 ) ;
}
if ( ( srcfile = fopen ( source_path, "w" ) ) == (FILE*) 0 )
{
fclose ( hdfile ) ;
fprintf ( stderr, "error: can't open '%s' !\n", source_path ) ;
return ( -1 ) ;
}
lnr = 0 ; /* assumes: editor counts lines from 1 to ... */
while ( ( akt = fgets ( line, sizeof ( line ), hdfile ) ) != (char *) 0 )
{
*( line + strlen ( line ) - 1 ) = '\0' ;
lnr ++ ;
for ( phase = 0 ; phase >= 0 ; akt ++ )
{
ch = *akt ;
if ( ch == '\0' )
{
phase = END_OF_LINE ;
}
switch ( phase )
{
case 0 : /* start of line : */
if ( ch == '.' )
{
phase ++ ; /* begin of ASCII line ? */
}
else
{
/* to ensure correct handling */
/* of EOL in hexbyte (phase 7): */
*( line + strlen ( line ) ) = ' ' ;
if ( isspace ( ch ) )
{
phase = 6 ; /* hexdump after linenumber ? */
}
else
{
if ( isxdigit ( ch ) )
{
phase = 5 ; /* hexdump linenumber */
}
else
{
errtext = "illegal first char" ;
phase = FORMAT_ERROR ;
}
}
}
break ;
case 1 : /* ASCII line ? */
if ( ch == 'a' || ch == 'A' )
{
phase ++ ; /* look for delimiter */
}
else
{
errtext = "no ASCII line !" ;
phase = FORMAT_ERROR ;
}
break ;
case 2 : /* scan for delimiter : */
if ( ! isspace ( ch ) )
{
delimiter = ch ;
phase ++ ; /* transfer ASCII text */
}
break ;
case 3 :
if ( ch == delimiter )
{
phase = END_OF_LINE ;
}
else
{
putc ( ch, srcfile ) ;
}
break ;
case 5 : /* linenumber of hexdump : */
if ( isspace ( ch ) )
{
phase ++ ;
}
else
{
if ( ! isxdigit ( ch ) )
{
errtext = "illegal char in linenumber" ;
phase = FORMAT_ERROR ;
}
}
break ;
case 6 : /* space before hexbyte : */
if ( ch == ';' )
{
phase = END_OF_LINE ;
}
else
{
if ( isxdigit ( ch ) )
{
bytestart = akt ;
phase ++ ; /* transform hexbyte */
}
else
{
if ( ! isspace ( ch ) )
{
errtext = "illegal char between hexbytes" ;
phase = FORMAT_ERROR ;
}
}
}
break ;
case 7 : /* in hexbyte : */
if ( isspace ( ch ) )
{
if ( akt - bytestart > 2 )
{
errtext = "illegal size of hexbyte" ;
phase = FORMAT_ERROR ;
}
else
{
sscanf ( bytestart, "%x", &delimiter ) ;
putc ( delimiter, srcfile ) ;
phase -- ; /* space between hexbytes */
}
}
else
{
if ( ! isxdigit ( ch ) )
{
errtext = "illegal char in hexbyte" ;
phase = FORMAT_ERROR ;
}
}
break ;
default :
break ;
}
}
if ( phase == FORMAT_ERROR )
{
fprintf ( stderr, " -> format error in line no. %d : %s !\n", lnr, errtext ) ;
fprintf ( stderr, " press 'return' to continue !\n" ) ;
getchar () ;
fclose ( srcfile ) ;
fclose ( hdfile ) ;
if ( *edit_goto == '\0' )
{ /* no goto option : */
sprintf ( line, "%s %s", editor, hd_path ) ;
}
else
{
sprintf ( line, "%s %s%d %s", editor, edit_goto, lnr, hd_path ) ;
}
system ( line ) ;
return ( dedump ( source_path ) ) ; /* recursive !!! */
}
}
fclose ( srcfile ) ;
fclose ( hdfile ) ;
return ( 0 ) ;
}
/****************************************************************/
/* main program : */
main ( argc, argv )
int argc ;
char *argv [] ;
{
register int cnt ;
char cmd_buf [512] ; /* for system-call */
getargs ( &argc, argv ) ; /* scan parameters : */
/* create dump files : */
for ( cnt = 1 ; cnt < argc ; cnt ++ )
{
gen_dump ( argv [ cnt ] ) ;
}
/* edit dump files : */
sprintf ( cmd_buf, "chd %s ; %s %s ", tempdir, editor, edit_opts ) ;
for ( cnt = 1 ; cnt < argc ; cnt ++ )
{
strcat ( cmd_buf, " " ) ;
strcat ( cmd_buf, get_filename ( argv [ cnt ] ) ) ;
strcat ( cmd_buf, ".hd " ) ;
}
system ( cmd_buf ) ;
/* retransform dump files : */
for ( cnt = 1 ; cnt < argc ; cnt ++ )
{
if ( dedump ( argv [ cnt ] ) >= 0 )
{
unlink ( hd_filename ( argv [ cnt ] ) ) ;
}
}
}