koreth@ssyx.ucsc.edu (Steven Grimm) (05/30/88)
Submitted-by: bammi@mandrill.ces.cwru.edu (Jwahar R. Bammi)
Posting-number: Volume 1, Issue 44
Archive-name: zmdm/part04
#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file RZ.C continued
#
CurArch=4
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file RZ.C"
sed 's/^X//' << 'SHAR_EOF' >> RZ.C
X fprintf(STDERR," transfer if the dest. file exists (ZMODEM ONLY)\n\n");
X
X
X if(fout != -1)
X {
X if (stfclose(fout) != 0)
X {
X fprintf(STDERR, "\r\nfile close ERROR\n");
X }
X fout = (-1);
X }
X
X#ifdef RDEBUG
X if(logf != (FILE *)NULL)
X fclose(logf);
X#endif
X
X return(1);
X}
X
X
X/*
X * Let's receive something already.
X */
Xwcreceive(argc, argp)
Xint argc;
Xchar **argp;
X{
X register int c;
X
X if (Batch || argc==0)
X {
X Crcflg=(Wcsmask==0377);
X if ( !Quiet)
X#ifndef REMOTE
X fprintf(STDERR, "\n%s: ready (CTRL-C to cancel)\n\n",
X Progname);
X#else
X fprintf(STDERR, "\n%s: ready\n\n",
X Progname);
X#endif
X if (c=tryz())
X {
X if (c == ZCOMPL)
X return OK;
X if (c == ERROR)
X goto fubar;
X c = rzfiles();
X if (c)
X goto fubar;
X }
X else
X {
X for (;;)
X {
X if (wcrxpn(secbuf)== ERROR)
X goto fubar;
X if (secbuf[0]==0)
X return OK;
X if (procheader(secbuf) == ERROR)
X goto fubar;
X if (wcrx()==ERROR)
X goto fubar;
X }
X }
X }
X else
X {
X Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
X
X strcpy(Pathname, *argp);
X#ifndef REMOTE
X fprintf(STDERR, "\n%s: ready to receive %s (CTRL-C to Cancel)\n\n",
X Progname, Pathname);
X#else
X fprintf(STDERR, "\n%s: ready to receive %s\n\n",
X Progname, Pathname);
X#endif
X
X#ifdef RDEBUG
X if(logf != (FILE *)NULL)
X fprintf(logf, "\nrz: ready to receive %s ", Pathname);
X#endif
X
X if((fout = stfopen(Pathname,"w")) <= 0)
X return ERROR;
X if (wcrx()==ERROR)
X goto fubar;
X }
X return OK;
X
Xfubar:
X canit();
X
X if (fout != -1)
X {
X if (stfclose(fout) != 0)
X {
X fprintf(STDERR, "\r\nfile close ERROR\n");
X }
X fout = (-1);
X }
X
X return ERROR;
X}
X
X
X/*
X * Fetch a pathname from the other end as a C ctyle ASCIZ string.
X * Length is indeterminate as long as less than Blklen
X * A null string represents no more files (YMODEM)
X */
Xwcrxpn(rpn)
Xchar *rpn; /* receive a pathname */
X{
X register int c;
X
X PURGELINE;
X
Xet_tu:
X Firstsec=TRUE; Eofseen=FALSE;
X sendline(Crcflg?WANTCRC:NAK);
X Lleft=0; /* Do read next time ... */
X while ((c = wcgetsec(rpn, 100)) != 0)
X {
X llog( "Pathname fetch returned %d\n", c);
X if (c == WCEOT)
X {
X sendline(ACK);
X Lleft=0; /* Do read next time ... */
X readline(1);
X goto et_tu;
X }
X return ERROR;
X }
X sendline(ACK);
X return OK;
X}
X
X/*
X * Adapted from CMODEM13.C, written by
X * Jack M. Wierda and Roderick W. Hart
X */
X
Xwcrx()
X{
X register int sectnum, sectcurr;
X register char sendchar;
X int cblklen; /* bytes to dump this block */
X
X Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
X sendchar=Crcflg?WANTCRC:NAK;
X
X for (;;)
X {
X sendline(sendchar); /* send it now, we're ready! */
X Lleft=0; /* Do read next time ... */
X sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
X report(sectcurr);
X if (sectcurr==(sectnum+1 &Wcsmask))
X {
X sectnum++;
X cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
X if (putsec(secbuf, cblklen)==ERROR)
X return ERROR;
X if ((Bytesleft-=cblklen) < 0)
X Bytesleft = 0;
X sendchar=ACK;
X }
X else if (sectcurr==(sectnum&Wcsmask))
X {
X log2( "Received dup Sector\n");
X sendchar=ACK;
X }
X else if (sectcurr==WCEOT)
X {
X if (closeit(0L))
X return ERROR;
X sendline(ACK);
X Lleft=0; /* Do read next time ... */
X return OK;
X }
X else if (sectcurr==ERROR)
X return ERROR;
X else
X {
X log2( "Sync Error\n");
X return ERROR;
X }
X }
X}
X
X
X/*
X * Wcgetsec fetches a Ward Christensen type sector.
X * Returns sector number encountered or ERROR if valid sector not received,
X * or CAN CAN received
X * or WCEOT if eot sector
X * time is timeout for first char, set to 4 seconds thereafter
X ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
X * (Caller must do that when he is good and ready to get next sector)
X */
Xwcgetsec(rxbuf, maxtime)
Xchar *rxbuf;
Xint maxtime;
X{
X register int checksum, wcj, firstch;
X register unsigned int oldcrc;
X register char *p;
X int sectcurr;
X
X for (Lastrx=errors=0; errors<RETRYMAX; errors++)
X {
X
X if ((firstch=readline(maxtime))==STX)
X {
X Blklen=KSIZE; goto get2;
X }
X if (firstch==SOH)
X {
X Blklen=SECSIZ;
Xget2:
X sectcurr=readline(1);
X if ((sectcurr+(oldcrc=readline(1)))==Wcsmask)
X {
X oldcrc=checksum=0;
X for (p=rxbuf,wcj=Blklen; --wcj>=0; )
X {
X if ((firstch=readline(1)) < 0)
X goto bilge;
X oldcrc=updcrc(firstch, oldcrc);
X checksum += (*p++ = firstch);
X }
X if ((firstch=readline(1)) < 0)
X goto bilge;
X if (Crcflg)
X {
X oldcrc=updcrc(firstch, oldcrc);
X if ((firstch=readline(1)) < 0)
X goto bilge;
X oldcrc=updcrc(firstch, oldcrc);
X if (oldcrc & 0xFFFF)
X llog("CRC=0%o\n", oldcrc);
X else
X {
X Firstsec=FALSE;
X return sectcurr;
X }
X }
X else if (((checksum-firstch)&Wcsmask)==0)
X {
X Firstsec=FALSE;
X return sectcurr;
X }
X else
X log2( "Checksum Error\n");
X }
X else
X log2("Sector number garbled 0%o 0%o\n",
X sectcurr, oldcrc);
X }
X /* make sure eot really is eot and not just mixmash */
X
X else if (firstch==EOT && Lleft==0)
X return WCEOT;
X
X else if (firstch==CAN)
X {
X if (Lastrx==CAN)
X {
X log2( "Sender CANcelled\n");
X return ERROR;
X }
X else
X {
X Lastrx=CAN;
X continue;
X }
X }
X else if (firstch==TIMEOUT)
X {
X if (Firstsec)
X goto humbug;
Xbilge:
X log2( "Timeout\n");
X }
X else
X llog( "Got 0%o sector header\n", firstch);
X
Xhumbug:
X Lastrx=0;
X while(readline(1)!=TIMEOUT)
X ;
X if (Firstsec)
X {
X sendline(Crcflg?WANTCRC:NAK);
X Lleft=0; /* Do read next time ... */
X }
X else
X {
X maxtime=40; sendline(NAK);
X Lleft=0; /* Do read next time ... */
X }
X }
X /* try to stop the bubble machine. */
X canit();
X return ERROR;
X}
X
X
X
X
X/*
X * Process incoming file information header
X */
Xprocheader(name)
Xchar *name;
X{
X register char *p;
X register int dot;
X char openmode[4];
X extern int strlen();
X
X /* convert to ST style path names */
X for( p = name; *p != '\0'; p++)
X {
X if(*p == '/')
X *p = '\\';
X }
X
X /* pick out the last extention in the filename in each part of path */
X while(p != name)
X {
X dot = 0; p-- ;
X while((p != name) && (*p != '\\'))
X {
X if(*p == '.')
X {
X if(dot == 0)
X {
X dot = 1;
X }
X else
X {
X /* replace all but the last dot with '_' */
X *p = '_';
X }
X }
X p--;
X }
X }
X
X /* set default parameters and overrides */
X strcpy(openmode,"w");
X
X Thisbinary = isbinary(name);
X
X if (Lzmanag)
X zmanag = Lzmanag;
X
X /*
X * Process ZMODEM remote file management requests
X */
X if ( zconv == ZCNL) /* Remote ASCII override */
X Thisbinary = 0;
X if (zconv == ZCBIN) /* Remote Binary override */
X ++Thisbinary;
X else if (zmanag == ZMAPND)
X strcpy(openmode, "a");
X
X if (ForceBinary == TRUE ) /* local binary force override */
X ++Thisbinary;
X
X /* ZMPROT check for existing file */
X if (zmanag == ZMPROT && existf(name, "r"))
X {
X return ERROR;
X }
X
X/* ATARI ST NOTE:
X * We will not accept rooted paths ie. paths that begin in '\' or '.\'
X * If the incoming filename is rooted, we skip the beginning
X * '\' '.\' or '..\'
X */
X
X if( (name[0] == '\\') || (name[0] == '.') )
X {
X /* skip over the leading stuff */
X if(name[0] == '\\')
X name = &name[1];
X else
X {
X if(name[1] == '.')
X name = &name[3]; /* Skip the "..\" */
X else
X name = &name[2]; /* Skip the ".\" */
X }
X }
X
X /* ST addition, create any dierctories in the path that don't exist */
X if( pathensure(name) == ERROR)
X return ERROR;
X
X Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
X
X p = name + 1 + strlen(name);
X if (*p)
X { /* file coming from Unix or DOS system */
X sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
X/* NA to atari
X if (Filemode & UNIXFILE)
X ++Thisbinary;
X*/
X#ifndef REMOTE
X if (Verbose)
X {
X fprintf(STDERR,
X "\nIncoming:\n\tName:\t%s\n\tBytes:\t%ld\n\
X\tModTime: %ld\n\tMode:\t%o\n\tBufSize: %ld\n\n",
X name, Bytesleft, Modtime, Filemode, (long)BBUFSIZ);
X
X#ifdef RDEBUG
X if(logf != (FILE *)NULL)
X fprintf(logf, "Incoming: %s %ld %lo %o\n",
X name, Bytesleft, Modtime, Filemode);
X#endif
X
X }
X#endif /* REMOTE */
X
X }
X else
X { /* File coming from CP/M system */
X for (p=name; *p; ++p) /* change / to _ */
X if ( *p == '/')
X *p = '_';
X
X if ( *--p == '.') /* zap trailing period */
X *p = 0;
X }
X
X strcpy(Pathname, name);
X#ifndef REMOTE
X if (Verbose)
X {
X fprintf(STDERR, "Receiving %s %s [mode %s]\n\n",
X name, Thisbinary?"BIN":"ASCII", openmode);
X
X#ifdef RDEBUG
X if(logf != (FILE *)NULL)
X fprintf(logf, "Receiving %s %s %s\n",
X name, Thisbinary?"BIN":"ASCII", openmode);
X#endif
X
X }
X#endif /* REMOTE */
X
X if ((fout=stfopen(name, openmode)) <= 0)
X return ERROR;
X
X return OK;
X}
X
X/*
X * Putsec writes the n characters of buf to receive file fout.
X * If not in binary mode, all characters
X * starting with CPMEOF are discarded.
X */
Xputsec(buf, n)
Xunsigned char *buf;
Xregister int n;
X{
X register unsigned char *p;
X
X if (Thisbinary)
X {
X for (p=buf; --n>=0; p++ )
X {
X if(stputc( *p, fout) < 0)
X {
X fprintf(STDERR, "\r\nError while Writing file\n");
X return ERROR;
X }
X }
X }
X else
X {
X if (Eofseen)
X return OK;
X
X for (p=buf; --n>=0; p++ )
X {
X if (*p == CPMEOF)
X {
X Eofseen=TRUE;
X return OK;
X }
X if(*p == '\n')
X {
X if(stputc('\r' ,fout) < 0)
X {
X fprintf(STDERR, "\r\nError while Writing file\n");
X return ERROR;
X }
X }
X if(stputc(*p ,fout) < 0)
X {
X fprintf(STDERR,"\r\nError while Writing file\n");
X return ERROR;
X }
X }
X }
X
X return OK;
X}
X
X/*
X * Log an error only if high verbose
X */
X/*VARARGS1*/
Xllog(s,p,u)
Xchar *s;
Xint p, u;
X{
X if (Verbose < 3)
X return;
X#ifdef RDEBUG
X fprintf(logf, "error %d: ", errors);
X fprintf(logf, s, p, u);
X#endif
X
X fprintf(STDERR, "\nerror %d: ", errors);
X fprintf(STDERR, s, p, u);
X}
X
X
X
X#ifndef STANDALONE
X/*
X * If called as rb use YMODEM protocol
X */
Xchkinvok(s)
Xchar *s;
X{
X Progname = s;
X if (s[0]=='r' && s[1]=='b')
X Nozmodem = TRUE;
X}
X#endif
X
X/*
X * Initialize for Zmodem receive attempt, try to activate Zmodem sender
X * Handles ZSINIT frame
X * Return ZFILE if Zmodem filename received, -1 on error,
X * ZCOMPL if transaction finished, else 0
X */
Xtryz()
X{
X register int n;
X register int cmdzack1flg;
X
X if (Nozmodem) /* Check for "rb" program name */
X return 0;
X
X
X for (n=Zmodem?10:5; --n>=0; )
X {
X /* Set buffer length (0) and capability flags */
X stohdr(0L);
X Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK; /* of course we can break */
X
X zshhdr(tryzhdrtype, Txhdr);
X/* zshhdr(Badclose?ZFERR:ZRINIT, Txhdr); */
Xagain:
X switch (zgethdr(Rxhdr, 0))
X {
X case ZRQINIT:
X continue;
X case ZEOF:
X continue;
X case TIMEOUT:
X continue;
X case ZFILE:
X zconv = Rxhdr[ZF0];
X zmanag = Rxhdr[ZF1];
X ztrans = Rxhdr[ZF2];
X tryzhdrtype = ZRINIT;
X Badclose = FALSE;
X if (zrdata(secbuf, KSIZE) == GOTCRCW)
X return ZFILE;
X zshhdr(ZNAK, Txhdr);
X goto again;
X case ZSINIT:
X if (zrdata(Attn, ZATTNLEN) == GOTCRCW)
X {
X zshhdr(ZACK, Txhdr);
X goto again;
X }
X zshhdr(ZNAK, Txhdr);
X goto again;
X case ZFREECNT:
X stohdr(~0L);
X zshhdr(ZACK, Txhdr);
X goto again;
X case ZCOMMAND:
X cmdzack1flg = Rxhdr[ZF0];
X if (zrdata(secbuf, KSIZE) == GOTCRCW)
X {
X if (cmdzack1flg & ZCACK1)
X stohdr(0L);
X else
X stohdr((long)sys2(secbuf));
X PURGELINE; /* dump impatient questions */
X do {
X zshhdr(ZCOMPL, Txhdr);
X }
X while (++errors<10 && zgethdr(Rxhdr,1) != ZFIN);
X ackbibi();
X if (cmdzack1flg & ZCACK1)
X exec2(secbuf);
X return ZCOMPL;
X }
X zshhdr(ZNAK, Txhdr); goto again;
X case ZCOMPL:
X goto again;
X default:
X continue;
X case ZFIN:
X ackbibi(); return ZCOMPL;
X case ZCAN:
X return ERROR;
X }
X }
X return 0;
X}
X
X/*
X * Receive 1 or more files with ZMODEM protocol
X */
Xrzfiles()
X{
X register int c;
X
X for (;;) {
X switch (c = rzfile()) {
X case ZEOF:
X case ZSKIP:
X switch (tryz()) {
X case ZCOMPL:
X return OK;
X default:
X return ERROR;
X case ZFILE:
X break;
X }
X continue;
X default:
X return c;
X case ERROR:
X return ERROR;
X }
X }
X}
X
X/*
X * Receive a file with ZMODEM protocol
X * Assumes file name frame is in secbuf
X */
Xrzfile()
X{
X register int c, n;
X long rxbytes;
X extern void rd_time();
X
X Eofseen=FALSE;
X if (procheader(secbuf) == ERROR) {
X return (tryzhdrtype = ZSKIP);
X/* zshhdr(ZSKIP, Txhdr);
X return ZSKIP; */
X }
X
X n = 10; rxbytes = 0L;
X
X Supexec(rd_time);
X start_time = pr_time;
X
X for (;;)
X {
X stohdr(rxbytes);
X zshhdr(ZRPOS, Txhdr);
Xnxthdr:
X switch (c = zgethdr(Rxhdr, 0)) {
X default:
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X case ZNAK:
X case TIMEOUT:
X if ( --n < 0)
X {
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X }
X case ZFILE:
X zrdata(secbuf, KSIZE);
X continue;
X case ZEOF:
X /* ++jrb */
X if (rclhdr(Rxhdr) != rxbytes)
X {
X /*
X * Ignore eof if it's at wrong place - force
X * a timeout because the eof might have gone
X * out before we sent our zrpos.
X */
X
X errors = 0; goto nxthdr;
X }
X/* --jrb
X if (rclhdr(Rxhdr) != rxbytes)
X {
X continue;
X }
X-- */
X if (closeit(rxbytes))
X {
X tryzhdrtype = ZFERR;
X Badclose = TRUE;
X vfile("rzfile: closeit returned <> 0");
X return ERROR;
X }
X vfile("rzfile: normal EOF");
X return c;
X case ERROR: /* Too much garbage in header search error */
X if ( --n < 0)
X {
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X }
X zmputs(Attn);
X continue;
X case ZDATA:
X n = 10;
X if (rclhdr(Rxhdr) != rxbytes)
X {
X zmputs(Attn);
X continue;
X }
Xmoredata:
X switch (c = zrdata(secbuf, KSIZE))
X {
X case ZCAN:
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X case ERROR: /* CRC error */
X if ( --n < 0)
X {
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X }
X zmputs(Attn);
X continue;
X case TIMEOUT:
X if ( --n < 0)
X {
X vfile("rzfile: zgethdr returned %d", c);
X return ERROR;
X }
X continue;
X case GOTCRCW:
X if(putsec(secbuf, Rxcount) == ERROR)
X return ERROR;
X rxbytes += Rxcount;
X lreport(rxbytes);
X stohdr(rxbytes);
X zshhdr(ZACK, Txhdr);
X goto nxthdr;
X case GOTCRCQ:
X if(putsec(secbuf, Rxcount) == ERROR)
X return ERROR;
X rxbytes += Rxcount;
X lreport(rxbytes);
X stohdr(rxbytes);
X zshhdr(ZACK, Txhdr);
X goto moredata;
X case GOTCRCG:
X if(putsec(secbuf, Rxcount) == ERROR)
X return ERROR;
X rxbytes += Rxcount;
X lreport(rxbytes);
X goto moredata;
X case GOTCRCE:
X if(putsec(secbuf, Rxcount) == ERROR)
X return ERROR;
X rxbytes += Rxcount;
X lreport(rxbytes);
X goto nxthdr;
X }
X }
X }
X}
X
X/*
X * Send a string to the modem, processing for \336 (sleep 1 sec)
X * and \335 (break signal)
X */
Xzmputs(s)
Xchar *s;
X{
X register int c;
X
X while (*s) {
X switch (c = *s++) {
X case '\336':
X stsleep(1); continue;
X case '\335':
X sendbrk(); continue;
X default:
X sendline(c);
X }
X }
X}
X
X
X
X/*
X * Close the receive dataset, return OK or ERROR
X */
Xcloseit(rxbytes)
Xlong rxbytes;
X{
X unsigned int timep[2];
X long end_time;
X extern void rd_time();
X
X if (stfclose(fout) != 0) {
X fprintf(STDERR, "\r\nfile close ERROR\n");
X return ERROR;
X }
X fout = (-1);
X
X Supexec(rd_time);
X end_time = pr_time;
X
X if (Modtime) {
X unix2st(Modtime, &timep[0], &timep[1]);
X touch(Pathname, timep);
X }
X
X /* if it is read only by owner on remote, then it is set
X * to read only on the ST, all other file modes are
X * irrelevant.
X */
X if (Filemode)
X {
X unsigned int fmode;
X
X fmode = (unsigned int)(Filemode & 000777);
X if( ((fmode & 0200) == 0) && ((fmode & 0400) != 0) )
X {
X /* it is readonly by owner on the remote, so
X * make it read only on the ST too
X */
X Fattrib(Pathname, 1, 0x01);
X }
X }
X#ifndef REMOTE
X if(rxbytes != 0L)
X fprintf(STDERR,"\n\n%s Closed\nTransfer Time %ld secs.\tfor %ld bytes\
X\tApprox %ld cps\n\n", Pathname, (end_time - start_time)/200L, rxbytes,
Xrxbytes/((end_time - start_time)/200L));
X else
X fprintf(STDERR,"\n\n%s Closed\n\n", Pathname);
X#endif
X lsct = 1;
X return OK;
X}
X
X/*
X * Ack a ZFIN packet, let byegones be byegones
X */
Xackbibi()
X{
X register int n;
X
X vfile("ackbibi:");
X Readnum = 1;
X stohdr(0L);
X for (n=4; --n>=0; )
X {
X zshhdr(ZFIN, Txhdr);
X for (;;) {
X switch (readline(100))
X {
X case 'O':
X readline(1); /* Discard 2nd 'O' */
X /* ***** FALL THRU TO ***** */
X case TIMEOUT:
X vfile("ackbibi complete");
X return;
X default:
X break;
X }
X }
X }
X}
X
X
X/*
X * Strip leading ! if present, do shell escape.
X */
Xsys2(s)
Xregister char *s;
X{
X if (*s == '!')
X ++s;
X return stsystem(s);
X}
X/*
X * Strip leading ! if present, do exec.
X */
Xexec2(s)
Xchar *s;
X{
X/** Are you kidding
X if (*s == '!')
X ++s;
X mode(0);
X execl("/bin/sh", "sh", "-c", s);
X**/
X}
X
X/*
X * Touch a file
X */
X#ifndef MANX
X#undef Fdatime /* There exist brain damaged versions of osbind.h */
X#define Fdatime(a,b,c) gemdos(0x57,a,b,c)
X#endif /* MANX has its _Gemdos stuff */
X
Xtouch(name, timep)
Xchar *name;
Xunsigned int *timep;
X{
X register int handl;
X
X if((handl = Fopen(name, 0)) < 0)
X {
X#ifndef REMOTE
X fprintf(STDERR,"*WARNING* Could not set file modification time for %s\n",
X name);
X#endif
X return;
X }
X
X
X Fdatime(timep, handl, 1);
X Fclose(handl);
X}
X
X/* -eof- */
SHAR_EOF
echo "File RZ.C is complete"
chmod 0600 RZ.C || echo "restore of RZ.C fails"
echo "x - extracting RZLNK (Text)"
sed 's/^X//' << 'SHAR_EOF' > RZLNK &&
Xc:\lib\gemstart.o common.o rz.o util.o tyme.o zm.o fileio.o
Xc:\lib\osbind.o c:\lib\gemlib c:\lib\libf
SHAR_EOF
chmod 0600 RZLNK || echo "restore of RZLNK fails"
echo "x - extracting SZ.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > SZ.C &&
X/*
X * ACKNOWLEDGEMENTS
X *
X * ZMDM was derived from rz/sz for Unix posted by
X * Chuck Forsberg (...!tektronix!reed!omen!caf ). We
X * thank him for his excellent code, and for giving
X * us permission to use and distribute his code and
X * documentation.
X *
X * Atari St version by:
X * Jwahar Bammi
X * usenet: mandrill!bammi@{decvax,sun}.UUCP
X * csnet: bammi@mandrill.ces.CWRU.edu
X * arpa: bammi@mandrill.ces.CWRU.edu
X * CompuServe: 71515,155
X */
X
X#include "config.h"
X#define SVERSION "sz 1.23 01-15-87"
X#define SSTVERSION "sz 1.01 03-07-87"
X#define OS "Unix V7/BSD"
X
X#ifndef STANDALONE
X#define RETURN return
X#else
Xint bibi() {} /* dummy */
X#endif
X
X/* #define SDEBUG */
X
X/*
X * sz.c By Chuck Forsberg
X *
X * cc -O sz.c -o sz USG (SYS III/V) Unix
X * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
X *
X * define CRCTABLE to use table driven CRC
X *
X * ******* Some systems (Venix, Coherent, Regulus) do not *******
X * ******* support tty raw mode read(2) identically to *******
X * ******* Unix. ONEREAD must be defined to force one *******
X * ******* character reads for these systems. *******
X *
X * A program for Unix to send files and commands to computers running
X * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
X *
X * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
X *
X * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
X *
X * St v 1.01
X * added support for 32 bit CRC's (Zmodem) ++jrb
X *
X */
X
X#include "zmdm.h"
X#include "common.h"
X#include "zmodem.h"
X
X#ifndef Vsync /* Atari forgot these in osbind.h */
X#define Vsync() xbios(37)
X#endif
X
X#ifndef Supexec
X /* Some versions of osbind don't define Supexec */
X#define Supexec(X) xbios(38,X)
X#endif
X
X#define SLOGFILE "szlog"
X
X#define purgeline() while(Bconstat(1)) Bconin(1)
X#define S_IFDIR 0x0010
X
X/*
X * Attention string to be executed by receiver to interrupt streaming data
X * when an error is detected. A pause (0336) may be needed before the
X * ^C (03) or after it.
X */
X#ifdef READCHECK
Xchar Myattn[] = { 0 };
X#else
X#ifdef USG
Xchar Myattn[] = { 03, 0336, 0 };
X#else
Xchar Myattn[] = { 0 };
X#endif
X#endif
X
X#if (MWC || MANX)
XFILE *fopen();
X#else
XFILE *fopen(), *fopenb();
X#endif
Xstatic unsigned long SaveIntr;
Xstatic int Resuming, ForceBin;
Xstatic int in;
X
X/* called by signal interrupt or terminate to clean things up */
Xbibis(n)
Xint n;
X{
X canit(); flush_modem(); mode(0);
X fprintf(STDERR, "\r\nsz: caught signal %d; exiting\n", n);
X
X aexit(128+n);
X}
X
X/* Called when Zmodem gets an interrupt (^X) */
X#ifdef ONINTR
Xonintr()
X{
X siggi = 0;
X longjmp(intrjmp, -1);
X}
X#endif
X
X#define ZKER
Xint Zctlesc; /* Encode control characters */
X
X#ifdef STANDALONE
Xint main(argc, argv)
X#else
Xint dosz(argc, argv)
X#endif
Xint argc;
Xchar **argv;
X{
X register char *cp;
X register int npats;
X int agcnt; char **agcv;
X char **patts;
X
X#ifdef STANDALONE
X#ifdef MWC
X extern char *lmalloc();
X#endif
X
X /* Set up Dta */
X Fsetdta(&statbuf);
X
X /* Get screen rez */
X rez = Getrez();
X drv_map = Drvmap();
X
X#if (MWC || MANX)
X#ifndef DYNABUF
X#ifdef MWC
X if((bufr = (unsigned char *)lmalloc((unsigned long)BBUFSIZ))
X == (unsigned char *)NULL)
X#else
X if((bufr = (unsigned char *)Malloc((unsigned long)BBUFSIZ))
X == (unsigned char *)NULL)
X#endif
X#else
X if((bufr = dalloc()) == (unsigned char *)NULL)
X#endif /* DYNABUF */
X {
X#ifdef REMOTE
X Bauxws("Sorry, could not allocate enough memory\r\n");
X#else
X Bconws("Sorry, could not allocate enough memory\r\n");
X#endif
X
X Pterm(4);
X }
X#else /* MWC || MANX */
X#ifdef DYNABUF
X if((bufr = dalloc()) == (unsigned char *)NULL)
X {
X#ifdef REMOTE
X Bauxws("Sorry, could not allocate enough memory\r\n");
X#else
X Bconws("Sorry, could not allocate enough memory\r\n");
X#endif
X Pterm(5);
X }
X#endif /* DYNABUF */
X#endif /* MWC || MANX */
X
X#ifndef REMOTE
X STDERR = stderr;
X#else
X#ifndef DLIBS
X if((STDERR = fopen("aux:", "rw")) == (FILE *)NULL)
X {
X Bauxws("Could not Open Aux Stream for Stderr\r\n");
X finish();
X }
X setbuf(STDERR, (char *)NULL);
X#else
X STDERR = stdaux;
X#endif /* DLIBS */
X
X#endif /* REMOTE */
X {
X int speed;
X speed = getbaud();
X Baudrate = BAUD_RATE(speed);
X SetIoBuf();
X Rsconf(speed, 0,-1,-1,-1,-1);
X Vsync(); Vsync();
X }
X#endif /* STANDALONE */
X
X SendType = 1;
X Rxtimeout = 600;
X npats=0;
X if (argc<2)
X {
X susage();
X RETURN(1);
X }
X
X initz();
X#ifndef STANDALONE
X schkinvok(argv[0]);
X#else
X Progname = "sz";
X#endif
X
X SaveIntr = Setexc(0x0102, -1L);
X BusErr = Setexc(2, -1L);
X AddrErr = Setexc(3, -1L);
X
X Verbose = 0;
X Resuming = FALSE;
X ForceBin = FALSE;
X in = (-1);
X vdebug = 0;
X
X#ifdef SDEBUG
X logf = (FILE *)NULL;
X#endif
X while (--argc) {
X cp = *++argv;
X if (*cp++ == '-' && *cp) {
X while ( *cp) {
X switch(*cp++) {
X case '+':
X Lzmanag = ZMAPND; break;
X#ifdef CSTOPB
X case '2':
X Twostop = TRUE; break;
X#endif
X case '7':
X Wcsmask=0177; break;
X
X/*
X On the St we look up the ext and decide. For Xmodem
X transfers, the file is always sent in binary mode
X and it is the responsibility of the receiver to
X strip CR if so desired.
X case 'a':
X Lzconv = ZCNL;
X Ascii = TRUE; break;
X case 'b':
X Lzconv = ZCBIN; break;
X*/
X
X/* ST extention, force binary, useful to back up every thing
X * in image mode, see -B option of rz too +jrb
X */
X case 'B':
X ForceBin = TRUE;
X Lzconv = ZCBIN;
X break;
X case 'C':
X if (--argc < 1) {
X susage();
X RETURN(1);
X }
X Cmdtries = atoi(*++argv);
X break;
X case 'i':
X Cmdack1 = ZCACK1;
X /* **** FALL THROUGH TO **** */
X case 'c':
X if (--argc != 1) {
X susage();
X RETURN(1);
X }
X Command = TRUE;
X Cmdstr = *++argv;
X break;
X case 'd':
X ++Dottoslash;
X /* **** FALL THROUGH TO **** */
X case 'f':
X Fullname=TRUE; break;
X case 'E':
X Zctlesc = (-1); break;
X case 'e':
X Zctlesc = 1; break;
X case 'k':
X Blklen=KSIZE; break;
X case 'L':
X if (--argc < 1) {
X susage();
X RETURN(1);
X }
X blkopt = atoi(*++argv);
X if (blkopt<32 || blkopt>1024)
X {
X susage();
X RETURN(1);
X }
X break;
X case 'l':
X if (--argc < 1) {
X susage();
X RETURN(1);
X }
X Tframlen = atoi(*++argv);
X if (Tframlen<32 || Tframlen>1024)
X {
X susage();
X RETURN(1);
X }
X break;
X case 'N':
X Lzmanag = ZMDIFF; break;
X case 'n':
X Lzmanag = ZMNEW; break;
X case 'o':
X Wantfcs32 = FALSE; break;
X case 'p':
X Lzmanag = ZMPROT; break;
X case 'r':
X Lzconv = ZCRESUM; Resuming = TRUE; break;
X case 'q':
X Quiet=TRUE; Verbose=0; break;
X case 't':
X if (--argc < 1) {
X susage();
X RETURN(1);
X }
X Rxtimeout = atoi(*++argv);
X if (Rxtimeout<10 || Rxtimeout>1000)
X {
X susage();
X RETURN(1);
X }
X break;
X#ifdef TESTATTN
X case 'T':
X Testattn = TRUE; break;
X#endif
X case 'u':
X ++Unlinkafter; break;
X case 'v':
X ++Verbose; break;
X case 'X':
X ++Modem; break;
X case 'y':
X Lzmanag = ZMCLOB; break;
X default:
X susage();
X RETURN(1);
X }
X }
X }
X else if ( !npats && argc>0) {
X if (argv[0][0]) {
X npats=argc;
X patts=argv;
X }
X }
X }
X if (npats < 1 && !Command)
X {
X susage();
X RETURN(1);
X }
X
X#ifdef SDEBUG
X if (Verbose > 2)
X {
X if ((logf = fopen(SLOGFILE, "a"))== (FILE *)NULL)
X {
X fprintf(STDERR, "Can't open log file %s\n",SLOGFILE);
X RETURN(0200);
X }
X fprintf(logf, "Progname=%s\n", Progname);
X vdebug = 1;
X fflush(logf);
X }
X#endif
X
X if ( !Quiet)
X {
X if (Verbose < 2)
X Verbose = 2;
X }
X
X
X Setexc(0x0102, bibis);
X Setexc(2, buserr);
X Setexc(3, addrerr);
X
X if(setjmp(busjmp))
X {
X /* On a bus error - instead of 2 bombs */
X fprintf(STDERR,"\r\nFATAL: Bus Error\n\n");
X#ifdef SDEBUG
X if(logf != (FILE *)NULL)
X fclose(logf);
X#endif
X if(in != -1)
X {
X stfclose(in);
X in = (-1);
X }
X canit();
X Setexc(2, BusErr);
X Setexc(3, AddrErr);
X Setexc(0x0102, SaveIntr);
X RETURN(2);
X }
X
X if(setjmp(addrjmp))
X {
X /* On address error - instead of 3 bombs */
X fprintf(STDERR,"\r\nFATAL: Address Error\n\n");
X#ifdef SDEBUG
X if(logf != (FILE *)NULL)
X fclose(logf);
X#endif
X if(in != -1)
X {
X stfclose(in);
X in = (-1);
X }
X canit();
X Setexc(2, BusErr);
X Setexc(3, AddrErr);
X Setexc(0x0102, SaveIntr);
X RETURN(3);
X }
X
X if((Exitcode = setjmp(abrtjmp)))
X {
X fprintf(STDERR,"\nTransfer ABORT\n\n");
X#ifdef SDEBUG
X if(logf != (FILE *)NULL)
X fclose(logf);
X#endif
X if(in != -1)
X {
X stfclose(in);
X in = (-1);
X }
X Setexc(2, BusErr);
X Setexc(3, AddrErr);
X Setexc(0x0102, SaveIntr);
X RETURN(Exitcode);
X }
X
X mode(1);
X
X
X if ( !Modem) {
X if (!Command && !Quiet && Verbose != 1)
X {
X fprintf(STDERR, "sz: %d file%s requested:\n",
X npats, npats>1?"s":"");
X for ( agcnt=npats, agcv=patts; --agcnt>=0; )
X {
X fprintf(STDERR, "%s ", *agcv++);
X }
X fprintf(STDERR, "\n\n");
X
X#ifdef SDEBUG
X if(Verbose > 2)
X {
X fprintf(logf, "sz: %d file%s requested:\n",
X npats, npats>1?"s":"");
X for ( agcnt=npats, agcv=patts; --agcnt>=0; )
X {
X fprintf(logf, "%s ", *agcv++);
X }
X fprintf(logf, "\n");
X fflush(logf);
X }
X#endif
X }
X if (!Nozmodem) {
X stohdr(0L);
X if (Command)
X Txhdr[ZF0] = ZCOMMAND;
X zshhdr(ZRQINIT, Txhdr);
X }
X }
X flush_modem();
X
X if (Command) {
X if (getzrxinit()) {
X Exitcode=0200; canit();
X }
X else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
X Exitcode=0200; canit();
X }
X } else if (wcsend(npats, patts)==ERROR) {
X Exitcode=0200;
X canit();
X }
X flush_modem();
X mode(0);
X
X#ifdef SDEBUG
X if(logf != (FILE *)NULL)
X fclose(logf);
X#endif
X if(in != -1)
X {
X fclose(in);
X in = (-1);
X }
X
X putc('\n', STDERR);
X Setexc(2, BusErr);
X Setexc(3, AddrErr);
X Setexc(0x0102, SaveIntr);
X RETURN((errcnt != 0) | Exitcode);
X
X}
X
X#ifdef STANDALONE
XRETURN(n)
Xint n;
X{
X ResetIoBuf();
X#if (MWC || MANX)
X#ifndef DYNABUF
X free(bufr);
X#else
X Mfree(bufr);
X#endif
X#else
X#ifdef DYNABUF
X Mfree(bufr);
X#endif
X#endif
X exit(n);
X}
X#endif /* STANDALONE */
X
Xwcsend(argc, argp)
Xchar *argp[];
X{
X register int n;
X
X Crcflg=FALSE;
X Firstsec=TRUE;
X for (n=0; n<argc; ++n) {
X Totsecs = 0;
X if (wcs(argp[n])==ERROR)
X return ERROR;
X }
X Totsecs = 0;
X if (Filcnt==0) { /* bitch if we couldn't open ANY files */
X if (1) {
X Command = TRUE;
X Cmdstr = "echo \"sz: Can't open any requested files\"";
X if (getzrxinit()) {
X Exitcode=0200; canit();
X }
X else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
X Exitcode=0200; canit();
X }
X Exitcode = 1; return OK;
X }
X canit();
X fprintf(STDERR,"\n\nCan't open any requested files.\n\n");
X return ERROR;
X }
X if (Zmodem)
X saybibi();
X else
X wctxpn("");
X return OK;
X}
X
Xwcs(oname)
Xchar *oname;
X{
X extern struct stat statbuf;
X char name[PATHLEN];
X
X strcpy(name, oname);
X ++Noeofseen; Lastread = 0; Lastc = (-1); Dontread = FALSE;
X
X /* Check for directory or block special files */
X if(Fsfirst(name,(int)(0x01 | 0x010 | 0x020)) != 0)
X {
X ++errcnt;
X return OK; /* may be others */
X }
X
X if (statbuf.st_mode & S_IFDIR ) {
X return OK;
X }
X
X if((in = stfopen(oname,"r")) <= 0){
X ++errcnt;
X return OK; /* pass over it, there may be others */
X }
X
X ++Filcnt;
X switch (wctxpn(name)) {
X case ERROR:
X return ERROR;
X case ZSKIP:
X return OK;
X }
X if (!Zmodem && wctx()==ERROR)
X return ERROR;
X if (Unlinkafter)
X unlink(oname);
X return 0;
X}
X
X#define ISDRIVE(X) ( (((X >= 'a') && (X <= 'n'))) || ((X >= 'A') && (X <= 'N')))
X/*
X * generate and transmit pathname block consisting of
X * pathname (null terminated),
X * file length, mode time and file mode in octal
X * as provided by the St's Fsfirst() call.
X * N.B.: modifies the passed name, may extend it!
X */
Xwctxpn(name)
Xchar *name;
X{
X register char *p, *q;
X char name2[PATHLEN];
X unsigned long unixtime;
X extern struct stat statbuf;
X extern unsigned long st2unix(); /* Convert St's date and time to unix
X time (seconds since Jan 1 1970 00:00:00) */
X
X if(*name)
X if(Fsfirst(name,(int)(0x01 | 0x020)) != 0)
X return ERROR;
X
X if (Modem) {
X#ifndef REMOTE
X if (*name) {
X fprintf(STDERR,
X "Outgoing:\n\t Name: %s\n\t Size: %ld Bytes\n\
X\tBlocks: %ld\n\tBufSize: %ld\n\n",
X name, statbuf.st_size, statbuf.st_size>>7, (long)BBUFSIZ);
X }
X#endif /* REMOTE */
X return OK;
X }
X
X vfile2("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
X
X if ( !Zmodem)
X if (getnak())
X return ERROR;
X
X /* convert to Unix style path names */
X /* skip any device identifier */
X if(ISDRIVE(name[0]) && (name[1] == ':'))
X name = &name[2];
X
X for(p = name; *p != '\0'; p++)
X {
X if(*p == '\\')
X *p = '/';
X }
X
X if(!Resuming)
X {
X if(ForceBin)
X {
X Lzconv = ZCBIN;
X Ascii = FALSE;
X }
X else
X {
X if(!isbinary(name))
X {
X /* We indicate to the other side */
X Lzconv = ZCNL;
X Ascii = TRUE;
X }
X else
X {
X Lzconv = ZCBIN;
X Ascii = FALSE;
X }
X }
X }
X
X q = (char *) 0;
X if (Dottoslash) { /* change . to . */
X for (p=name; *p; ++p) {
X if (*p == '/')
X q = p;
X else if (*p == '.')
X *(q=p) = '/';
X }
X if (q && strlen(++q) > 8) { /* If name>8 chars */
X q += 8; /* make it .ext */
X strcpy(name2, q); /* save excess of name */
X *q = '.';
X strcpy(++q, name2); /* add it back */
X }
X }
X
X for (p=name, q=secbuf ; *p; )
X if ((*q++ = *p++) == '/' && !Fullname)
X q = secbuf;
X *q++ = 0;
X p=q;
X while (q < (secbuf + KSIZE))
X *q++ = 0;
X if (*name)
X {
X unixtime = st2unix(statbuf.st_time, statbuf.st_date);
X sprintf(p, "%lu %lo %o", statbuf.st_size,
X unixtime,
X ((statbuf.st_mode & 0x01)?0444:0644));
X }
X
X if(Verbose)
X#ifndef REMOTE
X fprintf(STDERR,
X"Outgoing: [Hit CTRL-C to Cancel]\n\tName: %s\n\tSize: %ld Bytes\n\tBufSize:\
X %ld\n",
X name, statbuf.st_size, (long)BBUFSIZ);
X if(!Resuming)
X {
X fprintf(STDERR,"\tMode: %s\n\n", (Ascii)?"ASCII":"BINARY");
X }
X else
X {
X fprintf(STDERR,"\tMode: Resume Transfer Mode\n\n");
X }
X#endif
X
X#ifdef SDEBUG
X if(Verbose > 2)
X {
X fprintf(STDERR,"File: %s (%s)\n", name, p);
X fprintf(logf,"File: %s (%s)\n", name, p);
X fflush(logf);
X }
X#endif
X
X /* force 1k blocks if name won't fit in 128 byte block */
X if (secbuf[125])
X Blklen=KSIZE;
X else { /* A little goodie for IMP/KMD */
X if (Zmodem)
X Blklen = SECSIZ;
X secbuf[127] = (statbuf.st_size + 127) >>7;
X secbuf[126] = (statbuf.st_size + 127) >>15;
X }
X if (Zmodem)
X return zsendfile(secbuf, (int)(1+strlen(p)+
X (int)((long)p-(long)secbuf)), statbuf.st_size);
X if (wcputsec(secbuf, 0, SECSIZ)==ERROR)
X return ERROR;
X return OK;
X}
X
Xgetnak()
X{
X register int firstch;
X
X Lastrx = 0;
X for (;;) {
X switch (firstch = readock(800,1)) {
X case ZPAD:
X if (getzrxinit())
X return ERROR;
X Ascii = 0;
X return FALSE;
X case TIMEOUT:
X vfile("Timeout on pathname\n");
X return TRUE;
X case WANTG:
X#ifdef USG
X mode(2); /* Set cbreak, XON/XOFF, etc. */
X#endif
X Optiong = TRUE;
X Blklen=KSIZE;
X case WANTCRC:
X Crcflg = TRUE;
X case NAK:
X return FALSE;
X case CAN:
X if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
X return TRUE;
X default:
X break;
X }
X Lastrx = firstch;
X }
X}
X
X
Xwctx()
X{
X register int sectnum, attempts, firstch;
X
X Firstsec=TRUE;
X
X while ((firstch=readock(Rxtimeout, 2))!=NAK && firstch != WANTCRC
X && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
X ;
X if (firstch==CAN) {
X fprintf(STDERR, "\r\nReceiver CANcelled\n");
X return ERROR;
X }
X if (firstch==WANTCRC)
X Crcflg=TRUE;
X if (firstch==WANTG)
X Crcflg=TRUE;
X sectnum=1;
X while (filbuf(secbuf, Blklen)) {
X if (wcputsec(secbuf, sectnum, Blklen)==ERROR) {
X return ERROR;
X } else
X sectnum++;
X }
X
X#ifndef REMOTE
X if (Verbose>1)
X {
X fprintf(STDERR, "\nClosing\n\n");
X#ifdef SDEBUG
X if(Verbose > 2)
X {
X fprintf(logf, " Closing\n");
X fflush(logf);
X }
X#endif
X }
X#endif /* REMOTE */
X
X stfclose(in);
X in = (-1);
X
X attempts=0;
X do {
X vfile(" EOT ");
X purgeline();
X sendline(EOT);
X flush_modem();
X ++attempts;
X }
X while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX);
X if (attempts == RETRYMAX) {
X fprintf(STDERR, "\r\nNo ACK on EOT\n");
X return ERROR;
X }
X else
X return OK;
X}
X
Xwcputsec(buf, sectnum, cseclen)
Xchar *buf;
Xint sectnum;
Xint cseclen; /* data length of this sector to send */
X{
X register int checksum, wcj;
X register char *cp;
X unsigned int oldcrc;
X int firstch;
X int attempts;
X
X firstch=0; /* part of logic to detect CAN CAN */
X
X#ifndef REMOTE
X if (Verbose>1)
X {
X fprintf(STDERR, "\rBlock %06d %04dK ", Totsecs, (Totsecs>>3));
X#ifdef SDEBUG
X if(Verbose > 2)
X {
X fprintf(logf, "\rBlock %d %dK ", Totsecs, (Totsecs>>3) );
X fflush(logf);
X }
X#endif
X }
X#endif /* REMOTE */
X
X for (attempts=0; attempts <= RETRYMAX; attempts++) {
X Lastrx= firstch;
X sendline(cseclen==KSIZE?STX:SOH);
X sendline(sectnum);
X sendline(-sectnum -1);
X oldcrc=checksum=0;
X for (wcj=cseclen,cp=buf; --wcj>=0; ) {
X sendline(*cp);
X oldcrc=updcrc((0377& *cp), oldcrc);
X checksum += *cp++;
X }
X if (Crcflg) {
X oldcrc=updcrc(0,updcrc(0,oldcrc));
X sendline((int)oldcrc>>8);
X sendline((int)oldcrc);
X }
X else
X sendline(checksum);
X
X if (Optiong) {
X Firstsec = FALSE; return OK;
X }
X firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1);
Xgotnak:
X switch (firstch) {
X case CAN:
X if(Lastrx == CAN) {
Xcancan:
X fprintf(STDERR, "\r\nCancelled\n"); return ERROR;
X }
X break;
X case TIMEOUT:
X vfile("Timeout on sector ACK\n"); continue;
X case WANTCRC:
X if (Firstsec)
X Crcflg = TRUE;
X case NAK:
X vfile("NAK on sector\n"); continue;
X case ACK:
X Firstsec=FALSE;
X Totsecs += (cseclen>>7);
X return OK;
X case ERROR:
X vfile("Got burst for sector ACK\n"); break;
X default:
X vfile("Got %02x for sector ACK\n", firstch); break;
X }
X for (;;) {
X Lastrx = firstch;
X if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT)
X break;
X if (firstch == NAK || firstch == WANTCRC)
X goto gotnak;
X if (firstch == CAN && Lastrx == CAN)
X goto cancan;
X }
X }
X fprintf(STDERR, "\r\nRetry Count Exceeded\n");
X return ERROR;
X}
X
X/* fill buf with count chars padding with ^Z for CPM */
Xfilbuf(buf, count)
Xregister unsigned char *buf;
Xregister int count;
X{
X register int m;
X
X if((buf[0] = stgetc(in)) == EOF)
X return 0;
X
X for(m = 1; (m < count) && ((buf[m] = stgetc(in)) != EOF); m++)
X /* loop */ ;
X
X while (m < count)
X buf[m++] = 032;
X
X return count;
X
X}
X/* fill buf with count chars */
Xzfilbuf(buf, count)
Xregister char *buf;
X{
X register int c, m;
X
X m=count;
X while ((c=stgetc(in))!=EOF) {
X *buf++ =c;
X if (--m == 0)
X break;
X }
X return (count - m);
X}
X
X/*
X * readock(timeout, count) reads character(s) from file descriptor 0
X * (1 <= count <= 3)
X * it attempts to read count characters. If it gets more than one,
X * it is an error unless all are CAN
X * (otherwise, only normal response is ACK, CAN, or C)
X * Only looks for one if Optiong, which signifies cbreak, not raw input
X *
X * timeout is in tenths of seconds
X */
Xreadock(timeout, count)
Xint timeout, count;
X{
X register int c;
X static char byt[5];
X
X if (Optiong)
X count = 1; /* Special hack for cbreak */
X
X if (setjmp(tohere)) {
X vfile("TIMEOUT\n");
X return TIMEOUT;
X }
X c = timeout >> 3;
X if (c<2)
X c=2;
X#ifdef SDEBUG
X if (Verbose>3) {
X fprintf(STDERR, "Timeout=%d Calling alarm(%d) ", timeout, c);
X byt[1] = 0;
X fprintf(logf, "Timeout=%d Calling alarm(%d) ", timeout, c);
SHAR_EOF
echo "End of part 4"
echo "File SZ.C is continued in part 5"
echo "5" > s2_seq_.tmp
exit 0