home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
157_01
/
cmodem.c
< prev
next >
Wrap
Text File
|
1987-10-12
|
31KB
|
1,059 lines
/* HEADER: CUGaaa.bb;
FILENAME: cmodem.c;
TITLE: Xmodem communications in c;
COMPILERS: C86;
SYSTEM: ms-dos;
AUTHORS: Bill Rogers;
VERSION: 5.01;
DATE: 08/04/1985;
KEYWORDS: commnications, xmodem, ms-dos, pc-dos, 8251a, 8530;
SEE-ALSO: local.h;
DESCRIPTION:
"This program implements an elementary version of xmodem for
under ms-dos or pc-dos.";
WARNINGS:
"The zilog usart option is not yet tested.";
*/
/* The calling sequence is:
*
* cmodem
*
* The control sequences are:
*
* <ctrl-z><ctrl-z> send <ctrl-z>
* <ctrl-z>b300 set baud rate to 300 baud
* <ctrl-z>b1200 set baud rate to 12000 baud
* <ctrl-z>d dial telephone number
* <ctrl-z>e exit without hangup
* <ctrl-z>h hangup without exit
* <ctrl-z>i initialize port & baud rate
* <ctrl-z>nx...x enter telephone number x...x
* <ctrl-z>q quit with hangup
* <ctrl-z>rx...x receive file name x...x
* <ctrl-z>sx...x send file name x...x
* <ctrl-z>t trace file transmissions
* <ctrl-z>? display commands
*
* Revision history: Latest revision first.
*
* 12/Dec/84 Changed to C86 (Bill Rogers).
* 04/Jun/82 Removed PMMI defines and ifdef for Australia. Much
* more extensive documentation added. Modem port
* defines now obtained from BDSCIO.H. Code tidied up
* a bit and VARBAUD ifdefs added. Some messages
* changed and numerous small changes ( Bill Bolton).
* ??/???/81 Patched together from existing Cnet and YAM code
* (Steve Passe, Cnode SYSOP, USA).
* SCCS IDENTIFICATION */
static char SCCSID[] = "@(#)cmodem.c 5.0.1";
/*--------------------------------------------------------------------*/
/* INCLUDE */
#define EXTERN extern
#include <local.h>
#undef EXTERN
/*--------------------------------------------------------------------*/
/* DEFINE */
/* Select USART interface type. */
#define OCTAPORT /* Lomas HAZITALL or Lomas OCTAPORT */
/* ascii characters. */
#define NUL 0x00
#define SOH 0x01
#define EOT 0x04
#define ACK 0x06
#define HT 0x09
#define LF 0x0a
#define CR 0x0d
#define NAK 0x15
#define CAN 0x18
#define SUB 0x1a /* ^Z */
#define ESC 0x1b
/* Escape character for control. */
#define ESCCHAR 0x1a /* ^Z */
#ifdef HAZITALL
/* Intel 8253 programmable interval timer definition. */
#define CLOAD 0x8d /* load port. */
#define CCTRL 0x0f /* control port. */
#define CCTRLB 0x76 /* select counter 1,
load lsb, then msb,
square wave generator,
binary counter. */
#define B0300 417 /* 300 baud. */
#define B1200 104 /* 1200 baud. */
/* Intel 8251a serial port definition. */
#define MDATA 0x84 /* Data port. */
#define MSTAT 0x85 /* Status port. */
#define MOMASK 0x01 /* Output ready mask. */
#define MIMASK 0x02 /* Input ready mask. */
#define MCMD1 0x40 /* Internal reset. */
#define MMODE 0x6e /* One stop bit,
even parity,
disable parity,
8 bit character length,
16x baud rate factor. */
#define MCMD2 0x37 /* NA,
internal reset disabled,
rts enabled,
error reset enabled,
break disabled,
receive enabled,
dtr enabled,
send enabled. */
#endif
#ifdef OCTAPORT
/* Zilog 8530 serial port definition, including timer. */
#define B0300 830
#define B1200 206
#define MDATA 0x20 /* Data port. */
#define MSTAT 0x21 /* Status port. */
#define MCMND 0x22 /* Command port. */
#define MOMASK 0x04 /* Output ready mask. */
#define MIMASK 0x01 /* Input ready mask. */
#define MDEFSNUM 10
static unsigned char MDEFS[MDEFSNUM] = {
0x09, /* Select wr09 - master interrupt control. */
0xc0, /* 7-6: force hardware reset.
5-0: - */
0x0f, /* Select wr15 - external status/control. */
0x40, /* 7-0: Disable all interrupts. */
0x04, /* Select wr04 - receiver and transmitter control. */
0x44, /* 7-6: x16 clock,
5-4: 0
3-2: 1 stop bits,
1-1: even parity,
0-0: no parity. */
0x05, /* Select wr05 - transmitter control. */
0xea, /* 7-7: assert dtr,
6-5: transmit 8 bits,
4-4: disable break,
3-3: enable transmit.
2-2: 0
1-1: assert rts.
0-0: - */
0x03, /* Select wr03 - receiver control. */
0xc1 /* 7-6: receive 8 bits,
5-5: no autoenables,
4-1: 0,
0-0: enable receive. */
};
#define MBAUDNUM 10
#define MBAUDLOW 3 /* Index to baudrate low byte. */
#define MBAUDHIGH 5 /* Index to baudrate high byte. */
static unsigned char MBAUD[MBAUDNUM] = {
0x0e, /* Select wr14- miscellaneous control. */
0x00, /* 7-1: -
0-0: Disable baudrate generator. */
0x0c, /* Select wr12 - low byte of baudrate constant. */
11, /* 7-0: 1200 baud. */
0x0d, /* Select wr13 - high byte of baudrate constant. */
0, /* 7-0: 1200 baud. */
0x0b, /* Select wr11 - clock mode control. */
0x56, /* 7-7: no crystal,
6-5: receive clock = baudrate generator output,
4-3: transmit clock = baudrate generator output,
2-2: -
1-0: trxc-out=baudrate generator. */
0x0e, /* Select wr14 - miscellaneous control. */
0x03 /* 7-2: -
1-1: pclk source of clock,
0-0: Enable baudrate generator. */
};
#endif
/* Hayes modem command strings. */
#define ESCAPE_STR "+++"
#define HANGUP_STR "AT H0 \r"
#define DIAL_STR "AT DT "
#define CR_STR "\r"
/* DOS interrupts. */
#define DIR_IO 0x06 /* DOS function request - direct i/o */
#define INPUT 0xff /* DOS function sub-request - accept */
/* Flag values. */
#define OK ( 0)
#define ERROR (-1)
#define WCEOT (-2)
#define TIMEOUT (-3)
#define EMPTY (-4)
#define SECSIZ 128 /* Block size. */
#define RETRYMAX 10
#define PATHLEN 64 /* Send/receive file pathname length */
#define CLKMHZ 8 /* CPU speed in Mhz */
#define TIMECON 311 /* Constant to convert CLKMHZ to ticks.
*/
#define CONSTAT 2
#define CONIN 3
#define NORMAL 0x1c
#define ORIG 0x01
#define ANSWER 0x02
#define READY 0x5f
#define OPT300 0x20
#define OPT600 0x00
#define CLEAR 0x3f
/*--------------------------------------------------------------------*/
static int BAUDRATE;
static string PHONENUM[33] = "1,201-866-2258";
static bool TRACEFLAG = false;
static string YN[65];
static bool SENDOPEN;
static bool RCVOPEN;
static string SENDNAME[PATHLEN + 1];
static string RCVNAME[PATHLEN + 1];
static file *SENDFILE;
static file *RCVFILE;
static int T1PAUSE;
static char CHECKSUM;
static char LASTRX;
static int WCJ;
static int FIRSTCH;
extern file *fopen();
/*--------------------------------------------------------------------*/
static void DELAY(P_DELAY)
int P_DELAY; /* In. */
/* Delay, in units of 0.01 sec. */
{
static int TICKS = 465; /* For 8mhz 8086. */
int I;
int J;
int X = 0;
/* begin */
for (I = 0 ; I < P_DELAY ; I++ ) {
for (J = 0 ; J < TICKS ; J++) {
X = X;
}
}
}
/*--------------------------------------------------------------------*/
static void PRNALLCH(P_C)
metachar P_C; /* In. */
/* Print character.
Char Print
eof ^*
< 0 ^:
control ^x (x = '@'...'_')
tilde ^>
del ^?
>del .
*/
{
/* begin */
if (P_C == -1) {
putchar('^');
putchar('*');
} else if (P_C < 0) {
putchar('^');
putchar(':');
} else if (P_C == LF) {
putchar(P_C);
} else if (P_C == CR) {
putchar(P_C);
} else if (P_C < ' ') {
putchar('^');
putchar(P_C + 0x40);
} else if (P_C <= '}') {
putchar(P_C);
} else if (P_C <= 0x7f) {
putchar('^');
putchar(P_C + 0x20);
} else {
putchar('.');
}
}
/*--------------------------------------------------------------------*/
static metachar IN_MODEM()
/* Receive byte from modem port. */
{
metachar RTN;
extern metachar inportb();
/* begin */
if (inportb(MSTAT) & MIMASK) { /* status & char ready bit */
RTN = inportb(MDATA) & 0x00ff; /* ok, get the char */
} else {
RTN = EMPTY; /* return empty */
}
return RTN;
}
/*--------------------------------------------------------------------*/
static void OUT_MODEM(P_OUT_CHAR)
char P_OUT_CHAR;
/* Send byte to modem port. */
{
extern metachar inportb();
extern void outportb();
/* begin */
while ( ! (inportb(MSTAT) & MOMASK)) {
; /* wait */
}
outportb(MDATA,P_OUT_CHAR); /* finally, send it */
}
/*--------------------------------------------------------------------*/
static char GETCH()
/* Accept character from keyboard,
no wait, no ^C, no echo, no buffer flush. */
{
char RTN;
extern metachar bdos();
/* begin */
RTN = bdos(DIR_IO,INPUT) & 0x007f;
return RTN;
}
/*--------------------------------------------------------------------*/
static metachar READBYT(P_DELAY)
int P_DELAY;
/* Receive byte. Delay in units of 0.01 sec. */
{
metachar RTN;
static int TICKS = 10; /* For 8mhz 8086. */
int I;
int J;
extern metachar inportb();
/* begin */
for (I = 0 ; I < P_DELAY ; I++) {
for (J = 0 ; J < TICKS ; J++) {
RTN = IN_MODEM();
if (RTN != EMPTY) {
return RTN;
}
if (GETCH()) { /* Local forced timeout. */
RTN = TIMEOUT;
return RTN;
}
}
}
RTN = TIMEOUT;
return RTN;
}
/*--------------------------------------------------------------------*/
static void DELAY_ECHO(P_DELAY)
int P_DELAY;
/* Wait for echo, and echo to screen. Delay in units of 0.01 sec.*/
{
static int TICKS = 130; /* For 8mhz 8086. */
int I;
int J;
int X = 0;
metachar C;
metachar IN_MODEM();
/* begin */
for (I = 0 ; I < P_DELAY ; I++) {
for (J = 0 ; J < TICKS ; J++) {
C = IN_MODEM();
if (C != EMPTY) {
if (C != TIMEOUT) {
PRNALLCH(C);
}
}
}
}
}
/*--------------------------------------------------------------------*/
static void OUT_STR(P_OUT_STR)
string P_OUT_STR[];
/* Send string to modem port. */
{
int I;
metachar C;
/* begin */
I = 0;
while (P_OUT_STR[I] != '\0') {
OUT_MODEM(P_OUT_STR[I]);
C = READBYT(10);
if ( ! ((C == EMPTY) || (C == TIMEOUT))) {
PRNALLCH(C);
}
I++;
}
}
/*--------------------------------------------------------------------*/
static void PURGELINE()
/* Drain modem input. */
{
metachar TEMP;
extern metachar inportb();
/* begin */
while (inportb(MSTAT) & MIMASK) {
TEMP = inportb(MDATA);
}
}
/*--------------------------------------------------------------------*/
static int FILBUF(P_BUF,P_COUNT)
char *P_BUF;
int P_COUNT;
/* fill block from send file with count chars padding with ^Z for
CPM */
{
metachar C;
int M;
extern metachar fgetc();
/* begin */
M = P_COUNT;
while ((C = fgetc(SENDFILE)) != EOF) {
*P_BUF++ = C;
if (--M == 0) {
break;
}
}
if (M == P_COUNT) {
return 0;
} else {
/* won't pad properly under cp/m because of two different EOF's
(EOF & CPMEOF), and the fact that cp/m doesn't know type of
file instinctively, fix later */
while(--M >= 0) {
*P_BUF++ = SUB; /* ^Z. */
}
}
return P_COUNT;
}
/*--------------------------------------------------------------------*/
static int OPENTX()
/* Open send file. */
{
int RTN;
/* begin */
SENDFILE = fopen(SENDNAME,opnreadb);
if (SENDFILE == null) {
printf("\n**** Send File '%s' Failed to Open ****\n",SENDNAME);
RTN = ERROR;
} else {
printf("\n#### Send File '%s' Opened ####\n",SENDNAME);
SENDOPEN = true;
RTN = OK;
}
return (RTN);
}
/*--------------------------------------------------------------------*/
static void CLOSETX()
/* Close send file. */
{
int FLAG;
/* begin */
if (SENDOPEN) {
FLAG = fclose(SENDFILE);
if (FLAG == ERROR) {
printf("\n**** Send File '%s' Failed to Close ****\n",
SENDNAME);
exit(1);
} else {
printf("\n#### Send File '%s' Closed ####\n",SENDNAME);
SENDOPEN = false;
}
}
}
/*--------------------------------------------------------------------*/
static int OPENRX()
/* Open receive file. */
{
int RTN;
/* begin */
RCVFILE = fopen(RCVNAME,opnreadb);
if (RCVFILE != null) {
fclose(RCVFILE);
printf(
"\n**** Receive File '%s' Already Exists, Try Another Name ****\n",
RCVNAME);
RTN = ERROR;
} else {
RCVFILE = fopen(RCVNAME,crewritb);
if (RCVFILE == null) {
printf("\n**** Receive File '%s' Cannot Be Created ****\n",
RCVNAME);
RTN = ERROR;
} else {
printf("\n#### Receive File '%s' Opened ####\n",
RCVNAME);
RCVOPEN = true;
RTN = OK;
}
}
return (RTN);
}
/*--------------------------------------------------------------------*/
static void CLOSERX()
/* Close receive file. */
{
int FLAG;
/* begin */
if (RCVOPEN) {
fflush(RCVFILE);
FLAG = fclose(RCVFILE);
if (FLAG == ERROR) {
printf("\n**** Receive File '%s' Failed to Close ****\n",
RCVNAME);
exit(1);
} else {
printf("\n#### Receive File '%s' Closed ####\n",
RCVNAME);
RCVOPEN = false;
}
}
}
/*--------------------------------------------------------------------*/
static int WCPUTSEC(P_TXBUF,P_SECTNUM)
char *P_TXBUF;
int P_SECTNUM;
/* Send block. */
{
char ATTEMPTS;
int I;
char XBYT;
/* begin */
FIRSTCH = 0; /* part of logic to detect CAN CAN */
for (ATTEMPTS = 0 ; ATTEMPTS <= RETRYMAX ; ATTEMPTS++) {
LASTRX = FIRSTCH;
OUT_MODEM(SOH);
OUT_MODEM(P_SECTNUM);
OUT_MODEM(~P_SECTNUM); /* <tilde>P_SECTNUM */
CHECKSUM = 0;
for (I = 0 ; I < SECSIZ ; I++) {
OUT_MODEM(P_TXBUF[I]);
if (TRACEFLAG) {
PRNALLCH(P_TXBUF[I]);
}
CHECKSUM = CHECKSUM + P_TXBUF[I];
}
OUT_MODEM(CHECKSUM);
PURGELINE();
FIRSTCH = READBYT(1000);
if (FIRSTCH == CAN && LASTRX == CAN) {
CANCAN:
printf("\n#### Receiver CANcelled Sending ####\n");
return ERROR;
} else if (FIRSTCH == ACK) {
return OK;
} else if (FIRSTCH == TIMEOUT) {
printf("\n**** Timeout on Block ACK Attempt %4d ****\n",
ATTEMPTS);
} else {
printf("\n**** Got '%02x' for Block ACK Attempt %4d ****\n",
FIRSTCH,ATTEMPTS);
for( ; ; ) {
LASTRX = FIRSTCH;
if ((FIRSTCH = READBYT(10)) == TIMEOUT) {
break;
}
if (FIRSTCH == CAN && LASTRX == CAN) {
goto CANCAN;
}
}
}
}
printf("\n**** No ACK on Block - Abort ****\n");
return ERROR;
}
/*--------------------------------------------------------------------*/
static int WCTX()
/* Send. */
{
int SECTNUM;
char ATTEMPTS;
char TXBUF[SECSIZ + 1];
/* begin */
printf("\n#### Awaiting Initial NAK . . . ####\n");
while ((FIRSTCH = READBYT(1000)) != NAK &&
FIRSTCH != TIMEOUT &&
FIRSTCH != CAN) {
printf("\n**** Got '%02x', not NAK ****\n",FIRSTCH);
/* let user see it if strange char */
}
if (FIRSTCH == CAN) {
return ERROR;
}
if (FIRSTCH == TIMEOUT) {
printf("\n**** Timeout on Initial NAK! ****\n");
return ERROR;
}
SECTNUM = 1;
while (FILBUF(TXBUF,SECSIZ)) {
printf("\n#### Send Block #%4d ####\n",SECTNUM);
if (WCPUTSEC(TXBUF,SECTNUM) == ERROR) {
return ERROR;
} else {
SECTNUM++;
}
}
ATTEMPTS = 0;
do {
printf("\n#### Sending EOT . . . ####\n");
OUT_MODEM(EOT);
PURGELINE(); /* why? */
ATTEMPTS++;
} while ((FIRSTCH = (READBYT(1000)) != ACK) && ATTEMPTS < RETRYMAX);
/* wait for ACK */
if (ATTEMPTS == RETRYMAX) {
printf("\n**** No ACK on EOT, Abort ****\n");
return ERROR;
} else {
return OK;
}
}
/*--------------------------------------------------------------------*/
static void UPLOAD()
/* Send from local computer to remote computer. */
{
int I;
/* begin */
if (OPENTX() == ERROR) {
;
} else {
if (WCTX() == ERROR) {
printf("\n**** Abort ****\n");
for (I = 0 ; I < 10 ; I++) {
OUT_MODEM(CAN);
}
}
CLOSETX();
}
}
/*--------------------------------------------------------------------*/
static int WCGETSEC(P_RXBUF,P_TIME)
char *P_RXBUF;
int P_TIME;
/* This routine fetches a Ward Christensen type block.
Returns block number encountered or ERROR if valid block not
received,
or CAN CAN received
or WCEOT if eot block
P_TIME is timeout for first char, set to 4 seconds thereafter
***** NO ACK IS SENT IF SECTOR IS RECEIVED OK ****
(Caller must do that when he is good and ready to get next
block). */
{
int SECTCURR;
int ERRORS;
char *CP;
int I;
/* begin */
for (LASTRX = ERRORS = 0 ; ERRORS < RETRYMAX ; ERRORS++) {
do {
FIRSTCH = READBYT(P_TIME);
} while (FIRSTCH != SOH &&
FIRSTCH != TIMEOUT &&
FIRSTCH != EOT &&
FIRSTCH != CAN); /* wait for one of these */
if (FIRSTCH == SOH) {
SECTCURR = READBYT(10);
if ((SECTCURR + READBYT(10)) == 255) {
CHECKSUM = 0;
for (CP = P_RXBUF,WCJ = 128 ; --WCJ >= 0 ; ) {
*CP = READBYT(10);
if (TRACEFLAG) {
PRNALLCH(*CP);
}
CHECKSUM += (*CP++);
}
if (((CHECKSUM - READBYT(10)) & 0xff) == 0) {
return SECTCURR;
} else {
printf("\n**** Checksum Error - Errors %4d ****\n",
ERRORS);
}
} else {
printf("\n**** Block Number Garbled - Errors %4d ****\n",
ERRORS);
}
} else if (FIRSTCH == EOT) {
printf("\n#### Received EOT ####\n");
return WCEOT;
} else if (FIRSTCH == CAN) {
if (LASTRX == CAN) {
printf("\n#### Sender CANcelled ####\n");
return ERROR;
} else {
LASTRX = CAN;
continue;
}
} else if (FIRSTCH == TIMEOUT) {
printf("\n**** SOH Timeout - Errors %4d ****\n",ERRORS);
}
LASTRX = 0;
while (READBYT(10) != TIMEOUT) {
;
}
OUT_MODEM(NAK);
P_TIME = 1000;
}
/* try to stop the bubble machine. */
for (I = 0 ; I < 10 ; I++) {
OUT_MODEM(CAN);
}
return ERROR;
}
/*--------------------------------------------------------------------*/
static int WCRX()
/* Receive. */
{
int I;
int SECTNUM;
int SECTCURR;
char RXBUF[SECSIZ + 1];
char SENDCHAR;
int TIMER;
extern metachar fputc();
/* begin */
SECTNUM = 0;
SENDCHAR = NAK;
TIMER = 1000;
printf("\n#### Sending Initial NAK . . . ####\n");
for ( ; ; ) {
printf("\n#### Receive Block #%4d ####\n",SECTNUM);
OUT_MODEM(SENDCHAR); /* send it now, we're ready! */
SECTCURR = WCGETSEC(RXBUF,TIMER);
TIMER = 200;
if (SECTCURR == (SECTNUM + 1 & 0xff)) { /* mask low byte */
SECTNUM++;
for (I = 0 ; I < SECSIZ ; I++) {
if (fputc(RXBUF[I],RCVFILE) == ERROR) {
printf("\n**** Receive File '%s' Error ****\n",
RCVNAME);
return ERROR;
}
}
SENDCHAR = ACK;
} else if (SECTCURR == SECTNUM) {
printf("\n**** Received Duplicate Block %4d ****\n",
SECTCURR);
SENDCHAR = ACK;
} else if (SECTCURR == WCEOT) {
OUT_MODEM(ACK);
/* don't pad the file any more than it already is */
return OK;
} else {
printf("\n**** Synchronization Error ****\n");
return ERROR;
}
}
}
/*--------------------------------------------------------------------*/
static void DOWNLOAD()
/* Receive from remote computer to local computer. */
{
int I;
/* begin */
if (OPENRX() == ERROR) {
;
} else {
if (WCRX() == ERROR) {
printf("\n**** Abort ****\n");
for (I = 0 ; I < 10 ; I++) {
OUT_MODEM(CAN);
}
}
CLOSERX();
}
}
/*--------------------------------------------------------------------*/
static void DIAL()
/* Dial telephone number. */
{
/* begin */
printf("\n#### Dialing Telephone Number '%s' . . . ####\n",
PHONENUM);
DELAY(150);
OUT_STR(ESCAPE_STR);
DELAY_ECHO(150);
OUT_STR(DIAL_STR);
OUT_STR(PHONENUM);
OUT_STR(CR_STR);
DELAY_ECHO(300);
}
/*--------------------------------------------------------------------*/
static void HANGUP()
/* Hang up telephone. */
{
/* begin */
printf("\n#### Hanging Up Telephone . . . ####\n");
DELAY(150);
OUT_STR(ESCAPE_STR);
DELAY_ECHO(150);
OUT_STR(HANGUP_STR);
DELAY_ECHO(300);
}
/*--------------------------------------------------------------------*/
static void DOS()
/* Exit to DOS. Do not hang up telephone. */
{
/* begin */
printf("\n#### Exit to DOS. Do not Hang Up Telephone ####\n");
exit(0);
}
/*--------------------------------------------------------------------*/
static void QUIT()
/* Exit to DOS. Hang up telephone. */
{
/* begin */
printf("\n #### Exit to DOS. Hang Up Telephone ####\n");
HANGUP();
exit(0);
}
/*--------------------------------------------------------------------*/
static void BAUD()
/* Set baud rate. */
{
unsigned int LOAD_INT;
#ifdef HAZITALL
unsigned int LOAD_LOW_BYTE;
unsigned int LOAD_HIGH_BYTE;
#endif
#ifdef OCTAPORT
int I;
#endif
/* begin */
printf("\n#### Set Baud Rate ####\n");
if (BAUDRATE == 300) {
LOAD_INT = B0300;
} else {
LOAD_INT = B1200;
}
#ifdef HAZITALL
LOAD_HIGH_BYTE = (LOAD_INT >> 8) & 0x00ff;
LOAD_LOW_BYTE = LOAD_INT & 0x00ff;
outportb(CCTRL,CCTRLB);
outportb(CLOAD,LOAD_LOW_BYTE);
outportb(CLOAD,LOAD_HIGH_BYTE);
#endif
#ifdef OCTAPORT
MDEFS[MBAUDLOW] = (LOAD_INT >> 8) & 0x00ff;
MDEFS[MBAUDHIGH] = LOAD_INT & 0x00ff;
for (I = 0 ; I < MBAUDNUM ; I++) {
outportb(MCMND,MBAUD[I]);
}
#endif
}
/*--------------------------------------------------------------------*/
static void INITIALIZE_PORT()
/* Initialize the modem port. */
{
extern void outportb();
#ifdef OCTAPORT
int I;
#endif
/* begin */
printf("\n#### Initialize Modem Port ####\n");
#ifdef HAZITALL
outportb(MSTAT,NUL);
outportb(MSTAT,NUL);
outportb(MSTAT,NUL);
outportb(MSTAT,MCMD1);
outportb(MSTAT,MMODE);
outportb(MSTAT,MCMD2);
#endif
#ifdef OCTAPORT
for (I = 0 ; I < MDEFSNUM ; I++) {
outportb(MCMND,MDEFS[I]);
}
#endif
}
/*--------------------------------------------------------------------*/
static void INIT()
/* Initialize. */
{
/* begin */
printf("\n#### Initialize ####\n");
INITIALIZE_PORT();
BAUD();
}
/*--------------------------------------------------------------------*/
static void help()
/* Display COMMANDS. */
{
/* begin */
printf("\n COMMANDS:\n");
printf("\n 'b'aud <baudrate>");
printf("\n 'd'ial telephone number");
printf("\n 'e'xit without hangup");
printf("\n 'h'angup without exit");
printf("\n 'i'nitialize baudrate & port");
printf("\n 'n'umber <enter telephone number>");;
printf("\n 'q'uit with hangup");
printf("\n 'r'eceive <filename>");
printf("\n 's'end <filename>");
printf("\n 't'race transmissions");
printf("\n");
}
/*--------------------------------------------------------------------*/
static void COMMANDS(P_CMD)
char P_CMD;
/* Interpret command. */
{
/* begin */
switch (tolower(P_CMD)) {
case 'b':
printf("\nBaudrate: ");
scanf("%d",&BAUDRATE);
BAUD();
break;
case 'd':
DIAL();
break;
case 'e':
DOS();
break;
case 'h':
HANGUP();
break;
case 'i':
INIT();
break;
case 'n':
printf("\nTelephone Number: ");
scanf("%s",PHONENUM);
break;
case 'q':
QUIT();
break;
case 'r':
printf("\nReceive File: ");
scanf("%s",RCVNAME);
DOWNLOAD();
break;
case 's':
printf("\nSend File: ");
scanf("%s",SENDNAME);
UPLOAD();
break;
case 't':
printf("\nTrace Transmissions (y,n): ");
scanf("%s",YN);
if ((YN[0] = 'Y') || (YN[0] = 'y')) {
TRACEFLAG = true;
} else if ((YN[0] = 'N') || (YN[0] = 'n')) {
TRACEFLAG = false;
}
break;
case '?':
help();
break;
default:
printf("\nBad Command: '%c'\n",P_CMD);
}
}
/*--------------------------------------------------------------------*/
main()
{
metachar RECEIVED;
metachar TO_SEND;
bool ESCFLAG;
/* begin */
SENDOPEN = false;
RCVOPEN = false;
T1PAUSE = TIMECON * CLKMHZ;
ESCFLAG = false;
BAUDRATE = 1200;
printf(
"\n\nCMODEM--A 'Christensen Protocol' File Transfer Program\n\n");
while (true) {
if ((RECEIVED = IN_MODEM()) != EMPTY) {
putchar(RECEIVED);
} else if (TO_SEND = GETCH()) {
if (TO_SEND == ESCCHAR ) {
if (ESCFLAG) {
ESCFLAG = false;
OUT_MODEM(TO_SEND);
} else {
ESCFLAG = true;
}
} else {
if (ESCFLAG) {
ESCFLAG = false;
COMMANDS(TO_SEND);
} else {
OUT_MODEM(TO_SEND);
}
}
}
}
exit(0);
}
/*--------------------------------------------------------------------*/
/* end cmodem.c */
/*--------------------------------------------------------------------*/