808 lines
22 KiB
Bash
808 lines
22 KiB
Bash
#!/bin/sh
|
|
#
|
|
# $Id: ic35log.sh,v 1.6 2001/01/14 00:09:46 tsch Rel $
|
|
#
|
|
# process logs of IC35 communication
|
|
#
|
|
|
|
# setup parameters and defaults
|
|
PAGER="less -S"
|
|
PROGNAME=`basename $0`
|
|
TMPDIR=/tmp/dpkgmirr$$
|
|
|
|
usage()
|
|
{
|
|
echo "\
|
|
usage: $PROGNAME [options] [tarfile] logfile
|
|
process IC35 communication 'logfile', which may be gzip'd or contained
|
|
in optionally gzip'd 'tarfile'. options:
|
|
-l level level of output:
|
|
all show all communication (default)
|
|
syn2 suppress Level-1 of IC35sync protocol
|
|
syn4 decode Level-4 of IC35sync protocol
|
|
-s n prepend output with 1:linenumber 2:timestamp
|
|
-a show communication also as ASCII characters
|
|
-D debug/detail: output diagnostic data \
|
|
"
|
|
exit 2
|
|
}
|
|
|
|
# add ASCII chars to hex_logfile
|
|
#
|
|
showascii() # <hex_logfile >hex_ascii_logfile
|
|
{
|
|
awk '
|
|
BEGIN {
|
|
# create table chr[] for hex to char conversion
|
|
ascii = ascii " !\"#$%&\047()*+,-./"
|
|
ascii = ascii "0123456789:;<=>?"
|
|
ascii = ascii "@ABCDEFGHIJKLMNO"
|
|
ascii = ascii "PQRSTUVWXYZ[\\]^_"
|
|
ascii = ascii "`abcdefghijklmno"
|
|
ascii = ascii "pqrstuvwxyz{|}~"
|
|
for ( c = 0; c <= 255; ++c )
|
|
if ( 32 <= c && c <= 126 ) # 32=space 126=tilda
|
|
chr[ sprintf("%02X", c) ] = substr( ascii, c - 32+1, 1 )
|
|
else
|
|
chr[ sprintf("%02X", c) ] = "."
|
|
}
|
|
/WRx/ || /RDx/ {
|
|
if ( $1 == "WRx" || $1 == "RDx" ) {
|
|
if ( $1 == "WRx" ) dir = "WRa"
|
|
else dir = "RDa"
|
|
beghex = 3
|
|
} else {
|
|
if ( $2 == "WRx" ) dir = "WRa"
|
|
else dir = "RDa"
|
|
beghex = 4
|
|
}
|
|
ascblk = chr[$(beghex)]
|
|
for ( i = beghex+1; i <= NF; ++i )
|
|
ascblk = ascblk " " chr[$i]
|
|
print
|
|
if ( beghex == 3 )
|
|
printf( "%s %2d\t %s\n", dir, $2, ascblk )
|
|
else
|
|
printf( "%s %s %2d\t %s\n", $1, dir, $3, ascblk )
|
|
}' -
|
|
}
|
|
|
|
# convert 'portmon' logfile
|
|
# expects 'portmon' logfiles in Unix-format i.e. NL terminated lines
|
|
# (DOS-format CRLF terminated lines may break the awk script)
|
|
# for 'portmon' see http://www.sysinternals.com
|
|
#
|
|
ic35prot() # [-vskip=3] [-vDEBUG=1] <portmon_logfile >hex_logfile
|
|
{
|
|
awk $* '
|
|
# parameters
|
|
# skip number of leading bytes to skip from transmitted blocks
|
|
# blocks up to this much bytes are not printed, default 0
|
|
# stamp if non-zero/non-empty stamp transmit blocks with id (first
|
|
# field) from portmon log, to ease finding portmon log lines
|
|
# default: 0 / "" (disabled)
|
|
# MAXBPL maximum number of bytes to print per output line
|
|
# default: 128
|
|
# DEBUG if non-zero/non-empty print verbose debugging output
|
|
# default: 0 / "" (disabled)
|
|
|
|
# extract transmitted data bytes
|
|
# returns:
|
|
# -1 no data bytes: miss "Length" field
|
|
# 0 no data bytes: length value == 0
|
|
# > 0 length value
|
|
# xdlen number of logged bytes, maybe < length value
|
|
# xdata logged transmitted data bytes
|
|
#
|
|
function getxdata()
|
|
{
|
|
xlen = 0
|
|
xdata = ""
|
|
# search "Length" field
|
|
for ( i = 1; i <= NF; ++i )
|
|
if ( $i ~ "^Length" )
|
|
break
|
|
if ( i > NF ) { # "Length" field not found
|
|
# check if log from "ic35sync"
|
|
for ( i = 1; i <= NF; ++i )
|
|
if ( $i ~ "^[0-9A-F][0-9A-F][0-9A-F][0-9A-F]:$" )
|
|
break;
|
|
if ( i > NF )
|
|
return -1
|
|
# process log from "ic35sync"
|
|
xdata = ""
|
|
for ( i = i+1; i <= NF; ++i ) {
|
|
if ( $i !~ "^[0-9A-F][0-9A-F]$" )
|
|
break;
|
|
xdata = xdata $i " "
|
|
if ( --hadxmit == 0 )
|
|
break;
|
|
}
|
|
xdlen = length( xdata ) / 3
|
|
return xdlen
|
|
}
|
|
# get length value from next field, remove trail ":"
|
|
split( $(i+1), flds, ":" )
|
|
len = int( flds[1] )
|
|
if ( len == 0 )
|
|
return 0 # no data transmitted
|
|
# extract get data bytes after "Length" and <nn:>
|
|
lentxt = $(i) " " $(i+1)
|
|
xdata = substr( $0, index($0, lentxt) + length(lentxt)+1 )
|
|
# make string of 2dig-hex with trail " " for append
|
|
sub( "^[^0-9A-Fa-f]*", "", xdata ); # remove leading garbage
|
|
sub( "[^0-9A-Fa-f]*$", "", xdata ); # remove trailing garbage
|
|
xdata = xdata " "
|
|
xdlen = length( xdata ) / 3
|
|
# return length value, maybe not all bytes logged
|
|
return len
|
|
}
|
|
|
|
function prxdata( dir, xbuf, xlen,
|
|
_offs, _i, _hex, _pbuf, _plen )
|
|
{
|
|
if ( xlen <= skip )
|
|
return
|
|
_plen = length( xbuf )
|
|
_offs = skip * 3
|
|
if ( skip >= 3 )
|
|
_plen = length( xbuf ) - _offs - 2 * 3 # skip checksum also
|
|
printf( "%s%sx %2d\t%s\n", xstamp, dir, xlen, substr(xbuf,_offs,_plen) )
|
|
}
|
|
|
|
BEGIN {
|
|
# max.number of bytes per output line
|
|
if ( ! MAXBPL ) MAXBPL = 128
|
|
}
|
|
|
|
NF >= 2 {
|
|
if ( $2 == "ic35sync" || $2 == "ic35mgr" )
|
|
tsecs = $1
|
|
else
|
|
tsecs += $2
|
|
}
|
|
# Windows-98:
|
|
# 35 0.00034960 Ic35 syn VCOMM_ReadComm COM1 SUCCESS Length: 1: 57
|
|
/VCOMM_ReadComm/ && /SUCCESS/ {
|
|
if ( oldxdir == "WR" ) do_print = 1
|
|
xdir = "RD"
|
|
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
|
}
|
|
# 36 0.00005040 Ic35 syn VCOMM_GetCommQueueStatus COM1 SUCCESS RX: 6 TX: 0
|
|
/VCOMM_GetCommQueueStatus/ {
|
|
if ( DEBUG ) print "DBG: next ", $0
|
|
next
|
|
}
|
|
# 58 0.00063840 Ic35 syn VCOMM_WriteComm COM1 SUCCESS Length: 1: 41
|
|
/VCOMM_WriteComm/ {
|
|
if ( oldxdir == "RD" ) do_print = 1
|
|
xdir = "WR"
|
|
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
|
}
|
|
|
|
# Windows-NT:
|
|
# 22 0.00106488 IC35Mgr.exe IRP_MJ_READ Serial1 SUCCESS Length 1: 80
|
|
# 16 0.00000000 IC35 Sync.exe IRP_MJ_READ Serial0 Length 1
|
|
# 16 0.00000953 SUCCESS Length 1: 57
|
|
/IRP_MJ_READ/ {
|
|
if ( oldxdir == "WR" ) do_print = 1
|
|
if ( $0 ~ "SUCCESS" ) {
|
|
xdir = "RD"
|
|
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
|
} else if ( $0 !~ "TIMEOUT" ) {
|
|
hadread = 1
|
|
if ( DEBUG ) print "DBG: hadread", $0
|
|
} else {
|
|
do_print = 1
|
|
}
|
|
}
|
|
# 16 0.00000953 SUCCESS Length 1: 57
|
|
/SUCCESS/ && hadread {
|
|
xdir = "RD"
|
|
hadread = 0
|
|
if ( DEBUG ) print "DBG: dlyd RD", $0
|
|
}
|
|
# 15 0.07746540 TIMEOUT Length 0:
|
|
/TIMEOUT/ && hadread {
|
|
do_print = 1
|
|
}
|
|
# 419 0.00000000 IC35 Sync.exe IOCTL_SERIAL_CLR_DTR Serial0
|
|
/IOCTL_SERIAL_CLR_DTR/ {
|
|
do_print = 1
|
|
}
|
|
# 3 0.00000000 IC35 Sync.exe IRP_MJ_WRITE Serial0 Length 1: 41
|
|
/IRP_MJ_WRITE/ {
|
|
if ( oldxdir == "RD" ) do_print = 1
|
|
hadread = 0
|
|
xdir = "WR"
|
|
if ( DEBUG ) print "DBG: xdir=" xdir, $0
|
|
}
|
|
|
|
# ic35sync/Linux
|
|
# 01:11:48.3206 ic35sync 6 com_send(0x8055180,19) = 19
|
|
# 01:11:48.3206 ic35sync 6 0000: 02 13 00 83 0E 00 49 0B 00 01 07 03 00 00 00 00
|
|
# 01:11:48.3206 ic35sync 6 0010: 00 05 01
|
|
/ com_send\(/ {
|
|
if ( oldxdir == "RD" ) do_print = 1
|
|
hadxmit = $NF
|
|
xmitdir = "WR"
|
|
}
|
|
# 01:11:48.3703 ic35sync 6 com_recv(0xbffff89b,1) = 1
|
|
# 01:11:48.3703 ic35sync 6 0000: F2
|
|
# 01:11:48.3706 ic35sync 6 com_recv(0x8055181,2) = 2
|
|
# 01:11:48.3706 ic35sync 6 0000: 10 00
|
|
# 01:11:48.3800 ic35sync 6 com_recv(0x8055183,13) = 13
|
|
# 01:11:48.3800 ic35sync 6 0000: A0 0B 00 49 08 00 0A 00 00 06 20 2E 02
|
|
/ com_recv\(/ {
|
|
if ( oldxdir == "WR" ) do_print = 1
|
|
hadxmit = $NF
|
|
xmitdir = "RD"
|
|
}
|
|
/ [0-9A-F][0-9A-F][0-9A-F][0-9A-F]: / && hadxmit {
|
|
xdir = xmitdir
|
|
}
|
|
|
|
DEBUG {
|
|
print "DBG1: old,xdir=" oldxdir "," xdir, "xbuff=" xblen, "\047" xbuff "\047"
|
|
}
|
|
do_print {
|
|
prxdata( oldxdir, xbuff, xblen )
|
|
if ( txlen > xblen ) {
|
|
txdir = (oldxdir == "WR" ? "Wx " : "Rx ")
|
|
print txdir txlen
|
|
}
|
|
xbuff = ""
|
|
xblen = txlen = 0
|
|
do_print = 0
|
|
}
|
|
xdir {
|
|
if ( DEBUG ) print "DBG: do_x=" xdir, $0
|
|
xlen = getxdata() # get transmit data to xdata,xdlen
|
|
if ( xlen <= 0 )
|
|
next # no transmit / timeout
|
|
if ( xblen == 0 && stamp ) {
|
|
if ( stamp == 2 )
|
|
if ( tsecs ~ ":" )
|
|
xstamp = tsecs " "
|
|
else
|
|
xstamp = sprintf( "%010.4f ", tsecs )
|
|
else
|
|
xstamp = sprintf( "%05d\t", $1 )
|
|
}
|
|
xbuff = xbuff xdata # buffer transmit data
|
|
xblen += xlen
|
|
txlen += xlen
|
|
if ( xdlen != xlen || xblen >= MAXBPL ) { # not all logged or too much
|
|
prxdata( xdir, xbuff, xblen )
|
|
xbuff = ""
|
|
xblen = 0
|
|
}
|
|
oldxdir = xdir
|
|
xdir = ""
|
|
}
|
|
DEBUG {
|
|
print "DBG2: old,xdir=" oldxdir "," xdir, "xbuff=" xblen, "\047" xbuff "\047"
|
|
}
|
|
' -
|
|
}
|
|
|
|
# decode IC35sync Level-4 protocol
|
|
# expects output from ic35prot()
|
|
#
|
|
ic35L4prot() # [-vDEBUG=1] <hex_logfile >L4prot_logfile
|
|
{
|
|
awk $* '
|
|
# parameters
|
|
# DEBUG if non-zero/non-empty print verbose debugging output
|
|
# default: 0 / "" (disabled)
|
|
|
|
BEGIN {
|
|
# create table chr[] for hex to char conversion
|
|
ascii = ascii " !\"#$%&\047()*+,-./"
|
|
ascii = ascii "0123456789:;<=>?"
|
|
ascii = ascii "@ABCDEFGHIJKLMNO"
|
|
ascii = ascii "PQRSTUVWXYZ[\\]^_"
|
|
ascii = ascii "`abcdefghijklmno"
|
|
ascii = ascii "pqrstuvwxyz{|}~"
|
|
for ( c = 0; c <= 255; ++c ) {
|
|
xc = sprintf("%02X", c)
|
|
if ( 32 <= c && c <= 126 ) # 32=space 126=tilda
|
|
chr[ xc ] = substr( ascii, c - 32+1, 1 )
|
|
else
|
|
chr[ xc ] = "\\x" xc
|
|
}
|
|
}
|
|
|
|
# get block of bytes from hex transmit data
|
|
# convert to ASCII and enclose in " quotes
|
|
#
|
|
function ascblk( beg, len, _end, _blk, _i )
|
|
{
|
|
if ( (_end = beg + len-1) > NF )
|
|
_end = NF # truncate to end of input line
|
|
_blk = "\""
|
|
for ( _i = beg; _i <= _end; ++_i )
|
|
_blk = _blk chr[ $_i ]
|
|
_blk = _blk "\""
|
|
return _blk
|
|
}
|
|
|
|
# get byte block of bytes from hex transmit data
|
|
#
|
|
function hexblk( beg, len, _end, _blk, _i )
|
|
{
|
|
if ( (_end = beg + len-1) > NF )
|
|
_end = NF # truncate to end of input line
|
|
_blk = $beg
|
|
for ( _i = beg+1; _i <= _end; ++_i )
|
|
_blk = _blk " " $_i
|
|
return _blk
|
|
}
|
|
|
|
# convert hex strings to decimal
|
|
#
|
|
function hex2dec( hexstr, _xval, _xdig, _i )
|
|
{
|
|
if ( hexstr ~ "^0[Xx]" )
|
|
hexstr = substr(hexstr, 3)
|
|
_xval = 0
|
|
for ( _i = 1; _i <= length(hexstr); ++_i ) {
|
|
_xdig = index( "0123456789ABCDEFabcdef", substr(hexstr, _i, 1) ) - 1
|
|
if ( _xdig < 0 )
|
|
break
|
|
if ( _xdig >= 16 )
|
|
_xdig -= 16 - 10
|
|
_xval = _xval * 16 + _xdig
|
|
}
|
|
return _xval
|
|
}
|
|
|
|
# decode field data from IC35 record
|
|
function recdata( beg, fid, _i, _recblk )
|
|
{
|
|
if ( fid != "" ) { # file-id specified: this the header fragment
|
|
nflens = 0
|
|
if ( fid == "05" ) nflens = 21 # Addresses
|
|
else if ( fid == "06" ) nflens = 4 # Memo
|
|
else if ( fid == "07" ) nflens = 8 # ToDoList
|
|
else if ( fid == "08" ) nflens = 10 # Schedule
|
|
if ( nflens == 0 ) {
|
|
printf( "ERR: recdata(beg=%s,fid=%s) unkown fid\n", beg, fid )
|
|
return ""
|
|
}
|
|
delete flens
|
|
for ( _i = 1; _i <= nflens; ++_i )
|
|
flens[_i] = hex2dec( $(beg+_i-1) )
|
|
fidx = 1
|
|
fldrest = 0
|
|
}
|
|
if ( fldrest ) { # partial last field from previous fragment
|
|
_recblk = " f" fidx-1 "=" ascblk( beg, fldrest )
|
|
sub( "=\"", "=<", _recblk )
|
|
_i = beg + fldrest
|
|
fldrest = 0
|
|
} else { # record data on field boundary
|
|
_recblk = ""
|
|
if ( fid != "" ) _i = beg + nflens # header fragment
|
|
else _i = beg # 2nd ff. fragment
|
|
}
|
|
while ( _i <= NF && fidx <= nflens ) {
|
|
_recblk = _recblk " f" fidx "=" ascblk( _i, flens[fidx] )
|
|
_i += flens[fidx++]
|
|
}
|
|
if ( _i != NF+1 ) { # partial last field
|
|
fldrest = _i - (NF+1)
|
|
sub( "\"$", ">", _recblk )
|
|
}
|
|
return _recblk
|
|
}
|
|
|
|
# WRx 43 80 26 00 10 00 64 00 4A 1F 00 49 4E 56 45 4E 54 45 43 ...
|
|
# WRx 14 83 09 00 49 06 00 02 00 00
|
|
# WRx 8 83 00 03
|
|
# RDx 46 A0 29 00 10 00 D0 07 4A 22 00 49 4E 56 45 4E 54 45 43 ...
|
|
# RDx 13 A0 08 00 49 05 00 03 01
|
|
# RDx 8 A0 03 00
|
|
# variables:
|
|
# type indicates command "Cmd" "C??" or response "Rsp" "R??"
|
|
# "C??","R??" flag PDU contents not matching current knowledge
|
|
# pi parameter index: PDU paramters begin at pi-th input field
|
|
# pdu PDU identification for output, e.g. "identify", "openfile"
|
|
# pars decoded parameters from PDU for output
|
|
# l2l3 concatenation of Level-2 and Level-3 id-bytes
|
|
# l4 Level-4 command
|
|
# l2l3l4 concatenation of l2l3 and l4
|
|
# printhex flag to also output the hex input (for debugging)
|
|
# may be set by some decoder, reset on every input block
|
|
# DEBUG global debug flag to also output the hex input
|
|
#
|
|
/^WRx/ || /^RDx/ {
|
|
if ( $1 == "WRx" ) {
|
|
type = "Cmd"
|
|
pi = 2+3+3+2 + 1 # command parameter index
|
|
} else { # "RDx"
|
|
type = "Rsp"
|
|
pi = 2+3+3 + 1 # response parameter index
|
|
}
|
|
printhex = 0
|
|
pdu = pars = l2l3 = l4 = l2l3l4 = ""
|
|
if ( NF >= 2+3+3 ) { # have L2- and L3 id-bytes
|
|
l2l3 = $3 $6
|
|
if ( NF >= 2+3+3+2 ) { # have also L4 command
|
|
l4 = $9 $10
|
|
l2l3l4 = l2l3 l4
|
|
}
|
|
# identify
|
|
if ( l2l3 == "8010" ) {
|
|
# AdsGetDeviceVersion ?
|
|
pdu = "identify"
|
|
} else if ( l2l3 == "A010" ) {
|
|
pdu = "identify"
|
|
pars = ascblk(pi+25, 99) # "DCS15" version
|
|
|
|
# power, passwd
|
|
} else if ( l2l3l4 == "8249" "0301" ) {
|
|
pdu = "power"
|
|
pars = ascblk(pi, 5) # "Power"
|
|
pars = pars " " hexblk(pi+5, 99) # 00 00 00
|
|
if ( pars != "\"Power\" 00 00 00" )
|
|
type = "C??"
|
|
} else if ( l2l3 == "A049" && lastcmd == "power" ) {
|
|
pdu = "power"
|
|
pars = $(pi) $(pi+1) # 0301
|
|
if ( pars != "0301" || NF+1 - pi != 2 )
|
|
type = "R??"
|
|
} else if ( l2l3l4 == "8249" "0300" ) {
|
|
pdu = "passwd"
|
|
pars = ascblk(pi, 8) # [password]
|
|
if ( NF+1 - pi != 8 )
|
|
type = "C??"
|
|
} else if ( l2l3 == "A049" && lastcmd == "passwd" ) {
|
|
pdu = "passwd"
|
|
pars = $(pi) $(pi+1) # 0101
|
|
if ( pars != "0101" || NF+1 - pi != 2 )
|
|
type = "R??"
|
|
|
|
# getdtime, setdtime
|
|
} else if ( l2l3l4 == "8349" "0200" ) {
|
|
# AdsReadSysInfo ?
|
|
pdu = "getdtime"
|
|
pars = hexblk(pi, 99) # 00
|
|
if ( pars != "00" )
|
|
type = "C??"
|
|
} else if ( l2l3 == "A049" && lastcmd == "getdtime" ) {
|
|
pdu = "dtime"
|
|
pars = ascblk(pi, 14) # [mmddyyyyhhmmss]
|
|
tail = hexblk(pi+14, 99) # 00 00
|
|
if ( tail != "00 00" ) {
|
|
pars = pars " " tail
|
|
type = "R??"
|
|
}
|
|
} else if ( l2l3l4 == "8249" "0201" ) {
|
|
# AdsWriteSysInfo ?
|
|
pdu = "setdtime"
|
|
head = hexblk(pi, 1) # 00
|
|
pars = ascblk(pi+1, 14) # [mmddyyyyhhmmss]
|
|
tail = hexblk(pi+1+14, 99) # 00 00
|
|
if ( head != "00" && tail != "00 00" ) {
|
|
pars = head " " pars " " tail
|
|
type = "C??"
|
|
}
|
|
# response "A0"
|
|
# pdu = "done" below
|
|
|
|
# category
|
|
} else if ( l2l3l4 == "8249" "0302" ) {
|
|
# AdsReadCategoryData ?
|
|
pdu = "category"
|
|
pars = ascblk(pi, 8) # [category]
|
|
if ( NF+1 - pi != 8 )
|
|
type = "C??"
|
|
} else if ( l2l3 == "A049" && lastcmd == "category" ) {
|
|
pdu = "category"
|
|
pars = $(pi) $(pi+1)
|
|
if ( NF+1 - pi != 2 )
|
|
type = "R??"
|
|
|
|
# openfile, closefile
|
|
} else if ( l2l3l4 == "8249" "0002" ) {
|
|
# AdsOpenDataBase ?
|
|
pdu = "openfile"
|
|
head = hexblk( pi, 7 )
|
|
lf2 = hex2dec( $(pi+10) $(pi+9) $(pi+8) $(pi+7) )
|
|
lf = hex2dec( $(pi+11) )
|
|
fn = ascblk(pi+12, lf)
|
|
tail = hexblk( pi+12+lf, 99 )
|
|
if ( length( fn ) == lf + 2 \
|
|
&& lf2 == lf + 2 \
|
|
&& head == "00 00 00 00 00 00 00" \
|
|
&& tail == "02" )
|
|
pars = fn
|
|
else {
|
|
pars = head " lf2=" lf2 " lf=" lf " " fn " " tail
|
|
type = "C??"
|
|
}
|
|
# set current file-id, to determine num.of record fields
|
|
if ( fn ~ "Addresses" ) currfid = "05"
|
|
else if ( fn ~ "Memo" ) currfid = "06"
|
|
else if ( fn ~ "To Do List" ) currfid = "07"
|
|
else if ( fn ~ "Schedule" ) currfid = "08"
|
|
|
|
} else if ( l2l3 == "A049" && lastcmd == "openfile" ) {
|
|
pdu = "openfile"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
if ( NF+1 - pi != 2 )
|
|
type = "R??"
|
|
} else if ( l2l3l4 == "8249" "0003" ) {
|
|
# AdsCloseDataBase ? AdsCloseHandle ?
|
|
pdu = "closefile"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
tail = hexblk( pi+2, 99 )
|
|
if ( tail != "00 00 00 00" ) {
|
|
pars = pars " " tail
|
|
type = "C??"
|
|
}
|
|
# unset current file-id on close
|
|
currfid = ""
|
|
# response "A0"
|
|
# pdu = "done" below
|
|
|
|
# getflen
|
|
} else if ( l2l3l4 == "8349" "0103" ) {
|
|
# AdsGetRecordCount
|
|
pdu = "getflen"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
tail = hexblk( pi+2, 99 )
|
|
if ( tail != "00 00 00 00" ) {
|
|
pars = pars " " tail
|
|
type = "C??"
|
|
}
|
|
} else if ( l2l3l4 == "8349" "0104" ) {
|
|
# AdsGetModifiedRecordCount
|
|
pdu = "getflenmod"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
tail = hexblk( pi+2, 99 )
|
|
if ( tail != "00 00 00 00" ) {
|
|
pars = pars " " tail
|
|
type = "C??"
|
|
}
|
|
} else if ( l2l3 == "A049" && (lastcmd == "getflen" \
|
|
|| lastcmd == "getflenmod") ) {
|
|
pdu = lastcmd
|
|
pars = "n=" hex2dec( $(pi+1) ($pi) )
|
|
if ( NF+1 - pi != 2 )
|
|
type = "R??"
|
|
|
|
# read record
|
|
} else if ( l2l3l4 == "8349" "0105" ) {
|
|
# AdsReadRecordByID
|
|
pdu = "readrecrid"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
pars = pars " ri=" $(pi+3) $(pi+2)
|
|
pars = pars " " $(pi+4)
|
|
pars = pars " fi=" $(pi+5)
|
|
reqrid = hex2dec( $(pi+5) $(pi+4) $(pi+3) $(pi+2) )
|
|
if ( NF+1 - pi != 6 )
|
|
type = "C??"
|
|
} else if ( l2l3l4 == "8349" "0106" ) {
|
|
# AdsReadRecordByIndex
|
|
pdu = "readrec"
|
|
reqrid = ""
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
pars = pars " ix=" hex2dec( $(pi+3) $(pi+2) )
|
|
tail = hexblk( pi+4, 99 )
|
|
if ( tail != "00 00" ) {
|
|
pars = pars " " tail
|
|
type = "C??"
|
|
}
|
|
} else if ( l2l3l4 == "8349" "0107" ) {
|
|
# AdsReadNextModifiedRecord
|
|
pdu = "readrecmod"
|
|
reqrid = ""
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
tail = hexblk(pi+2, 99)
|
|
if ( NF+1 - pi != 6 || tail != "00 00 00 00" ) {
|
|
pars = pars " " tail
|
|
type = "C??"
|
|
}
|
|
} else if ( (l2l3 == "A049" \
|
|
|| l2l3 == "2048") && (lastcmd == "readrec" \
|
|
|| lastcmd == "readrecmod" \
|
|
|| lastcmd == "readrecrid") ) {
|
|
pdu = "rechdr" (l2l3 == "2048" ? "(more)" : "(last)")
|
|
rsprid = hex2dec( $(pi+3) $(pi+2) $(pi+1) $(pi) )
|
|
pars = "ri=" $(pi+1) $(pi)
|
|
pars = pars " " $(pi+2)
|
|
pars = pars " fi=" $(pi+3)
|
|
pars = pars " ch=" $(pi+4)
|
|
if ( NF+1 - pi == 5 )
|
|
pars = pars " (nodata)"
|
|
else if ( lastcmd == "readrecrid" && rsprid != reqrid )
|
|
pars = pars " notfound (" NF+1 - (pi+5) " bytes garbage)"
|
|
else
|
|
pars = pars " " recdata( pi+5, $(pi+3) )
|
|
reqrid = ""
|
|
} else if ( (l2l3 == "A049" \
|
|
|| l2l3 == "2048") && lastcmd == "readmore" ) {
|
|
pdu = "recdat" (l2l3 == "2048" ? "(more)" : "(last)")
|
|
pars = " "
|
|
pars = pars " " recdata( pi, "" )
|
|
|
|
# write record
|
|
} else if ( l2l3l4 == "0248" "0108" \
|
|
|| l2l3l4 == "8249" "0108" ) {
|
|
# AdsWriteRecord
|
|
pdu = "writerec" (l2l3 == "0248" ? "(more)" : "(last)")
|
|
fdesc = $(pi+1) $(pi)
|
|
zero1 = hexblk(pi+2, 4)
|
|
p678 = hexblk(pi+6, 3)
|
|
zero2 = hexblk(pi+9, 2)
|
|
lrec = hex2dec( $(pi+14) $(pi+13) $(pi+12) $(pi+11) )
|
|
if ( zero1 == "00 00 00 00" && zero2 == "00 00" ) {
|
|
pars = "fd=" fdesc " " p678 " lr=" lrec
|
|
pars = pars " " recdata( pi+15, currfid )
|
|
} else {
|
|
pars = "fd=" fdesc " " zero1 " " p678 " " zero2 " lr=" lrec
|
|
pars = pars " " recdata( pi+15, currfid )
|
|
type = "C??"
|
|
}
|
|
# update record
|
|
} else if ( l2l3l4 == "0248" "0109" \
|
|
|| l2l3l4 == "8249" "0109" ) {
|
|
# AdsUpdateRecord
|
|
pdu = "updatrec" (l2l3 == "0248" ? "(more)" : "(last)")
|
|
pars1 = "fd=" $(pi+1) $(pi)
|
|
pars1 = pars1 " ri=" $(pi+3) $(pi+2)
|
|
pars1 = pars1 " " $(pi+4)
|
|
pars1 = pars1 " fi=" $(pi+5)
|
|
pars1 = pars1 " " hexblk(pi+6, 3)
|
|
zero2 = hexblk(pi+9, 2)
|
|
pars2 = " lr=" hex2dec( $(pi+14) $(pi+13) $(pi+12) $(pi+11) )
|
|
if ( zero2 == "00 00" ) {
|
|
pars = pars1 pars2
|
|
pars = pars " " recdata( pi+15, currfid )
|
|
} else {
|
|
pars = pars1 " " zero2 pars2
|
|
pars = pars " " recdata( pi+15, currfid )
|
|
type = "C??"
|
|
}
|
|
} else if ( (l2l3 == "0248" \
|
|
|| l2l3 == "8249") && (lastcmd == "writerec(more)" \
|
|
|| lastcmd == "updatrec(more)") ) {
|
|
pdu = substr(lastcmd, 1, 8)
|
|
pdu = pdu (l2l3 == "0248" ? "(more)" : "(last)")
|
|
pars = " "
|
|
pars = pars " " recdata( pi-2, "" )
|
|
# response l2 == "90"
|
|
# pdu = "writemore" below
|
|
} else if ( l2l3 == "A049" && (lastcmd == "writerec(last)" \
|
|
|| lastcmd == "updatrec(last)") ) {
|
|
pdu = substr(lastcmd, 1, 8)
|
|
pars = "ri=" $(pi+1) $(pi)
|
|
pars = pars " " $(pi+2)
|
|
pars = pars " fi=" $(pi+3)
|
|
if ( NF+1 - pi != 4 )
|
|
type = "R??"
|
|
|
|
# delete record
|
|
} else if ( l2l3l4 == "8249" "0102" ) {
|
|
# AdsDeleteRecord
|
|
pdu = "deleterec"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
pars = pars " ri=" $(pi+3) $(pi+2)
|
|
pars = pars " " $(pi+4)
|
|
pars = pars " fi=" $(pi+5)
|
|
if ( NF+1 - pi != 6 || $(pi+4) != "00" )
|
|
type = "C??"
|
|
# response l2 == "A0"
|
|
# pdu = "done" below
|
|
|
|
# reset changeflag
|
|
} else if ( l2l3l4 == "8249" "010A" ) {
|
|
# AdsCommitRecord
|
|
pdu = "resetchg"
|
|
pars = "fd=" $(pi+1) $(pi)
|
|
pars = pars " ri=" $(pi+3) $(pi+2)
|
|
pars = pars " " $(pi+4)
|
|
pars = pars " fi=" $(pi+5)
|
|
if ( $(pi+4) != "00" || NF+1 - pi != 6 )
|
|
type = "C??"
|
|
# response l2 == "A0"
|
|
# pdu = "done" below
|
|
|
|
}
|
|
|
|
# short PDUs with Level-2 id-byte only
|
|
} else if ( NF == 2+3 ) {
|
|
if ( $3 == "83" ) {
|
|
pdu = "readmore"
|
|
} else if ( $3 == "90" ) {
|
|
pdu = "writemore"
|
|
} else if ( $3 == "81" ) {
|
|
pdu = "disconn"
|
|
} else if ( $3 == "A0" ) {
|
|
pdu = "done"
|
|
}
|
|
}
|
|
|
|
if ( $1 == "WRx" ) {
|
|
lastcmd = pdu
|
|
if ( pdu == "" ) type = "C??" # unknown command PDU
|
|
if ( type !~ "^C..$" )
|
|
print "INTERNAL ERROR"
|
|
} else { # "RDx"
|
|
lastrsp = pdu
|
|
if ( pdu == "" ) type = "R??" # unknown response PDU
|
|
if ( type !~ "^R..$" )
|
|
print "INTERNAL ERROR"
|
|
}
|
|
|
|
if ( type == "C??" || type == "R??" \
|
|
|| DEBUG || printhex )
|
|
print # show hex data for unknown PDU / params
|
|
printf( "%s %2d\t", type, $2 )
|
|
if ( pdu == "" ) {
|
|
for ( i = 3; i <= NF; ++i ) printf( " %s", $i )
|
|
printf( "\n" )
|
|
} else {
|
|
printf( " %-14s %s\n", pdu, pars )
|
|
}
|
|
}
|
|
' -
|
|
}
|
|
|
|
# process options
|
|
#
|
|
LEVEL=all
|
|
while getopts "l:s:aDh" OPT
|
|
do case $OPT in
|
|
l ) LEVEL=$OPTARG ;;# level of output
|
|
s ) STAMP="-vstamp=$OPTARG" ;;# prepend lineno/time stamp
|
|
a ) ASCII=1 ;;# also ASCII chars
|
|
D ) DEBUG="-vDEBUG=1" ; KEEPTMP=1 ;;# debug/diagnostic
|
|
h|? ) usage ;;# for other options give help and exit
|
|
esac
|
|
done
|
|
shift `expr $OPTIND - 1`
|
|
[ $# -eq 1 -o $# -eq 2 ] || usage
|
|
|
|
# the real work ..
|
|
#
|
|
case "$LEVEL" in
|
|
all)
|
|
PASS1="ic35prot $STAMP $DEBUG"
|
|
if [ -n "$ASCII" ]
|
|
then PASS2=showascii
|
|
else PASS2=cat
|
|
fi
|
|
;;
|
|
syn2)
|
|
PASS1="ic35prot -vskip=3 $DEBUG"
|
|
if [ -n "$ASCII" ]
|
|
then PASS2=showascii
|
|
else PASS2=cat
|
|
fi
|
|
;;
|
|
syn4)
|
|
PASS1="ic35prot -vskip=3"
|
|
PASS2="ic35L4prot $DEBUG"
|
|
;;
|
|
*)
|
|
echo "$PROGNAME -- unsupported output level: $LEVEL"
|
|
exit 1
|
|
esac
|
|
|
|
if [ $# -eq 2 ] ; then
|
|
if [ "$1" != "-" ] && expr "`file $1`" : '.*\<gzip.*' >/dev/null ; then
|
|
tar -xOzf $1 $2 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
|
else
|
|
tar -xOf $1 $2 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
|
fi
|
|
else
|
|
if [ "$1" != "-" ] && expr "`file $1`" : '.*\<gzip.*' >/dev/null ; then
|
|
zcat $1 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
|
else
|
|
cat $1 | tr -d '\015' | $PASS1 | $PASS2 | $PAGER
|
|
fi
|
|
fi
|