This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/Xmodem/zmodemdump.c

583 lines
12 KiB
C
Raw Normal View History

2016-04-02 23:26:17 +00:00
#ifndef lint
static const char rcsid[] = "$Id: zmodemdump.c,v 1.2 2001/10/25 23:56:29 efalk Exp $" ;
#endif
/* variation on serialmon companion program serialdump, which
* interprets data as a zmodem dialog
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/termios.h>
#include <sys/types.h>
#include <sys/time.h>
#include <assert.h>
#include "crctab.h"
#define MAXBUF 2048
#define MAXLINE 16
#define MAXHBUF 128
#define OLINELEN (MAXLINE*2)
#define CAN 030
#define XON 021
#define ZDLE 030
#define ZPAD '*'
#define ZBIN 'A'
#define ZHEX 'B'
#define ZBIN32 'C'
#define ZBINR32 'D'
#define ZVBIN 'a'
#define ZVHEX 'b'
#define ZVBIN32 'c'
#define ZVBINR32 'd'
#define ZRESC 0177
#define ZRQINIT 0 /* request receive init */
#define ZRINIT 1 /* receive init */
#define ZSINIT 2 /* send init sequence, define Attn */
#define ZACK 3 /* ACK */
#define ZFILE 4 /* file name, from sender */
#define ZSKIP 5 /* skip file command, from receiver */
#define ZNAK 6 /* last packet was garbled */
#define ZABORT 7 /* abort */
#define ZFIN 8 /* finish session */
#define ZRPOS 9 /* resume file from this position, from receiver */
#define ZDATA 10 /* data packets to follow, from sender */
#define ZEOF 11 /* end of file, from sender */
#define ZFERR 12 /* fatal i/o error, from receiver */
#define ZCRC 13 /* request for file crc, from receiver */
#define ZCHALLENGE 14 /* "send this number back to me", from receiver */
#define ZCOMPL 15 /* request is complete */
#define ZCAN 16 /* other end cancelled with CAN-CAN-CAN-CAN-CAN */
#define ZFREECNT 17 /* request for free bytes on filesystem */
#define ZCOMMAND 18 /* command, from sending program */
#define ZSTDERR 19 /* output this message to stderr */
#define ZCRCE 'h'
#define ZCRCG 'i'
#define ZCRCQ 'j'
#define ZCRCW 'k'
#define ZRUB0 'l'
#define ZRUB1 'm'
typedef enum {Idle, Padding, HexHeader, Header16, Header32,
InData, InCrc} ZState ;
typedef struct {
ZState state ;
int headertype ;
int data[4] ;
int crcBytes[4] ;
int count ;
int zdlePend ; /* ZDLE received */
int crcCmd ;
int crclen ;
u_long crc ;
} Zinfo ;
u_char buffer[MAXBUF] ;
u_char line[MAXLINE] ;
u_char hbuffer[MAXHBUF] ;
int linecnt = 0 ;
int hbufcnt = 0 ;
main( int argc, char **argv )
{
int i,j ;
int len ;
int which ;
struct timeval timestamp, oldtime ;
struct tm *tm ;
Zinfo Ainfo, Binfo ;
printf("serial log. 'A' is application, 'B' is serial port\n\n") ;
oldtime.tv_sec = 0 ;
Ainfo.state = Binfo.state = Idle ;
Ainfo.zdlePend = Binfo.zdlePend = 0 ;
while( (i=fread((char *)&which, sizeof(which), 1, stdin)) > 0 )
{
i = fread((char *)&timestamp, sizeof(timestamp), 1, stdin) ;
i = fread((char *)&len, sizeof(len), 1, stdin) ;
if( timestamp.tv_sec != oldtime.tv_sec ||
timestamp.tv_usec != oldtime.tv_usec )
{
if( linecnt > 0 )
dumpLine() ;
tm = localtime(&timestamp.tv_sec) ;
printf("%c: %2d:%2.2d:%2.2d.%2.2d\n", 'A'+which,
tm->tm_hour,tm->tm_min,tm->tm_sec, timestamp.tv_usec/10000 ) ;
oldtime = timestamp ;
}
while( len > 0 )
{
i = MAXBUF ;
if( len < i ) i = len ;
j = fread(buffer, 1, i, stdin) ;
assert(j <= MAXBUF) ;
len -= j ;
parseData(which ? &Binfo : &Ainfo, j) ;
}
while( len > 0 )
{
i = MAXLINE - linecnt ;
if( len < i ) i = len ;
assert(linecnt+i <= MAXLINE) ;
j = fread(line+linecnt, 1, i, stdin) ;
assert(linecnt+j <= MAXLINE) ;
len -= j ;
linecnt += j ;
if( linecnt >= MAXLINE )
dumpLine() ;
}
}
if( linecnt > 0 )
dumpLine() ;
exit(0) ;
}
char
toprintable(char c)
{
c &= 0177 ;
if( c >= 0x20 && c <= 0x7e )
return c ;
else
return '.' ;
}
dumpLine()
{
int i,j ;
if( linecnt <= 0 )
return ;
if( linecnt > MAXLINE ) linecnt = MAXLINE ;
printf(" ") ;
for(i=0; i<linecnt; ++i) {
assert(i <= MAXLINE) ;
printf("%2.2x ", line[i]) ;
}
for(; i<MAXLINE; ++i)
printf(" ") ;
printf("\t|") ;
for(i=0; i<linecnt; ++i) {
assert(i <= MAXLINE) ;
printf("%c",toprintable(line[i])) ;
}
printf("|\n") ;
linecnt = 0 ;
}
static u_char hexHeaderStart[] = {ZPAD,ZPAD,ZDLE,ZHEX} ;
static u_char header16Start[] = {ZPAD,ZDLE,ZBIN} ;
static u_char header32Start[] = {ZPAD,ZDLE,ZBIN32} ;
parseData( Zinfo *info, int len )
{
u_char *ptr, c ;
int idx ;
for(ptr = buffer; --len >= 0; ptr++) {
assert(ptr >= buffer && ptr < buffer+MAXBUF) ;
c = *ptr ;
if( c != XON )
switch( info->state ) {
case Idle:
if( c != ZPAD )
dataChar(c) ;
else {
info->state = Padding ;
info->count = 1 ;
hbuffer[0] = c ;
}
break ;
case Padding:
if( c == ZDLE ) {
info->zdlePend = 1 ;
}
else if( info->zdlePend ) {
info->zdlePend = 0 ;
info->count = 0 ;
switch(c) {
case ZHEX:
info->state = HexHeader ;
info->crclen=2 ;
info->crc = 0 ;
break ;
case ZBIN:
info->state = Header16 ;
info->crclen=2 ;
info->crc = 0 ;
break ;
case ZBIN32:
info->state = Header32 ;
info->crclen=4 ;
info->crc = 0xffffffff ;
break ;
default:
cancelHeader(info) ; break ;
}
}
else if( c == ZPAD )
{
if( info->count < 2 ) {
assert(info->count < MAXHBUF) ;
hbuffer[info->count++] = c ;
}
else
dataChar(c) ;
}
else
cancelHeader(info) ; break ;
break ;
case HexHeader:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 16 ) { /* end of header */
info->headertype = hex2(hbuffer+0) ;
info->data[0] = hex2(hbuffer+2) ;
info->data[1] = hex2(hbuffer+4) ;
info->data[2] = hex2(hbuffer+6) ;
info->data[3] = hex2(hbuffer+8) ;
info->crcBytes[0] = hex2(hbuffer+10) ;
info->crcBytes[1] = hex2(hbuffer+12) ;
displayHeader(info) ;
}
break ;
case Header16:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 7 ) { /* end of header */
info->headertype = hbuffer[0] ;
info->data[0] = hbuffer[1] ;
info->data[1] = hbuffer[2] ;
info->data[2] = hbuffer[3] ;
info->data[3] = hbuffer[4] ;
info->crcBytes[0] = hbuffer[5] ;
info->crcBytes[1] = hbuffer[6] ;
displayHeader(info) ;
}
break ;
case Header32:
if( c == ZDLE && !info->zdlePend ) {
info->zdlePend = 1 ;
break ;
}
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
idx = info->count++ ;
assert(idx < MAXHBUF) ;
hbuffer[idx] = c ;
if( info->count >= 9 ) { /* end of header */
info->headertype = hbuffer[0] ;
info->data[0] = hbuffer[1] ;
info->data[1] = hbuffer[2] ;
info->data[2] = hbuffer[3] ;
info->data[3] = hbuffer[4] ;
info->crcBytes[0] = hbuffer[5] ;
info->crcBytes[1] = hbuffer[6] ;
info->crcBytes[2] = hbuffer[7] ;
info->crcBytes[3] = hbuffer[8] ;
displayHeader(info) ;
}
break ;
case InData:
if( info->zdlePend )
{
info->zdlePend = 0 ;
switch( c ) {
case ZCRCE:
case ZCRCW:
case ZCRCG:
case ZCRCQ:
info->crcCmd = c ;
dumpLine() ;
info->state = InCrc ;
info->count = 0 ;
break ;
default:
c = zdle(c) ;
dataChar(c) ;
break ;
}
}
else if( c == ZDLE )
info->zdlePend = 1 ;
else
dataChar(c) ;
break ;
case InCrc:
if( info->zdlePend ) {
c = zdle(c) ;
info->zdlePend = 0 ;
}
if( c == ZDLE )
info->zdlePend = 1 ;
else
{
dataChar(c) ;
if( ++info->count >= info->crclen )
{
dumpCrc() ;
switch( info->crcCmd ) {
case ZCRCE:
printf(" ZCRCE: end of frame, header follows\n") ;
info->state = Idle ;
break ;
case ZCRCW:
printf(" ZCRCW: end of frame, send ZACK\n") ;
info->state = Idle ;
break ;
case ZCRCG:
printf(" ZCRCG: more data follows:\n") ;
info->state = InData ;
break ;
case ZCRCQ:
printf(" ZCRCQ: send ZACK, more data follows:\n") ;
info->state = InData ;
break ;
}
}
}
break ;
}
}
}
/* handle a character that's not part of the protocol */
dataChar(int c)
{
assert(linecnt < MAXLINE) ;
line[linecnt++] = c ;
if( linecnt >= MAXLINE )
dumpLine() ;
}
/* here if we thought we were in a header, but were wrong */
cancelHeader( Zinfo *info )
{
int i ;
for(i=0; i<info->count; ++i) {
assert(i < MAXHBUF) ;
dataChar(hbuffer[i]) ;
}
info->state = Idle ;
}
/* here to display a full header. CRC's not currently checked */
displayHeader( Zinfo *info )
{
int i ;
u_long crc ;
int h32 = info->state == Header32 ;
static char *names[] = {
"ZRQINIT", "ZRINIT", "ZSINIT", "ZACK", "ZFILE", "ZSKIP",
"ZNAK", "ZABORT", "ZFIN", "ZRPOS", "ZDATA", "ZEOF", "ZFERR",
"ZCRC", "ZCHALLENGE", "ZCOMPL", "ZCAN", "ZFREECNT",
"ZCOMMAND", "ZSTDERR",} ;
dumpLine() ;
printf(" ") ;
switch( info->state ) {
case HexHeader: printf("hex header") ; break ;
case Header16: printf("bin header") ; break ;
case Header32: printf("bin32 header") ; break ;
}
printf(" %d: %s: d=[%x %x %x %x]", info->headertype,
info->headertype <= ZSTDERR ? names[info->headertype] : "BAD HEADER",
info->data[0], info->data[1], info->data[2], info->data[3]) ;
switch( info->state ) {
case HexHeader:
case Header16:
printf(" crc=[%x %x]", info->crcBytes[0], info->crcBytes[1]) ;
break ;
case Header32:
printf(" crc=[%x %x %x %x]",
info->crcBytes[0], info->crcBytes[1],
info->crcBytes[2], info->crcBytes[3]) ;
break ;
}
switch( info->headertype ) {
case ZRQINIT:
case ZRINIT:
case ZACK:
case ZSKIP:
case ZNAK:
case ZABORT:
case ZFIN:
case ZRPOS:
case ZEOF:
case ZFERR:
case ZCRC:
case ZCHALLENGE:
case ZCOMPL:
case ZCAN:
case ZFREECNT:
case ZCOMMAND:
printf("\n") ;
info->state = Idle ;
break ;
case ZSINIT:
case ZFILE:
case ZDATA:
case ZSTDERR:
printf(", data follows:\n") ;
info->state = InData ;
info->count = 0 ;
break ;
}
if( !h32 )
{
crc = 0 ;
crc = updcrc(info->headertype, crc) ;
crc = updcrc(info->data[0], crc) ;
crc = updcrc(info->data[1], crc) ;
crc = updcrc(info->data[2], crc) ;
crc = updcrc(info->data[3], crc) ;
crc = updcrc(info->crcBytes[0], crc) ;
crc = updcrc(info->crcBytes[1], crc) ;
if( crc&0xffff != 0 )
printf(" CRC ERROR\n") ;
}
else
{
crc = 0xffffffff ;
crc = UPDC32(info->headertype, crc) ;
crc = UPDC32(info->data[0], crc) ;
crc = UPDC32(info->data[1], crc) ;
crc = UPDC32(info->data[2], crc) ;
crc = UPDC32(info->data[3], crc) ;
crc = UPDC32(info->crcBytes[0], crc) ;
crc = UPDC32(info->crcBytes[1], crc) ;
crc = UPDC32(info->crcBytes[2], crc) ;
crc = UPDC32(info->crcBytes[3], crc) ;
if( crc != 0xdebb20e3 )
printf(" CRC ERROR\n") ;
}
}
dumpCrc()
{
int i,j ;
if( linecnt <= 0 )
return ;
if( linecnt > MAXLINE ) linecnt = MAXLINE ;
printf(" crc: ") ;
for(i=0; i<linecnt; ++i) {
assert(i < MAXLINE) ;
printf("%2.2x ", line[i]) ;
}
printf("\n") ;
linecnt = 0 ;
}
/* return value of 2 hex digits */
int
hex2(char *chrs)
{
return (hex1(chrs[0]) << 4) + hex1(chrs[1]) ;
}
/* return value of a hex digit */
int
hex1(int chr)
{
chr -= '0' ;
if( chr > 9 )
chr -= 'A'-'0'-10 ;
if( chr > 15 )
chr -= 'a' - 'A' ;
return chr ;
}
/* apply ZDLE to chr */
int
zdle(int chr)
{
switch( chr ) {
case ZRUB0: return 0177 ;
case ZRUB1: return 0377 ;
default:
if( (chr & 0140) == 0100 )
return chr ^ 0100 ;
return -1 ;
}
}