page%swap@Sun.COM (Bob Page) (10/20/89)
Submitted-by: acs@pccuts.pcc.amdahl.com (Tony Sumrall)
Posting-number: Volume 89, Issue 180
Archive-name: comm/vt100r29.3
# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
# Zmodem/rbsb.c
# Zmodem/zm.c
# Zmodem/sz.c
# This is archive 3 of a 9-part kit.
# This archive created: Thu Oct 19 22:30:29 1989
if `test ! -d Zmodem`
then
mkdir Zmodem
echo "mkdir Zmodem"
fi
echo "extracting Zmodem/rbsb.c"
sed 's/^X//' << \SHAR_EOF > Zmodem/rbsb.c
X/*
X *
X * -rev 04-16-87
X * This file contains Unix specific code for setting terminal modes,
X * very little is specific to ZMODEM or YMODEM per se (that code is in
X * sz.c and rz.c). The CRC-16 routines used by XMODEM, YMODEM, and ZMODEM
X * are also in this file, a fast table driven macro version
X *
X * This file is #included so the main file can set parameters such as HOWMANY.
X * See the main files (rz.c/sz.c) for compile instructions.
X */
X#ifdef AMIGA
X#define OS "the Amiga"
Xstruct IOExtSer *SetSer();
XULONG Len,Stop,ParFlags;
Xchar ParityCH; /* parity character N=none,E=even,O=odd */
X
X/*
X * if op is 0 then clean up and prepare for exit
X * if op is 1 then init serial port, timers etc.
X * bomb for the other modes
X */
Xmode(op)
Xint op;
X{
X struct IOExtSer *Ser;
X
X switch(op)
X {
X case 1:if( SetTimer()!=0 ) return ERROR;
X else {
X InitParams();
X if( (Ser=SetSer(InitSer?Baudrate:-1,Len,Stop,SERF_SHARED|SERF_XDISABLED|ParFlags))==NULL )
X return ERROR;
X }
X UpDateParms(Ser);
X fprintf(stderr,"Transferring at %d baud, %d%c%d\n",Baudrate,Len,ParityCH,Stop);
X#ifndef RZ /* sz needs bigger buffer for higher speeds */
X if (Baudrate > 300)
X BufferSize = 256;
X if (Baudrate > 1200)
X BufferSize = 512;
X if (Baudrate > 2400)
X BufferSize = KSIZE;
X if (Rxbuflen && BufferSize>Rxbuflen)
X BufferSize = Rxbuflen;
X if (blkopt && BufferSize > blkopt)
X BufferSize = blkopt;
X Next=OutBuf=(UBYTE *)malloc(BufferSize);
X#endif
X return OK;
X
X case 0:
X CloseSer();
X CloseTimer();
X#ifndef RZ
X if(OutBuf) free(OutBuf);
X#endif
X return OK;
X
X default: /* bomb for other modes */
X return ERROR;
X }
X
X}
X
XInitParams()
X{
X FILE *fparm;
X
X if( (fparm=fopen("zmodem.init","r"))==NULL &&
X (fparm=fopen("S:zmodem.init","r"))==NULL)
X {
X /* default to preferences */
X InitSer = FALSE;
X }
X else
X {
X gmt_diff=100;
X fscanf(fparm,"%d %d%c%d %d",&Baudrate,&Len,&ParityCH,&Stop,&gmt_diff);
X if(gmt_diff!=100) gmt_diff_set=TRUE;
X fclose(fparm);
X switch(ParityCH)
X {
X case 'E':
X case 'e': ParFlags = SERF_PARTY_ON;break;
X
X case 'o':
X case 'O': ParFlags = SERF_PARTY_ON|SERF_PARTY_ODD;break;
X
X default : ParFlags = NULL;
X }
X }
X}
X
XUpDateParms(SS)
Xstruct IOExtSer *SS;
X{
X if( !InitSer)
X {
X Baudrate = SS->io_Baud;
X Len = SS->io_ReadLen;
X Stop = SS->io_StopBits;
X if( SS->io_SerFlags & SERF_PARTY_ON)
X {
X if( SS->io_SerFlags & SERF_PARTY_ODD)
X ParityCH = 'O';
X else
X ParityCH= 'E';
X }
X else
X ParityCH = 'N';
X }
X if( Len<8 || ParityCH!='N')
X {
X /* set 7 bit text mode */
X Wcsmask = 0177;
X#ifdef RZ
X Rxascii=TRUE;
X#else
X Lzconv = 2; /* This 2 is really ZCNL, but the way the includes are */
X Ascii = TRUE; /* set up I had to hack it this way */
X#endif
X }
X}
X
Xsleep(n)
Xint n;
X{
X
X
X if(n>0) Delay (50*n);
X return (0);
X}
X#else /* UNIX versions */
X#ifdef V7
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sgtty.h>
X#define OS "V7/BSD"
X#endif
X
X#ifndef OS
X#ifndef USG
X#define USG
X#endif
X#endif
X
X#ifdef USG
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <termio.h>
X#include <sys/ioctl.h>
X#define OS "SYS III/V"
X#endif
X
X#if HOWMANY > 255
XHowmany must be 255 or less
X#endif
X
Xstruct {
X unsigned baudr;
X int speedcode;
X} speeds[] = {
X 110, B110,
X 300, B300,
X 600, B600,
X 1200, B1200,
X 2400, B2400,
X 4800, B4800,
X 9600, B9600,
X 19200, EXTA,
X 9600, EXTB,
X 0,
X};
X
Xint Twostop; /* Use two stop bits */
X
Xstatic unsigned
Xgetspeed(code)
X{
X register n;
X
X for (n=0; speeds[n].baudr; ++n)
X if (speeds[n].speedcode == code)
X return speeds[n].baudr;
X return 0;
X}
X
X
X
X#ifdef ICANON
Xstruct termio oldtty, tty;
X#else
Xstruct sgttyb oldtty, tty;
Xstruct tchars oldtch, tch;
X#endif
X
Xint iofd = 0; /* File descriptor for ioctls & reads */
X
X/*
X * mode(n)
X * 3: save old tty stat, set raw mode with flow control
X * 2: set a cbreak, XON/XOFF control mode if using Pro-YAM's -g option
X * 1: save old tty stat, set raw mode
X * 0: restore original tty mode
X */
Xmode(n)
X{
X static did0 = FALSE;
X
X vfile("mode:%d", n);
X switch(n) {
X#ifdef USG
X case 2: /* Cbreak mode used by sb when -g detected */
X if(!did0)
X (void) ioctl(iofd, TCGETA, &oldtty);
X tty = oldtty;
X
X tty.c_iflag = BRKINT|IXON;
X
X tty.c_oflag = 0; /* Transparent output */
X
X tty.c_cflag &= ~PARENB; /* Disable parity */
X tty.c_cflag |= CS8; /* Set character size = 8 */
X if (Twostop)
X tty.c_cflag |= CSTOPB; /* Set two stop bits */
X
X tty.c_lflag =
X#ifdef XCLUDE
X XCLUDE |
X#endif
X Zmodem ? 0 : ISIG;
X
X tty.c_cc[VINTR] = 030; /* Interrupt char */
X tty.c_cc[VMIN] = 1;
X
X (void) ioctl(iofd, TCSETAW, &tty);
X did0 = TRUE;
X return OK;
X case 1:
X case 3:
X if(!did0)
X (void) ioctl(iofd, TCGETA, &oldtty);
X tty = oldtty;
X
X tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
X
X /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
X tty.c_lflag &= ~(ECHO | ICANON | ISIG);
X#ifdef XCLUDE
X tty.c_lflag |= XCLUDE;
X#endif
X
X tty.c_oflag = 0; /* Transparent output */
X
X tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */
X tty.c_cflag |= CS8; /* Set character size = 8 */
X if (Twostop)
X tty.c_cflag |= CSTOPB; /* Set two stop bits */
X#ifdef NFGVMIN
X tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
X#else
X tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
X#endif
X tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
X (void) ioctl(iofd, TCSETAW, &tty);
X did0 = TRUE;
X Baudrate = getspeed(tty.c_cflag & CBAUD);
X return OK;
X#endif
X#ifdef V7
X case 2: /* This doesn't work ... */
X printf("No mode(2) in V7/BSD!"); bibi(99);
X if(!did0) {
X ioctl(iofd, TIOCEXCL, 0);
X ioctl(iofd, TIOCGETP, &oldtty);
X ioctl(iofd, TIOCGETC, &oldtch);
X }
X tty = oldtty;
X tch = oldtch;
X tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */
X tty.sg_flags |= (ODDP|EVENP|CBREAK);
X tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
X ioctl(iofd, TIOCSETP, &tty);
X ioctl(iofd, TIOCSETC, &tch);
X did0 = TRUE;
X return OK;
X case 1:
X case 3:
X if(!did0) {
X ioctl(iofd, TIOCEXCL, 0);
X ioctl(iofd, TIOCGETP, &oldtty);
X ioctl(iofd, TIOCGETC, &oldtch);
X }
X tty = oldtty;
X tty.sg_flags |= RAW;
X tty.sg_flags &= ~ECHO;
X ioctl(iofd, TIOCSETP, &tty);
X did0 = TRUE;
X Baudrate = getspeed(tty.sg_ospeed);
X return OK;
X#endif
X case 0:
X if(!did0)
X return ERROR;
X#ifdef USG
X (void) ioctl(iofd, TCSBRK, 1); /* Wait for output to drain */
X (void) ioctl(iofd, TCFLSH, 1); /* Flush input queue */
X (void) ioctl(iofd, TCSETAW, &oldtty); /* Restore original modes */
X (void) ioctl(iofd, TCXONC,1); /* Restart output */
X#endif
X#ifdef V7
X ioctl(iofd, TIOCSETP, &oldtty);
X ioctl(iofd, TIOCSETC, &oldtch);
X ioctl(iofd, TIOCNXCL, 0);
X#endif
X return OK;
X default:
X return ERROR;
X }
X}
X#endif
X
Xsendbrk()
X{
X#ifdef AMIGA
X SendBreak();
X#else
X#ifdef V7
X#ifdef TIOCSBRK
X#define CANBREAK
X sleep(1);
X ioctl(iofd, TIOCSBRK, 0);
X sleep(1);
X ioctl(iofd, TIOCCBRK, 0);
X#endif
X#endif
X#ifdef USG
X#define CANBREAK
X ioctl(iofd, TCSBRK, 0);
X#endif
X#endif /* AMIGA */
X}
X
X#ifdef AMIGA
Xrdchk()
X{
X if (SerOpen) {
X if (Lleft>0) return Lleft;
X else return CharsWaiting();
X }
X}
X#else
X#ifdef FIONREAD
X#define READCHECK
X/*
X * Return non 0 iff something to read from io descriptor f
X */
Xrdchk(f)
X{
X static long lf;
X
X ioctl(f, FIONREAD, &lf);
X return ((int) lf);
X}
X#endif
X#ifdef SVR2
X#define READCHECK
X#include <fcntl.h>
X
Xchar checked = '\0' ;
X/*
X * Nonblocking I/O is a bit different in System V, Release 2
X */
Xrdchk(f)
X{
X int lf, savestat = fcntl(f, F_GETFL) ;
X
X fcntl(f, F_SETFL, savestat | O_NDELAY) ;
X lf = read(f, &checked, 1) ;
X fcntl(f, F_SETFL, savestat) ;
X return(lf) ;
X}
X#endif
X#endif
X
X/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
Xstatic unsigned short crctab[256] = {
X 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
X 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
X 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
X 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
X 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
X 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
X 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
X 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
X 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
X 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
X 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
X 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
X 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
X 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
X 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
X 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
X 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
X 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
X 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
X 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
X 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
X 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
X 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
X 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
X 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
X 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
X 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
X 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
X 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
X 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
X 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
X 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
X};
X
X/*
X * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
X * NOTE: First srgument must be in range 0 to 255.
X * Second argument is referenced twice.
X *
X * Programmers may incorporate any or all code into their programs,
X * giving proper credit within the source. Publication of the
X * source routines is permitted so long as proper credit is given
X * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
X * Omen Technology.
X */
X
X#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
X
X/*
X * Copyright (C) 1986 Gary S. Brown. You may use this program, or
X * code or tables extracted from it, as desired without restriction.
X */
X
X/* First, the polynomial itself and its table of feedback terms. The */
X/* polynomial is */
X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
X/* Note that we take it "backwards" and put the highest-order term in */
X/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
X/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
X/* the MSB being 1. */
X
X/* Note that the usual hardware shift register implementation, which */
X/* is what we're using (we're merely optimizing it by doing eight-bit */
X/* chunks at a time) shifts bits into the lowest-order term. In our */
X/* implementation, that means shifting towards the right. Why do we */
X/* do it this way? Because the calculated CRC must be transmitted in */
X/* order from highest-order term to lowest-order term. UARTs transmit */
X/* characters in order from LSB to MSB. By storing the CRC this way, */
X/* we hand it to the UART in the order low-byte to high-byte; the UART */
X/* sends each low-bit to hight-bit; and the result is transmission bit */
X/* by bit from highest- to lowest-order term without requiring any bit */
X/* shuffling on our part. Reception works similarly. */
X
X/* The feedback terms table consists of 256, 32-bit entries. Notes: */
X/* */
X/* The table can be generated at runtime if desired; code to do so */
X/* is shown later. It might not be obvious, but the feedback */
X/* terms simply represent the results of eight shift/xor opera- */
X/* tions for all combinations of data and CRC register values. */
X/* */
X/* The values must be right-shifted by eight bits by the "updcrc" */
X/* logic; the shift must be unsigned (bring in zeroes). On some */
X/* hardware you could probably optimize the shift in assembler by */
X/* using byte-swap instructions. */
X
Xstatic long cr3tab[] = { /* CRC polynomial 0xedb88320 */
X0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
X0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
X0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
X0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
X0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
X0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
X0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
X0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
X0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
X0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
X0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
X0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
X0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
X0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
X0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
X0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
X0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
X0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
X0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
X0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
X0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
X0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
X0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
X0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
X0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
X0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
X0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
X0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
X0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
X0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
X0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
X0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
X};
X
X#ifdef NFGM
Xlong
XUPDC32(b, c)
Xlong c;
X{
X return (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF));
X}
X
X#else
X
X#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))
X#endif
X
X/* End of rbsb.c */
SHAR_EOF
echo "extracting Zmodem/zm.c"
sed 's/^X//' << \SHAR_EOF > Zmodem/zm.c
X/*
X * Z M . C
X * ZMODEM protocol primitives
X * 07-28-87 Chuck Forsberg Omen Technology Inc
X *
X * Entry point Functions:
X * zsbhdr(type, hdr) send binary header
X * zshhdr(type, hdr) send hex header
X * zgethdr(hdr, eflag) receive header - binary or hex
X * zsdata(buf, len, frameend) send data
X * zrdata(buf, len) receive data
X * stohdr(pos) store position data in Txhdr
X * long rclhdr(hdr) recover position offset from header
X */
X
X#ifndef CANFDX
X#include "zmodem.h"
Xint Rxtimeout = 100; /* Tenths of seconds to wait for something */
X#endif
X
X
X#ifndef UNSL
X#define UNSL
X#endif
X
X
X/* Globals used by ZMODEM functions */
Xint Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */
Xint Rxtype; /* Type of header received */
Xint Rxcount; /* Count of data bytes received */
Xchar Rxhdr[4]; /* Received header */
Xchar Txhdr[4]; /* Transmitted header */
Xlong Rxpos; /* Received file position */
Xlong Txpos; /* Transmitted file position */
Xint Txfcs32; /* TURE means send binary frames with 32 bit FCS */
Xint Crc32t; /* Display flag indicating 32 bit CRC being sent */
Xint Crc32; /* Display flag indicating 32 bit CRC being received */
Xint Znulls; /* Number of nulls to send at beginning of ZDATA hdr */
Xchar Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */
X
X
Xstatic char *frametypes[] = {
X "Carrier Lost", /* -3 */
X "TIMEOUT", /* -2 */
X "ERROR", /* -1 */
X#define FTOFFSET 3
X "ZRQINIT",
X "ZRINIT",
X "ZSINIT",
X "ZACK",
X "ZFILE",
X "ZSKIP",
X "ZNAK",
X "ZABORT",
X "ZFIN",
X "ZRPOS",
X "ZDATA",
X "ZEOF",
X "ZFERR",
X "ZCRC",
X "ZCHALLENGE",
X "ZCOMPL",
X "ZCAN",
X "ZFREECNT",
X "ZCOMMAND",
X "ZSTDERR",
X "xxxxx"
X#define FRTYPES 22 /* Total number of frame types in this array */
X /* not including psuedo negative entries */
X};
X
X/* Send ZMODEM binary header hdr of type type */
Xzsbhdr(type, hdr)
Xregister char *hdr;
X{
X register n;
X register unsigned short crc;
X
X vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X if (type == ZDATA)
X for (n = Znulls; --n >=0; )
X zsendline(0);
X
X xsendline(ZPAD); xsendline(ZDLE);
X
X if (Crc32t=Txfcs32)
X zsbh32(hdr, type);
X else {
X xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
X
X for (n=4; --n >= 0; ++hdr) {
X zsendline(*hdr);
X crc = updcrc((0377& *hdr), crc);
X }
X crc = updcrc(0,updcrc(0,crc));
X zsendline(crc>>8);
X zsendline(crc);
X }
X#ifndef AMIGA
X if (type != ZDATA)
X flushmo();
X#else
X flushmo();
X#endif
X}
X
X
X/* Send ZMODEM binary header hdr of type type */
Xzsbh32(hdr, type)
Xregister char *hdr;
X{
X register n;
X register UNSL long crc;
X
X xsendline(ZBIN32); zsendline(type);
X crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
X
X for (n=4; --n >= 0; ++hdr) {
X crc = UPDC32((0377 & *hdr), crc);
X zsendline(*hdr);
X }
X crc = ~crc;
X for (n=4; --n >= 0;) {
X zsendline((int)crc);
X crc >>= 8;
X }
X#ifdef AMIGA
X flushmo();
X#endif
X}
X
X/* Send ZMODEM HEX header hdr of type type */
Xzshhdr(type, hdr)
Xregister char *hdr;
X{
X register n;
X register unsigned short crc;
X
X vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
X sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
X zputhex(type);
X Crc32t = 0;
X
X crc = updcrc(type, 0);
X for (n=4; --n >= 0; ++hdr) {
X zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
X }
X crc = updcrc(0,updcrc(0,crc));
X zputhex(crc>>8); zputhex(crc);
X
X /* Make it printable on remote machine */
X sendline(015); sendline(012);
X /*
X * Uncork the remote in case a fake XOFF has stopped data flow
X */
X if (type != ZFIN && type != ZACK)
X sendline(021);
X flushmo();
X}
X
X/*
X * Send binary array buf of length length, with ending ZDLE sequence frameend
X */
Xzsdata(buf, length, frameend)
Xregister char *buf;
X{
X register unsigned short crc;
X
X vfile("zsdata: length=%d end=%x", length, frameend);
X if (Crc32t)
X zsda32(buf, length, frameend);
X else {
X crc = 0;
X for (;--length >= 0; ++buf) {
X zsendline(*buf); crc = updcrc((0377 & *buf), crc);
X }
X xsendline(ZDLE); xsendline(frameend);
X crc = updcrc(frameend, crc);
X
X crc = updcrc(0,updcrc(0,crc));
X zsendline(crc>>8); zsendline(crc);
X }
X if (frameend == ZCRCW) {
X xsendline(XON); flushmo();
X }
X#ifdef AMIGA
X else flushmo();
X#endif
X}
X
Xzsda32(buf, length, frameend)
Xregister char *buf;
X{
X register UNSL long crc;
X
X crc = 0xFFFFFFFFL;
X for (;--length >= 0;++buf) {
X crc = UPDC32((0377 & *buf), crc);
X zsendline(*buf);
X }
X xsendline(ZDLE); xsendline(frameend);
X crc = UPDC32(frameend, crc);
X
X crc = ~crc;
X for (length=4; --length >= 0;) {
X zsendline((int)crc); crc >>= 8;
X }
X}
X
X/*
X * Receive array buf of max length with ending ZDLE sequence
X * and CRC. Returns the ending character or error code.
X * NB: On errors may store length+1 bytes!
X */
Xzrdata(buf, length)
Xregister char *buf;
X{
X register c;
X register unsigned short crc;
X register char *end;
X register d;
X
X if (Rxframeind == ZBIN32)
X return zrdat32(buf, length);
X
X crc = Rxcount = 0; end = buf + length;
X while (buf <= end) {
X if ((c = zdlread()) & ~0377) {
Xcrcfoo:
X switch (c) {
X case GOTCRCE:
X case GOTCRCG:
X case GOTCRCQ:
X case GOTCRCW:
X crc = updcrc((d=c)&0377, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = updcrc(c, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = updcrc(c, crc);
X if (crc & 0xFFFF) {
X zperr("Bad data CRC");
X return ERROR;
X }
X Rxcount = length - (end - buf);
X vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
X return d;
X case GOTCAN:
X zperr("Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X zperr("TIMEOUT");
X return c;
X default:
X zperr("Bad data subpacket");
X return c;
X }
X }
X *buf++ = c;
X crc = updcrc(c, crc);
X }
X zperr("Data subpacket too long");
X return ERROR;
X}
X
Xzrdat32(buf, length)
Xregister char *buf;
X{
X register c;
X register UNSL long crc;
X register char *end;
X register d;
X
X crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length;
X while (buf <= end) {
X if ((c = zdlread()) & ~0377) {
Xcrcfoo:
X switch (c) {
X case GOTCRCE:
X case GOTCRCG:
X case GOTCRCQ:
X case GOTCRCW:
X d = c; c &= 0377;
X crc = UPDC32(c, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = UPDC32(c, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = UPDC32(c, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = UPDC32(c, crc);
X if ((c = zdlread()) & ~0377)
X goto crcfoo;
X crc = UPDC32(c, crc);
X if (crc != 0xDEBB20E3) {
X zperr("Bad data CRC");
X return ERROR;
X }
X Rxcount = length - (end - buf);
X vfile("zrdat32: cnt = %d ret = %x", Rxcount, d);
X return d;
X case GOTCAN:
X zperr("Sender Canceled");
X return ZCAN;
X case TIMEOUT:
X zperr("TIMEOUT");
X return c;
X default:
X zperr("Bad data subpacket");
X return c;
X }
X }
X *buf++ = c;
X crc = UPDC32(c, crc);
X }
X zperr("Data subpacket too long");
X return ERROR;
X}
X
X
X/*
X * Read a ZMODEM header to hdr, either binary or hex.
X * eflag controls local display of non zmodem characters:
X * 0: no display
X * 1: display printing characters only
X * 2: display all non ZMODEM characters
X * On success, set Zmodem to 1, set Rxpos and return type of header.
X * Otherwise return negative on error.
X * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
X */
Xzgethdr(hdr, eflag)
Xchar *hdr;
X{
X register c, n, cancount;
X
X n = Zrwindow + Baudrate; /* Max bytes before start of frame */
X Rxframeind = Rxtype = 0;
X
Xstartover:
X cancount = 5;
Xagain:
X /* Return immediate ERROR if ZCRCW sequence seen */
X switch (c = readline(Rxtimeout)) {
X case RCDO:
X case TIMEOUT:
X goto fifi;
X case CAN:
Xgotcan:
X if (--cancount <= 0) {
X c = ZCAN; goto fifi;
X }
X switch (c = readline(1)) {
X case TIMEOUT:
X goto again;
X case ZCRCW:
X c = ERROR;
X /* **** FALL THRU TO **** */
X case RCDO:
X goto fifi;
X default:
X break;
X case CAN:
X if (--cancount <= 0) {
X c = ZCAN; goto fifi;
X }
X goto again;
X }
X /* **** FALL THRU TO **** */
X default:
Xagn2:
X if ( --n == 0) {
X zperr("Garbage count exceeded");
X return(ERROR);
X }
X if (eflag && ((c &= 0177) & 0140))
X bttyout(c);
X else if (eflag > 1)
X bttyout(c);
X goto startover;
X case ZPAD|0200: /* This is what we want. */
X case ZPAD: /* This is what we want. */
X break;
X }
X cancount = 5;
Xsplat:
X switch (c = noxrd7()) {
X case ZPAD:
X goto splat;
X case RCDO:
X case TIMEOUT:
X goto fifi;
X default:
X goto agn2;
X case ZDLE: /* This is what we want. */
X break;
X }
X
X switch (c = noxrd7()) {
X case RCDO:
X case TIMEOUT:
X goto fifi;
X case ZBIN:
X Rxframeind = ZBIN; Crc32 = FALSE;
X c = zrbhdr(hdr);
X break;
X case ZBIN32:
X Crc32 = Rxframeind = ZBIN32;
X c = zrbhdr32(hdr);
X break;
X case ZHEX:
X Rxframeind = ZHEX; Crc32 = FALSE;
X c = zrhhdr(hdr);
X break;
X case CAN:
X goto gotcan;
X default:
X goto agn2;
X }
X Rxpos = hdr[ZP3] & 0377;
X Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
X Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
X Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
Xfifi:
X switch (c) {
X case GOTCAN:
X c = ZCAN;
X /* **** FALL THRU TO **** */
X case ZNAK:
X case ZCAN:
X case ERROR:
X case TIMEOUT:
X case RCDO:
X zperr("Got %s", frametypes[c+FTOFFSET]);
X /* **** FALL THRU TO **** */
X default:
X if (c >= -3 && c <= FRTYPES)
X vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
X else
X vfile("zgethdr: %d %lx", c, Rxpos);
X }
X return c;
X}
X
X/* Receive a binary style header (type and position) */
Xzrbhdr(hdr)
Xregister char *hdr;
X{
X register c, n;
X register unsigned short crc;
X
X if ((c = zdlread()) & ~0377)
X return c;
X Rxtype = c;
X crc = updcrc(c, 0);
X
X for (n=4; --n >= 0; ++hdr) {
X if ((c = zdlread()) & ~0377)
X return c;
X crc = updcrc(c, crc);
X *hdr = c;
X }
X if ((c = zdlread()) & ~0377)
X return c;
X crc = updcrc(c, crc);
X if ((c = zdlread()) & ~0377)
X return c;
X crc = updcrc(c, crc);
X if (crc & 0xFFFF) {
X zperr("Bad Header CRC"); return ERROR;
X }
X Zmodem = 1;
X return Rxtype;
X}
X
X/* Receive a binary style header (type and position) with 32 bit FCS */
Xzrbhdr32(hdr)
Xregister char *hdr;
X{
X register c, n;
X register UNSL long crc;
X
X if ((c = zdlread()) & ~0377)
X return c;
X Rxtype = c;
X crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
X#ifdef DEBUGZ
X vfile("zrbhdr32 c=%X crc=%lX", c, crc);
X#endif
X
X for (n=4; --n >= 0; ++hdr) {
X if ((c = zdlread()) & ~0377)
X return c;
X crc = UPDC32(c, crc);
X *hdr = c;
X#ifdef DEBUGZ
X vfile("zrbhdr32 c=%X crc=%lX", c, crc);
X#endif
X }
X for (n=4; --n >= 0;) {
X if ((c = zdlread()) & ~0377)
X return c;
X crc = UPDC32(c, crc);
X#ifdef DEBUGZ
X vfile("zrbhdr32 c=%X crc=%lX", c, crc);
X#endif
X }
X if (crc != 0xDEBB20E3) {
X zperr("Bad Header CRC"); return ERROR;
X }
X Zmodem = 1;
X return Rxtype;
X}
X
X
X/* Receive a hex style header (type and position) */
Xzrhhdr(hdr)
Xchar *hdr;
X{
X register c;
X register unsigned short crc;
X register n;
X
X if ((c = zgethex()) < 0)
X return c;
X Rxtype = c;
X crc = updcrc(c, 0);
X
X for (n=4; --n >= 0; ++hdr) {
X if ((c = zgethex()) < 0)
X return c;
X crc = updcrc(c, crc);
X *hdr = c;
X }
X if ((c = zgethex()) < 0)
X return c;
X crc = updcrc(c, crc);
X if ((c = zgethex()) < 0)
X return c;
X crc = updcrc(c, crc);
X if (crc & 0xFFFF) {
X zperr("Bad Header CRC"); return ERROR;
X }
X if (readline(1) == '\r') /* Throw away possible cr/lf */
X readline(1);
X Zmodem = 1; return Rxtype;
X}
X
X/* Send a byte as two hex digits */
Xzputhex(c)
Xregister c;
X{
X static char digits[] = "0123456789abcdef";
X
X if (Verbose>8)
X vfile("zputhex: %02X", c);
X sendline(digits[(c&0xF0)>>4]);
X sendline(digits[(c)&0xF]);
X}
X
X/*
X * Send character c with ZMODEM escape sequence encoding.
X * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
X */
Xzsendline(c)
Xregister c;
X{
X static lastsent;
X
X switch (c &= 0377) {
X case ZDLE:
X xsendline(ZDLE);
X xsendline (lastsent = (c ^= 0100));
X break;
X case 015:
X case 0215:
X if (!Zctlesc && (lastsent & 0177) != '@')
X goto sendit;
X /* **** FALL THRU TO **** */
X case 020:
X case 021:
X case 023:
X case 0220:
X case 0221:
X case 0223:
X xsendline(ZDLE);
X c ^= 0100;
Xsendit:
X xsendline(lastsent = c);
X break;
X default:
X if (Zctlesc && ! (c & 0140)) {
X xsendline(ZDLE);
X c ^= 0100;
X }
X xsendline(lastsent = c);
X }
X}
X
X/* Decode two lower case hex digits into an 8 bit byte value */
Xzgethex()
X{
X register c;
X
X c = zgeth1();
X if (Verbose>8)
X vfile("zgethex: %02X", c);
X return c;
X}
Xzgeth1()
X{
X register c, n;
X
X if ((c = noxrd7()) < 0)
X return c;
X n = c - '0';
X if (n > 9)
X n -= ('a' - ':');
X if (n & ~0xF)
X return ERROR;
X if ((c = noxrd7()) < 0)
X return c;
X c -= '0';
X if (c > 9)
X c -= ('a' - ':');
X if (c & ~0xF)
X return ERROR;
X c += (n<<4);
X return c;
X}
X
X/*
X * Read a byte, checking for ZMODEM escape encoding
X * including CAN*5 which represents a quick abort
X */
Xzdlread()
X{
X register c;
X
Xagain:
X switch (c = readline(Rxtimeout)) {
X case ZDLE:
X break;
X case 023:
X case 0223:
X case 021:
X case 0221:
X goto again;
X default:
X if (Zctlesc && !(c & 0140)) {
X goto again;
X }
X return c;
X }
Xagain2:
X if ((c = readline(Rxtimeout)) < 0)
X return c;
X if (c == CAN && (c = readline(Rxtimeout)) < 0)
X return c;
X if (c == CAN && (c = readline(Rxtimeout)) < 0)
X return c;
X if (c == CAN && (c = readline(Rxtimeout)) < 0)
X return c;
X switch (c) {
X case CAN:
X return GOTCAN;
X case ZCRCE:
X case ZCRCG:
X case ZCRCQ:
X case ZCRCW:
X return (c | GOTOR);
X case ZRUB0:
X return 0177;
X case ZRUB1:
X return 0377;
X case 023:
X case 0223:
X case 021:
X case 0221:
X goto again2;
X default:
X if (Zctlesc && ! (c & 0140)) {
X goto again2;
X }
X if ((c & 0140) == 0100)
X return (c ^ 0100);
X break;
X }
X zperr("Bad escape sequence %x", c);
X return ERROR;
X}
X
X/*
X * Read a character from the modem line with timeout.
X * Eat parity, XON and XOFF characters.
X */
Xnoxrd7()
X{
X register c;
X
X for (;;) {
X if ((c = readline(Rxtimeout)) < 0)
X return c;
X switch (c &= 0177) {
X case XON:
X case XOFF:
X continue;
X default:
X if (Zctlesc && !(c & 0140))
X continue;
X case '\r':
X case '\n':
X case ZDLE:
X return c;
X }
X }
X}
X
X/* Store long integer pos in Txhdr */
Xstohdr(pos)
Xlong pos;
X{
X Txhdr[ZP0] = pos;
X Txhdr[ZP1] = pos>>8;
X Txhdr[ZP2] = pos>>16;
X Txhdr[ZP3] = pos>>24;
X}
X
X/* Recover a long integer from a header */
Xlong
Xrclhdr(hdr)
Xregister char *hdr;
X{
X register long l;
X
X l = (hdr[ZP3] & 0377);
X l = (l << 8) | (hdr[ZP2] & 0377);
X l = (l << 8) | (hdr[ZP1] & 0377);
X l = (l << 8) | (hdr[ZP0] & 0377);
X return l;
X}
X
X/* End of zm.c */
SHAR_EOF
echo "extracting Zmodem/sz.c"
sed 's/^X//' << \SHAR_EOF > Zmodem/sz.c
X#define VERSION "sz 1.36 08-31-87"
X#define PUBDIR "/usr/spool/uucppublic"
X
X/*% cc -M0 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
X *
X * sz.c By Chuck Forsberg
X *
X * Amiga version by Frank Harper using Aztec C 3.4b
X *
X * cc +L sz.c;cc +L SerIO.c;cc +L term.c;ln sz.o SerIO.o term.o -lc32
X * or just use the makefile
X *
X * See Amiga.doc for more details on Amiga version
X *
X * cc -O sz.c -o sz USG (SYS III/V) Unix
X * cc -O -DSVR2 sz.c -o sz Sys V Release 2 with non-blocking input
X * Define to allow reverse channel checking
X * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
X *
X * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Xenix
X *
X * ln sz sb **** All versions ****
X * ln sz sx **** All versions ****
X *
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 * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS
X * in accordance with the 7-31-87 ZMODEM Protocol Description
X */
X
X
Xchar *substr(), *getenv();
X
X#define PATHLEN 256
X#define OK 0
X#define ERROR (-1)
X
X#ifdef AMIGA
X#include <stdio.h>
X#include <ctype.h>
X#include <stat.h>
X#include <devices/timer.h>
X#include <devices/serial.h>
X#include <libraries/dos.h>
X#include "intuition/intuition.h"
X
X#define LOGFILE "szlog"
X#define READCHECK
X
Xvoid *malloc();
Xvoid *OpenLibrary();
Xstruct Window *OpenWindow();
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct NewWindow nw = {
X 0, 0, /* start position */
X 640, 120, /* width, height */
X -1, -1, /* detail pen, block pen */
X CLOSEWINDOW, /* IDCMP flags */
X ACTIVATE | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING | WINDOWCLOSE
X | NOCAREREFRESH, /* window flags */
X NULL, /* pointer to first user gadget */
X NULL, /* pointer to user checkmark */
X (UBYTE *)"Sz", /* window title */
X NULL, /* pointer to screen (later) */
X NULL, /* pointer to superbitmap */
X 50,40,-1,-1, /* sizing limits min and max */
X WBENCHSCREEN /* type of screen in which to open */
X };
X
Xint Lleft;
Xint InitSer = FALSE;
Xint gmt_diff_set=FALSE; /* Has GMT offset been set? */
Xint gmt_diff; /* Local time offset from GMT time */
Xint SendProtect=TRUE; /* send file protection bits? */
Xint Term=FALSE; /* Use Terminal mode ? */
Xint WaitC=TRUE; /* Wait for confirmation before closing window?*/
Xstruct IOStdReq *ConWriteReq, *ConReadReq;
Xstruct Window *Win;
Xstruct MsgPort *ConReadPort,*ConWritePort;
Xint WinOutPut;
Xint FullDuplex=TRUE;
XULONG InSerSigMask, OutSerSigMask;
XUBYTE SerOpen;
XULONG IOTimeSigMask;
Xstruct IOExtSer *InSer, *OutSer;
Xstruct MsgPort *InSerPort, *OutSerPort;
Xstruct timerequest *IOTime;
Xstruct MsgPort *TimerPort;
X#else
X#define LOGFILE "/tmp/szlog"
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X
X#define FALSE 0
X#define TRUE 1
X#endif /* AMIGA */
X
X#define HOWMANY 2
Xint Zmodem=0; /* ZMODEM protocol requested */
Xunsigned Baudrate;
Xunsigned Txwindow; /* Control the size of the transmitted window */
Xunsigned Txwspac; /* Spacing between zcrcq requests */
Xunsigned Txwcnt; /* Counter used to space ack requests */
Xlong Lrxpos; /* Receiver's last reported offset */
Xint Fromcu = 0; /* Were called from cu or yam */
Xint errors;
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
XFILE *in;
X
X/* Ward Christensen / CP/M parameters - Don't change these! */
X#define ENQ 005
X#define CAN ('X'&037)
X#define XOFF ('s'&037)
X#define XON ('q'&037)
X#define SOH 1
X#define STX 2
X#define EOT 4
X#define ACK 6
X#define NAK 025
X#define CPMEOF 032
X#define WANTCRC 0103 /* send C not NAK to get crc not checksum */
X#define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
X#define TIMEOUT (-2)
X#define RCDO (-3)
X#define RETRYMAX 10
X#define SECSIZ 128 /* cp/m's Magic Number record size */
X#define KSIZE 1024
X
Xchar Lastrx;
Xchar Crcflg;
Xint Wcsmask=0377;
Xint Verbose=0;
Xint Modem2=0; /* XMODEM Protocol - don't send pathnames */
Xint Restricted=0; /* restricted; no /.. or ../ in filenames */
Xint Quiet=0; /* overrides logic that would otherwise set verbose */
Xint Ascii=0; /* Add CR's for brain damaged programs */
Xint Fullname=0; /* transmit full pathname */
Xint Unlinkafter=0; /* Unlink file after it is sent */
Xint Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */
Xint firstsec;
Xint errcnt=0; /* number of files unreadable */
Xint blklen=SECSIZ; /* length of transmitted records */
Xint Optiong; /* Let it rip no wait for sector ACK's */
Xint Noeofseen;
Xint Totsecs; /* total number of sectors this file */
Xchar txbuf[KSIZE];
Xint Filcnt=0; /* count of number of files opened */
Xint Lfseen=0;
Xunsigned Rxbuflen = 16384; /* Receiver's max buffer length */
Xint Tframlen = 0; /* Override for tx frame length */
Xint blkopt=0; /* Override value for zmodem blklen */
Xint Rxflags = 0;
Xlong bytcnt;
Xint Wantfcs32 = TRUE; /* want to send 32 bit FCS */
Xchar Lzconv; /* Local ZMODEM file conversion request */
Xchar Lzmanag; /* Local ZMODEM file management request */
Xint Lskipnocor;
Xchar Lztrans;
Xchar zconv; /* ZMODEM file conversion request */
Xchar zmanag; /* ZMODEM file management request */
Xchar ztrans; /* ZMODEM file transport request */
Xint Command; /* Send a command, then exit. */
Xchar *Cmdstr; /* Pointer to the command string */
Xint Cmdtries = 11;
Xint Cmdack1; /* Rx ACKs command, then do it */
Xint Exitcode = 0;
X#ifndef AMIGA
Xint Testattn; /* Force receiver to send Attn, etc with qbf. */
X#endif
Xchar *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
Xlong Lastread; /* Beginning offset of last buffer read */
Xint Lastn; /* Count of last buffer read or -1 */
Xint Dontread; /* Don't read the buffer, it's still there */
Xlong Lastsync; /* Last offset to which we got a ZRPOS */
Xint Beenhereb4; /* How many times we've been ZRPOS'd same place */
X
X#ifndef AMIGA /* No setjmp's in amiga version */
Xjmp_buf tohere; /* For the interrupt on RX timeout */
Xjmp_buf intrjmp; /* For the interrupt on RX CAN */
X#endif
X
X#ifndef AMIGA
X/* called by signal interrupt or terminate to clean things up */
Xbibi(n)
X{
X canit(); fflush(stdout); mode(0);
X fprintf(stderr, "sz: caught signal %d; exiting\n", n);
X if (n == SIGQUIT)
X abort();
X exit(128+n);
X}
X
X/* Called when Zmodem gets an interrupt (^X) */
Xonintr()
X{
X signal(SIGINT, SIG_IGN);
X longjmp(intrjmp, -1);
X}
X
X#define sendline(c) putchar(c & Wcsmask)
X
X#define xsendline(c) putchar(c)
X
X#else /* AMIGA */
X
XWaitbibi(n)
Xint n;
X{
X ConPutChar(ConWriteReq,7);
X ConPutStr(ConWriteReq,"\nsz: Transfer aborted");
X if( WaitC ) WaitClose();
X bibi(n);
X}
X
XWaitClose()
X{
X ULONG IntuiMask;
X
X IntuiMask = 1 << (Win->UserPort->mp_SigBit);
X while(!CheckQuit()) Wait(IntuiMask);
X}
X
Xbibi(n)
X{
X canit(); mode(0);
X if (in) fclose(in);
X CleanUp();
X exit(128+n);
X}
X
XAmigaInit()
X{
X IntuitionBase = (struct IntuitionBase *)
X OpenLibrary("intuition.library", 33L);
X if (IntuitionBase == NULL) {
X puts("Unable to open 1.2 or higher intuition.library");
X exit(1);
X }
X Win = OpenWindow(&nw);
X if ( Win == NULL ) {
X puts("Unable to open window");
X CleanUp();
X exit(1);
X }
X WinOutPut=TRUE;
X if( OpenConsole(&ConWriteReq,&ConReadReq,Win)) {
X puts("Couldn't open console");
X CleanUp();
X exit(1);
X }
X}
X
XCleanUp()
X{
X CloseConsole(ConReadReq,ConWriteReq);
X if( Win ) CloseWindow(Win);
X if(IntuitionBase) CloseLibrary(IntuitionBase);
X}
X
X#define sendline(c) xsendline(c & Wcsmask)
X
Xint nchars=0;
Xint BufferSize=128;
XUBYTE *OutBuf,*Next;
X
Xxsendline(c)
Xint c;
X{
X *Next++=c;
X if(++nchars==BufferSize) flushmo();
X}
X
X#undef fflush()
X
X /* Zmodem uses fflush to flush any pending output to the modem */
Xfflush(f)
XFILE *f;
X{
X
X LWriteSer(OutBuf,nchars);
X nchars=0;
X Next=OutBuf;
X}
X
Xfprintf(f,s,a1,a2,a3,a4)
XFILE *f;
Xchar *s;
Xchar *a1,*a2,*a3,*a4;
X{
X char buf[256];
X
X sprintf(buf,s,a1,a2,a3,a4);
X if( WinOutPut ) ConPutStr(ConWriteReq,buf);
X else fputs(buf,f);
X}
X#endif /* AMIGA */
X
Xflushmo()
X{
X fflush(stdout);
X}
X
Xint Zctlesc; /* Encode control characters */
Xint Nozmodem = 0; /* If invoked as "sb" */
Xchar *Progname = "sz";
Xint Zrwindow = 1400; /* RX window size (controls garbage count) */
X#include "rbsb.c" /* most of the system dependent stuff here */
X#include "zm.c"
X
X
Xmain(argc, argv)
Xchar *argv[];
X{
X register char *cp;
X register npats;
X int agcnt; char **agcv;
X char **patts;
X#ifndef AMIGA
X static char xXbuf[BUFSIZ];
X#endif
X if ((cp = getenv("ZNULLS")) && *cp)
X Znulls = atoi(cp);
X if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
X Restricted=TRUE;
X chkinvok(argv[0]);
X
X Rxtimeout = 600;
X npats=0;
X#ifdef AMIGA
X AmigaInit();
X#endif
X if (argc<2)
X usage();
X#ifndef AMIGA
X setbuf(stdout, xXbuf);
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#ifndef AMIGA
X case '1':
X iofd = 1; break;
X#ifdef CSTOPB
X case '2':
X Twostop = TRUE; break;
X#endif
X#endif
X case '7':
X Wcsmask=0177; break;
X case 'a':
X Lzconv = ZCNL;
X Ascii = TRUE; break;
X case 'b':
X Lzconv = ZCBIN; break;
X#ifdef AMIGA
X case 'B':
X Nozmodem = TRUE; blklen=KSIZE; break;
X#endif
X case 'C':
X if (--argc < 1) {
X usage();
X }
X Cmdtries = atoi(*++argv);
X break;
X#ifdef AMIGA
X case 'I':
X InitSer = TRUE; break;
X#endif
X case 'i':
X Cmdack1 = ZCACK1;
X /* **** FALL THROUGH TO **** */
X case 'c':
X if (--argc != 1) {
X usage();
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#ifdef AMIGA
X case 'h':
X FullDuplex = FALSE; break;
X#endif
X case 'k':
X blklen=KSIZE; break;
X case 'L':
X if (--argc < 1) {
X usage();
X }
X blkopt = atoi(*++argv);
X if (blkopt<24 || blkopt>1024)
X usage();
X break;
X case 'l':
X if (--argc < 1) {
X usage();
X }
X Tframlen = atoi(*++argv);
X if (Tframlen<32 || Tframlen>1024)
X usage();
X break;
X#ifdef AMIGA
X case 'm':
X SendProtect = FALSE; break;
X#endif
X case 'N':
X Lzmanag = ZMNEWL; 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;
X case 'q':
X Quiet=TRUE; Verbose=0; break;
X#ifdef AMIGA
X case 'Q':
X WaitC = FALSE; break;
X#endif
X case 't':
X if (--argc < 1) {
X usage();
X }
X Rxtimeout = atoi(*++argv);
X if (Rxtimeout<10 || Rxtimeout>1000)
X usage();
X break;
X case 'T':
X#ifndef AMIGA
X Testattn = TRUE; break;
X#else
X Term=TRUE; break;
X#endif
X case 'u':
X ++Unlinkafter; break;
X case 'v':
X ++Verbose; break;
X case 'w':
X if (--argc < 1) {
X usage();
X }
X Txwindow = atoi(*++argv);
X if (Txwindow < 256)
X Txwindow = 256;
X Txwindow = (Txwindow/64) * 64;
X Txwspac = Txwindow/4;
X if (blkopt > Txwspac
X || (!blkopt && Txwspac < 1024))
X blkopt = Txwspac;
X break;
X case 'X':
X ++Modem2; break;
X case 'Y':
X Lskipnocor = TRUE;
X /* **** FALLL THROUGH TO **** */
X case 'y':
X Lzmanag = ZMCLOB; break;
X default:
X usage();
X }
X }
X }
X else if ( !npats && argc>0) {
X if (argv[0][0]) {
X npats=argc;
X patts=argv;
X#ifndef AMIGA
X if ( !strcmp(*patts, "-"))
X iofd = 1;
X#endif
X }
X }
X }
X if (npats < 1 && !Command)
X usage();
X#ifdef AMIGA
X if( mode(1)==ERROR) {
X fprintf(stderr,"Couldn't initialize serial port\n");
X Waitbibi(1);
X }
X if (Term) {
X fprintf(stderr,"Entering terminal mode, click on close box when ready to start file transfer\n");
X term();
X }
X#endif
X if (Verbose) {
X if (freopen(LOGFILE, "a", stderr)==NULL) {
X printf("Can't open log file %s\n",LOGFILE);
X exit(0200);
X }
X setbuf(stderr, NULL);
X#ifdef AMIGA
X WinOutPut=FALSE;
X#endif
X }
X if ((Fromcu=from_cu()) && !Quiet) {
X if (Verbose == 0)
X Verbose = 2;
X }
X
X#ifndef AMIGA
X mode(1);
X if (signal(SIGINT, bibi) == SIG_IGN) {
X signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
X } else {
X signal(SIGINT, bibi); signal(SIGKILL, bibi);
X }
X if ( !Fromcu)
X signal(SIGQUIT, SIG_IGN);
X signal(SIGTERM, bibi);
X#endif
X if ( !Modem2) {
X if (!Nozmodem) {
X#ifndef AMIGA
X printf("rz\r"); fflush(stdout);
X#else
X LWriteSer("\rrz\r",4); /* try to fire up remote rz */
X#endif
X }
X if (!Command && !Quiet && Verbose != 1) {
X fprintf(stderr, "%s: %d file%s requested:\r\n",
X Progname, npats, npats>1?"s":"");
X for ( agcnt=npats, agcv=patts; --agcnt>=0; ) {
X fprintf(stderr, "%s ", *agcv++);
X }
X fprintf(stderr, "\r\n");
X#ifndef AMIGA /* What is that backspace doing there? */
X printf("\r\n\bSending in Batch Mode\r\n");
X#else
X fprintf(stderr,"\nSending in Batch Mode\n");
X#endif
X }
X if (!Nozmodem) {
X stohdr(0L);
X if (Command)
X Txhdr[ZF0] = ZCOMMAND;
X zshhdr(ZRQINIT, Txhdr);
X }
X }
X fflush(stdout);
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 fflush(stdout);
X#ifdef AMIGA
X fprintf(stderr,"\n");
X if( (errcnt!=0)| Exitcode) {
X fprintf(stderr,"Unable to complete transfer\n");
X ConPutChar(ConWriteReq,7);
X }
X else
X fprintf(stderr,"File transfer succesful\n");
X if (Term) {
X fprintf(stderr,"Re-entering terminal mode. Click on close box to exit Sz.\n");
X term();
X }
X else if( WaitC ) {
X fprintf(stderr,"Click on close box to exit Sz\n");
X WaitClose();
X }
X CleanUp();
X#endif
X mode(0);
X exit((errcnt != 0) | Exitcode);
X /*NOTREACHED*/
X}
X
Xwcsend(argc, argp)
Xchar *argp[];
X{
X register n;
X
X Crcflg=FALSE;
X firstsec=TRUE;
X bytcnt = -1;
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 (getnak()) {
X Exitcode=0200; canit();
X }
X if (!Zmodem)
X canit();
X else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
X Exitcode=0200; canit();
X }
X Exitcode = 1; return OK;
X }
X canit();
X fprintf(stderr,"\r\nCan't open any requested files.\r\n");
X return ERROR;
X }
X if (Zmodem)
X saybibi();
X else if ( !Modem2)
X wctxpn("");
X return OK;
X}
X
Xwcs(oname)
Xchar *oname;
X{
X register c;
X register char *p;
X struct stat f;
X char name[PATHLEN];
X
X strcpy(name, oname);
X
X#ifndef AMIGA
X if (Restricted) {
X /* restrict pathnames to current tree or uucppublic */
X if ( substr(name, "../")
X || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
X canit();
X fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
X return ERROR;
X }
X }
X if ( !strcmp(oname, "-")) {
X if ((p = getenv("ONAME")) && *p)
X strcpy(name, p);
X else
X sprintf(name, "s%d.sz",getpid());
X in = stdin;
X }
X else
X#endif
X if ((in=fopen(oname, "r"))==NULL) {
X ++errcnt;
X return OK; /* pass over it, there may be others */
X }
X ++Noeofseen; Lastread = 0; Lastn = -1; Dontread = FALSE;
X
X#ifndef AMIGA
X /* Check for directory or block special files */
X fstat(fileno(in), &f);
X c = f.st_mode & S_IFMT;
X if (c == S_IFDIR || c == S_IFBLK) {
X fclose(in);
X return OK;
X }
X#else
X stat(oname, &f);
X fprintf(stderr, "%s: File size: %lu bytes\n", oname, f.st_size);
X#endif
X ++Filcnt;
X switch (wctxpn(name)) {
X case ERROR:
X return ERROR;
X case ZSKIP:
X return OK;
X }
X if (!Zmodem && wctx(f.st_size)==ERROR)
X return ERROR;
X if (Unlinkafter)
X unlink(oname);
X return 0;
X}
X
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 Unix fstat 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 struct stat f;
X#ifdef AMIGA
X USHORT mode;
X char *name3;
X#endif
X
X if (Modem2) {
X#ifndef AMIGA
X if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) {
X#else
X if ((in!=stdin) && *name && stat(name, &f)!= -1) {
X#endif
X fprintf(stderr, "Sending %s, %ld blocks: ",
X name, f.st_size>>7);
X }
X fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
X return OK;
X }
X zperr("Awaiting pathname nak for %s", *name?name:"<END>");
X if ( !Zmodem)
X if (getnak())
X return ERROR;
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#ifdef AMIGA
X for (p = name3 = name; *p; )
X if(*p++ == ':') {
X name3 = p;
X break;
X }
X
X for (p=name3, q=txbuf ; *p; )
X#else
X for (p=name, q=txbuf ; *p; )
X#endif
X if ((*q++ = *p++) == '/' && !Fullname)
X q = txbuf;
X *q++ = 0;
X p=q;
X while (q < (txbuf + KSIZE))
X *q++ = 0;
X#ifndef AMIGA
X if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)
X sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
X#else /* translate AMIGA modes to UNIX modes */
X if (!Ascii && (in!=stdin) && *name && stat(name, &f)!= -1) {
X mode=0;
X /*
X * Translate amiga file modes into UNIX file modes
X *
X */
X if((f.st_attr&FIBF_READ)==0) mode|=0400;
X if((f.st_attr&FIBF_WRITE)==0) mode|=0200;
X if((f.st_attr&FIBF_EXECUTE)==0) mode|=0100;
X /*
X * Unix's st_mtime starts from 1 Jan 1970 GMT,
X * while Manx's st_mtime starts from 1 Jan 1978
X *
X * So we adjust before sending (iff gmt_diff has been set)
X */
X sprintf(p, "%lu %lo %o", f.st_size,
X gmt_diff_set?f.st_mtime+24*60*60*(6*365+2*366)-gmt_diff*60*60:0
X ,SendProtect?mode:0);
X }
X#endif
X /* force 1k blocks if name won't fit in 128 byte block */
X if (txbuf[125])
X blklen=KSIZE;
X else { /* A little goodie for IMP/KMD */
X if (Zmodem)
X blklen = SECSIZ;
X txbuf[127] = (f.st_size + 127) >>7;
X txbuf[126] = (f.st_size + 127) >>15;
X }
X if (Zmodem)
X return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));
X if (wcputsec(txbuf, 0, SECSIZ)==ERROR)
X return ERROR;
X return OK;
X}
X
Xgetnak()
X{
X register firstch;
X
X Lastrx = 0;
X for (;;) {
X switch (firstch = readock(800,1)) {
X
X case ZPAD:
X if (getzrxinit())
X return ERROR;
X Ascii = 0;
X return FALSE;
X case TIMEOUT:
X zperr("Timeout on pathname");
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(flen)
Xlong flen;
X{
X register int thisblklen;
X register int sectnum, attempts, firstch;
X long charssent;
X
X charssent = 0; firstsec=TRUE; thisblklen = blklen;
X vfile("wctx:file length=%ld", flen);
X
X while ((firstch=readock(Rxtimeout, 2))!=NAK && firstch != WANTCRC
X && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
X ;
X if (firstch==CAN) {
X zperr("Receiver CANcelled");
X return ERROR;
X }
X if (firstch==WANTCRC)
X Crcflg=TRUE;
X if (firstch==WANTG)
X Crcflg=TRUE;
X sectnum=0;
X for (;;) {
X if (flen <= (charssent + 896L))
X thisblklen = 128;
X if ( !filbuf(txbuf, thisblklen))
X break;
X if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
X return ERROR;
X charssent += thisblklen;
X }
X fclose(in);
X attempts=0;
X do {
X purgeline();
X sendline(EOT);
X fflush(stdout);
X ++attempts;
X }
X while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX);
X if (attempts == RETRYMAX) {
X zperr("No ACK on EOT");
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 checksum, wcj;
X register char *cp;
X unsigned oldcrc;
X int firstch;
X int attempts;
X
X firstch=0; /* part of logic to detect CAN CAN */
X
X if (Verbose>2)
X fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 );
X else if (Verbose>1)
X fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
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#ifdef AMIGA
X flushmo();
X#endif
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 zperr("Cancelled"); return ERROR;
X }
X break;
X case TIMEOUT:
X zperr("Timeout on sector ACK"); continue;
X case WANTCRC:
X if (firstsec)
X Crcflg = TRUE;
X case NAK:
X zperr("NAK on sector"); continue;
X case ACK:
X firstsec=FALSE;
X Totsecs += (cseclen>>7);
X return OK;
X case ERROR:
X zperr("Got burst for sector ACK"); break;
X default:
X zperr("Got %02x for sector ACK", 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 zperr("Retry Count Exceeded");
X return ERROR;
X}
X
X/* fill buf with count chars padding with ^Z for CPM */
Xfilbuf(buf, count)
Xregister char *buf;
X{
X register c, m;
X
X if ( !Ascii) {
X m = read(fileno(in), buf, count);
X if (m <= 0)
X return 0;
X while (m < count)
X buf[m++] = 032;
X return count;
X }
X m=count;
X if (Lfseen) {
X *buf++ = 012; --m; Lfseen = 0;
X }
X while ((c=getc(in))!=EOF) {
X if (c == 012) {
X *buf++ = 015;
X if (--m == 0) {
X Lfseen = TRUE; break;
X }
X }
X *buf++ =c;
X if (--m == 0)
X break;
X }
X if (m==count)
X return 0;
X else
X while (--m>=0)
X *buf++ = CPMEOF;
X return count;
X}
X/* fill buf with count chars */
Xzfilbuf(buf, count)
Xregister char *buf;
X{
X register c, m;
X
X m=count;
X while ((c=getc(in))!=EOF) {
X *buf++ =c;
X if (--m == 0)
X break;
X }
X return (count - m);
X}
X
X/* VARARGS1 */
Xvfile(f, a, b, c)
Xregister char *f;
X{
X if (Verbose > 2) {
X fprintf(stderr, f, a, b, c);
X fprintf(stderr, "\n");
X }
X}
X
X#ifndef AMIGA
Xalrm()
X{
X longjmp(tohere, -1);
X}
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)
X{
X register int c;
X static char byt[5];
X
X if (Optiong)
X count = 1; /* Special hack for cbreak */
X
X fflush(stdout);
X if (setjmp(tohere)) {
X zperr("TIMEOUT");
X return TIMEOUT;
X }
X c = timeout/10;
X if (c<2)
X c=2;
X if (Verbose>5) {
X fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);
X byt[1] = 0;
X }
X signal(SIGALRM, alrm); alarm(c);
X#ifdef ONEREAD
X c=read(iofd, byt, 1); /* regulus raw read is unique */
X#else
X c=read(iofd, byt, count);
X#endif
X alarm(0);
X if (Verbose>5)
X fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
X if (c<1)
X return TIMEOUT;
X if (c==1)
X return (byt[0]&0377);
X else
X while (c)
X if (byt[--c] != CAN)
X return ERROR;
X return CAN;
X}
X#else /* AMIGA */
X#ifdef BUG
X /*
X * This code implements what the readock function is supposed to do
X * but it breaks zmodem's YMODEM protocol for some strange reason???
X * So I've just ifdef'd it out and replaced it with another function
X * that forces 1 byte reads.
X */
Xreadock(timeout,count)
Xint timeout,count;
X{
X ULONG mask;
X int act;
X static char byt[5];
X
X IOTime->tr_time.tv_secs = timeout/10;
X IOTime->tr_time.tv_micro = 100000*(timeout%10); /* tenths of seconds */
X IOTime->tr_node.io_Command = TR_ADDREQUEST;
X SendIO(IOTime);
X SendSer(count,byt);
X mask=Wait( InSerSigMask | IOTimeSigMask | SIGBREAKF_CTRL_C);
X if ((mask&SIGBREAKF_CTRL_C)!=0) {
X KillIO(IOTime,mask);
X KillIO( (struct IOStdReq *)InSer,mask);
X Waitbibi();
X }
X else if ((mask&InSerSigMask)!=0) {
X KillIO(IOTime,mask);
X GetMsg(InSerPort);
X act=(int)InSer->IOSer.io_Actual;
X if (Verbose>5)
X fprintf(stderr, "ret cnt=%d %x %x\n", act, byt[0], byt[1]);
X if (act==1)
X return (byt[0]&0377);
X else
X while (act)
X if (byt[--act] != CAN)
X return ERROR;
X return CAN;
X }
X else { /* it was the timer signal */
X KillIO( (struct IOStdReq *)InSer,mask);
X WaitIO(IOTime);
X zperr("TIMEOUT");
X return TIMEOUT;
X }
X}
X#else /* KLUDGE */
Xreadock(timeout,count)
Xint timeout,count;
X{
X int act;
X static char byt[5];
X
X if((byt[0]=ReadSer(timeout))==TIMEOUT) {
X zperr("TIMEOUT");
X return TIMEOUT;
X }
X act=rdchk()+1;
X if(act>1) byt[1]=ReadSer(timeout);
X if (Verbose>5)
X fprintf(stderr, "ret cnt=%d %x %x\n", act, byt[0], byt[1]);
X if (act==1)
X return (byt[0]&0377);
X else
X while (act)
X if (byt[--act] != CAN)
X return ERROR;
X return CAN;
X}
X#endif /* BUG */
X#endif /* AMIGA */
X
Xreadline(n)
X{
X return (readock(n, 1));
X}
X
Xpurgeline()
X{
X#ifdef AMIGA
X PurgeSer();
X#else
X#ifdef USG
X ioctl(iofd, TCFLSH, 0);
X#else
X lseek(iofd, 0L, 2);
X#endif
X#endif /* AMIGA */
X}
X
X/* send cancel string to get the other end to shut up */
Xcanit()
X{
X static char canistr[] = {
X 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
X };
X
X#ifndef AMIGA
X printf(canistr);
X fflush(stdout);
X#else
X LWriteSer(canistr,strlen(canistr));
X#endif
X}
X
X/*
X * Log an error
X */
X/*VARARGS1*/
Xzperr(s,p,u)
Xchar *s, *p, *u;
X{
X if (Verbose <= 0)
X return;
X fprintf(stderr, "\nRetry %d: ", errors);
X fprintf(stderr, s, p, u);
X fprintf(stderr, "\n");
X}
X#ifndef AMIGA
X/*
X * return 1 iff stdout and stderr are different devices
X * indicating this program operating with a modem on a
X * different line
X */
Xfrom_cu()
X{
X struct stat a, b;
X fstat(1, &a); fstat(2, &b);
X return (a.st_rdev != b.st_rdev);
X}
X#else /* AMIGA */
Xfrom_cu()
X{
X return TRUE;
X}
X#endif
X
X/*
X * substr(string, token) searches for token in string s
X * returns pointer to token within string if found, NULL otherwise
X */
Xchar *
Xsubstr(s, t)
Xregister char *s,*t;
X{
X register char *ss,*tt;
X /* search for first char of token */
X for (ss=s; *s; s++)
X if (*s == *t)
X /* compare token with substring */
X for (ss=s,tt=t; ;) {
X if (*tt == 0)
X return s;
X if (*ss++ != *tt++)
X break;
X }
X return NULL;
X}
X
Xchar *babble[] = {
X "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
X " (Y) = Option applies to YMODEM only",
X " (Z) = Option applies to ZMODEM only",
X#ifndef AMIGA
X "Usage: sz [-12+abdefkLlNnquvwYy] [-] file ...",
X " sz [-12Ceqv] -c COMMAND",
X " sb [-12adfkquv] [-] file ...",
X " sx [-12akquv] [-] file",
X#else
X "Usage: sz [-+abBdefhIkLmlNnqQTuvwXYy] file ...",
X " sz [-CehIqQTv] -c COMMAND",
X " sb [-adfhIkqQTuv] file ...",
X " sx [-ahIkqQTuv] file",
X#endif
X#ifndef AMIGA
X " 1 Use stdout for modem input",
X#ifdef CSTOPB
X " 2 Use 2 stop bits",
X#endif
X#endif
X " + Append to existing destination file (Z)",
X " a (ASCII) change NL to CR/LF",
X " b Binary file transfer override",
X#ifdef AMIGA
X " B Ymodem file transfer",
X#endif
X " c send COMMAND (Z)",
X " d Change '.' to '/' in pathnames (Y/Z)",
X " e Escape all control characters (Z)",
X " f send Full pathname (Y/Z)",
X#ifdef AMIGA
X " h Half duplex mode (only for Terminal mode)",
X#endif
X " i send COMMAND, ack Immediately (Z)",
X#ifdef AMIGA
X " I use serial parameters from ZMODEM.INIT file",
X#endif
X " k Send 1024 byte packets (Y)",
X " L N Limit subpacket length to N bytes (Z)",
X " l N Limit frame length to N bytes (l>=L) (Z)",
X#ifdef AMIGA
X " m Don't send file mode bits",
X#endif
X " n send file if source newer (Z)",
X " N send file if source newer or longer (Z)",
X " o Use 16 bit CRC instead of 32 bit CRC (Z)",
X " p Protect existing destination file (Z)",
X " r Resume/Recover interrupted file transfer (Z)",
X " q Quiet (no progress reports)",
X#ifdef AMIGA
X " Q Quit without waiting for click in close box",
X " T enter Terminal mode before transferring",
X#endif
X " u Unlink file after transmission",
X " v Verbose - provide debugging information",
X " w N Window is N bytes (Z)",
X#ifdef AMIGA
X " X Xmodem file transfer",
X#endif
X " Y Yes, overwrite existing file, skip if not present at rx (Z)",
X " y Yes, overwrite existing file (Z)",
X#ifndef AMIGA
X "- as pathname sends standard input as sPID.sz or environment ONAME",
X#endif
X ""
X};
X
X#ifdef AMIGA
Xusage()
X{
X char **pp;
X int i,n,rows,cols,height;
X struct Screen Scr;
X char rep[20];
X
X /* Expand window, to show as many lines at once as possible */
X MoveWindow(Win,-Win->LeftEdge,-Win->TopEdge);
X if( !GetScreenData(&Scr,sizeof(struct Screen),WBENCHSCREEN)) {
X puts("Couldn't get screen size");
X CleanUp();
X exit(1);
X }
X rows=Scr.Height;
X cols=Scr.Width;
X SizeWindow(Win,cols>640?640-Win->Width:cols-Win->Width,
X rows-Win->Height);
X Delay(15); /* Wait until window is resized */
X ConPutStr(ConWriteReq,"\2330 q"); /* get window bounds */
X n = 0;
X while((rep[n] = ConGetC(ConReadReq)) != 'r' && n++ < 20)
X ;
X height=0;
X i=5;
X while(rep[i]>='0' && rep[i]<='9' && i<n) {
X height*=10;
X height+=rep[i++]-'0';
X }
X for (pp=babble,i=1; **pp; ++pp,i++) {
X fprintf(stderr, "%s\n", *pp);
X if((i%height)==(height-1)) {
X WaitKey();
X ConPutStr(ConWriteReq,"\2331\0731\110\233\112"); /* Erase screen */
X }
X }
X fprintf(stderr,"%s by Chuck Forsberg, amiga version 1.0 by Frank Harper\n",VERSION);
X WaitKey();
X bibi(1);
X}
X
XWaitKey()
X{
X char ConChar;
X ULONG mask,IntuiMask,ConInMask;
X
X IntuiMask = 1 << (Win->UserPort->mp_SigBit);
X ConInMask = 1 << (ConReadPort->mp_SigBit);
X ConPutStr(ConWriteReq,"\23307\155 Press a key \23300\155");
X QueueRead(ConReadReq,&ConChar);
X mask=Wait(ConInMask|IntuiMask);
X if(CheckQuit()) { /* Hit close box? */
X KillIO(ConReadReq);
X bibi(1);
X }
X GetMsg(ConReadPort);
X}
X#else
Xusage()
X{
X char **pp;
X for (pp=babble; **pp; ++pp)
X fprintf(stderr, "%s\n", *pp);
X fprintf(stderr, "%s for %s by Chuck Forsberg\n", VERSION,OS);
X exit(1);
X}
X#endif
X/*
X * Get the receiver's init parameters
X */
Xgetzrxinit()
X{
X register n;
X struct stat f;
X
X for (n=10; --n>=0; ) {
X
X switch (zgethdr(Rxhdr, 1)) {
X case ZCHALLENGE: /* Echo receiver's challenge numbr */
X stohdr(Rxpos);
X zshhdr(ZACK, Txhdr);
X continue;
X case ZCOMMAND: /* They didn't see out ZRQINIT */
X stohdr(0L);
X zshhdr(ZRQINIT, Txhdr);
X continue;
X case ZRINIT:
X Rxflags = 0377 & Rxhdr[ZF0];
X Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
X Zctlesc |= Rxflags & TESCCTL;
X Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
X vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
X#ifndef AMIGA
X if ( !Fromcu)
X signal(SIGINT, SIG_IGN);
X#ifdef USG
X mode(2); /* Set cbreak, XON/XOFF, etc. */
X#endif
X#ifndef READCHECK
X#ifndef USG
X /* Use 1024 byte frames if no sample/interrupt */
X if (Rxbuflen < 32 || Rxbuflen > 1024) {
X Rxbuflen = 1024;
X vfile("Rxbuflen=%d", Rxbuflen);
X }
X#endif
X#endif
X#endif
X /* Override to force shorter frame length */
X if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
X Rxbuflen = Tframlen;
X if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
X Rxbuflen = Tframlen;
X vfile("Rxbuflen=%d", Rxbuflen);
X
X#ifndef AMIGA
X /* If using a pipe for testing set lower buf len */
X fstat(iofd, &f);
X if ((f.st_mode & S_IFMT) != S_IFCHR
X && (Rxbuflen == 0 || Rxbuflen > 4096))
X Rxbuflen = 4096;
X /*
X * If input is not a regular file, force ACK's each 1024
X * (A smarter strategey could be used here ...)
X */
X fstat(fileno(in), &f);
X if (((f.st_mode & S_IFMT) != S_IFREG)
X && (Rxbuflen == 0 || Rxbuflen > 1024))
X Rxbuflen = 1024;
X vfile("Rxbuflen=%d", Rxbuflen);
X#endif
X return (sendzsinit());
X case ZCAN:
X case TIMEOUT:
X return ERROR;
X case ZRQINIT:
X if (Rxhdr[ZF0] == ZCOMMAND)
X continue;
X default:
X zshhdr(ZNAK, Txhdr);
X continue;
X }
X }
X return ERROR;
X}
X
X/* Send send-init information */
Xsendzsinit()
X{
X register c;
X
X if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
X return OK;
X errors = 0;
X for (;;) {
X stohdr(0L);
X if (Zctlesc) {
X Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
X }
X else
X zsbhdr(ZSINIT, Txhdr);
X zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
X c = zgethdr(Rxhdr, 1);
X switch (c) {
X case ZCAN:
X return ERROR;
X case ZACK:
X return OK;
X default:
X if (++errors > 19)
X return ERROR;
X continue;
X }
X }
X}
X
X/* Send file name and related info */
Xzsendfile(buf, blen)
Xchar *buf;
X{
X register c;
X
X for (;;) {
X Txhdr[ZF0] = Lzconv; /* file conversion request */
X Txhdr[ZF1] = Lzmanag; /* file management request */
X if (Lskipnocor)
X Txhdr[ZF1] |= ZMSKNOLOC;
X Txhdr[ZF2] = Lztrans; /* file transport request */
X Txhdr[ZF3] = 0;
X zsbhdr(ZFILE, Txhdr);
X zsdata(buf, blen, ZCRCW);
Xagain:
X c = zgethdr(Rxhdr, 1);
X switch (c) {
X case ZRINIT:
X while ((c = readline(50)) > 0)
X if (c == ZPAD) {
X goto again;
X }
X /* **** FALL THRU TO **** */
X default:
X continue;
X case ZCAN:
X case TIMEOUT:
X case ZABORT:
X case ZFIN:
X return ERROR;
X case ZSKIP:
X fclose(in); return c;
X case ZRPOS:
X /*
X * Suppress zcrcw request otherwise triggered by
X * lastyunc==bytcnt
X */
X Lastsync = (bytcnt = Txpos = Rxpos) -1;
X fseek(in, Rxpos, 0);
X Dontread = FALSE;
X return zsendfdata();
X }
X }
X}
X
X/* Send the data in the file */
Xzsendfdata()
X{
X register c, e, n;
X register newcnt;
X register long tcount = 0;
X int junkcount; /* Counts garbage chars received by TX */
X static int tleft = 6; /* Counter for test mode */
X
X if (Baudrate > 300)
X blklen = 256;
X if (Baudrate > 1200)
X blklen = 512;
X if (Baudrate > 2400)
X blklen = KSIZE;
X if (Rxbuflen && blklen>Rxbuflen)
X blklen = Rxbuflen;
X if (blkopt && blklen > blkopt)
X blklen = blkopt;
X vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
X vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
X Lrxpos = 0;
X junkcount = 0;
X Beenhereb4 = FALSE;
Xsomemore:
X#ifndef AMIGA
X if (setjmp(intrjmp)) {
X#else
X goto start; /* get things going right away */
X#endif
Xwaitack:
X junkcount = 0;
X c = getinsync(0);
Xgotack:
X switch (c) {
X default:
X case ZCAN:
X fclose(in);
X return ERROR;
X case ZSKIP:
X fclose(in);
X return c;
X case ZACK:
X case ZRPOS:
X break;
X case ZRINIT:
X return OK;
X }
X#ifdef READCHECK
X /*
X * If the reverse channel can be tested for data,
X * this logic may be used to detect error packets
X * sent by the receiver, in place of setjmp/longjmp
X * rdchk(fdes) returns non 0 if a character is available
X */
X#ifndef AMIGA
X while (rdchk(iofd)) {
X#else
X while (rdchk()) {
X#endif
X#ifdef SVR2
X switch (checked)
X#else
X switch (readline(1))
X#endif
X {
X case CAN:
X case ZPAD:
X c = getinsync(1);
X goto gotack;
X case XOFF: /* Wait a while for an XON */
X case XOFF|0200:
X readline(100);
X }
X }
X#endif /* READCHECK */
X#ifndef AMIGA
X }
X
X if ( !Fromcu)
X signal(SIGINT, onintr);
X#endif
Xstart:
X newcnt = Rxbuflen;
X Txwcnt = 0;
X stohdr(Txpos);
X zsbhdr(ZDATA, Txhdr);
X#ifndef AMIGA
X /*
X * Special testing mode. This should force receiver to Attn,ZRPOS
X * many times. Each time the signal should be caught, causing the
X * file to be started over from the beginning.
X */
X if (Testattn) {
X if ( --tleft)
X while (tcount < 20000) {
X printf(qbf); fflush(stdout);
X tcount += strlen(qbf);
X#ifdef READCHECK
X while (rdchk(iofd)) {
X#ifdef SVR2
X switch (checked)
X#else
X switch (readline(1))
X#endif
X {
X case CAN:
X case ZPAD:
X#ifdef TCFLSH
X ioctl(iofd, TCFLSH, 1);
X#endif
X goto waitack;
X case XOFF: /* Wait for XON */
X case XOFF|0200:
X readline(100);
X }
X }
X#endif /* READCHECK */
X }
X signal(SIGINT, SIG_IGN); canit();
X sleep(3); purgeline(); mode(0);
X printf("\nsz: Tcount = %ld\n", tcount);
X if (tleft) {
X printf("ERROR: Interrupts Not Caught\n");
X exit(1);
X }
X exit(0);
X }
X#endif
X
X do {
X if (Dontread) {
X n = Lastn;
X } else {
X n = zfilbuf(txbuf, blklen);
X Lastread = Txpos; Lastn = n;
X }
X Dontread = FALSE;
X if (n < blklen)
X e = ZCRCE;
X else if (junkcount > 3)
X e = ZCRCW;
X else if (bytcnt == Lastsync)
X e = ZCRCW;
X else if (Rxbuflen && (newcnt -= n) <= 0)
X e = ZCRCW;
X else if (Txwindow && (Txwcnt += n) >= Txwspac) {
X Txwcnt = 0; e = ZCRCQ;
X }
X else
X e = ZCRCG;
X if (Verbose>1)
X fprintf(stderr, "\r%7ld ZMODEM%s ",
X Txpos, Crc32t?" CRC-32":"");
X zsdata(txbuf, n, e);
X bytcnt = Txpos += n;
X if (e == ZCRCW)
X goto waitack;
X#ifdef READCHECK
X /*
X * If the reverse channel can be tested for data,
X * this logic may be used to detect error packets
X * sent by the receiver, in place of setjmp/longjmp
X * rdchk(fdes) returns non 0 if a character is available
X */
X fflush(stdout);
X#ifndef AMIGA
X while (rdchk(iofd)) {
X#else
X while (rdchk()) {
X#endif
X#ifdef SVR2
X switch (checked)
X#else
X switch (readline(1))
X#endif
X {
X case CAN:
X case ZPAD:
X c = getinsync(1);
X if (c == ZACK)
X break;
X#ifdef TCFLSH
X ioctl(iofd, TCFLSH, 1);
X#endif
X /* zcrce - dinna wanna starta ping-pong game */
X zsdata(txbuf, 0, ZCRCE);
X goto gotack;
X case XOFF: /* Wait a while for an XON */
X case XOFF|0200:
X readline(100);
X default:
X ++junkcount;
X }
X }
X#endif /* READCHECK */
X if (Txwindow) {
X while ((tcount = Txpos - Lrxpos) >= Txwindow) {
X vfile("%ld window >= %u", tcount, Txwindow);
X if (e != ZCRCQ)
X zsdata(txbuf, 0, e = ZCRCQ);
X c = getinsync(1);
X if (c != ZACK) {
X#ifdef TCFLSH
X ioctl(iofd, TCFLSH, 1);
X#endif
X zsdata(txbuf, 0, ZCRCE);
X goto gotack;
X }
X }
X vfile("window = %ld", tcount);
X }
X } while (n == blklen);
X#ifndef AMIGA
X if ( !Fromcu)
X signal(SIGINT, SIG_IGN);
X#endif
X
X for (;;) {
X stohdr(Txpos);
X zsbhdr(ZEOF, Txhdr);
X switch (getinsync(0)) {
X case ZACK:
X continue;
X case ZRPOS:
X goto somemore;
X case ZRINIT:
X return OK;
X case ZSKIP:
X fclose(in);
X return c;
X default:
X fclose(in);
X return ERROR;
X }
X }
X}
X
X/*
X * Respond to receiver's complaint, get back in sync with receiver
X */
Xgetinsync(flag)
X{
X register c;
X
X for (;;) {
X#ifndef AMIGA
X if (Testattn) {
X printf("\r\n\n\n***** Signal Caught *****\r\n");
X Rxpos = 0; c = ZRPOS;
X } else
X#endif
X c = zgethdr(Rxhdr, 0);
X switch (c) {
X case ZCAN:
X case ZABORT:
X case ZFIN:
X case TIMEOUT:
X return ERROR;
X case ZRPOS:
X /* ************************************* */
X /* If sending to a modem beuufer, you */
X /* might send a break at this point to */
X /* dump the modem's buffer. */
X if (Lastn >= 0 && Lastread == Rxpos) {
X Dontread = TRUE;
X } else {
X clearerr(in); /* In case file EOF seen */
X fseek(in, Rxpos, 0);
X }
X bytcnt = Lrxpos = Txpos = Rxpos;
X if (Lastsync == Rxpos) {
X if (++Beenhereb4 > 4)
X if (blklen > 256)
X blklen /= 2;
X }
X Lastsync = Rxpos;
X return c;
X case ZACK:
X Lrxpos = Rxpos;
X if (flag || Txpos == Rxpos)
X return ZACK;
X continue;
X case ZRINIT:
X case ZSKIP:
X fclose(in);
X return c;
X case ERROR:
X default:
X zsbhdr(ZNAK, Txhdr);
X continue;
X }
X }
X}
X
X
X/* Say "bibi" to the receiver, try to do it cleanly */
Xsaybibi()
X{
X for (;;) {
X stohdr(0L); /* CAF Was zsbhdr - minor change */
X zshhdr(ZFIN, Txhdr); /* to make debugging easier */
X switch (zgethdr(Rxhdr, 0)) {
X case ZFIN:
X sendline('O'); sendline('O'); flushmo();
X case ZCAN:
X case TIMEOUT:
X return;
X }
X }
X}
X
X/* Local screen character display function */
Xbttyout(c)
X{
X#ifndef AMIGA
X if (Verbose)
X#else
X if (Verbose>2)
X#endif
X putc(c, stderr);
X}
X
X/* Send command and related info */
Xzsendcmd(buf, blen)
Xchar *buf;
X{
X register c;
X long cmdnum;
X
X#ifndef AMIGA
X cmdnum = getpid();
X#endif
X errors = 0;
X for (;;) {
X stohdr(cmdnum);
X Txhdr[ZF0] = Cmdack1;
X zsbhdr(ZCOMMAND, Txhdr);
X zsdata(buf, blen, ZCRCW);
Xlisten:
X Rxtimeout = 100; /* Ten second wait for resp. */
X c = zgethdr(Rxhdr, 1);
X
X switch (c) {
X case ZRINIT:
X goto listen; /* CAF 8-21-87 */
X case ERROR:
X case TIMEOUT:
X if (++errors > Cmdtries)
X return ERROR;
X continue;
X case ZCAN:
X case ZABORT:
X case ZFIN:
X case ZSKIP:
X case ZRPOS:
X return ERROR;
X default:
X if (++errors > 20)
X return ERROR;
X continue;
X case ZCOMPL:
X Exitcode = Rxpos;
X saybibi();
X return OK;
X case ZRQINIT:
X vfile("******** RZ *******");
X#ifndef AMIGA
X system("rz");
X#else
X Execute("rz",0L,0L);
X#endif
X vfile("******** SZ *******");
X goto listen;
X }
X }
X}
X
X/*
X * If called as sb use YMODEM protocol
X */
Xchkinvok(s)
Xchar *s;
X{
X register char *p;
X
X p = s;
X while (*p == '-')
X s = ++p;
X while (*p)
X if (*p++ == '/')
X s = p;
X if (*s == 'v') {
X Verbose=1; ++s;
X }
X Progname = s;
X if (s[0]=='s' && s[1]=='b') {
X Nozmodem = TRUE; blklen=KSIZE;
X }
X if (s[0]=='s' && s[1]=='x') {
X Modem2 = TRUE;
X }
X}
X/* End of sz.c */
SHAR_EOF
echo "End of archive 3 (of 9)"
# if you want to concatenate archives, remove anything after this line
exit