home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
modem
/
byepc300.arc
/
BYEXMDM.ARC
/
XMDM.C
< prev
next >
Wrap
Text File
|
1987-10-28
|
29KB
|
1,097 lines
/*
** Program: <xmdm.c>
**
** Purpose: Allows XMDM file transmission for use with BYE-PC.
**
** Date: 02/29/85
**
** Requirments: Requires the following modules to compile and link:
**
** <xmdm.c> ;main xmodem source code module.
** <crc.asm> ;crc & timing utilities.
** <byexface.c> ;modem i/o interface to BYE-PC.
** Revisions:
**
** Ver: 1.08 Modified 'xmdm_nak()' to switch receive modes
** 03/15/87 after 10 retries in either CRC or Checksum.
**
** Ver: 1.09 Modified 'get_a_block()' and 'put_a_block()' to clear
** 03/15/87 the buffers before filling it with data. The old
** functions left trash in the buffer, which ended up
** in the last block of the file rather than nulls.
**
** Ver: 1.10 Added 'drx_flush()' to handle resync after many
** 05/21/87 severe noise errors. Added Ctrl-Break disable on
** local keyboard.
**
** Ver: 1.11 Fixed bugs in xrecvbuf().
** 06/01/87
**
** Ver: 1.12 More bugs, version 1.11 would randomly lockup
** 06/01/87 the system. I have trashed the C functions in
** 'timer()' and 'getticks()' with an assembly
** timing function. This assembly function was added
** to the module 'crc.asm'.
**
** Ver: 1.13 Tweaked the timing values used in 'xrecvbuf()'
** 08/03/87 to offer better error recovery.
**
** Ver: 1.14 Altered all function names used to access BYE-PC.
** 08/08/87 All function that use BYE-PC functions are now
** preceeded by '_bye_".
**
** Ver: 1.15 Moved carrier checking inside of tx and rx buffer
** 08/08/87 routines. Modified the transmit block counter in
** the function 'xpreface()'.
*/
/* Include Headers */
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include <dos.h>
#include <ctype.h>
#include <string.h>
#include <process.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "byexface.h"
/* xmodem configuration */
#define P_UPLOAD /* define for private uploads */
#define C_STATUS /* check status before uploading & dnloading */
/* #define C_EXE /* .COM & .EXE files are invalid to send */
#ifdef P_UPLOAD
#define P_PATH "C:\\UPLOADS\\" /* private upload path */
#endif
/* end xmodem configuration */
#define VER 1 /* XMODEM Version# */
#define REV 16 /* XMODEM Revision# */
#define YES 1 /* generic defines */
#define NO 0
#define ON 1
#define OFF 0
#define TRUE 1
#define FALSE 0
#define SOH 1 /* communications defines */
#define CRC 'C'
#define EOT 4
#define ACK 6
#define NAK 0x15
#define CTRL_X 0x18 /* xmdm abort keys */
#define CTRL_C 0x03
#define BYE_VER 3 /* requires BYE-PC version 3.00 or greater */
#define BYE_REV 0
#define BIT_4 16 /* xmdm send flag */
#define BIT_5 32 /* xmdm receive flag */
#define BLKSIZ 128 /* xmdm block size */
/* function declarations */
void xmodem_optns(), timer();
void drx_flush();
void xmdm_rxblk();
void check_cd();
int xmdm_init();
int xmdm_send(), get_a_block();
int xmdm_receive(), put_a_block(), xpreface(), xsendbuf();
int xrecvbuf(), xmdm_nak(), mdm_tgetc(), mdm_tputc();
int executable();
long getticks();
/* external assembler routines */
extern unsigned crc_value();
extern void crc_init(), crc_sum(), ctrl_break();
/* static declarations */
char First; /* first block sent flag */
int Crcflg; /* crc mode flag */
int Blkcnt; /* logical block counter (no reset) */
int Blkhdr; /* physical block counter (0 - 255) */
/*-------------------------------------------------------------------*/
/* This function responds to xmdm commands and scans the file name */
/* for correct format & paramters. If all is ok, then the send or */
/* receive command is called with the given file name. */
/*-------------------------------------------------------------------*/
main(argc, argv)
int argc;
char *argv[];
{
char fname[32], optns[3];
int rtn;
unsigned cstat;
if (argc < 3)
{
xmodem_optns(); /* show error msg */
exit(1); /* exit back to dos */
}
if (rtn = _bye_check(BYE_VER, BYE_REV))
{
printf("\nXMODEM ERROR: BYE-PC ");
switch(rtn)
{
case 1:
printf("is not loaded!\n");
break;
case 2:
printf("loaded is the wrong Version!\n");
break;
case 3:
printf("loaded is the wrong Revision!\n");
break;
default:
printf("returned invalid error code!\n");
break;
}
exit(1);
}
ctrl_break(OFF); /* disable local ctrl-break */
_bye_setbreak(CTRL_NOTRAP); /* dont trap/filter ^C & ^S data */
_bye_setcd(OFF); /* disable CD loss checking */
strncpy(optns, argv[1], 2); /* get xmdm options */
strncpy(fname, argv[2], 31); /* get file name */
if (toupper((int)optns[1]) == 'C') /* test for Checksum mode only */
Crcflg = NO;
else
Crcflg = YES;
cstat = _bye_getcsw() & 0x003F; /* get xmdm status bits */
switch(toupper((int)optns[0])) /* Tx or Rx a file? */
{
case 'S': /* is it send command? */
#ifdef C_STATUS
if (!(cstat & BIT_4))
{
printf("\nSorry, Uploads not permitted at this time...\n");
break;
}
#endif
#ifdef C_EXE
if (executable(fname) && (cstat != 0xffff))
{
printf("\nSorry, can't send .EXE and .COM files...\n");
break;
}
#endif
xmdm_send(fname); /* try to send file */
break;
case 'R': /* is it receive command? */
#ifdef C_STATUS
if (!(cstat & BIT_5))
printf("\nSorry, Downloads not permitted at this time...\n");
else
#endif
xmdm_receive(fname); /* try to receive a file */
break;
default:
xmodem_optns(); /* show error msg */
break;
}
_bye_stdout(ON); /* turn on console Rx & Tx */
_bye_stdin(ON);
_bye_setcd(ON); /* enable carrier loss checking */
_bye_setbreak(CTRL_TRAP); /* enable trap ^C & ^S data */
ctrl_break(ON); /* reenable local ctrl-break */
exit(0); /* exit back to DOS */
}
/*-------------------------------------------------------------------*/
/* Scan file name for a .COM or .EXE file extension */
/*-------------------------------------------------------------------*/
#ifdef C_EXE
int executable(fname)
char *fname;
{
char *p;
if ((p = strchr(fname, '.')) == NULL)
return(0);
else
{
if (!strncmp(p, ".COM", 4))
return(1);
if (!strncmp(p, ".EXE", 4))
return(1);
}
return(0);
}
#endif
/*-------------------------------------------------------------------*/
/* Show list of valid XMODEM options to user. */
/*-------------------------------------------------------------------*/
void xmodem_optns()
{
printf("\nXMODEM for use with BYE-PC\n");
printf("Version %1d.%-2.2d Copyright (c) 1986, 1987, MCODE Software\n\n", VER, REV);
printf("\tXMODEM S {d:filename} ---> Send file in CRC mode\n");
printf("\tXMODEM R {d:filename} ---> Receive file in CRC mode\n");
printf("\tXMODEM SC {d:filename} --> Send file in Checksum mode\n");
printf("\tXMODEM RC {d:filename} --> Receive File Checksum mode\n");
printf("\n[Only the above options are allowed at this time!]\n\n");
}
/*-------------------------------------------------------------------*/
/* XMODEM U P L O A D - S E N D A F I L E */
/*-------------------------------------------------------------------*/
/* This function is supplied a file name and a crc flag. The */
/* file is searched for on the disk, if the file name exists it */
/* is opened for binary read and transmitted in XMODEM protocol. */
/*-------------------------------------------------------------------*/
int xmdm_send(fname)
char fname[];
{
char buf[BLKSIZ+10];
int result, igetret, iret, exit, c, bps;
long ksize, numblocks, stime;
FILE *fp; /* file stream pointer */
ksize = stime = numblocks = 0L;
if ((fp = fopen(fname, "rb")) == NULL) /* open for binary read */
{
printf("\n+++ File Open Error! +++\n");
return(EOF);
}
if ((ksize = filelength(fileno(fp))) == EOF) /* get file size */
{
printf("\n+++ File Length Read Error! +++\n");
return(EOF);
}
if (ksize < (long)BLKSIZ)
ksize = (long)BLKSIZ;
numblocks = (ksize / (long)BLKSIZ) + 1L; /* calculate # of blocks */
switch(_bye_baud()) /* get baud rate from BYE */
{
case 0:
bps = 300;
break;
case 1:
bps = 1200;
break;
case 2:
bps = 2400;
break;
default:
bps = 9600;
break;
}
stime = ksize / (long)(bps / 10); /* send time in secs */
printf("\nXMODEM for use with BYE-PC\n");
printf("Version %1d.%-2.2d Copyright (c) 1986, 1987, MCODE Software\n", VER, REV);
printf("[Use CTRL-X to cancel file send]\n\n");
printf("File Open : %s\n", fname);
printf("File Size : ");
if (ksize > 1024L)
printf("%ldk (%ld blocks)\n", (ksize / 1024L) + 1L, numblocks);
else
printf("%ld bytes (%ld blocks)\n", ksize, numblocks);
printf("Send Time : ");
if (stime > 60L)
printf("%ld min(s) %ld sec(s)", stime/60L, stime%60L);
else
printf("%ld sec(s)", stime);
printf(" at %dbps\n", bps);
if (Crcflg)
printf("(CRC Mode)\n\n");
else
printf("(Checksum Mode)\n\n");
printf("Ready to send...\n\n");
/*------------------------------------------------------------------*/
/* Major Loop: The file is open. While it is not EOF, get blocks */
/* of BLKSIZ bytes each and send them using xsendbuf(). If we hit */
/* EOF in the middle of a buffer, (a) set a flag that indicates */
/* sending EOT after this block is succsessfully received, and (b) */
/* zero pad the block out to BLKSIZ bytes. */
/*------------------------------------------------------------------*/
timer(10*18); /* wait 10 seconds before starting */
_bye_stdout(OFF);
_bye_stdin(OFF); /* disable INT10 & INT16 merging */
exit = 1;
First = Blkcnt = Blkhdr = 1;
while (exit)
{
memset(buf, '\0', BLKSIZ); /* null out data buffer */
igetret = get_a_block(buf, fp); /* get block from file */
if (iret = xsendbuf(buf))
break;
if (First) /* reset first block flag */
First = 0;
printf("Block Sent:%-5.5d (%-4.4Xh)\r", Blkcnt, Blkcnt);
if(!iret && (igetret != 0))
{
while(TRUE)
{
if (mdm_tputc(EOT, 1) == EOF) /* send an EOT */
break;
c = mdm_tgetc(2); /* get return */
if (c == ACK || c == EOF) /* ACK or error to end */
break;
}
exit = 0; /* now exit */
}
++Blkcnt;
}
fclose(fp); /* close the file */
printf("\n\nEnd XMODEM Send...\n");
}
/* End of XMODEM SEND */
/*
** Function: int get_a_block(buf, fp)
**
** Parms: char *buf; -> buffer to read data from
** FILE *fp; -> file stream pointer
**
** Purpose: Reads a block of data into pointer 'buf' for BLKSIZ
** bytes.
**
** Return: 1 = last block of data read.
** 0 = more data to read from disk.
*/
int get_a_block(buf, fp)
char *buf;
FILE *fp;
{
int bytes;
bytes = fread(buf, sizeof(char), BLKSIZ, fp);
if (bytes < BLKSIZ)
return(1);
else
return(0);
}
/*-------------------------------------------------------------------*/
/* XMODEM D O W N L O A D - R E C E I V E A F I L E */
/*-------------------------------------------------------------------*/
/* The file is opened if does not currently exists and NAK's are */
/* sent to the remote station to start the receive process. Each */
/* block is written to disk as it is received. If more than 10 */
/* errors occurs in a single block, the fiel Rx is canceled and the */
/* incomplete file is deleted from disk. */
/*-------------------------------------------------------------------*/
int xmdm_receive(file)
char file[];
{
char fname[64], buf[BLKSIZ+10];
int iputret, iret, exit;
int cancel = YES;
FILE *fp;
#ifdef P_UPLOAD
strcpy(fname, P_PATH); /* get private upload path name */
strcat(fname, file);
#else
strcpy(fname, file);
#endif
if (!access(fname, 0)) /* check for file exsistance */
{
printf ("\n+++ File Already Exists! +++\n");
return (EOF);
}
if ((fp = fopen(fname, "wb")) == NULL) /* open file to write to */
{
printf ("\n+++ File Open Error! +++\n");
return (EOF);
}
else
{
printf("\nXMODEM for use with BYE-PC\n");
printf("Version %1d.%-2.2d Copyright (c) 1986, 1987, MCODE Software\n", VER, REV);
printf("[Use CTRL-X to cancel file receive]\n\n");
printf("File Open: %s\n", file);
if (Crcflg)
printf("(CRC Mode)\n\n");
else
printf("(Checksum Mode)\n\n");
printf("Ready to receive...\n\n");
}
/*------------------------------------------------------------------*/
/* Major xmodem receive loop. The file has been created. Get the */
/* first block from the other end, store it; repeat this until the */
/* transmitter sends EOT. Use xrecvbuf(). Check block numbers */
/*------------------------------------------------------------------*/
_bye_stdout(OFF);
_bye_stdin(OFF);
timer(10*18); /* wait 10 secs before starting */
First = Blkcnt = Blkhdr = 1;
exit = 1;
while(exit)
{
memset(buf, '\0', BLKSIZ);
if ((iret = xrecvbuf(buf)) == 0) /* attempt to Rx a block */
{
if (put_a_block(buf, fp) == EOF)
{
printf("\n+++ Disk Write Error! +++\n");
cancel = YES;
exit = 0;
break;
}
else
printf("Block Received:%-5.5d (%-4.4Xh)\r", Blkcnt, Blkcnt);
}
else
{
switch(iret)
{
case 2: /* EOT to end Rx */
cancel = NO;
break;
case 3:
case 9:
break;
default: /* any error except EOT */
printf("\n+++ Too many errors - Aborting Receive! +++\n");
break;
}
exit = 0;
}
if (First)
First = 0;
++Blkcnt;
}
fclose(fp); /* close the file */
if (cancel)
{
unlink(fname);
printf("\n+++ Incomplete file deleted +++\n");
}
else
printf("\n\nEnd XMODEM Receive...\n");
}
/*
** Function: int put_a_block(buf, fp)
**
** Parms: char *buf; -> buffer to read data from
** FILE *fp; -> file stream pointer
**
** Purpose: Writes a block of data starting at pointer 'buf'
** for the xmdm block size .
**
** Return: EOF = Error writing data
** 0 = data written disk
*/
int put_a_block(buf, fp)
char *buf;
FILE *fp;
{
int bytes;
bytes = fwrite(buf, sizeof(char), BLKSIZ, fp);
if (bytes < BLKSIZ)
return(EOF);
else
return(0);
}
/*-------------------------------------------------------------------*/
/* XMODEM Send Data Block routines. */
/*-------------------------------------------------------------------*/
/*
**
** (1) Send prefix (SOH, Block number, Block number XOR 255)
** (2) Send BLKSIZ bytes from User Buffer and compute checksum
** (3) Send Checksum
**
** Returns: 0 = Successful sending Block.
** 1 = I/O error to or from the modem.
** 2 = Initial NAK not received from receiver.
** 3 = Unable to send block after 10 retries.
** 4 = Remote station canceled file send.
*/
int xsendbuf(buf)
char *buf;
{
char *p;
int c, i, chksum, errorcount, try;
unsigned crc;
try = 0; /* xmdm start tx attempt number */
errorcount = 10; /* maximum error count */
while(errorcount)
{
check_cd(); /* make sure we still have carrier */
if(First && errorcount == 10) /* if First time through wait for NAK */
{
_bye_rxflush(); /* clear rx-queue */
i = mdm_tgetc(30); /* 30 sec timeout */
switch(i)
{
case EOF:
printf("[Initial NAK Timed out]\n");
if (try++ > 6)
return(2);
break;
case 'C':
Crcflg = YES;
First = 0;
printf("[CRC Requested]\n");
break;
case NAK:
Crcflg = NO;
First = 0;
printf("[Checksum Requested]\n");
break;
case CTRL_X:
printf("+++ Remote Station Canceled Send +++\n");
return(4);
default:
printf("[Initial NAK Missing] -- Received:%-2.2xh\n", i);
if (try++ > 6)
return(2);
break;
}
continue; /* keep on trying till we error out */
}
p = buf; /* pointer to buffer to send */
chksum = 0; /* clear checksum & CRC storage */
crc_init(); /* clear the CRC accumlator */
drx_flush(); /* clear the rx queue */
if(xpreface() == EOF) /* send prefix */
return(1);
for (i = 1; i <= BLKSIZ; i++)
{
c = (int)*p++;
if(mdm_tputc(c, 1) == EOF) /* send data byte */
return (1);
if (Crcflg)
crc_sum(c); /* sum the CRC value */
else
chksum += c; /* sum the Checksum value */
}
if (Crcflg)
{
crc_sum(0); /* final CRC calculation */
crc_sum(0);
crc = crc_value(); /* get the CRC value */
if(mdm_tputc(crc >> 8, 1) == EOF) /* send MSB of CRC */
return(1);
if(mdm_tputc(crc & 0x00ff, 1) == EOF) /* send LSB of CRC */
return(1);
}
else
{
if(mdm_tputc(chksum, 1) == EOF) /* send checksum */
return(1);
}
/* wait for response back from remote */
while(1)
{
if ((i = mdm_tgetc(5)) == ACK) /* wait for response */
{
if (errorcount != 10) /* newline if errors */
printf("\n");
Blkhdr++; /* advance block ctr */
return(0); /* received ACK */
}
else if (i == NAK)
{
printf("\n<Re-sending Block>"); /* transmit error */
break;
}
else if (i == EOF)
{
printf("\n<Sync Error>");
errorcount = 1; /* last pass */
break;
}
}
--errorcount;
}
printf("\n+++ Too many errors - Aborting Send! +++\n");
return(3); /* indicate failure */
}
/*
** Function: int xpreface()
**
** Parms: void
**
** Purpose: sends the SOH, the block number and the complemented
** block number for a xmdm data block.
**
** Return: 0 = preface sent
** EOF = i/o error
*/
int xpreface()
{
if (mdm_tputc(SOH, 1) == EOF) /* send the SOH */
return(EOF);
if (Blkhdr > 0xff) /* recycle block ctr */
Blkhdr = 0;
if (mdm_tputc(Blkhdr, 1) == EOF) /* send block */
return(EOF);
if (mdm_tputc((255 - Blkhdr), 1) == EOF) /* send compliment blk */
return(EOF);
return (0);
}
/*-------------------------------------------------------------------*/
/* XMODEM Receive Data Block routines. */
/*-------------------------------------------------------------------*/
/*
** Receive XMODEM buffer to user buffer
**
** This function must be called with enough time to spare before the
** application expects to receive the beginning of an XMODEM block.
**
** (1) Get a few characters from receive buffer.
** (2) Test block number, inverse block number -
** (3) Get BLKSIZ bytes data, calculate checksum on the fly.
** (4) Receive checksum from other station, compare with computed.
**
** Return: 0 - Received block correctly
** 1 - timeout on tx or rx i/o attempt
** 2 - EOT received from remote end
** 3 - User cancelled with Ctrl-X or Ctrl-C
** 4 - Missing SOH in block
** 5 - Bad block number
** 6 - Short block error
** 7 - Long block error
** 8 - Checksum or CRC error
** 9 - No response after sending initial NAK's
*/
int xrecvbuf(buf)
char *buf;
{
char *p;
int rxblk, rxnblk, chksum, stat;
int rstat, rxsize, rtn, bytes;
int i, c, errorcount;
unsigned crc;
if (Crcflg)
bytes = BLKSIZ + 2; /* CRC mode */
else
bytes = BLKSIZ + 1; /* Checksum mode */
errorcount = 11;
while(errorcount--)
{
check_cd(); /* make sure we still have carrier */
if (First && errorcount == 10)
{
stat = xmdm_init(); /* initiate xmdm receive */
if (Crcflg) /* did we change modes? */
bytes = BLKSIZ + 2; /* reset to CRC mode */
else
bytes = BLKSIZ + 1; /* reset to Checksum mode */
if (!stat)
goto start; /* was xmdm rx initiated? */
else
return(stat); /* no, return with error */
}
else if (errorcount < 10) /* is this a block resend? */
{
timer(18*2); /* wait about 2 seconds */
drx_flush(1); /* flush out stream data */
if (mdm_tputc(NAK, 1) == EOF) /* now send the NAK. */
return(1);
}
if ((c = mdm_tgetc(15)) == EOF) /* 15 secs on 1st char */
return(9);
else if (c == EOT) /* EOT to end xmdm rx */
{
if (mdm_tputc(ACK, 1) == EOF) /* send back an ACK */
return(1);
else
return(2);
}
else if (c != SOH) /* if SOH then ok */
{
rstat = 4;
printf("\n<Missing SOH>");
continue;
}
start: rstat = 5; /* assume wrong block number */
if ((rxblk = mdm_tgetc(5)) == EOF) /* get block number from sender */
return(1);
if ((rxnblk = mdm_tgetc(5)) == EOF) /* get not block number */
return(1);
if (((rxnblk & 0x00ff) + (rxblk & 0x00ff)) != 255)
{
printf("\n<Bad Block Number>");
continue;
}
xmdm_rxblk(5, bytes); /* collect 'bytes' of data */
rstat = 6;
if(_bye_rxsize() < bytes) /* short block error */
{
printf("\n<Short Block Error>");
continue;
}
rstat = 7;
if(_bye_rxsize() > bytes) /* long block error */
{
printf("\n<Long Block Error>");
continue;
}
p=buf; /* correct byte count has now */
chksum = 0; /* been received, get characters */
crc_init(); /* reset crc accumulator */
for(i = 1; i <= BLKSIZ; ++i) /* from queue & put in user buffer */
{
if ((c = mdm_tgetc(5)) == EOF) /* calculate checksum on the fly */
return(1);
*p++ = (char)c;
if (Crcflg)
crc_sum(c);
else
chksum += c;
}
rstat = 8; /* assume checksum/CRC error */
if (Crcflg)
{
crc_sum(0); /* finish CRC calc */
crc_sum(0);
if ((c = mdm_tgetc(5)) == EOF) /* get LSB of CRC */
return(1);
crc = (c & 0x00ff);
if ((c = mdm_tgetc(5)) == EOF)
return(1);
crc = (crc << 8) + (c & 0x00ff); /* get MSB of CRC */
if(crc != crc_value()) /* compare incoming with calculated */
{
printf("\n<CRC Error>");
continue;
}
}
else
{
if ((c = mdm_tgetc(5)) == EOF) /* get first byte */
return(1);
if ((c & 0x00ff) != (chksum & 0x00ff)) /* compare incoming with calculated */
{
printf("\n<Check Sum Error>");
continue;
}
}
if (mdm_tputc(ACK, 1) == EOF) /* send ACK to start other blocks */
return(1);
if (errorcount != 10)
printf("\n");
return(0); /* success at last */
}
return(rstat); /* return error */
}
/*
** Function: int xmdm_nak()
**
** Parms: <none>
**
** Purpose: Starts the begging of an xmdm transfer.
** Note: if 'l=4' this function will switch
** between CRC and Checksum mode two times while
** waiting for the first SOH character. The purpose
** of this function is to send out NAK's or C's to
** signal remote to begin sending. Once a SOH is
** received, the receive is ready to continue.
**
** Returns: 0 = SOH received valid
** 1 = port timeout errors in tx/rx.
** 2 = no response back from remote.
** 3 = user cancelled receive.
*/
int xmdm_nak()
{
int i, l, c, schr, trys;
for (l = 1; l <= 2; l++) /* If l=2, we will start with CRC and */
{ /* switch to Checksum mode with up to */
if (Crcflg) /* 10 time out errors in each mode. */
{
schr = CRC;
if (l > 1)
{
printf("[Switching to Checksum mode]\n");
Crcflg = NO;
schr = NAK;
}
}
else
{
schr = NAK;
if (l > 1)
{
printf("[Switching to CRC mode]\n");
Crcflg = YES;
schr = CRC;
}
}
for (i = 1; i <= 10; ++i)
{
_bye_rxflush(); /* clear rx buffer */
if(mdm_tputc(schr, 1) == EOF) /* send NAK for first block */
return(1);
c = mdm_tgetc(5); /* wait for 5 seconds on SOH */
switch(c)
{
case EOF: /* try again if timed out */
break;
case SOH:
if (Crcflg)
printf("[CRC Requested]\n");
else
printf("[Checksum Requested]\n");
return(0);
case CTRL_X:
printf("\n+++ Remote station canceled transfer +++\n");
return(3);
default:
printf("[Initial SOH Missing] -- Received: %-2.2xh\n", c);
timer(18*2); /* wait 2 seconds */
break;
}
}
}
return(2); /* something sent back */
}
/*
** Function: int xmdm_init()
**
** Parms: void
**
** Purpose: Initiates an xmodem receive.
**
** Returns: 0 = SOH recieved rx data ready to begin
** 1 = i/o errors occured
** 3 = remote user canceled receive
** 9 = no response to NAK's or C's
*/
int xmdm_init()
{
int stat;
stat = xmdm_nak(); /* if first block and sent */
switch(stat) /* if first block and sent */
{ /* send out NAK's and wait */
case 0: /* a response from remote. */
First = NO;
break;
case 1: /* any i/o errors? */
return(1);
case 2: /* no reponse to NAK's? */
return(9);
default: /* user cancel? */
return(3);
}
return(0);
}
/*
** Function: void xmdm_rxblk(s, n)
**
** Parms: int s; -> # of secs to collect data
** int n; -> bytes to collect
**
** Purpose: Waits for 'n' bytes to be received in the rx-queue
** or for 's' seconds to pass, whichever occurs first.
**
** Returns:
*/
void xmdm_rxblk(s, n)
int s, n;
{
int secs, size;
secs = s * 10; /* delay in terms of 18ms */
while(secs--)
{
if (_bye_rxsize() >= n) /* break when count reached */
break;
timer(1); /* wait for ~18ms & recheck */
}
}
/*-------------------------------------------------------------------*/
/* Timed Modem I/O and Hardware Timing Routines. */
/*-------------------------------------------------------------------*/
/*
** Function: int mdm_tgetc(n)
**
** Parms: unsigned n -> maximun timeout in seconds.
**
** Purpose: Get a character from modem with timeout.
**
** Returns: Character or EOF if timeout waiting to get
** the character
*/
int mdm_tgetc(n)
unsigned n;
{
unsigned s, c;
n *= 18; /* express in terms of 18ms */
for (s=0; s < n; ++s)
{
if ((c = _bye_getc()) != EOF)
return((int)c);
timer(1); /* wait 18ms and retry */
}
return(EOF);
}
/*
** Function: int mdm_tputc(c, n)
**
** Parms: int c -> character to send to modem.
** int n -> timeout count in seconds.
**
** Purpose: Send a character to modem with timeout.
**
** Returns: EOF if timeout waiting to send.
**
*/
int mdm_tputc(c, n)
int c, n;
{
int s;
for (s=0; s < n; ++s)
{
if (_bye_putc(c) != EOF)
return(0);
timer(18); /* wait 1 second */
}
return(EOF);
}
/*
** Function: void drx_flush(d)
**
** Parms: int d; -> delay pause between rx queue size check
** in 18ms increments.
**
** Purpose: Flushes the rx-queue of data, pauses for the specified
** delay time, and rechecks the rx-queue for more data to
** flush. This is used to clear the rx-queue until the
** stream of data halts. Primarilry used for re-sync'ing.
**
** Return: void
*/
void drx_flush(d)
int d;
{
unsigned size;
while(_bye_rxsize()) /* loop while data is received */
{
_bye_rxflush(); /* clear out the rx-data queue */
timer(d); /* delay so more data may collect */
}
}
/*
** Function: void check_cd()
**
** Parms: void
**
** Purpose: This function checks to make sure carrier is still
** found. If carrier is not found, the system is re-
** booted to hang up for the next call.
**
** Return: void
*/
void check_cd()
{
if (!_bye_getcd()) /* check carrier detect */
{
printf("\n+++ CARRIER LOST IN XMODEM! +++\n\b");
fcloseall(); /* close any files open */
timer(5*18); /* wait five seconds */
_bye_warmboot(); /* re-boot the system */
/* just in case we did'nt boot */
_bye_stdout(ON); /* turn on console Rx & Tx */
_bye_stdin(ON);
_bye_setcd(ON); /* enable carrier loss checking */
_bye_setbreak(CTRL_TRAP); /* enable trap ^C & ^S data */
ctrl_break(ON); /* reenable local ctrl-break */
exit(1); /* exit with error level set */
}
}