home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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 */
- }
- }
-
-