Zmodem protocol changes

This commit is contained in:
Michiel Broek 2006-03-18 18:32:22 +00:00
parent de58423731
commit 9d82aca2c3
5 changed files with 218 additions and 140 deletions

View File

@ -52,7 +52,7 @@ struct tchars oldtch, tch;
#endif #endif
int hanged_up = 0; int hanged_up = 0;
unsigned Baudrate = 2400; unsigned Baudrate = 9600; /* Default, set by first io_mode() call */
int current_mode = -1; int current_mode = -1;
@ -188,26 +188,29 @@ int io_mode(int fd, int n)
#ifdef USE_TERMIOS #ifdef USE_TERMIOS
case 2: case 2:
if (!did0) { if (!did0) {
did0 = TRUE;
tcgetattr(fd,&oldtty); tcgetattr(fd,&oldtty);
} }
tty = oldtty; tty = oldtty;
tty.c_iflag = 0; /* Transparant input */ tty.c_iflag = BRKINT | IXON;
tty.c_oflag = 0; /* Transparent output */ tty.c_oflag = 0; /* Transparent output */
tty.c_cflag &= ~( CSIZE | CSTOPB | PARENB | PARODD); /* Disable parity and all character sizes */ tty.c_cflag &= ~( CSIZE | PARENB ); /* Disable parity and all character sizes */
tty.c_cflag |= CS8 | CREAD | HUPCL | CLOCAL; tty.c_cflag |= CS8 | CREAD;
tty.c_lflag = 0; tty.c_lflag = (protocol == ZM_ZMODEM) ? 0 : ISIG;
tty.c_cc[VMIN] = 1; tty.c_cc[VINTR] = (protocol == ZM_ZMODEM) ? -1:030; /* Interrupt char */
tty.c_cc[VTIME] = 0; tty.c_cc[VQUIT] = -1; /* Quit char */
tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
tty.c_cc[VTIME] = 1;
tcsetattr(fd,TCSADRAIN,&tty); tcsetattr(fd,TCSADRAIN,&tty);
did0 = TRUE;
Baudrate = getspeed(cfgetospeed(&tty));
Syslog('t', "Baudrate = %d", Baudrate);
return 0; return 0;
case 1: case 1:
case 3: case 3:
if (!did0) { if (!did0) {
did0 = TRUE;
tcgetattr(fd,&oldtty); tcgetattr(fd,&oldtty);
#ifdef __linux__ #ifdef __linux__
Syslog('t', "iflag%s%s%s%s%s%s%s%s%s%s%s%s%s", Syslog('t', "iflag%s%s%s%s%s%s%s%s%s%s%s%s%s",
@ -313,37 +316,37 @@ int io_mode(int fd, int n)
(oldtty.c_lflag & NOFLSH) ? " NOFLSH":""); (oldtty.c_lflag & NOFLSH) ? " NOFLSH":"");
#endif #endif
} }
tty = oldtty; tty = oldtty;
tty.c_iflag = IGNBRK; tty.c_iflag = n==3 ? (IXON|IXOFF) : IXOFF;
if (n == 3) { /* with flow control */
tty.c_iflag |= IXOFF; /* Enable XON/XOFF flow control on input */
tty.c_cflag |= CRTSCTS; /* hardware flowcontrol */
}
/* /*
* Setup raw mode: no echo, noncanonical (no edit chars), * Setup raw mode: no echo, noncanonical (no edit chars),
* no signal generating chars, and no extended chars (^V, * no signal generating chars, and no extended chars (^V,
* ^O, ^R, ^W). * ^O, ^R, ^W).
*/ */
tty.c_lflag = 0; /* Transparant input */ tty.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
tty.c_oflag = 0; /* Transparent output */ // tty.c_lflag = 0; /* Transparant input */
tty.c_cflag &= ~( CSIZE | CSTOPB | PARENB | PARODD); /* Same baud rate, disable parity */ tty.c_oflag = 0; /* Transparent output */
tty.c_cflag |= CS8 | CREAD | HUPCL | CLOCAL;
tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ tty.c_cflag &= ~( CSIZE | PARENB ); /* Same baud rate, disable parity */
tty.c_cc[VTIME] = 0; tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 2; /* This many chars satisfies reads */
tty.c_cc[VTIME] = 1;
tcsetattr(fd,TCSADRAIN,&tty); tcsetattr(fd,TCSADRAIN,&tty);
Baudrate = getspeed(cfgetospeed(&tty)); Baudrate = getspeed(cfgetospeed(&tty));
Syslog('t', "Baudrate = %d", Baudrate); Syslog('t', "Baudrate = %d", Baudrate);
did0 = TRUE;
return 0; return 0;
case 0: case 0:
if (!did0) if (!did0)
return -1; return -1;
tcdrain (fd); /* wait until everything is sent */ tcdrain (fd); /* wait until everything is sent */
tcflush (fd,TCIOFLUSH); /* flush input queue */ tcflush (fd,TCIOFLUSH); /* flush input queue */
tcsetattr (fd,TCSADRAIN,&oldtty); tcsetattr (fd,TCSADRAIN,&oldtty); /* Restore */
tcflow (fd,TCOON); /* restart output */ tcflow (fd,TCOON); /* restart output */
return 0; return 0;
#endif #endif
@ -383,7 +386,7 @@ void sendbrk(void)
if (isatty(0)) { if (isatty(0)) {
#ifdef USE_TERMIOS #ifdef USE_TERMIOS
tcsendbreak(0, 0); tcsendbreak(0, 200);
#endif #endif
#ifdef USE_TERMIO #ifdef USE_TERMIO
ioctl(0, TCSBRK, 0); ioctl(0, TCSBRK, 0);

View File

@ -77,7 +77,6 @@ int Rxtimeout = 10; /* Seconds to wait for something, receiver */
char *txbuf=NULL; char *txbuf=NULL;
static int lastsent; /* Last char we sent */ static int lastsent; /* Last char we sent */
static int Not8bit; /* Seven bits seen on header */ static int Not8bit; /* Seven bits seen on header */
static char zsendline_tab[256];
extern unsigned Baudrate; extern unsigned Baudrate;
extern int zmodem_requested; extern int zmodem_requested;
@ -200,6 +199,9 @@ void zsbhdr(int type, char *shdr)
} }
BUFFER_FLUSH(); BUFFER_FLUSH();
if (type != ZDATA)
fflush(stdout);
} }
@ -272,6 +274,7 @@ void zshhdr(int type, char *shdr)
BUFFER_BYTE(021); BUFFER_BYTE(021);
BUFFER_FLUSH(); BUFFER_FLUSH();
fflush(stdout);
} }
@ -308,6 +311,9 @@ void zsdata(register char *buf, int length, int frameend)
BUFFER_BYTE(XON); BUFFER_BYTE(XON);
BUFFER_FLUSH(); BUFFER_FLUSH();
if (frameend != ZCRCG)
fflush(stdout);
} }
@ -322,10 +328,7 @@ void zsda32(register char *buf, int length, int frameend)
crc = 0xFFFFFFFFL; crc = 0xFFFFFFFFL;
for (;--length >= 0; ++buf) { for (;--length >= 0; ++buf) {
c = *buf & 0377; c = *buf & 0377;
if (c & 0140) zsendline(c);
BUFFER_BYTE(lastsent = c);
else
zsendline(c);
crc = updcrc32(c, crc); crc = updcrc32(c, crc);
} }
BUFFER_BYTE(ZDLE); BUFFER_BYTE(ZDLE);
@ -476,7 +479,7 @@ void garbitch(void)
int zgethdr(char *shdr) int zgethdr(char *shdr)
{ {
register int c, n, cancount, tmcount; register int c, n, cancount, tmcount;
int Zrwindow = 1024; int Zrwindow = 1400;
n = Zrwindow + Baudrate; n = Zrwindow + Baudrate;
Rxframeind = Rxtype = 0; Rxframeind = Rxtype = 0;
@ -488,10 +491,11 @@ again:
/* /*
* Return immediate ERROR if ZCRCW sequence seen * Return immediate ERROR if ZCRCW sequence seen
*/ */
if (((c = GETCHAR(Rxtimeout)) < 0) && (c != TIMEOUT)) // if (((c = GETCHAR(Rxtimeout)) < 0) && (c != TIMEOUT))
goto fifi; // goto fifi;
else { // else {
switch(c) { // switch(c) {
switch (c = GETCHAR(Rxtimeout)) {
case 021: case 021:
case 0221: goto again; case 0221: goto again;
case HANGUP: goto fifi; case HANGUP: goto fifi;
@ -539,7 +543,7 @@ agn2:
case ZPAD: /* This is what we want. */ case ZPAD: /* This is what we want. */
break; break;
} }
} // }
cancount = 5; cancount = 5;
splat: splat:
@ -566,7 +570,8 @@ splat:
c = zrhhdr(shdr); c = zrhhdr(shdr);
break; break;
case CAN: goto gotcan; case CAN: goto gotcan;
default: goto agn2; default: Syslog('z', "Zmodem: zgethdr got %d char", c);
goto agn2;
} }
for (n = 4; ++n < ZMAXHLEN; ) /* Clear unused hdr bytes */ for (n = 4; ++n < ZMAXHLEN; ) /* Clear unused hdr bytes */
@ -739,68 +744,36 @@ void zputhex(int c)
*/ */
void zsendline(int c) void zsendline(int c)
{ {
switch(zsendline_tab[(unsigned) (c&=0377)]) { switch (c &= 0377) {
case 0: BUFFER_BYTE(lastsent = c); case 0377:
break; lastsent = c;
case 1: BUFFER_BYTE(ZDLE); if (Zctlesc || Zsendmask[32]) {
c ^= 0100; BUFFER_BYTE(ZDLE); c = ZRUB1;
BUFFER_BYTE(lastsent = c); }
break; BUFFER_BYTE(c);
case 2: if ((lastsent & 0177) != '@') { break;
case ZDLE:
BUFFER_BYTE(ZDLE);
BUFFER_BYTE(lastsent = (c ^= 0100));
break;
case 021:
case 023:
case 0221:
case 0223:
BUFFER_BYTE(ZDLE);
c ^= 0100;
BUFFER_BYTE(lastsent = c); BUFFER_BYTE(lastsent = c);
} else { break;
BUFFER_BYTE(ZDLE); default:
c ^= 0100; if (((c & 0140) == 0) && (Zctlesc || Zsendmask[c & 037])) {
BUFFER_BYTE(ZDLE); c ^= 0100;
}
BUFFER_BYTE(lastsent = c); BUFFER_BYTE(lastsent = c);
}
break;
} }
} }
void zsendline_init(void)
{
int i;
Syslog('z', "zsendline_init() Zctlesc=%d", Zctlesc);
for (i = 0; i < 256; i++) {
if (i & 0140)
zsendline_tab[i] = 0;
else {
switch(i) {
case ZDLE:
case XOFF: /* ^Q */
case XON: /* ^S */
case (XOFF | 0200):
case (XON | 0200):
zsendline_tab[i]=1;
break;
case 020: /* ^P */
case 0220:
zsendline_tab[i]=1;
break;
case 015:
case 0215:
if (Zctlesc)
zsendline_tab[i]=1;
else
zsendline_tab[i]=2;
break;
default:
if (Zctlesc)
zsendline_tab[i]=1;
else
zsendline_tab[i]=0;
}
}
}
// zsendline_tab[255] = 1; /* IAC */
}
/* Decode two lower case hex digits into an 8 bit byte value */ /* Decode two lower case hex digits into an 8 bit byte value */
int zgethex(void) int zgethex(void)
{ {

View File

@ -22,7 +22,14 @@
#define ZBIN 'A' /* Binary frame indicator (CRC-16) */ #define ZBIN 'A' /* Binary frame indicator (CRC-16) */
#define ZHEX 'B' /* HEX frame indicator */ #define ZHEX 'B' /* HEX frame indicator */
#define ZBIN32 'C' /* Binary frame with 32 bit FCS */ #define ZBIN32 'C' /* Binary frame with 32 bit FCS */
#define ZBINR32 'D' /* RLE packed Binary frame with 32 bit FCS */
#define ZVBIN 'a' /* Binary frame indicator (CRC-16) */
#define ZVHEX 'b' /* HEX frame indicator */
#define ZVBIN32 'c' /* Binary frame with 32 bit FCS */
#define ZVBINR32 'd' /* RLE packed Binary frame with 32 bit FCS */
#define ZRESC 0176 /* RLE flag/escape character */
#define ZMAXHLEN 16 /* Max header information length NEVER CHANGE */ #define ZMAXHLEN 16 /* Max header information length NEVER CHANGE */
#define ZMAXSPLEN 1024 /* Max subpacket length NEVER CHANGE */
/* Frame types (see array "frametypes" in zm.c) */ /* Frame types (see array "frametypes" in zm.c) */
@ -75,19 +82,28 @@
#define ZP3 3 /* High order 8 bits of file position */ #define ZP3 3 /* High order 8 bits of file position */
/* Parameters for ZRINIT header */ /* Parameters for ZRINIT header */
#define ZRPXWN 8 /* 9th byte in header contains window size/256 */
#define ZRPXQQ 9 /* 10th to 14th bytes contain quote mask */
/* Bit Masks for ZRINIT flags byte ZF0 */ /* Bit Masks for ZRINIT flags byte ZF0 */
#define CANFDX 01 /* Rx can send and receive true FDX */ #define CANFDX 01 /* Rx can send and receive true FDX */
#define CANOVIO 02 /* Rx can receive data during disk I/O */ #define CANOVIO 02 /* Rx can receive data during disk I/O */
#define CANBRK 04 /* Rx can send a break signal */ #define CANBRK 04 /* Rx can send a break signal */
#define CANRLE 010 /* Receiver can decode RLE */
#define CANLZW 020 /* Receiver can uncompress */ #define CANLZW 020 /* Receiver can uncompress */
#define CANFC32 040 /* Receiver can use 32 bit Frame Check */ #define CANFC32 040 /* Receiver can use 32 bit Frame Check */
#define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */ #define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */
#define ESC8 0200 /* Receiver expects 8th bit to be escaped */ #define ESC8 0200 /* Receiver expects 8th bit to be escaped */
/* Bit Masks for ZRINIT flags byte ZF1 */ /* Bit Masks for ZRINIT flags byte ZF1 */
#define CANVHDR 01 /* Variable headers OK */
#define ZRRQWN 8 /* Receiver specified window size in ZRPXWN */
#define ZRRQQQ 16 /* Additional control chars to quote in ZRPXQQ */
#define ZRQNVH (ZRRQWN|ZRRQQQ) /* Variable len hdr reqd to access info */
/* Parameters for ZSINIT frame */ /* Parameters for ZSINIT frame */
#define ZATTNLEN 32 /* Max length of attention string */ #define ZATTNLEN 32 /* Max length of attention string */
#define ALTCOFF ZF1 /* Offset to alternate canit string, 0 if not used */
/* Bit Masks for ZSINIT flags byte ZF0 */ /* Bit Masks for ZSINIT flags byte ZF0 */
#define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */ #define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */
#define TESC8 0200 /* Transmitter expects 8th bit to be escaped */ #define TESC8 0200 /* Transmitter expects 8th bit to be escaped */
@ -115,7 +131,9 @@
#define ZTRLE 3 /* Run Length encoding */ #define ZTRLE 3 /* Run Length encoding */
/* Extended options for ZF3, bit encoded */ /* Extended options for ZF3, bit encoded */
#define ZXSPARS 64 /* Encoding for sparse file operations */ #define ZXSPARS 64 /* Encoding for sparse file operations */
#define ZCANVHDR 01 /* Variable headers OK */
/* Receiver window size override */ /* Receiver window size override */
#define ZRWOVR 4 /* byte position for receive window override/256 */
/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */ /* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */
#define ZCACK1 1 /* Acknowledge, then do command */ #define ZCACK1 1 /* Acknowledge, then do command */
@ -134,7 +152,7 @@ char Rxhdr[ZMAXHLEN]; /* Received header */
char Txhdr[ZMAXHLEN]; /* Transmitted header */ char Txhdr[ZMAXHLEN]; /* Transmitted header */
char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */
char *Altcan; /* Alternate canit string */ char *Altcan; /* Alternate canit string */
//char Zsendmask[33]; /* Additional control characters to mask */ char Zsendmask[33]; /* Additional control characters to mask */
int Zctlesc; int Zctlesc;
enum zm_type_enum { enum zm_type_enum {
@ -159,7 +177,6 @@ int zdlread(void);
void stohdr(int); void stohdr(int);
int rclhdr(register char *); int rclhdr(register char *);
char *protname(void); char *protname(void);
void zsendline_init(void);
void purgeline(int); void purgeline(int);
void canit(int); void canit(int);

View File

@ -88,7 +88,6 @@ int zmrcvfiles(int want1k, int wantg)
Syslog('+', "%s: start receive", protname()); Syslog('+', "%s: start receive", protname());
get_frame_buffer(); get_frame_buffer();
zsendline_init();
Rxtimeout = 10; Rxtimeout = 10;
if (secbuf == NULL) if (secbuf == NULL)

View File

@ -47,6 +47,7 @@ static int zfilbuf(void);
static int zsendfile(char*,int); static int zsendfile(char*,int);
static int zsendfdata(void); static int zsendfdata(void);
static int getinsync(int); static int getinsync(int);
void initzsendmsk(char *p);
static FILE *in; static FILE *in;
static int Eofseen; /* EOF seen on input set by zfilbuf */ static int Eofseen; /* EOF seen on input set by zfilbuf */
@ -61,14 +62,23 @@ static int blkopt; /* Override value for zmodem blklen */
static int errors; static int errors;
static int Lastsync; static int Lastsync;
static int bytcnt; static int bytcnt;
static int maxbytcnt;
static int Lrxpos=0; static int Lrxpos=0;
static int Lztrans=0; static int Lztrans=0;
static int Lzmanag=0; static int Lzmanag=0;
static int Lskipnocor=0; static int Lskipnocor=0;
static int Lzconv=0; static int Lzconv=0;
static int Beenhereb4; static int Beenhereb4;
static char Myattn[]={0}; static int Canseek = 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */
/*
* Attention string to be executed by receiver to interrupt streaming data
* when an error is detected. A pause (0336) may be needed before the
* ^C (03) or after it.
*/
static char Myattn[]={ 0 };
static int skipsize; static int skipsize;
static jmp_buf intrjmp; /* For the interrupt on RX CAN */
struct timeval starttime, endtime; struct timeval starttime, endtime;
struct timezone tz; struct timezone tz;
static int use8k = FALSE; static int use8k = FALSE;
@ -81,6 +91,16 @@ extern char *frametypes[];
extern unsigned Baudrate; extern unsigned Baudrate;
/* Called when ZMODEM gets an interrupt (^X) */
void onintr(int );
void onintr(int c)
{
signal(SIGINT, SIG_IGN);
Syslog('z', "Zmodem: got signal interrupt");
longjmp(intrjmp, -1);
}
int zmsndfiles(down_list *lst, int try8) int zmsndfiles(down_list *lst, int try8)
{ {
int rc, maxrc = 0; int rc, maxrc = 0;
@ -89,12 +109,12 @@ int zmsndfiles(down_list *lst, int try8)
Syslog('+', "Zmodem: start Zmodem%s send", try8 ? "-8K":""); Syslog('+', "Zmodem: start Zmodem%s send", try8 ? "-8K":"");
get_frame_buffer(); get_frame_buffer();
zsendline_init();
use8k = try8; use8k = try8;
protocol = ZM_ZMODEM; protocol = ZM_ZMODEM;
Rxtimeout = 60; Rxtimeout = 60;
bytcnt = maxbytcnt = -1;
if ((rc = initsend())) { if ((rc = initsend())) {
if (txbuf) if (txbuf)
free(txbuf); free(txbuf);
@ -132,7 +152,7 @@ int zmsndfiles(down_list *lst, int try8)
free(txbuf); free(txbuf);
txbuf = NULL; txbuf = NULL;
del_frame_buffer(); del_frame_buffer();
// io_mode(0, 1); io_mode(0, 1);
Syslog('z', "Zmodem: send rc=%d", maxrc); Syslog('z', "Zmodem: send rc=%d", maxrc);
return (maxrc < 2)?0:maxrc; return (maxrc < 2)?0:maxrc;
@ -144,7 +164,7 @@ static int initsend(void)
{ {
Syslog('z', "Zmodem: initsend"); Syslog('z', "Zmodem: initsend");
// io_mode(0, 1); io_mode(0, 1);
PUTSTR((char *)"rz\r"); PUTSTR((char *)"rz\r");
stohdr(0L); stohdr(0L);
zshhdr(ZRQINIT, Txhdr); zshhdr(ZRQINIT, Txhdr);
@ -266,19 +286,19 @@ int getzrxinit(void)
case ZRINIT: case ZRINIT:
Rxflags = 0377 & Rxhdr[ZF0]; Rxflags = 0377 & Rxhdr[ZF0];
Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
{ Zctlesc |= Rxflags & TESCCTL;
int old = Zctlesc; if (Rxhdr[ZF1] & ZRRQQQ) { /* Escape ctrls */
Zctlesc |= Rxflags & TESCCTL; initzsendmsk(Rxhdr + ZRPXQQ);
/* update table - was initialised to not escape */ Syslog('z', "Zmodem: requested ZRPXQQ");
if (Zctlesc && !old)
zsendline_init();
} }
Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
if ( !(Rxflags & CANFDX)) if ( !(Rxflags & CANFDX))
Txwindow = 0; Txwindow = 0;
Syslog('z', "Zmodem: Remote allowed Rxbuflen=%d", Rxbuflen); Syslog('z', "Zmodem: Rxbuflen=%d", Rxbuflen);
// io_mode(0, 2); /* Set cbreak, XON/XOFF, etc. */
signal(SIGINT, SIG_IGN);
io_mode(0, 2); /* Set cbreak, XON/XOFF, etc. */
/* Set initial subpacket length */ /* Set initial subpacket length */
if (blklen < 1024) { /* Command line override? */ if (blklen < 1024) { /* Command line override? */
@ -288,6 +308,8 @@ int getzrxinit(void)
blklen = 512; blklen = 512;
if (Baudrate > 2400) if (Baudrate > 2400)
blklen = 1024; blklen = 1024;
if (Baudrate < 300)
blklen = 1024;
} }
if (Rxbuflen && blklen>Rxbuflen) if (Rxbuflen && blklen>Rxbuflen)
blklen = Rxbuflen; blklen = Rxbuflen;
@ -337,7 +359,8 @@ int sendzsinit(void)
} else } else
zsbhdr(ZSINIT, Txhdr); zsbhdr(ZSINIT, Txhdr);
Syslog('z', "sendzsinit Myattn \"%s\"", printable(Myattn, 0)); Syslog('z', "sendzsinit Myattn \"%s\"", printable(Myattn, 0));
zsdata(Myattn, 1 + strlen(Myattn), ZCRCW); // zsdata(Myattn, 1 + strlen(Myattn), ZCRCW);
zsdata(Myattn, ZATTNLEN, ZCRCW);
c = zgethdr(Rxhdr); c = zgethdr(Rxhdr);
switch (c) { switch (c) {
case ZCAN: return TERROR; case ZCAN: return TERROR;
@ -375,9 +398,12 @@ int zfilbuf(void)
*/ */
int zsendfile(char *buf, int blen) int zsendfile(char *buf, int blen)
{ {
int c; int c, i, m, n;
register unsigned int crc = -1; register unsigned int crc = -1;
int lastcrcrq = -1; int lastcrcrq = -1;
int lastcrcof = -1;
int l;
char *p;
Syslog('z', "zsendfile %s (%d)", buf, blen); Syslog('z', "zsendfile %s (%d)", buf, blen);
for (errors=0; ++errors<11;) { for (errors=0; ++errors<11;) {
@ -414,15 +440,42 @@ again:
case ZNAK: case ZNAK:
continue; continue;
case ZCRC: case ZCRC:
if (Rxpos != lastcrcrq) { l = Rxhdr[9] & 0377;
l = (l<<8) + (Rxhdr[8] & 0377);
l = (l<<8) + (Rxhdr[7] & 0377);
l = (l<<8) + (Rxhdr[6] & 0377);
if (Rxpos != lastcrcrq || l != lastcrcof) {
lastcrcrq = Rxpos; lastcrcrq = Rxpos;
crc = 0xFFFFFFFFL; crc = 0xFFFFFFFFL;
fseek(in, 0L, 0); // fseek(in, 0L, 0);
while (((c = getc(in)) != EOF) && --lastcrcrq) // while (((c = getc(in)) != EOF) && --lastcrcrq)
crc = updcrc32(c, crc); // crc = updcrc32(c, crc);
crc = ~crc; // crc = ~crc;
clearerr(in); /* Clear possible EOF */ // clearerr(in); /* Clear possible EOF */
lastcrcrq = Rxpos; // lastcrcrq = Rxpos;
if (Canseek >= 0) {
fseek(in, bytcnt = l, 0); i = 0;
Syslog('z', "Zmodem: CRC32 on %ld bytes", Rxpos);
do {
/* No rx timeouts! */
if (--i < 0) {
i = 32768L/blklen;
PUTCHAR(SYN);
fflush(stdout);
}
bytcnt += m = n = zfilbuf();
if (bytcnt > maxbytcnt)
maxbytcnt = bytcnt;
for (p = txbuf; --m >= 0; ++p) {
c = *p & 0377;
crc = updcrc32(c, crc);
}
Syslog('z', "bytcnt=%d crc=%08X", bytcnt, crc);
} while (n && bytcnt < lastcrcrq);
crc = ~crc;
clearerr(in); /* Clear possible EOF */
}
} }
stohdr(crc); stohdr(crc);
zsbhdr(ZCRC, Txhdr); zsbhdr(ZCRC, Txhdr);
@ -441,7 +494,7 @@ again:
skipsize = Rxpos; skipsize = Rxpos;
if (fseek(in, Rxpos, 0)) if (fseek(in, Rxpos, 0))
return TERROR; return TERROR;
Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1; Lastsync = (maxbytcnt = bytcnt = Txpos = Lrxpos = Rxpos) -1;
return zsendfdata(); return zsendfdata();
} }
} }
@ -471,7 +524,8 @@ int zsendfdata(void)
junkcount = 0; junkcount = 0;
Beenhereb4 = 0; Beenhereb4 = 0;
somemore: somemore:
if (0) { // if (0) {
if (setjmp(intrjmp)) {
waitack: waitack:
junkcount = 0; junkcount = 0;
c = getinsync(0); c = getinsync(0);
@ -486,18 +540,18 @@ gotack:
return c; return c;
case ZACK: Syslog('z', "zmsend: got ZACK"); case ZACK: Syslog('z', "zmsend: got ZACK");
break; // Possible bug, added 23-08-99 break; // Possible bug, added 23-08-99
case ZRPOS: blklen = ((blklen >> 2) > 64) ? (blklen >> 2) : 64; case ZRPOS: /* blklen = ((blklen >> 2) > 64) ? (blklen >> 2) : 64;
goodblks = 0; goodblks = 0;
goodneeded = ((goodneeded << 1) > 16) ? 16 : goodneeded << 1; goodneeded = ((goodneeded << 1) > 16) ? 16 : goodneeded << 1;
Syslog('z', "zmsend: blocklen now %d", blklen); Syslog('z', "zmsend: blocklen now %d", blklen); */
break; break;
case TIMEOUT: /* Put back here 08-09-1999 mb */ // case TIMEOUT: /* Put back here 08-09-1999 mb */
Syslog('z', "zmsend: zsendfdata TIMEOUT"); // Syslog('z', "zmsend: zsendfdata TIMEOUT");
goto to; // goto to;
case HANGUP: /* New, added 08-09-1999 mb */ // case HANGUP: /* New, added 08-09-1999 mb */
Syslog('z', "zmsend: zsendfdata HANGUP"); // Syslog('z', "zmsend: zsendfdata HANGUP");
fclose(in); // fclose(in);
return c; // return c;
} }
/* /*
@ -520,7 +574,9 @@ gotack:
} }
} }
} }
to: //to:
signal(SIGINT, onintr);
newcnt = Rxbuflen; newcnt = Rxbuflen;
Txwcnt = 0; Txwcnt = 0;
stohdr(Txpos); stohdr(Txpos);
@ -544,12 +600,14 @@ to:
alarm_on(); alarm_on();
zsdata(txbuf, n, e); zsdata(txbuf, n, e);
bytcnt = Txpos += n; bytcnt = Txpos += n;
if (bytcnt > maxbytcnt)
maxbytcnt = bytcnt;
if ((blklen < maxblklen) && (++goodblks > goodneeded)) { // if ((blklen < maxblklen) && (++goodblks > goodneeded)) {
blklen = ((blklen << 1) < maxblklen) ? blklen << 1 : maxblklen; // blklen = ((blklen << 1) < maxblklen) ? blklen << 1 : maxblklen;
goodblks = 0; // goodblks = 0;
Syslog('z', "zmsend: blocklen now %d", blklen); // Syslog('z', "zmsend: blocklen now %d", blklen);
} // }
if (e == ZCRCW) if (e == ZCRCW)
goto waitack; goto waitack;
@ -591,7 +649,8 @@ to:
Syslog('z', "window = %ld", tcount); Syslog('z', "window = %ld", tcount);
} }
} while (!Eofseen); } while (!Eofseen);
signal(SIGINT, SIG_IGN);
for (;;) { for (;;) {
stohdr(Txpos); stohdr(Txpos);
zsbhdr(ZEOF, Txhdr); zsbhdr(ZEOF, Txhdr);
@ -599,6 +658,7 @@ egotack:
switch (getinsync(0)) { switch (getinsync(0)) {
case ZACK: Syslog('z', "zsendfdata() ZACK"); case ZACK: Syslog('z', "zsendfdata() ZACK");
goto egotack; // continue in old source goto egotack; // continue in old source
case ZNAK: continue;
case ZRPOS: goto somemore; case ZRPOS: goto somemore;
case ZRINIT: fclose(in); case ZRINIT: fclose(in);
return OK; return OK;
@ -630,10 +690,17 @@ int getinsync(int flag)
case ZCAN: case ZCAN:
case ZABORT: case ZABORT:
case ZFIN: case ZFIN:
case TERROR: /* case TERROR: */
case TIMEOUT: Syslog('+', "Zmodem: Got %s sending data", frametypes[c+FTOFFSET]); case TIMEOUT: Syslog('+', "Zmodem: Got %s sending data", frametypes[c+FTOFFSET]);
return TERROR; return TERROR;
case ZRPOS: /* ************************************* */ case ZRPOS: if (Rxpos > bytcnt) {
Syslog('z', "Zmodem: getinsync: Rxpos=%lx bytcnt=%lx Maxbytcnt=%lx",
Rxpos, bytcnt, maxbytcnt);
if (Rxpos > maxbytcnt)
Syslog('+', "Nonstandard Protocol at %lX", Rxpos);
return ZRPOS;
}
/* ************************************* */
/* If sending to a buffered modem, you */ /* If sending to a buffered modem, you */
/* might send a break at this point to */ /* might send a break at this point to */
/* dump the modem's buffer. */ /* dump the modem's buffer. */
@ -667,6 +734,7 @@ int getinsync(int flag)
case ZRINIT: return c; case ZRINIT: return c;
case ZSKIP: Syslog('+', "Zmodem: File skipped by receiver request"); case ZSKIP: Syslog('+', "Zmodem: File skipped by receiver request");
return c; return c;
case TERROR:
default: zsbhdr(ZNAK, Txhdr); default: zsbhdr(ZNAK, Txhdr);
continue; continue;
} }
@ -674,3 +742,21 @@ int getinsync(int flag)
} }
/*
* Set additional control chars to mask in Zsendmask
* according to bit array stored in char array at p
*/
void initzsendmsk(char *p)
{
int c;
for (c = 0; c < 33; ++c) {
if (p [c >> 3] & (1 << (c & 7))) {
Zsendmask[c] = 1;
Syslog('z', "Zmodem: escaping %02o", c);
}
}
}