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/deps/Xmodem/zmutil.c
2017-03-18 14:37:16 +10:00

409 lines
7.6 KiB
C

#ifndef lint
static const char rcsid[] = "$Id: zmutil.c,v 1.1.1.1 2001/03/08 00:01:48 efalk Exp $" ;
#endif
/*
* Copyright (c) 1995 by Edward A. Falk
*/
/**********
*
*
* @@@@@ @ @ @ @ @@@@@ @@@ @
* @ @@ @@ @ @ @ @ @
* @ @ @ @ @ @ @ @ @
* @ @ @ @ @ @ @ @ @
* @@@@@ @ @ @ @@@ @ @@@ @@@@@
*
* ZMUTIL - utilties used by zmodem protocol.
*
* Routines provided here:
*
*
* int ZXmitHdrHex(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in hex.
*
*
* int ZXmitHdrBin(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in binary.
*
*
* int ZXmitHdrBin32(type, data, info)
* int type ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header in binary with 32-bit crc.
*
*
* int ZXmitHdr(type, format, data, info)
* int type, format ;
* u_char data[4] ;
* ZModem *info ;
*
* transmit zmodem header
*
*
* int ZXmitData(format, data, len, term, info)
* int format, len ;
* u_char term ;
* u_char *data ;
* ZModem *info ;
*
* transmit buffer of data.
*
*
* u_long FileCrc(name)
* char *name ;
*
* compute 32-bit crc for a file, returns 0 on not found
*
*
* u_char *ZEnc4(n)
* u_long n ;
*
* convert u_long to 4 bytes.
*
* u_long ZDec4(buf)
* u_char buf[4] ;
*
* convert 4 bytes to u_long
*
*
*
* Edward A. Falk
*
* January, 1995
*
*
*
**********/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include "zmodem.h"
#include "crctab.h"
static char hexChars[] = "0123456789abcdef" ;
extern char *hdrnames[] ;
FILE *zmodemlogfile = NULL ;
/* put a number as two hex digits */
static u_char *
putHex( u_char *ptr, u_char c )
{
*ptr++ = hexChars[(c>>4)&0xf] ;
*ptr++ = hexChars[c&0xf] ;
return ptr ;
}
/* put a number with ZDLE escape if needed */
u_char *
putZdle( register u_char *ptr, register u_char c, register ZModem *info )
{
register u_char c2 = c & 0177 ;
if( c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 ||
c2 == 0177 || (c2 == 015 && info->atSign) ||
#ifdef COMMENT
c2 == 035 || (c2 == '~' && info->lastCR) ||
#endif /* COMMENT */
c2 == 035 ||
(c2 < 040 && info->escCtrl) )
{
*ptr++ = ZDLE ;
if( c == 0177 )
*ptr = ZRUB0 ;
else if( c == 0377 )
*ptr = ZRUB1 ;
else
*ptr = c^0100 ;
}
else
*ptr = c ;
info->atSign = c2 == '@' ;
info->lastCR = c2 == '\r' ;
return ++ptr ;
}
int
ZXmitHdrHex( int type, u_char data[4], ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_int crc ;
int i ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZHEX ;
ptr = putHex(ptr, type) ; crc = updcrc(type, 0) ;
for( i=4; --i >= 0; ++data ) {
ptr = putHex(ptr, *data) ;
crc = updcrc(*data, crc) ;
}
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putHex(ptr, (crc>>8)&0xff) ;
ptr = putHex(ptr, crc&0xff) ;
*ptr++ = '\r' ;
*ptr++ = '\n' ;
if( type != ZACK && type != ZFIN )
*ptr++ = XON ;
return ZXmitStr(buffer, ptr-buffer, info) ;
}
int
ZXmitHdrBin( int type, u_char data[4], register ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_int crc ;
int len ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZBIN ;
ptr = putZdle(ptr, type, info) ; crc = updcrc(type, 0) ;
for( len=4; --len >= 0; ++data ) {
ptr = putZdle(ptr, *data, info) ;
crc = updcrc(*data, crc) ;
}
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putZdle(ptr, (crc>>8)&0xff, info) ;
ptr = putZdle(ptr, crc&0xff, info) ;
len = ptr-buffer ;
return ZXmitStr(buffer, len, info) ;
}
int
ZXmitHdrBin32( int type, u_char data[4], ZModem *info )
{
u_char buffer[128] ;
register u_char *ptr = buffer ;
register u_long crc ;
int len ;
zmodemlog("sending %s: %2.2x %2.2x %2.2x %2.2x = %lx\n",
hdrnames[type], data[0], data[1], data[2], data[3],
ZDec4(data)) ;
*ptr++ = ZPAD ;
*ptr++ = ZDLE ;
*ptr++ = ZBIN32 ;
ptr = putZdle(ptr, type, info) ; crc = UPDC32(type, 0xffffffffL) ;
for( len=4; --len >= 0; ++data ) {
ptr = putZdle(ptr, *data, info) ;
crc = UPDC32(*data, crc) ;
}
crc = ~crc ;
for(len=4; --len >= 0; crc >>= 8)
ptr = putZdle(ptr, crc&0xff, info) ;
len = ptr-buffer ;
return ZXmitStr(buffer, len, info) ;
}
int
ZXmitHdr( int type, int format, u_char data[4], ZModem *info)
{
if( format == ZBIN && info->crc32 )
format = ZBIN32 ;
switch( format ) {
case ZHEX:
return ZXmitHdrHex(type, data, info) ;
case ZBIN:
return ZXmitHdrBin(type, data, info) ;
case ZBIN32:
return ZXmitHdrBin32(type, data, info) ;
default:
return 0 ;
}
}
/* TODO: if input is not a file, need to keep old data
* for possible retransmission */
int
ZXmitData( int format, int len, u_char term, u_char *data, ZModem *info)
{
register u_char *ptr = info->buffer ;
register u_int crc ;
if( format == ZBIN && info->crc32 )
format = ZBIN32 ;
zmodemlog("ZXmiteData: fmt=%c, len=%d, term=%c\n", format, len, term) ;
crc = (format == ZBIN) ? 0 : 0xffffffff ;
while( --len >= 0 ) {
if( format == ZBIN )
crc = updcrc(*data, crc) ;
else
crc = UPDC32(*data, crc) ;
ptr = putZdle(ptr, *data++, info) ;
}
*ptr++ = ZDLE ;
if( format == ZBIN )
crc = updcrc(term, crc) ;
else
crc = UPDC32(term, crc) ;
*ptr++ = term ;
if( format == ZBIN ) {
crc = updcrc(0,crc) ; crc = updcrc(0,crc) ;
ptr = putZdle(ptr, (crc>>8)&0xff, info) ;
ptr = putZdle(ptr, crc&0xff, info) ;
}
else {
crc = ~crc ;
for(len=4; --len >= 0; crc >>= 8)
ptr = putZdle(ptr, crc&0xff, info) ;
}
return ZXmitStr(info->buffer, ptr-info->buffer, info) ;
}
/* compute 32-bit crc for a file, returns 0 on not found */
u_long
FileCrc( char *name )
{
u_long crc ;
FILE *ifile = fopen(name, "r") ;
int i ;
if( ifile == NULL ) /* shouldn't happen, since we did access(2) */
return 0 ;
crc = 0xffffffff ;
while( (i=fgetc(ifile)) != EOF )
crc = UPDC32(i, crc) ;
fclose(ifile) ;
return ~crc ;
}
u_char *
ZEnc4( u_long n )
{
static u_char buf[4] ;
buf[0] = n&0xff ; n >>= 8 ;
buf[1] = n&0xff ; n >>= 8 ;
buf[2] = n&0xff ; n >>= 8 ;
buf[3] = n&0xff ;
return buf ;
}
u_long
ZDec4( u_char buf[4] )
{
return buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24) ;
}
char *
sname2(ZMState state)
{
static char *names[] = {
"RStart", "RSinitWait", "RFileName", "RCrc", "RFile", "RData",
"RDataErr", "RFinish", "TStart", "TInit", "FileWait", "CrcWait",
"Sending", "SendWait", "SendDone", "SendEof", "TFinish",
"CommandData", "CommandWait", "StderrData", "Done", "YTStart",
"YTFile", "YTDataWait", "YTData", "YTEOF", "YTFin", "YRStart",
"YRDataWait", "YRData", "YREOF"} ;
return names[(int)state] ;
}
char *
sname(ZModem *info)
{
return sname2(info->state) ;
}
#ifdef DEBUG
void
zmodemlog(const char *fmt, ... )
{
va_list ap;
struct timeval tv ;
struct tm *tm ;
static int do_ts = 1 ;
if( zmodemlogfile == NULL )
return ;
if( do_ts ) {
gettimeofday(&tv, NULL) ;
tm = localtime(&tv.tv_sec) ;
fprintf(zmodemlogfile, "%2.2d:%2.2d:%2.2d.%2.2ld: ",
tm->tm_hour, tm->tm_min, tm->tm_sec,
tv.tv_usec/10000) ;
}
do_ts = strchr(fmt, '\n') != NULL ;
va_start(ap, fmt) ;
vfprintf(zmodemlogfile, fmt, ap) ;
va_end(ap) ;
}
#endif /* DEBUG */