home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
HEATH
/
HMSRC20.LBR
/
HM8.CZ
/
HM8.C
Wrap
Text File
|
2000-06-30
|
16KB
|
786 lines
/************************* START OF MODULE 8 ********************************/
/* rz.c By Chuck Forsberg modified for cp/m by Hal Maney */
#define C80
#include "hmodem80.h"
#include "zmodem.h"
int Tryzhdrtype; /* Header type to send corresponding to Last rx close */
wcreceive(filename)
char *filename;
{
char *grabmem();
static int c;
rlabel();
QuitFlag = FALSE;
Zctlesc = 0;
Baudrate = Baudtable[Current.cbaudindex];
Tryzhdrtype = ZRINIT;
Secbuf = alloc(KSIZE + 1);
if (allocerror(Secbuf))
return NERROR;
Cpmbuf = grabmem(&Cpbufsize);
if (allocerror(Cpmbuf))
return NERROR;
Cpindex = 0; /* just in case */
Rxtimeout = 100; /* 10 seconds */
Errors = 0;
#ifdef DEBUG
printf("\nbuffer size = %u\n",Cpbufsize);
#endif
savecurs();
hidecurs();
box();
if (filename==0) { /* batch transfer */
Crcflag=(Wcsmask==0377);
if (c=tryz()) { /* zmodem transfer */
report(PROTOCOL,"ZMODEM Receive");
if (c == ZCOMPL)
goto good;
if (c == NERROR)
goto fubar;
c = rzmfile();
if (c)
goto fubar;
}
else { /* ymodem batch transfer */
report(PROTOCOL,"YMODEM Receive");
report(BLKCHECK,Crcflag?"CRC":"Checksum");
for (;;) {
if (opabort())
goto fubar;
if (wcrxpn(Secbuf)== NERROR)
goto fubar;
if (Secbuf[0]==0)
goto good;
if (procheader(Secbuf) == NERROR)
goto fubar;
if (wcrx()==NERROR)
goto fubar;
}
}
}
else {
report(PROTOCOL,"XMODEM Receive");
strcpy(Pathname,filename);
checkpath(Pathname);
Fd=fopen(Pathname, "wb");
if (openerror(Fd,Pathname))
goto fubar1;
if (wcrx()==NERROR) /* xmodem */
goto fubar;
}
good:
free(Cpmbuf);
free(Secbuf);
showcurs();
restcurs();
return OK;
fubar:
canit();
if (Fd)
fclose(Fd);
fubar1:
free(Cpmbuf);
free(Secbuf);
showcurs();
restcurs();
return NERROR;
}
/*
* Fetch a pathname from the other end as a C ctyle ASCIZ string.
* Length is indeterminate as long as less than Blklen
* A null string represents no more files (YMODEM)
*/
wcrxpn(rpn)
char *rpn; /* receive a pathname */
{
static int c;
purgeline();
et_tu:
Firstsec=TRUE;
Eofseen=FALSE;
mcharout(Crcflag?WANTCRC:NAK);
while ((c = wcgetsec(rpn, 100)) != 0) {
if (QuitFlag)
return NERROR;
if (c == WCEOT) {
mcharout(ACK);
readline(INTRATIME);
goto et_tu;
}
return NERROR;
}
mcharout(ACK);
return OK;
}
/*
* Adapted from CMODEM13.C, written by
* Jack M. Wierda and Roderick W. Hart
*/
wcrx()
{
static int sectnum, sectcurr;
static char sendchar;
static char *p;
static int cblklen; /* bytes to dump this block */
Firstsec=TRUE;
sectnum=0;
Eofseen=FALSE;
sendchar=Crcflag?WANTCRC:NAK;
report(BLKCHECK,Crcflag?"CRC":"Checksum");
for (;;) {
if (opabort())
return NERROR;
mcharout(sendchar); /* send it now, we're ready! */
sectcurr = wcgetsec(Secbuf,Firstsec||(sectnum&0177)?50:130);
if (sectcurr==(sectnum+1 &Wcsmask)) {
sreport(++sectnum);
cblklen = Blklen;
if (putsec(Secbuf, cblklen)==NERROR)
return NERROR;
sendchar=ACK;
}
else if (sectcurr==(sectnum&Wcsmask)) {
zperr("Duplicate Sector",TRUE);
sendchar=ACK;
}
else if (sectcurr==WCEOT) {
if (closeit())
return NERROR;
mcharout(ACK);
return OK;
}
else if (sectcurr==NERROR)
return NERROR;
else {
zperr( "Sync Error",TRUE);
return NERROR;
}
}
}
/*
* Wcgetsec fetches a Ward Christensen type sector.
* Returns sector number encountered or NERROR if valid sector not received,
* or CAN CAN received
* or WCEOT if eot sector
* time is timeout for first char, set to 4 seconds thereafter
***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
* (Caller must do that when he is good and ready to get next sector)
*/
wcgetsec(rxbuf, maxtime)
char *rxbuf;
int maxtime;
{
static int checksum, wcj, firstch;
static unsigned oldcrc;
static char *p;
static int sectcurr;
static int tries;
for (Lastrx=Errors=0; Errors < RETRYMAX; ) { /* errors incr by zperr */
if (opabort())
return NERROR;
if ((firstch=readline(maxtime))==STX) {
Blklen=KSIZE;
goto get2;
}
if (firstch==SOH) {
Blklen=SECSIZ;
get2:
sectcurr=readline(INTRATIME);
if ((sectcurr+(oldcrc=readline(INTRATIME)))==Wcsmask) {
oldcrc=checksum=0;
for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
if ((firstch=readline(INTRATIME)) < 0)
goto bilge;
oldcrc=updcrc(firstch, oldcrc);
checksum += (*p++ = firstch);
}
if ((firstch=readline(INTRATIME)) < 0)
goto bilge;
if (Crcflag) {
oldcrc=updcrc(firstch, oldcrc);
if ((firstch=readline(INTRATIME)) < 0)
goto bilge;
oldcrc=updcrc(firstch, oldcrc);
if (oldcrc & 0xFFFF)
zperr( "CRC Error",TRUE);
else {
Firstsec=FALSE;
return sectcurr;
}
}
else if (((checksum-firstch)&Wcsmask)==0) {
Firstsec=FALSE;
return sectcurr;
}
else
zperr("Checksum error",TRUE);
}
else
zperr("Block nr garbled",TRUE);
}
/* make sure eot really is eot and not just mixmash */
else if (firstch==EOT && readline(10)==TIMEOUT)
return WCEOT;
else if (firstch==CAN) {
if (Lastrx==CAN) {
zperr( "Sender CANcelled",TRUE);
return NERROR;
}
else {
Lastrx=CAN;
continue;
}
}
else if (firstch==TIMEOUT) {
if (Firstsec) {
zperr( "TIMEOUT",TRUE);
goto humbug;
}
bilge:
zperr( "TIMEOUT",TRUE);
}
else
zperr( "Bad header",TRUE);
humbug:
Lastrx=0;
while(readline(50) != TIMEOUT)
if (QuitFlag)
return NERROR;
if (Firstsec) {
if (Xmodem && (Errors == RETRYMAX/2))
Crcflag = !Crcflag;
report(BLKCHECK,Crcflag?"CRC":"Checksum");
mcharout(Crcflag?WANTCRC:NAK);
}
else {
maxtime=40;
mcharout(NAK);
}
}
/* try to stop the bubble machine. */
canit();
return NERROR;
}
/*
* Process incoming file information header
*/
procheader(name)
char *name;
{
long atol();
static char *p, *ap;
/*
* Process YMODEM,ZMODEM remote file management requests
*/
clrreports();
p = name + 1 + strlen(name);
if (*p) { /* file coming from Unix or DOS system */
ap = p;
while (*p != ' ') /* find first space */
++p;
*p = '\0'; /* ap now points to a long integer in ascii */
report(FILESIZE,ap);
report(SENDTIME,ttime(atol(ap)));
}
strcpy(Pathname, name);
checkpath(Pathname);
Fd=fopen(Pathname, "wb");
if (openerror(Fd,Pathname))
return NERROR;
return OK;
}
/*
* Putsec writes the n characters of buf to receive file Fd.
*/
putsec(buf, n)
char *buf;
int n;
{
static int status;
status = 0xff;
while (n--) {
Cpmbuf[Cpindex++] = *buf++;
if (Cpindex >= Cpbufsize) {
status = write(Fd,Cpmbuf,Cpbufsize);
if (!status)
zperr("Disk write error",TRUE);
Cpindex = 0;
}
}
return status ? 0 : NERROR;
}
/*
* substr(string, token) searches for token in string s
* returns pointer to token within string if found, NULL otherwise
*/
char *
substr(s, t)
char *s,*t;
{
static int i;
if ((i=index(s,t)) != -1)
return s+i;
else
return NULL;
}
/* send cancel string to get the other end to shut up */
canit()
{
static char canistr[] = {
24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
};
mstrout(canistr,FALSE);
purgeline();
}
clrreports()
{
static int i;
for (i=4; i<13; i++)
clrline(i);
}
zperr(string,incrflag)
char *string;
int incrflag;
{
clrline(MESSAGE);
report(MESSAGE,string);
if (incrflag)
dreport(ERRORS,++Errors);
}
report(row,string)
int row;
char *string;
{
locate(row,61);
printf(string);
}
dreport(row,value)
int row, value;
{
static char buf[7];
report(row,itoa(value,buf));
}
lreport(row,value)
int row;
long value;
{
static char buf[20];
report(row,ltoa(value,buf));
}
sreport(sct)
int sct;
{
static long bytes;
bytes = (long)Blklen;
bytes *= sct;
dreport(BLOCKS,sct);
lreport(KBYTES,bytes);
}
clrline(line)
int line;
{
report(line," ");
}
checkpath(name) /* eliminate bad paths */
char *name;
{
static char *p;
static int i;
for (p=name; *p; p++) { /* dump strange characters */
if (!isalpha(*p) && !isdigit(*p) && (*p != '.')) {
*p = '\0';
strcat(name,p+1);
}
}
if ((i=index(name,".")) > 8) {
p = name + i;
name[8] = '.';
name[9] = '\0';
p[3] = '\0';
strcat(name,p);
}
name[12] = '\0';
addatadrive(name);
report(PATHNAME,name);
}
/*
* Initialize for Zmodem receive attempt, try to activate Zmodem sender
* Handles ZSINIT frame
* Return ZFILE if Zmodem filename received, -1 on error,
* ZCOMPL if transaction finished, else 0
*/
tryz()
{
static int c, n, *ip;
static int cmdzack1flg;
if (Nozmodem) /* ymodem has been forced */
return 0;
for (n=Zmodem?15:5; --n>=0; ) {
if (opabort())
return NERROR;
/* Set buffer length (0) and capability flags */
stohdr(0L);
Txhdr[ZF0] = CANFC32 | CANFDX;
if (Zctlesc)
Txhdr[ZF0] |= TESCCTL;
ip = (int *)&Txhdr[ZP0];
*ip = Cpbufsize;
zshhdr(Tryzhdrtype, Txhdr);
if (Tryzhdrtype == ZSKIP) /* Don't skip too far */
Tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
again:
switch (zgethdr(Rxhdr, 0)) {
case ZRQINIT:
continue;
case ZEOF:
continue;
case TIMEOUT:
continue;
case ZFILE:
Zconv = Rxhdr[ZF0];
Zmanag = Rxhdr[ZF1];
Ztrans = Rxhdr[ZF2];
Tryzhdrtype = ZRINIT;
c = zrdata(Secbuf, KSIZE);
if (c == GOTCRCW)
return ZFILE;
zshhdr(ZNAK, Txhdr);
goto again;
case ZSINIT:
Zctlesc = TESCCTL & Rxhdr[ZF0];
if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
zshhdr(ZACK, Txhdr);
goto again;
}
zshhdr(ZNAK, Txhdr);
goto again;
case ZFREECNT:
stohdr(0L);
zshhdr(ZACK, Txhdr);
goto again;
case ZCOMMAND:
cmdzack1flg = Rxhdr[ZF0];
if (zrdata(Secbuf, KSIZE) == GOTCRCW) {
stohdr(0L);
purgeline(); /* dump impatient questions */
do {
zshhdr(ZCOMPL, Txhdr);
zperr("Waiting for ZFIN",FALSE);
if (opabort())
return NERROR;
}
while (++Errors<20 && zgethdr(Rxhdr,1) != ZFIN);
ackbibi();
return ZCOMPL;
}
zshhdr(ZNAK, Txhdr);
goto again;
case ZCOMPL:
goto again;
default:
continue;
case ZFIN:
ackbibi();
return ZCOMPL;
case ZCAN:
return NERROR;
}
}
return 0;
}
/*
* Receive 1 or more files with ZMODEM protocol
*/
rzmfile()
{
static int c;
for (;;) {
if (opabort())
return NERROR;
switch (c = rzfile()) {
case ZEOF:
case ZSKIP:
switch (tryz()) {
case ZCOMPL:
return OK;
default:
return NERROR;
case ZFILE:
break;
}
continue;
default:
return c;
case NERROR:
return NERROR;
}
}
}
/*
* Receive a file with ZMODEM protocol
* Assumes file name frame is in Secbuf
*/
rzfile()
{
static int c, n;
static long rxbytes;
Eofseen=FALSE;
if (procheader(Secbuf) == NERROR) {
return (Tryzhdrtype = ZSKIP);
}
n = 20;
rxbytes = 0L;
for (;;) {
if (opabort())
return NERROR;
stohdr(rxbytes);
zshhdr(ZRPOS, Txhdr);
nxthdr:
switch (c = zgethdr(Rxhdr, 0)) {
default:
return NERROR;
case ZNAK:
case TIMEOUT:
if ( --n < 0) {
return NERROR;
}
case ZFILE:
zrdata(Secbuf, KSIZE);
continue;
case ZEOF:
if (rclhdr(Rxhdr) != rxbytes) {
/*
* Ignore eof if it's at wrong place - force
* a timeout because the eof might have gone
* out before we sent our zrpos.
*/
Errors = 0;
goto nxthdr;
}
if (closeit()) {
Tryzhdrtype = ZFERR;
return NERROR;
}
lreport(KBYTES,rxbytes);
report(BLKCHECK,Crc32?"CRC-32":"CRC-16");
return c;
case NERROR: /* Too much garbage in header search error */
if ( --n < 0) {
return NERROR;
}
zmputs(Attn);
continue;
case ZDATA:
if (rclhdr(Rxhdr) != rxbytes) {
if ( --n < 0) {
return NERROR;
}
zmputs(Attn);
continue;
}
moredata:
lreport(KBYTES,rxbytes);
report(BLKCHECK,Crc32?"CRC-32":"CRC-16");
switch (c = zrdata(Secbuf, KSIZE)) {
case ZCAN:
return NERROR;
case NERROR: /* CRC error */
if ( --n < 0) {
return NERROR;
}
zmputs(Attn);
continue;
case TIMEOUT:
if ( --n < 0) {
return NERROR;
}
continue;
case GOTCRCW:
n = 20;
putsec(Secbuf, Rxcount);
rxbytes += Rxcount;
stohdr(rxbytes);
#ifdef DEBUG
lreport(BLOCKS,rxbytes); /* put it any old place */
#endif;
zshhdr(ZACK, Txhdr);
mcharout(XON);
goto nxthdr;
case GOTCRCQ:
n = 20;
putsec(Secbuf, Rxcount);
rxbytes += Rxcount;
stohdr(rxbytes);
zshhdr(ZACK, Txhdr);
goto moredata;
case GOTCRCG:
n = 20;
putsec(Secbuf, Rxcount);
rxbytes += Rxcount;
goto moredata;
case GOTCRCE:
n = 20;
putsec(Secbuf, Rxcount);
rxbytes += Rxcount;
goto nxthdr;
}
}
}
}
/*
* Send a string to the modem, processing for \336 (sleep 1 sec)
* and \335 (break signal)
*/
zmputs(s)
char *s;
{
static int c;
while (*s) {
if (opabort())
return NERROR;
switch (c = *s++) {
case '\336':
wait(1);
continue;
case '\335':
sendbrk();
continue;
default:
mcharout(c);
}
}
}
sendbrk(){} /* do later */
/*
* Close the receive dataset, return OK or NERROR
*/
closeit()
{
static int status;
status = OK;
if (Cpindex) {
status = write(Fd,Cpmbuf,128*roundup(Cpindex,128)) ? OK : NERROR;
Cpindex = 0;
}
if (status == NERROR)
zperr("Disk write error",TRUE);
if (fclose(Fd)==NERROR) {
Fd = 0;
zperr("File close error",TRUE);
return NERROR;
}
return status;
}
/*
* Ack a ZFIN packet, let byegones be byegones
*/
ackbibi()
{
static int n;
stohdr(0L);
for (n=3; --n>=0; ) {
purgeline();
zshhdr(ZFIN, Txhdr);
switch (readline(100)) {
case 'O':
readline(INTRATIME); /* Discard 2nd 'O' */
return;
case RCDO:
return;
case TIMEOUT:
default:
break;
}
}
}
opabort()
{
Lastkey = getch() & 0xff;
if (Lastkey == ESC) {
flush();
if (!Inhost && !Dialing)
report(MESSAGE,"Operator abort");
QuitFlag = TRUE;
}
return QuitFlag;
}
long
atol(string)
char *string;
{
static long value, lv;
static char *p;
value = 0L;
p = string + strlen(string); /* end of string */
while (!isdigit(*p))
p--;
for (lv = 1L; isdigit(*p) && p >= string; lv *= 10)
value += ((*p--) - '0') * lv;
return value;
}
/************************** END OF MODULE 8 *********************************/