home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
win100b
/
wkkerm.w
< prev
next >
Wrap
Text File
|
1991-10-19
|
9KB
|
395 lines
/*
* Protocol module for Windows Kermit
*
* Copyright (c) 1990, 1991 by
* William S. Hall
* 3665 Benton Street #66
* Santa Clara, CA 95051
*
* This module must be preprocessed by wart
*/
#define NOCOMM
#define NOKANJI
#define NOSOUND
#define NOATOM
#include <windows.h>
#include <stdio.h>
#include <string.h>
#ifdef COLUMBIA
#include "wkkerm.h"
#else
#include "wnkerm.h"
#endif
/* The state machine returns 0 to show completion or 1 if more input
* is expected. Currently, these return values are not used.
*/
#define RESUME return(0)
#define CONTINUE return(1)
/* local function prototypes */
static int near input(void);
static char vcmd;
static int vstate;
/* protocol states */
%states get rsfile rsdata ipkt rgen
%states ssinit ssfile ssdata sseof sseot
/* Protocol description.
*/
%%
/* Begin file send
*/
s {
krm_tinit(); /* initialize */
Kermit.start = 'w'; /* switch to wait */
}
/* Begin get
*/
r {
krm_tinit();
vstate = get;
vcmd = 0;
krm_sinit('I');
BEGIN ipkt;
}
/* Begin host command
*/
c {
krm_tinit();
vstate = rgen;
vcmd = 'C';
krm_sinit('I');
BEGIN ipkt;
}
/* Begin generic command
*/
g {
krm_tinit();
vstate = rgen;
vcmd = 'G';
krm_sinit('I');
BEGIN ipkt;
}
/* Wait to send first packet
*/
w {
if (Kermit.delay) { /* timer will reset this parameter */
Kermit.start = 'w'; /* wait to send first packet */
CONTINUE;
} else {
if (krm_sinit('S') < 0) { /* transmit sendinit packet */
krm_err(IDS_KRM_SENDINIT_ERROR); /* error; inform remote */
RESUME; /* quit */
}
krmFlushQue(); /* flush any pending input in local buffer */
BEGIN ssinit; /* prepare to open file and send file name */
}
}
/* Begin receive file
*/
v {
krm_tinit(); /* initialize */
BEGIN get;
}
<ipkt>Y {
krm_spar(krm_rcvpkt.data, krm_rcvpkt.len); /* read send-init data */
if (vcmd) {
if (krm_sendcmd(vcmd, Kermit.pFilelist) < 0) {
krm_err(IDS_KRM_SENDCMD_ERROR); /* error; inform remote */
RESUME; /* quit */
}
vcmd = 0;
}
if (vstate == get)
if (krm_srinit(Kermit.pFilelist) < 0) {
krm_err(IDS_KRM_SENDR_ERROR);
RESUME;
}
BEGIN vstate;
}
<ipkt>E {
if (vcmd)
if (krm_sendcmd(vcmd, Kermit.pFilelist) < 0) {
krm_err(IDS_KRM_SENDCMD_ERROR); /* error; inform remote */
RESUME; /* quit */
}
vcmd = 0;
if (vstate == get)
if (krm_srinit(Kermit.pFilelist) < 0) {
krm_err(IDS_KRM_SENDR_ERROR);
RESUME;
}
BEGIN vstate;
}
/* got ACK of sendinit packet
*/
<ssinit>Y {
krm_spar(krm_rcvpkt.data, krm_rcvpkt.len); /* set init data */
Kermit.bctu = Kermit.bctr; /* select block check type */
Kermit.pFile = krm_getnextfile(TRUE); /* get file to send */
if (krm_sfile() < 0) { /* send file name packet */
krm_err(IDS_KRM_SENDFILENAME_ERROR); /* error; inform remote */
RESUME; /* quit */
}
BEGIN ssfile; /* prepare to send first data packet */
}
/* Got ACK of file name packet
*/
<ssfile>Y {
int x;
krm_savename(); /* post the remote's name for file */
if ((x = krm_sdata()) == 0) { /* no data in file */
if (krm_seof("") < 0) { /* send end of file */
krm_err(IDS_KRM_SENDEOF_ERROR); /* error; inform remote */
RESUME; /* quit */
}
BEGIN sseof;
}
else if (x < 0) { /* error in sending file */
krm_rclose(FALSE); /* close the file */
krm_err(IDS_KRM_SENDDATA_ERROR); /* post error to remote and quit */
RESUME;
}
else
BEGIN ssdata; /* prepare to receive data */
}
/* Got ACK to data packet
*/
<ssdata>Y {
krm_checkcnx(); /* check if transaction cancelled */
if (Kermit.abort) {
if (Kermit.abort == KRM_FILEABORT) /* cancel file send */
Kermit.abort = 0;
if (krm_seof("D") < 0) { /* tell remote about cancellation */
krm_err(IDS_KRM_SENDEOF_ERROR); /* error; inform remote */
RESUME; /* quit */
}
BEGIN sseof; /* prepare to send end of file */
}
else {
int x;
if ((x = krm_sdata()) == 0) { /* no more data */
if (krm_seof("") < 0) { /* send end of file */
krm_err(IDS_KRM_SENDEOF_ERROR); /* error; inform remote */
RESUME; /* quit */
}
BEGIN sseof; /* prepare to send end of file */
}
else if (x < 0) { /* error */
krm_rclose(FALSE); /* close the file */
krm_err(IDS_KRM_SENDDATA_ERROR); /* inform remote */
RESUME; /* quit */
}
}
}
/* Got ACK to end of file packet
*/
<sseof>Y {
if (Kermit.pFile = krm_getnextfile(FALSE)) { /* any more files? */
if (krm_sfile() < 0) { /* send next file name */
krm_err(IDS_KRM_SENDFILENAME_ERROR); /* error, inform remote */
RESUME; /* quit */
}
BEGIN ssfile; /* prepare for next file */
}
else { /* no more files to send */
if (krm_seot() < 0) { /* send break */
krm_err(IDS_KRM_SENDEOT_ERROR); /* error, inform remote */
RESUME; /* quit */
}
BEGIN sseot; /* prepare to exit file send */
}
}
/* Got ACK to end of transmission packet
*/
<sseot>Y {
krm_tend(IDS_KRM_TRANSACTION_DONE); /* clean up */
RESUME; /* quit */
}
/* resend of previous I packet ACK,
same sequence number */
<get>Y {
krm_srinit(Kermit.pFilelist);
}
<rgen>Y {
if (krm_rcvpkt.len > 0)
krm_tend(KRM_DATA_PACKET);
else
krm_tend(IDS_KRM_TRANSACTION_DONE); /* clean up */
RESUME; /* quit */
}
/* Got sendinit packet
*/
<rgen,get>S {
BYTE data[KRM_MAXDATALEN + 1];
krm_spar(krm_rcvpkt.data, krm_rcvpkt.len); /* read send-init data */
krm_ack(krm_rpar(data), data); /* return init data in ACK */
Kermit.bctu = Kermit.bctr; /* set block check type */
BEGIN rsfile; /* prepare for file name */
}
/* Got file name packet
*/
<rgen,rsfile>F {
if (krm_rcvfil()) { /* try to open file */
char buf[KRM_MAXDATALEN + 1];
int inlen, outlen;
inlen = strlen(Kermit.pFile); /* return our name to remote */
outlen = krm_encode(buf, Kermit.pFile, sizeof(buf) - 1, &inlen);
krm_ack(outlen, buf); /* send the name in ACK */
BEGIN rsdata; /* prepare to receive data */
}
else {
krm_err(IDS_KRM_FILE_OPEN_ERROR); /* error, inform remote */
RESUME; /* quit */
}
}
<rgen,rsfile>X {
if (krm_opent()) {
krm_ack(0, "");
BEGIN rsdata;
}
else {
krm_err(IDS_KRM_TERMINAL_OPEN_ERROR);
RESUME;
}
}
/* Got data packet
*/
<rsdata>D {
if (krm_rcvdata()) {
switch(Kermit.abort) { /* see if abort flag is on */
case KRM_BATCHABORT:
krm_ack(1, "Z"); /* cancel remaining files */
Kermit.abort = 0;
break;
case KRM_FILEABORT:
krm_ack(1, "X"); /* cancel current file */
Kermit.abort = 0;
break;
default:
krm_ack(0, ""); /* continue */
}
}
else {
krm_rclose(TRUE); /* error in storing data */
krm_err(IDS_KRM_FILE_WRITE_ERROR); /* inform host */
RESUME; /* quit */
}
}
/* Got end of file packet
*/
<rsdata>Z { /* see if remote wants us to delete file */
if (krm_rclose(krm_rcvpkt.len &&
(krm_rcvpkt.data[0] == 'D') ? TRUE : FALSE)) {
krm_ack(0, ""); /* acknowledge */
BEGIN rsfile; /* prepare for next file */
}
else {
krm_err(IDS_KRM_FILE_CLOSE_ERROR); /* error; inform remote */
RESUME; /* quit */
}
}
/* Got end of transmission packet
*/
<rsfile>B {
krm_ack(0, ""); /* acknowledge */
krm_tend(IDS_KRM_TRANSACTION_DONE); /* clean up */
RESUME; /* quit */
}
/* Packet is incomplete; return.
*/
$ {
CONTINUE; /* continue until packet is filled */
}
/* Got error packet
*/
E {
krm_rclose(TRUE); /* close any open files */
krm_tend(KRM_DATA_PACKET); /* clean up */
RESUME; /* quit */
}
/* Unrecognized packet
*/
. {
krm_rclose(TRUE); /* close any open files */
krm_err(IDS_KRM_UNKNOWN_PACKET); /* post error to remote */
RESUME; /* quit */
}
%%
/* input
*
* provide packet type to state machine
*/
static int near input()
{
register int type;
if (Kermit.start) {
type = Kermit.start;
Kermit.start = 0;
}
else {
type = krm_rpack(); /* read input */
if ((type != '$') && (type != 'E')) {
/* packet is complete but is not an error packet */
if ((Kermit.seq != krm_rcvpkt.seq) || strchr("NQT", type)) {
/* something is wrong with packet */
if (Kermit.retries >= KermParams.RetryLimit) {
/* pretend we have an error packet */
krmCreatePseudoPacket('E', PS_DONE, IDS_KRM_TOOMANYRETRIES);
type = 'E';
}
else if ((type == 'N') &&
(krm_rcvpkt.seq == ((Kermit.seq + 1) & 63))) {
/* this is OK since NAK for next packet is ACK for previous */
type = 'Y';
Kermit.retries = 0;
}
else {
/* resend previous packet and try again */
Kermit.retries += 1;
Kermit.totalretries += 1;
krm_resend();
type = '$';
}
}
else /* packet is OK; reset retry count */
Kermit.retries = 0;
}
}
return (type);
}