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