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
/
MODEMS
/
ZMODEM
/
RZMP-SRC.LBR
/
RZMP4.CZ
/
RZMP4.C
Wrap
Text File
|
2000-06-30
|
15KB
|
726 lines
/************************ START OF RZMP MODULE 3 ****************************/
/* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */
/* Further modified rjm to remove xmodem/ymodem stuff for rzmp */
#define RZMP
#include "zmp.h"
#include "zmodem.h"
#ifdef AZTEC_C
#include "libc.h"
#else
#include <stdio.h>
#endif
#include <setjmp.h>
jmp_buf jb_stop;
/*
* 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. 0337 causes a break to be sent.
*/
#define SLEEP 0336
char *ltoa(), *alloc(), *grabmem();
char Myattn[] = { CTRLC,SLEEP,0 };
unsigned Txwindow = 0; /* Control the size of the transmitted window */
unsigned Txwspac; /* Spacing between zcrcq requests */
unsigned Txwcnt; /* Counter used to space ack requests */
int Noeofseen;
int Totsecs; /* total number of sectors this file */
char *Txbuf;
int Filcnt; /* count of number of files opened */
unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
int Rxflags = 0;
long Bytcnt;
long Lastread; /* Beginning offset of last buffer read */
int Lastn; /* Count of last buffer read or -1 */
int Dontread; /* Don't read the buffer, it's still there */
long Lastsync; /* Last offset to which we got a ZRPOS */
int Beenhereb4; /* How many times we've been ZRPOS'd same place */
int Incnt; /* count for chars not read from the Cpmbuf */
wcsend(argc, argp)
int argc; /* nr of files to send */
char *argp[]; /* list of file names */
{
int n, status;
slabel();
QuitFlag = FALSE;
Zctlesc = 0;
Incnt = 0;
Baudrate = Baudtable[Current.cbaudindex];
Filcnt = Errors = 0;
#ifdef AZTEC_C
Fd = 0;
#else
Fd = -1;
#endif
Txbuf = alloc(KSIZE);
if (allocerror(Txbuf))
return NERROR;
Cpmbuf = grabmem(&Cpbufsize);
if (allocerror(Cpmbuf))
return NERROR;
Cpindex = 0; /* just in case */
Crcflag = FALSE;
Firstsec = TRUE;
Bytcnt = -1;
Rxtimeout = 600;
savecurs();
hidecurs();
box();
status = NERROR;
report(PROTOCOL,"ZMODEM Send");
stohdr(0L);
zshhdr(ZRQINIT, Txhdr);
if (getzrxinit()==NERROR)
goto badreturn;
for (n=0; n<argc; ++n) {
strcpy(Pathname,argp[n]);
if (Private) {
deldrive(Pathname); /* remove any du: */
addu(Pathname,Dprivdrive,Dprivuser);
}
if (checkname(Pathname))
continue; /* bad filetype */
clrreports();
Totsecs = 0;
if (opabort() || wcs(Pathname) == NERROR)
goto badreturn;
tfclose();
(*Downloads)++; /* only bump count if successful */
savelog(Pathname); /* and write to disk */
}
Totsecs = 0;
if (Filcnt==0) { /* we couldn't open ANY files */
canit();
goto badreturn;
}
zperr("Complete",FALSE);
saybibi();
status = OK;
badreturn:
free(Cpmbuf);
free(Txbuf);
showcurs();
restcurs();
if (status == NERROR)
tfclose();
return status;
}
wcs(oname)
char *oname;
{
unsigned length;
long flen;
#ifdef AZTEC_C
if ((Fd=fopen(oname,"rb"))==BUFIOT) {
#else
if ((Fd=open(oname,0))==UBIOT) {
#endif
zperr("Can't open file",TRUE);
wait(2);
return OK; /* pass over it, there may be others */
}
++Noeofseen;
Lastread = 0L;
Lastn = -1;
Dontread = FALSE;
++Filcnt;
fstat(oname,&Fs);
switch (wctxpn(oname)) { /* transmit path name */
case NERROR:
canit(); /* Send CAN */
return NERROR;
case ZSKIP:
return OK;
}
length = Fs.records;
flen = (long)length * 128;
return 0;
}
/*
* generate and transmit pathname block consisting of
* pathname (null terminated),
* file length, mode time (null) and file mode (null)
* in octal.
* N.B.: modifies the passed name, may extend it!
*/
wctxpn(name)
char *name;
{
static char *p;
char buf[20];
static unsigned length;
static long nrbytes;
memset(Txbuf,'\0',KSIZE);
length = Fs.records;
nrbytes = (long)length * 128;
report(PATHNAME,name);
lreport(FILESIZE,nrbytes);
dreport(FBLOCKS,length);
report(SENDTIME,ttime(nrbytes));
strcpy(Txbuf,name);
deldrive(Txbuf); /* remove drive ind if any */
p = Txbuf + strlen(Txbuf);
++p;
strcpy(p,ltoa(nrbytes,buf));
return zsendfile(Txbuf, 1+strlen(p)+(p-Txbuf));
}
/* itoa - convert n to characters in s. */
char *itoa(n, s)
char s[];
short n;
{
static short c, k;
static char *p, *q;
if ((k = n) < 0) /* record sign */
n = -n; /* make n positive */
q = p = s;
do { /* generate digits in reverse order */
*p++ = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (k < 0) *p++ = '-';
*p = 0;
/* reverse string in place */
while (q < --p) {
c = *q; *q++ = *p; *p = c; }
return (s);
}
/* ltoa - convert n to characters in s. */
char *ltoa(n, s)
char s[];
long n;
{
static long c, k;
static char *p, *q;
if ((k = n) < 0) /* record sign */
n = -n; /* make n positive */
q = p = s;
do { /* generate digits in reverse order */
*p++ = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (k < 0) *p++ = '-';
*p = 0;
/* reverse string in place */
while (q < --p) {
c = *q; *q++ = *p; *p = c; }
return (s);
}
/* fill buf with count chars padding with ^Z for CPM */
filbuf(buf, count)
char *buf;
int count;
{
static int c, m;
c = m = newload(buf, count);
if (m <= 0)
return 0;
while (m < count)
buf[m++] = CTRLZ;
return c;
}
newload(buf, count)
int count;
char *buf;
{
static int j;
j = 0;
while (count--) {
if (Incnt <= 0) {
#ifdef AZTEC_C
Incnt = fread( Cpmbuf, 1, Cpbufsize, Fd);
#else
Incnt = read( Fd, Cpmbuf, Cpbufsize );
#endif
Cpindex = 0;
if (Incnt <= 0)
break;
}
buf[j++] = Cpmbuf[Cpindex++];
--Incnt;
}
return (j ? j : -1);
}
/*
* Get the receiver's init parameters
*/
getzrxinit()
{
static int n;
for (n=10; --n>=0; ) {
if (opabort())
return NERROR;
switch (zgethdr(Rxhdr, 1)) {
case ZCHALLENGE: /* Echo receiver's challenge numbr */
stohdr(Rxpos);
zshhdr(ZACK, Txhdr);
continue;
case ZCOMMAND: /* They didn't see out ZRQINIT */
stohdr(0L);
zshhdr(ZRQINIT, Txhdr);
continue;
case ZRINIT:
Rxflags = 0377 & Rxhdr[ZF0];
Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
Zctlesc |= Rxflags & TESCCTL;
Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
return (sendzsinit());
case ZCAN:
case TIMEOUT:
return NERROR;
case ZRQINIT:
if (Rxhdr[ZF0] == ZCOMMAND)
continue;
default:
zshhdr(ZNAK, Txhdr);
continue;
}
}
return NERROR;
}
/* Send send-init information */
sendzsinit()
{
int tries;
stohdr(0L); /* All flags are undefined */
strcpy(Txbuf,Myattn); /* Copy Attn string */
for (tries = 0; tries < 20; tries++)
{
if (opabort())
return NERROR;
zsbhdr(ZSINIT,Txhdr); /* Send binary header */
zsdata(Txbuf,strlen(Txbuf) + 1,ZCRCW); /* Send string */
if (zgethdr(Rxhdr,0) == ZACK)
return OK;
zperr("Bad ACK: ZSINIT",FALSE);
}
return NERROR;
}
/* Send file name and related info */
zsendfile(buf, blen)
char *buf;
int blen;
{
static int c;
for (;;) {
if (opabort())
return NERROR;
Txhdr[ZF0] = 0; /* file conversion request */
Txhdr[ZF1] = 0; /* file management request */
Txhdr[ZF2] = 0; /* file transport request */
Txhdr[ZF3] = 0;
zsbhdr(ZFILE, Txhdr);
zsdata(buf, blen, ZCRCW);
again:
c = zgethdr(Rxhdr, 1);
switch (c) {
case ZRINIT:
while ((c = readline(INTRATIME)) > 0)
if (c == ZPAD) {
goto again;
}
/* **** FALL THRU TO **** */
default:
continue;
case ZCAN:
case TIMEOUT:
case ZABORT:
case ZFIN:
return NERROR;
case ZSKIP:
return c;
case ZRPOS:
/*
* Suppress zcrcw request otherwise triggered by
* lastyunc==Bytcnt
*/
Lastsync = (Bytcnt = Txpos = Rxpos) -1L;
#ifdef AZTEC_C
fseek(Fd, Rxpos, 0); /* absolute offset */
#else
lseek(Fd, Rxpos, 0); /* absolute offset */
#endif
clrline(KBYTES);
Incnt = 0;
Dontread = FALSE;
c = zsndfdata();
Sending = FALSE;
return c;
}
}
}
/* Send the data in the file */
zsndfdata()
{
static int c, e, n;
static int newcnt;
static long tcount;
static int junkcount; /* Counts garbage chars received by TX */
tcount = 0L;
Blklen = 128;
if (Baudrate > 300)
Blklen = 256;
if (Baudrate > 1200)
Blklen = 512;
if (Baudrate > 2400)
Blklen = KSIZE;
if (Rxbuflen && Blklen>Rxbuflen)
Blklen = Rxbuflen;
Lrxpos = 0L;
junkcount = 0;
Beenhereb4 = FALSE;
Sending = Firstsec = TRUE;
somemore:
if (NULL) {
waitack:
junkcount = 0;
c = getinsync(0);
if (QuitFlag)
return NERROR;
gotack:
if (setjmp(jb_stop)) { /* come here if rx stops us */
rxint:
c = getinsync(1);
}
switch (c) {
default:
case ZCAN:
return NERROR;
case ZSKIP:
return c;
case ZACK:
case ZRPOS:
break;
case ZRINIT:
return OK;
}
/*
* If the reverse channel can be tested for data,
* this logic may be used to detect error packets
* sent by the receiver, in place of setjmp/longjmp
* minprdy() returns non 0 if a character is available
*/
while (minprdy()) {
if (QuitFlag)
return NERROR;
switch (readline(1)) {
case CTRLC:
case CAN:
case ZPAD:
goto rxint;
case XOFF: /* Wait a while for an XON */
case XOFF|0200:
readline(100);
}
}
}
if (setjmp(jb_stop)) { /* rx interrupt */
c = getinsync(1);
if (c == ZACK)
goto gotanother;
purgeline();
/* zcrce - dinna wanna starta ping-pong game */
zsdata(Txbuf, 0, ZCRCE);
goto gotack;
}
newcnt = Rxbuflen;
Txwcnt = 0;
stohdr(Txpos);
zsbhdr(ZDATA, Txhdr);
do {
if (QuitFlag)
return NERROR;
if (Dontread) {
n = Lastn;
}
else {
n = filbuf(Txbuf, Blklen);
Lastread = Txpos;
Lastn = n;
}
Dontread = FALSE;
if (n < Blklen)
e = ZCRCE;
else if (junkcount > 3)
e = ZCRCW;
else if (Bytcnt == Lastsync)
e = ZCRCW;
else if (Rxbuflen && (newcnt -= n) <= 0)
e = ZCRCW;
else if (Txwindow && (Txwcnt += n) >= Txwspac) {
Txwcnt = 0;
e = ZCRCQ;
}
else
e = ZCRCG;
zsdata(Txbuf, n, e);
Txpos += (long)n;
Bytcnt = Txpos;
crcrept(Crc32t); /* praps report crc mode */
lreport(KBYTES,Bytcnt);
if (e == ZCRCW)
goto waitack;
/*
* If the reverse channel can be tested for data,
* this logic may be used to detect error packets
* sent by the receiver, in place of setjmp/longjmp
* minprdy() returns non 0 if a character is available
*/
while (minprdy()) {
if (QuitFlag)
return NERROR;
switch (readline(1)) {
case CAN:
case CTRLC:
case ZPAD:
c = getinsync(1);
if (c == ZACK)
break;
purgeline();
/* zcrce - dinna wanna starta ping-pong game */
zsdata(Txbuf, 0, ZCRCE);
goto gotack;
case XOFF: /* Wait a while for an XON */
case XOFF|0200:
readline(100);
default:
++junkcount;
}
gotanother:;
}
if (Txwindow) {
while ((tcount = Txpos - Lrxpos) >= Txwindow) {
if (QuitFlag)
return NERROR;
if (e != ZCRCQ)
zsdata(Txbuf, 0, e = ZCRCQ);
c = getinsync(1);
if (c != ZACK) {
purgeline();
zsdata(Txbuf, 0, ZCRCE);
goto gotack;
}
}
}
}
while (n == Blklen);
for (;;) {
if (QuitFlag)
return NERROR;
stohdr(Txpos);
zsbhdr(ZEOF, Txhdr);
switch (getinsync(0)) {
case ZACK:
continue;
case ZRPOS:
goto somemore;
case ZRINIT:
return OK;
case ZSKIP:
return c;
default:
return NERROR;
}
}
}
/*
* Respond to receiver's complaint, get back in sync with receiver
*/
getinsync(flag) /* flag means that there was an error */
int flag;
{
static int c;
unsigned u;
for (;;) {
if (opabort())
return NERROR;
c = zgethdr(Rxhdr, 0);
c = c < FRTYPES ? c : FRTYPES-1;
sprintf(Buf,"Got %s", frametypes[c+FTOFFSET]);
zperr(Buf,flag);
switch (c) {
case ZCAN:
case ZABORT:
case ZFIN:
case TIMEOUT:
return NERROR;
case ZRPOS:
/* ************************************* */
/* If sending to a modem beuufer, you */
/* might send a break at this point to */
/* dump the modem's buffer. */
if (Lastn >= 0 && Lastread == Rxpos) {
Dontread = TRUE;
}
else {
#ifdef AZTEC_C
u = fseek(Fd, Rxpos, 0); /* absolute offset */
if (u != EOF)
uneof(Fd); /* Reset EOF flag */
#else
u = lseek(Fd, Rxpos, 0); /* absolute offset */
#endif
clrline(KBYTES);
Incnt = 0;
}
Bytcnt = Lrxpos = Txpos = Rxpos;
if (Lastsync == Rxpos) {
if (++Beenhereb4 > 4)
if (Blklen > 256)
Blklen /= 2;
}
Lastsync = Rxpos;
return c;
case ZACK:
Lrxpos = Rxpos;
if (flag || Txpos == Rxpos)
return ZACK;
continue;
case ZRINIT:
case ZSKIP:
return c;
case NERROR:
default:
zsbhdr(ZNAK, Txhdr);
continue;
}
}
}
/* Say "bibi" to the receiver, try to do it cleanly */
saybibi()
{
for (;;) {
stohdr(0L); /* CAF Was zsbhdr - minor change */
zshhdr(ZFIN, Txhdr); /* to make debugging easier */
switch (zgethdr(Rxhdr, 0)) {
case ZFIN:
xmchout('O');
xmchout('O');
case ZCAN:
case TIMEOUT:
return;
}
}
}
char *
ttime(fsize)
long fsize;
{
static int efficiency, cps, seconds;
static char buffer[10];
efficiency = 9;
cps = (Baudrate/100) * efficiency;
seconds = (int)(fsize/cps);
sprintf(buffer,"%d:%02d",seconds/60,seconds%60);
return buffer;
}
tfclose() /* close file if still open */
{
#ifdef AZTEC_C
if (Fd)
fclose(Fd);
Fd = 0;
#else
if (Fd >= 0)
close(Fd);
Fd = -1;
#endif
}
/* output a character to the modem and test the receive channel */
xmchout(c)
char c;
{
testrxc(200); /* test receive channel in case xoff */
mcharout(c); /* then send it */
}
/* Test receive channel for xon/xoff and interrupt while sending */
testrxc(timeout)
short timeout; /* timeout in seconds */
{
static char c;
c = minprdy() ? mcharinp() : '\0'; /* get a character if any */
if (c) {
if (c == CTRLS) {
while (((c = readline(10)) != CTRLQ) && timeout--);
if (c < 1)
c = CTRLC; /* timeout */
}
StopFlag = ((c == CTRLC) || (c == CTRLX) || (c == '*'));
if (StopFlag && Sending)
longjmp(jb_stop,c); /* zmodem transmit interrupt */
}
}
/* print send mode label */
slabel()
{
putlabel("SEND FILE mode: Press ESC to Abort...");
}
/************************** END OF MODULE 3 *********************************/