Industrial ZMODEM - memory efficient ZMODEM send and receive modules
Include full 32 bit CRC for maximum data integrity.
Copyright 2004 Omen Technology Inc All Rights Reserved


These programs may be compiled and run on a modern Linux system
for testing or to gain familiarity with the code and its operation.

Special defines:

#define ADDRLE to add RLE compression.

#define XEDSINIT saves a bit of code for clients that do not
use the ZSINIT frame.  This will have to be determined by
testing with individual client programs.

#define BOTH  - allows isz.c and irz.c to be compiled together
for applications that need both

#define UNIX -- pulls in Linux versions of readline, sendline, etc.
from the file rbunix.c. The file rbunix.c uses the Linux/Unix select()
interface to get finer time resolution and better reliability than the
setjmp/alrm interface used in oldrbunix.c.

#define DIAGS  -  adds calls to vfile() to provide
debugging information

#define DEBUGZ  - adds several vfile() calls to give more
debugging information

#define FLUSH - for higher performance under operating systems, adds
support for a buffered sendline function that does not automatically
start output on each call.  flushmoc() starts output and returns;
flushmo() should not return until all characters have been sent.  The
difference between flushmo() and flushmoc() is important only at slow
baudrates when the time to output the buffer contents is comparable to
the readline() timeout.

#define LDP - special unofficial code to deal with time dispersive
communications paths where "packets" arrive out of order, sometimes
after considerable delay.  If you don't know what this is about, you
don't want to.

#define NFGM - creates a function call for UPDCRC32 instead of defining
a macro

#define ZSTAB - use a table driven zsendline() and an inline
replacement for zsendline within the zsda32 inner loop.
This may increase performance depending on the application.
It may be possible to further increase performance by assembly coding
this inner loop.  N.B.: this version  does not recognize requests
to escape all control characters.

#define KKSIZE 8192     Use 8192 byte subpackets.  Only for use
with ZMODEM-90 clients.

#define MANYREGISTERS   Possible speedup for slow chips with many registers
including some Motorola 68000 family chips.  Use with #define ZSTAB

#define NOFF - adds code to escape the 0xFF character.  This is
useful in some telnet applications where the telnet client and
server do not handle 0xFF efficiently.

#ifdef NOCOPYTX
To avoid a memory copy, secbuf is changed to a pointer.  The zfilbuf
function now sets secbuf to pointer to the next section of data.

The variable secbuf must be initialized to a scratch buffer (read/write)
before calling wcs().  Zfilbuf() will not be called until this data
(the file name, etc.) is no longer needed.

#ifdef TCFLSH - Unix specific

#ifdef UNSL - some compilers understand "unsigned long", some don't.


Most customer problems relate to the customer supplied readline()
function.  Be sure you understand the nature of the timeout
before coding.  If readline() does not timeout as specified EVERY TIME
file transfers will needlessly fail under stress.
Give Omen Technology a call if you have questions.


/*
 *
 * irz.c By Chuck Forsberg
 *  Copyright 2004 Omen Technology INC All Rights Reserved
 *
 *  Entry:
 *	rz();  returns RZOK or RZFAIL
 *

 *
 * sendline(c)  sends a character to host
 * purgeline()	empty receive queue
 * int readline(tenths) read a char from host, timeout in seconds/10
        The interrupt service routine associated with
        readline buffers characters from the host.  Readline()
        returns them one at a time.  Return is immediate if
        at least one is in the receive queue.  If no bytes received
	within specified number of tents of a second, return -2.

	return received byte 0 to 0377
	negative return values indicate error:
		return -1 on recoverable error
		return -2 on timeout
	trap fatal errors (loss of carrier, etc.), close file
 *
 * sendbrk() send a break signal (not likely to be needed)
 *
 * long crprocheader(s) parse filename, decide what to do with
 *	if (zconv==ZCRESUM) means sender requests crash recovery
 * incoming file:
 *	return ERROR to skip
 *	opens it for writing
 *	Returns restart address if crash recovery desired, else 0
 *
 * putsec(s, n) write n bytes, trap errors
 * closeit(status) finish writing, close file
 *	trap on error
 *	N.B: closeit might be called after the file is closed.
 *
 * sleep(seconds)   pause for specified number of seconds
 *   <<<< not used if XEDSINIT is defined  >>>>
 *
 * When trapping on errors, close file, call canit() unless line dropped
 */

#define XEDSINIT to code remove handling of ZSINIT packet

/*
 ****************************************************************************
 *
 * isz.c By Chuck Forsberg,  Omen Technology INC
 *  Copyright 2004 Omen Technology INC All Rights Reserved
 *  Entry: see sample main() in code below
 *
 *  External functions called:
 *
 * sendline(c)  sends a character to host
 *
 * purgeline()	empty receive queue
 *
 * int readline(tenths) read char from host, timeout in seconds/10
  (see description above)
 *
 * int checkline() return non 0 if readline has 1 or more bytes ready
 *  (it is permissible for checkline to "eat" ONE character)
 *
 * zfilbuf() fill buffer with blklen bytes, set Eofseen if EOT, return count
 *
 * zseek(long whence) clear EOF, errors, seek
 *
 * zclose(status) close the input dataset associated with zfilbuf() et al.
 *	N.B: zclose might be called after the file is closed.
 *
 * When trapping on errors, close file, call canit() unless line dropped
 *
 ****************************************************************************
 */

main(argc, argv)
char **argv;
{
	startz();		/* Initialize receiver */

	/*
	 *  To ask receiver for crash rocovery, set
	 *		Lzconv = ZCRESUM;
	 * call wcs() once for each file.
	 *  Initialize zfilbuf before calling wcs()
	 *  The string is the file name, null terminated
	 *    file length is not sent
	 */
	if (wcs("file.ext"))
		exit(1);
	if (wcs("file2.ext"))	/* And so on for each file in the batch */
		exit(1);

	saybibi();		/* Orderly conclusion of ZMODEM session */

	exit(0);
	
}


# this compiles irz and isz for 80186 target to get
# an idea of the memory footprint
/usr/ods30/bin/cc -M1 -Os -c irz.c
size irz.o
	irz.c
	4135 + 1835 + 1094 = 7064 = 0x1b98


/usr/ods30/bin/cc -M1 -Os -c isz.c
size isz.o
	isz.c
	4802 + 1857 + 1118 = 7777 = 0x1e61

# compiled with ADDRLE
	irz.c
	5220 + 1648 + 1095 = 7963 = 0x1f1b
	isz.c
	5924 + 1672 + 1084 = 8680 = 0x21e8
