710 lines
24 KiB
C
710 lines
24 KiB
C
/* $Id: zmodem.h,v 1.2 2001/10/25 23:56:29 efalk Exp $ */
|
||
|
||
#ifndef ZMODEM_H
|
||
#define ZMODEM_H
|
||
|
||
|
||
/* Master header file for Zmodem protocol driver routines */
|
||
|
||
#if 0
|
||
|
||
These routines are intended to be incorportated into other programs,
|
||
and do not constitute a zmodem program by themselves, although a
|
||
demo zmodem program that uses these routines has been included.
|
||
|
||
All information pertaining to a transfer session is kept in a data
|
||
structure defined by the caller. This makes it possible for the
|
||
caller to drive multiple simultaneous sessions.
|
||
|
||
Caller provides I/O, timing and query routines. Caller remains
|
||
in control at all times. Typical use is to call these routines
|
||
from a select(2) loop.
|
||
|
||
Overview:
|
||
|
||
Transmit files:
|
||
|
||
1 Init ZModem structure and open communications channel.
|
||
2 Call ZmodemTInit() to begin protocol.
|
||
3 Read characters from remote end and pass them to
|
||
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
|
||
4 Call ZmodemTFile() to begin transfer of a file.
|
||
5 Read characters from remote end and pass them to
|
||
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
|
||
6 repeat steps 4&5 for all files.
|
||
7 Call ZmodemTFinish() to indicate that all files have been
|
||
transfered.
|
||
8 Read characters from remote end and pass them to
|
||
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
|
||
|
||
Receive files:
|
||
|
||
1 Init ZModem structure and open communications channel.
|
||
2 Call ZmodemRInit() to begin protocol.
|
||
3 Read characters from remote end and pass them to
|
||
ZmodemRcv() until ZmodemRcv() returns ZmDone or an error.
|
||
|
||
|
||
|
||
In detail:
|
||
|
||
1) Create a ZModem structure as defined below and fill it in.
|
||
|
||
'ifd', 'ofd' are the file descriptors used for input and output.
|
||
The interpretation of ifd and ofd is entirely up to the calling
|
||
routines, since the caller will be providing I/O functions.
|
||
|
||
'zrinitflags' is composed of the flags described below.
|
||
They describe the receive channel capabilities
|
||
and affect how the protocol will be carried out.
|
||
Define these to receive files. When sending files, these
|
||
flags will be defined from the remote end.
|
||
|
||
'zsinitflags' is composed of the flags described below.
|
||
They describe the transmit channel capabilities
|
||
and affect how the protocol will be carried out.
|
||
Define these to send files. When receiving files, these
|
||
flags will be defined from the remote end.
|
||
|
||
'attn': For transmit, this is the optional nul-terminated
|
||
attention string to be sent by the receiver to interrupt the
|
||
transmission. For example, it might simply contain ^O to flush
|
||
the buffers, or it might interrupt the sending program. Caller
|
||
needs to handle this interrupt properly and call ZmodemAttention().
|
||
|
||
For receive, this is the optional nul-terminated attention string
|
||
defined at the remote end. Caller needs to provide a function that
|
||
can execute this sequence.
|
||
|
||
'timeout' is read-only, set by the zmodem package. It is the
|
||
timeout value in seconds. If this much time passes without
|
||
anything being received, caller should call the ZmodemTimeout()
|
||
function. Note that timeout may be zero, in which case the
|
||
ZTimeout function should be called immediately if no characters
|
||
are ready to be received.
|
||
|
||
'packetsize' is set to the preferred data packet size. Define
|
||
this when sending files. Recommended length values are 256
|
||
bytes below 2400 bps, 512 at 2400 bps, and 1024 above 4800 bps
|
||
or when the data link is known to be relatively error free.
|
||
Ignored during receive.
|
||
|
||
'bufsize' is set to the size of the receive buffer size. Define
|
||
this when receiving files. When sending files, this will be
|
||
defined at the other end.
|
||
|
||
'windowsize' is used to prevent network connections from
|
||
buffering too many characters during transmit. Setting
|
||
'windowsize' to nonzero causes zmodem to request status reports
|
||
from the receiver during transmit, and to pause if more than
|
||
this many bytes have been sent but not yet acknowledged. Set
|
||
to zero to turn off windowing. Ignored during receive.
|
||
|
||
Other fields are used to track the internal state of the zmodem
|
||
driver functions.
|
||
|
||
Since this is a source package, you are, of course, free to extend
|
||
the ZModem structure as you see fit.
|
||
|
||
|
||
2) Define the following functions:
|
||
|
||
int
|
||
ZXmitStr(u_char *str, int len, ZModem *info)
|
||
Transmit a buffer. Return 0 on success, ZmErrSys on error.
|
||
|
||
void
|
||
ZIFlush(ZModem *info)
|
||
Flush all unread input on receive channel. Do nothing if
|
||
this is not possible.
|
||
|
||
void
|
||
ZOFlush(ZModem *info)
|
||
Flush all buffered but not-yet-transmitted output
|
||
on transmit channel. Do nothing if this is not possible.
|
||
|
||
int
|
||
ZAttn(ZModem *info)
|
||
Send attention signal defined in ZModem->attn. Do
|
||
nothing if this field is NULL. Otherwise, this field
|
||
is a nul-terminated character string to be
|
||
transmitted. There are two special characters defined
|
||
below: ATTNBRK (0335) indicates that a BREAK signal
|
||
should be sent, and ATTNPSE (0336) represents a
|
||
1-second pause.
|
||
|
||
void
|
||
ZFlowControl(int onoff, ZModem *info)
|
||
Turn flow control on or off depending on the onoff flag.
|
||
|
||
void
|
||
ZStatus(int type, int value, char *status)
|
||
Called to provide status information. Ignore or display
|
||
at your option. Status string is not static, so copy
|
||
it if you need it beyond this call. Type is defined
|
||
below under "ZStatus() types".
|
||
|
||
FILE *
|
||
ZOpenFile(char *name, u_long crc, ZModem *info)
|
||
|
||
Called when receiving files, this function decides
|
||
whether or not to accept the specified file, and
|
||
if so, opens it for writing and returns the stdio
|
||
file handle. If this function decides not to accept
|
||
the file, or cannot open the file, it returns NULL
|
||
and the remote sender is told to skip this file.
|
||
|
||
info->f0-f3 are the transfer flags, described below under
|
||
"ZFILE transfer flags". These describe the type of
|
||
transfer desired (binary/ascii), and conditions for the
|
||
transfer, such as 'transfer if source newer or longer'.
|
||
|
||
info->len is the length of the file in bytes. info->date is
|
||
the last modification date of the file, in seconds since
|
||
1-jan-1970. info->mode is the unix file mode + 01000000, or
|
||
zero if not known. info->filesRem and info->bytesRem are the
|
||
number of files and bytes remaining to be transferred
|
||
if known, zero otherwise. 'crc' is the file crc-32 value.
|
||
This is only provided if F1 contains ZMCRC.
|
||
|
||
int
|
||
ZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info)
|
||
Write a buffer of data to the file. Normally, you would
|
||
simply call fwrite(buffer, 1, len, file), but you may
|
||
want to translate line endings, etc. File transfer
|
||
flags are available as info->f0,f1,f2,f3.
|
||
|
||
Return 0 on success, ZmErrSys on failure, with errno
|
||
describing the failure.
|
||
|
||
|
||
int
|
||
ZCloseFile(ZModem *info)
|
||
Close file after successful completion. File modification
|
||
date and modes should be set at this time.
|
||
|
||
void
|
||
ZIdleStr(u_char *buffer, int len, ZModem *info)
|
||
Called to pass text that is received out-of-protocol.
|
||
This function may ignore or display this text at your
|
||
option.
|
||
|
||
|
||
3) Open the communications channel.
|
||
|
||
If possible, this should be a full-duplex channel with full
|
||
8-bit transmission. Hardware flow control and/or XON/XOFF
|
||
flow control should be enabled.
|
||
|
||
|
||
4) Call these routines:
|
||
|
||
All functions return 0 on success, nonzero on failure. See
|
||
"error code definitions", below.
|
||
|
||
Send:
|
||
|
||
int
|
||
ZmodemTInit(ZModem *info)
|
||
Begin a Zmodem transmit session.
|
||
|
||
int
|
||
ZmodemRcv(u_char *buffer, int len, ZModem *info)
|
||
Call whenever characters are received. If this function
|
||
returns ZmDone, previous function has completed successfully,
|
||
either call ZmodemTFile() to start next file, or call
|
||
ZmodemTFinish() to terminate the session.
|
||
|
||
int
|
||
ZmodemTimeout(ZModem *info)
|
||
Call whenever the timeout period expires and no
|
||
characters have been received.
|
||
|
||
int
|
||
ZmodemAttention(ZModem *info)
|
||
Call whenever the attention sequence has been received
|
||
from the remote end. It is safe to call this function
|
||
from an interrupt handler.
|
||
|
||
int
|
||
ZmodemTFile(char *filename, char *rfilename,
|
||
u_char f0,f1,f2,f3, int filesRem, int bytesRem, ZModem *info)
|
||
Begin transmitting a file. If filename is not NULL,
|
||
then this function will open it. Otherwise, info->file
|
||
must point to a stdio stream that is open for input.
|
||
It is preferable to provide the filename, so that
|
||
Zmodem can transmit file size and other information.
|
||
'rfilename' is the filename given to the remote end.
|
||
This may be the same as filename, the file part of
|
||
filename, or something else alltogether. 'rfilename'
|
||
must not be longer than the smallest data packet the
|
||
remote end might be willing to receive (about 200
|
||
characters). f0-f3 are transfer flags, see "ZCBIN"
|
||
below. 'filesRem' and 'bytesRem' are the number of files
|
||
and bytes remaining to be transmitted, if known; zero if
|
||
not.
|
||
|
||
If 'filename' cannot be accessed, ZmodemTFile() returns
|
||
ZmErrCantOpen. The link is still established, so you
|
||
need to either proceed with the next file or call
|
||
ZmodemTFinish().
|
||
|
||
int
|
||
ZmodemTFinish(ZModem *info)
|
||
Call after final file transfer has completed successfully.
|
||
|
||
int
|
||
ZmodemAbort(ZModem *info)
|
||
Call to abort transfer. Physical connection remains
|
||
open until you close it.
|
||
|
||
|
||
Receive:
|
||
|
||
int
|
||
ZmodemRInit(ZModem *info)
|
||
Call to get ready to receive first file. This function
|
||
will inform the sender that we are ready to receive.
|
||
|
||
int
|
||
ZmodemRcv(u_char *buffer, int len, ZModem *info)
|
||
Call whenever characters are received. If this
|
||
function returns ZmDone, all file transfers have
|
||
completed successfully.
|
||
|
||
int
|
||
ZmodemTimeout(ZModem *info)
|
||
Call whenever the timeout period expires and no
|
||
characters have been received.
|
||
|
||
int
|
||
ZmodemAbort(ZModem *info)
|
||
Call to abort transfer.
|
||
|
||
Ymodem and Xmodem:
|
||
|
||
int YmodemTInit(ZModem *info)
|
||
int XmodemTInit(ZModem *info)
|
||
int YmodemRInit(ZModem *info)
|
||
int XmodemRInit(ZModem *info)
|
||
Same semantics as ZmodemTInit and ZmodemRInit. It is
|
||
not normally necessary to call the Ymodem*Init() functions
|
||
as the Zmodem protocol will automatically switch to Ymodem
|
||
when needed.
|
||
|
||
|
||
Utility:
|
||
|
||
u_long
|
||
FileCrc(char *name)
|
||
Return CRC-32 of file.
|
||
|
||
5) Return Values:
|
||
|
||
ZmDone Done. Proceed with next file or ZmodemTFinish
|
||
(transmit) or exit (receive).
|
||
|
||
ZmErrInt Internal error. Link has been closed.
|
||
ZmErrSys System error, see errno. Link is closed.
|
||
ZmErrNotOpen not used.
|
||
ZmFileTooLong not used.
|
||
ZmFileCantWrite not used.
|
||
ZmErrCantOpen Can not open file, see errno. Link is still open.
|
||
ZmErrInitTo Transmitter failed to respond to init req. Link closed.
|
||
ZmErrSequence Packet received out of sequence. Link is closed.
|
||
ZmErrCancel Cancelled by remote end. Link is closed.
|
||
ZmErrRcvTo Remote end timed out during transfer. Link is closed.
|
||
ZmErrSndTo Remote end timed out during transfer. Link is closed.
|
||
ZmErrCmdTo Remote end timed out during transfer. Link is closed.
|
||
|
||
Note that "link is closed" means that the remote end is (presumably)
|
||
no longer operating. The actual communications channel is not
|
||
closed unless you close it. "Link is still open" means that the
|
||
remote end is still ready to receive the next file.
|
||
|
||
#endif
|
||
|
||
/* PARAMETERS
|
||
*
|
||
* The following #defines control the behavior of the Zmodem
|
||
* package. Note that these may be replaced with variables
|
||
* if you like. For example, "#define DoInitRZ" may be replaced
|
||
* with "extern int DoInitRz" to use a global variable, or with
|
||
* "#define DoInitRZ (info->doInitRz)" to use a variable you
|
||
* add to the ZModem structure.
|
||
*
|
||
* It is assumed that the compiler is good enough to optimize
|
||
* "if( 0 )" and "if( 1 )" cases. If not, you may wish to modify
|
||
* the source code to use #ifdef instead.
|
||
*/
|
||
|
||
#define DoInitRZ 1 /* send initial "rz\r" when transmitting */
|
||
#define AllowCommand 0 /* allow remote end to execute commands */
|
||
#define SendSample 1 /* sender can sample reverse channel */
|
||
#define SendAttn 1 /* sender can be interrupted with Attn signal */
|
||
#define ResponseTime 10 /* reasonable response time for sender to
|
||
* respond to requests from receiver */
|
||
#define SerialNo 1 /* receiver serial # */
|
||
#define MaxNoise 64 /* max "noise" characters before transmission
|
||
* pauses */
|
||
#define MaxErrs 20 /* Max receive errors before cancel */
|
||
#define AlwaysSinit 1 /* always send ZSINIT header, even if not
|
||
* needed, this makes protocol more robust */
|
||
|
||
#define SendOnly 0 /* compiles smaller version for send only */
|
||
#define RcvOnly 0 /* compiles smaller version for receive only */
|
||
|
||
/* constants */
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <sys/types.h>
|
||
|
||
|
||
|
||
|
||
/* Internal State */
|
||
|
||
typedef enum zmstate {
|
||
/* receive */
|
||
RStart, /* sent RINIT, waiting for ZFILE or SINIT */
|
||
RSinitWait, /* got SINIT, waiting for data */
|
||
RFileName, /* got ZFILE, waiting for filename & info */
|
||
RCrc, /* got filename, want crc too */
|
||
RFile, /* got filename, ready to read */
|
||
RData, /* reading data */
|
||
RDataErr, /* encountered error, ignoring input */
|
||
RFinish, /* sent ZFIN, waiting for 'OO' */
|
||
|
||
/* transmit */
|
||
TStart, /* waiting for INIT frame from other end */
|
||
TInit, /* received INIT, sent INIT, waiting for ZACK */
|
||
FileWait, /* sent file header, waiting for ZRPOS */
|
||
CrcWait, /* sent file crc, waiting for ZRPOS */
|
||
Sending, /* sending data subpackets, ready for int */
|
||
SendWait, /* waiting for ZACK */
|
||
SendDone, /* file finished, need to send EOF */
|
||
SendEof, /* sent EOF, waiting for ZACK */
|
||
TFinish, /* sent ZFIN, waiting for ZFIN */
|
||
|
||
/* general */
|
||
CommandData, /* waiting for command data */
|
||
CommandWait, /* waiting for command to execute */
|
||
StderrData, /* waiting for stderr data */
|
||
Done,
|
||
|
||
/* x/ymodem transmit */
|
||
YTStart, /* waiting for 'G', 'C' or NAK */
|
||
YTFile, /* sent filename, waiting for ACK */
|
||
YTDataWait, /* ready to send data, waiting for 'C' */
|
||
YTData, /* sent data, waiting for ACK */
|
||
YTEOF, /* sent eof, waiting for ACK */
|
||
YTFin, /* sent null filename, waiting for ACK */
|
||
|
||
/* x/ymodem receive */
|
||
YRStart, /* sent 'C', waiting for filename */
|
||
YRDataWait, /* received filename, waiting for data */
|
||
YRData, /* receiving filename or data */
|
||
YREOF /* received first EOT, waiting for 2nd */
|
||
|
||
} ZMState ;
|
||
|
||
|
||
|
||
|
||
typedef struct {
|
||
int ifd ; /* input fd, for use by caller's routines */
|
||
int ofd ; /* output fd, for use by caller's routines */
|
||
FILE *file ; /* file being transfered */
|
||
int zrinitflags ; /* receiver capabilities, see below */
|
||
int zsinitflags ; /* sender capabilities, see below */
|
||
char *attn ; /* attention string, see below */
|
||
int timeout ; /* timeout value, in seconds */
|
||
int bufsize ; /* receive buffer size, bytes */
|
||
int packetsize ; /* preferred transmit packet size */
|
||
int windowsize ; /* max window size */
|
||
|
||
/* file attributes: read-only */
|
||
|
||
int filesRem, bytesRem ;
|
||
u_char f0,f1,f2,f3 ; /* file flags */
|
||
int len,mode,fileType ; /* file flags */
|
||
u_long date ; /* file date */
|
||
|
||
/* From here down, internal to Zmodem package */
|
||
|
||
ZMState state ; /* protocol internal state */
|
||
char *filename ; /* filename */
|
||
char *rfilename ; /* remote filename */
|
||
int crc32 ; /* use 32-bit crc */
|
||
int pktLen ; /* length of this packet */
|
||
int DataType ; /* input data type */
|
||
int PacketType ; /* type of this packet */
|
||
int rcvlen ;
|
||
int chrCount ; /* chars received in current header/buffer */
|
||
int crcCount ; /* crc characters remaining at end of buffer */
|
||
int canCount ; /* how many CAN chars received? */
|
||
int noiseCount ; /* how many noise chars received? */
|
||
int errorFlush ; /* ignore incoming data because of error */
|
||
u_char *buffer ; /* data buffer */
|
||
u_long offset ; /* file offset */
|
||
u_long lastOffset ; /* last acknowledged offset */
|
||
u_long zrposOffset ; /* last offset specified w/zrpos */
|
||
int ylen, bufp ; /* len,location of last Ymodem packet */
|
||
int fileEof ; /* file eof reached */
|
||
int packetCount ; /* # packets received */
|
||
int errCount ; /* how many data errors? */
|
||
int timeoutCount ; /* how many times timed out? */
|
||
int windowCount ; /* how much data sent in current window */
|
||
int atSign ; /* last char was '@' */
|
||
int lastCR ; /* last char was CR */
|
||
int escCtrl ; /* other end requests ctrl chars be escaped */
|
||
int escHibit ; /* other end requests hi bit be escaped */
|
||
int escape ; /* next character is escaped */
|
||
int interrupt ; /* received attention signal */
|
||
int waitflag ; /* next send should wait */
|
||
/* parser state */
|
||
enum {Idle, Padding, Inhdr, Indata, Finish, Ysend, Yrcv} InputState ;
|
||
enum {XMODEM, YMODEM, ZMODEM} Protocol ;
|
||
u_char hdrData[9] ; /* header type and data */
|
||
u_char fileFlags[4] ; /* file xfer flags */
|
||
u_long crc ; /* crc of incoming header/data */
|
||
enum {Full, StrWindow, SlidingWindow, Segmented} Streaming ;
|
||
} ZModem ;
|
||
|
||
|
||
/* ZRINIT flags. Describe receiver capabilities */
|
||
|
||
#define CANFDX 1 /* Rx is Full duplex */
|
||
#define CANOVIO 2 /* Rx can overlap I/O */
|
||
#define CANBRK 4 /* Rx can send a break */
|
||
#define CANCRY 010 /* Rx can decrypt */
|
||
#define CANLZW 020 /* Rx can uncompress */
|
||
#define CANFC32 040 /* Rx can use 32-bit crc */
|
||
#define ESCCTL 0100 /* Rx needs control chars escaped */
|
||
#define ESC8 0200 /* Rx needs 8th bit escaped. */
|
||
|
||
/* ZSINIT flags. Describe sender capabilities */
|
||
|
||
#define TESCCTL 0100 /* Tx needs control chars escaped */
|
||
#define TESC8 0200 /* Tx needs 8th bit escaped. */
|
||
|
||
|
||
/* ZFILE transfer flags */
|
||
|
||
/* F0 */
|
||
#define ZCBIN 1 /* binary transfer */
|
||
#define ZCNL 2 /* convert NL to local eol convention */
|
||
#define ZCRESUM 3 /* resume interrupted file xfer, or append to a
|
||
growing file. */
|
||
|
||
/* F1 */
|
||
#define ZMNEWL 1 /* transfer if source newer or longer */
|
||
#define ZMCRC 2 /* transfer if different CRC or length */
|
||
#define ZMAPND 3 /* append to existing file, if any */
|
||
#define ZMCLOB 4 /* replace existing file */
|
||
#define ZMNEW 5 /* transfer if source is newer */
|
||
#define ZMDIFF 6 /* transfer if dates or lengths different */
|
||
#define ZMPROT 7 /* protect: transfer only if dest doesn't exist */
|
||
#define ZMCHNG 8 /* change filename if destination exists */
|
||
#define ZMMASK 037 /* mask for above. */
|
||
#define ZMSKNOLOC 0200 /* skip if not present at Rx end */
|
||
|
||
/* F2 */
|
||
#define ZTLZW 1 /* lzw compression */
|
||
#define ZTRLE 3 /* run-length encoding */
|
||
|
||
/* F3 */
|
||
#define ZCANVHDR 1 /* variable headers ok */
|
||
#define ZRWOVR 4 /* byte position for receive window override/256 */
|
||
#define ZXSPARS 64 /* encoding for sparse file ops. */
|
||
|
||
|
||
|
||
/* ATTN string special characters. All other characters sent verbose */
|
||
|
||
#define ATTNBRK '\335' /* send break signal */
|
||
#define ATTNPSE '\336' /* pause for one second */
|
||
|
||
|
||
/* ZStatus() types */
|
||
|
||
#define RcvByteCount 0 /* value is # bytes received */
|
||
#define SndByteCount 1 /* value is # bytes sent */
|
||
#define RcvTimeout 2 /* receiver did not respond, aborting */
|
||
#define SndTimeout 3 /* value is # of consecutive send timeouts */
|
||
#define RmtCancel 4 /* remote end has cancelled */
|
||
#define ProtocolErr 5 /* protocol error has occurred, val=hdr */
|
||
#define RemoteMessage 6 /* message from remote end */
|
||
#define DataErr 7 /* data error, val=error count */
|
||
#define FileErr 8 /* error writing file, val=errno */
|
||
#define FileBegin 9 /* file transfer begins, str=name */
|
||
#define FileEnd 10 /* file transfer ends, str=name */
|
||
#define FileSkip 11 /* file being skipped, str=name */
|
||
|
||
|
||
/* error code definitions [O] means link still open */
|
||
|
||
#define ZmDone -1 /* done */
|
||
#define ZmErrInt -2 /* internal error */
|
||
#define ZmErrSys -3 /* system error, see errno */
|
||
#define ZmErrNotOpen -4 /* communication channel not open */
|
||
#define ZmErrCantOpen -5 /* can't open file, see errno [O] */
|
||
#define ZmFileTooLong -6 /* remote filename too long [O] */
|
||
#define ZmFileCantWrite -7 /* could not write file, see errno */
|
||
#define ZmDataErr -8 /* too many data errors */
|
||
#define ZmErrInitTo -10 /* transmitter failed to respond to init req. */
|
||
#define ZmErrSequence -11 /* packet received out of sequence */
|
||
#define ZmErrCancel -12 /* cancelled by remote end */
|
||
#define ZmErrRcvTo -13 /* remote receiver timed out during transfer */
|
||
#define ZmErrSndTo -14 /* remote sender timed out during transfer */
|
||
#define ZmErrCmdTo -15 /* remote command timed out */
|
||
|
||
|
||
/* zmodem-supplied functions: */
|
||
|
||
|
||
extern int ZmodemTInit(ZModem *info) ;
|
||
extern int ZmodemTFile(char *file, char *rmtname,
|
||
u_int f0, u_int f1, u_int f2, u_int f3,
|
||
int filesRem, int bytesRem, ZModem *info) ;
|
||
extern int ZmodemTFinish(ZModem *info) ;
|
||
extern int ZmodemAbort(ZModem *info) ;
|
||
extern int ZmodemRInit(ZModem *info) ;
|
||
extern int ZmodemRcv(u_char *str, int len, ZModem *info) ;
|
||
extern int ZmodemTimeout(ZModem *info) ;
|
||
extern int ZmodemAttention(ZModem *info) ;
|
||
|
||
extern int YmodemTInit(ZModem *info) ;
|
||
extern int XmodemTInit(ZModem *info) ;
|
||
extern int YmodemRInit(ZModem *info) ;
|
||
extern int XmodemRInit(ZModem *info) ;
|
||
|
||
extern u_long FileCrc(char *name) ;
|
||
extern char *sname(ZModem *) ;
|
||
extern char *sname2(ZMState) ;
|
||
|
||
#ifdef DEBUG
|
||
extern FILE *zmodemlogfile ;
|
||
extern void zmodemlog(const char *, ...) ;
|
||
#else
|
||
#define zmodemlog
|
||
#endif
|
||
|
||
|
||
|
||
|
||
/* caller-supplied functions: */
|
||
|
||
|
||
extern int ZXmitChr(u_char c, ZModem *info) ;
|
||
extern int ZXmitStr(u_char *str, int len, ZModem *info) ;
|
||
extern void ZIFlush(ZModem *info) ;
|
||
extern void ZOFlush(ZModem *info) ;
|
||
extern int ZAttn(ZModem *info) ;
|
||
extern void ZStatus(int type, int value, char *status) ;
|
||
extern FILE *ZOpenFile(char *name, u_long crc, ZModem *info) ;
|
||
|
||
|
||
/* From here on down, internal to Zmodem package */
|
||
|
||
|
||
/* ZModem character definitions */
|
||
|
||
#define ZDLE 030 /* zmodem escape is CAN */
|
||
#define ZPAD '*' /* pad */
|
||
#define ZBIN 'A' /* introduces 16-bit crc binary header */
|
||
#define ZHEX 'B' /* introduces 16-bit crc hex header */
|
||
#define ZBIN32 'C' /* introduces 32-bit crc binary header */
|
||
#define ZBINR32 'D' /* introduces RLE packed binary frame w/32-bit crc */
|
||
#define ZVBIN 'a' /* alternate ZBIN */
|
||
#define ZVHEX 'b' /* alternate ZHEX */
|
||
#define ZVBIN32 'c' /* alternate ZBIN32 */
|
||
#define ZVBINR32 'd' /* alternate ZBINR32 */
|
||
#define ZRESC 0177 /* RLE flag/escape character */
|
||
|
||
|
||
|
||
/* ZModem header type codes */
|
||
|
||
#define ZRQINIT 0 /* request receive init */
|
||
#define ZRINIT 1 /* receive init */
|
||
#define ZSINIT 2 /* send init sequence, define Attn */
|
||
#define ZACK 3 /* ACK */
|
||
#define ZFILE 4 /* file name, from sender */
|
||
#define ZSKIP 5 /* skip file command, from receiver */
|
||
#define ZNAK 6 /* last packet was garbled */
|
||
#define ZABORT 7 /* abort */
|
||
#define ZFIN 8 /* finish session */
|
||
#define ZRPOS 9 /* resume file from this position, from receiver */
|
||
#define ZDATA 10 /* data packets to follow, from sender */
|
||
#define ZEOF 11 /* end of file, from sender */
|
||
#define ZFERR 12 /* fatal i/o error, from receiver */
|
||
#define ZCRC 13 /* request for file crc, from receiver */
|
||
#define ZCHALLENGE 14 /* "send this number back to me", from receiver */
|
||
#define ZCOMPL 15 /* request is complete */
|
||
#define ZCAN 16 /* other end cancelled with CAN-CAN-CAN-CAN-CAN */
|
||
#define ZFREECNT 17 /* request for free bytes on filesystem */
|
||
#define ZCOMMAND 18 /* command, from sending program */
|
||
#define ZSTDERR 19 /* output this message to stderr */
|
||
|
||
|
||
/* ZDLE escape sequences */
|
||
|
||
|
||
#define ZCRCE 'h' /* CRC next, frame ends, header follows */
|
||
#define ZCRCG 'i' /* CRC next, frame continues nonstop */
|
||
#define ZCRCQ 'j' /* CRC next, send ZACK, frame continues nonstop */
|
||
#define ZCRCW 'k' /* CRC next, send ZACK, frame ends */
|
||
#define ZRUB0 'l' /* translate to 0177 */
|
||
#define ZRUB1 'm' /* translate to 0377 */
|
||
|
||
|
||
/* ascii definitions */
|
||
|
||
#define SOH 1 /* ^A */
|
||
#define STX 2 /* ^B */
|
||
#define EOT 4 /* ^D */
|
||
#define ACK 6 /* ^F */
|
||
#define DLE 16 /* ^P */
|
||
#define XON 17 /* ^Q */
|
||
#define XOFF 19 /* ^S */
|
||
#define NAK 21 /* ^U */
|
||
#define SYN 22 /* ^V */
|
||
#define CAN 24 /* ^X */
|
||
|
||
|
||
|
||
extern int ZXmitHdr() ;
|
||
extern int ZXmitHdrHex() ;
|
||
extern int ZXmitHdrBin() ;
|
||
extern int ZXmitHdrBin32() ;
|
||
extern u_char *putZdle( u_char *ptr, u_char c, ZModem *info ) ;
|
||
|
||
extern u_char *ZEnc4() ;
|
||
extern u_long ZDec4() ;
|
||
|
||
|
||
/* state table entry. There is one row of the table per
|
||
* possible state. Each row is a row of all reasonable
|
||
* inputs for this state. The entries are sorted so that
|
||
* the most common inputs occur first, to reduce search time
|
||
* Unexpected input is reported and ignored, as it might be
|
||
* caused by echo or something.
|
||
*
|
||
* Extra ZRINIT headers are the receiver trying to resync.
|
||
*/
|
||
|
||
typedef struct {
|
||
int type ; /* frame type */
|
||
int (*func)() ; /* transition function */
|
||
int IFlush ; /* flag: flush input first */
|
||
int OFlush ; /* flag: flush output first */
|
||
ZMState newstate ; /* new state. May be overridden by func */
|
||
} StateTable ;
|
||
|
||
|
||
|
||
|
||
#endif
|