home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
prog1
/
zmnp11.lzh
/
CU.C
next >
Wrap
C/C++ Source or Header
|
1990-02-08
|
19KB
|
745 lines
/****************************************************************************
* Author : G Todd *
* Language : Turbo C 2.0 *
* Logfile : cu.c *
* Project : Comms library. *
* Date : 19 Jan 90 *
* Revision : 1.1 GT Originate. *
*****************************************************************************
* Purpose : Testbed/demo for comms library. *
* : Copyright 1990 Giles Todd. *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <signal.h>
#include "zmnp.h"
typedef enum { FALSE, TRUE } BOOLEAN;
typedef unsigned char BYTE;
typedef unsigned short int WORD;
#ifdef __TURBOC__
extern unsigned _stklen = 16384; /* big stack */
#endif
/****************************************************************************
* Function prototypes. *
****************************************************************************/
int main (int argc, char *argv[]);
static void usage (char *progname);
static void send_char (int c);
static void badarg (char *progname, char *arg);
static void mnperror (int errcode);
static void send_files (void);
static void send_command (void);
static void get_files (void);
#ifdef __TURBOC__
static void openwindow (void);
static void reporter (int type, void *data);
void tout (char *s);
static void closewindow (void);
#endif
/****************************************************************************
* Global and static data. *
****************************************************************************/
static BOOLEAN mnp_on = FALSE; /* TRUE = MNP running */
static char z_down[] = "**\030B00000000000000\r\n\021";
static char hst_mnp_off[] = "AT&M0\r"; /* HST 'no MNP' string */
static BYTE rx_buf[BUFSIZ]; /* Receive buffer. */
/****************************************************************************
* Program code. *
****************************************************************************/
int main (int argc, char *argv[])
{
int rate = 5; /* 2400 bps */
int data = 8; /* 8 data bits */
int parity = 0; /* no parity */
int stop = 1; /* 1 stop bit */
int port = 1; /* COM1 */
int handshake = 1; /* RTS/CTS */
unsigned short tx_free; /* free in Tx buffer */
unsigned short rx_rdy; /* ready in Rx buffer */
int c; /* for keyboard input */
BOOLEAN esc_flag = FALSE; /* TRUE: last char was '~' */
int i; /* loop counter */
union REGS regs; /* for ioctl call */
int mnpmode = -1; /* -1 = no MNP, 0 = orig, 1 = ans */
struct link_stat_blk mnpstat; /* MNP status */
long speed; /* line speed */
int zmatch = 0; /* match count for z_down string */
void (*sig_ptr) (int); /* old SIGINT handler */
/* Set 'raw' mode for stdin and stdout. */
for (i = 0; i < 2; i++)
{
regs.x.ax = 0x4400; /* get device info */
regs.x.bx = i; /* handle */
intdos (®s, ®s);
regs.x.dx |= 0x20; /* set 'raw' mode */
regs.x.ax = 0x4401; /* set device info */
regs.x.bx = i;
intdos (®s, ®s);
}
/* Look for options. */
if (argc > 1)
{
for (i = 1; i < argc; i++)
{
if (argv[i][0] != '-')
badarg (argv[0], argv[i]);
switch (argv[i][1])
{
case 'o': /* MNP originate */
mnpmode = 0;
break;
case 'a': /* MNP answer */
mnpmode = 1;
break;
case 'p': /* COM port */
sscanf (&argv[i][2], "%d", &port);
if (port != 1 && port != 2)
badarg (argv[0], argv[i]);
break;
case 's': /* line speed */
sscanf (&argv[i][2], "%ld", &speed);
/* Select baud rate token from speed. Roll on ANSI C. */
if (speed == 110L)
rate = 1;
else if (speed == 300L)
rate = 2;
else if (speed == 600L)
rate = 3;
else if (speed == 1200L)
rate = 4;
else if (speed == 2400L)
rate = 5;
else if (speed == 4800L)
rate = 6;
else if (speed == 9600L)
rate = 7;
else if (speed == 19200L)
rate = 8;
else if (speed == 38400L)
rate = 9;
else if (speed == 56000L)
rate = 10;
else if (speed == 115200L)
rate = 11;
else
badarg (argv[0], argv[i]);
break;
default:
badarg (argv[0], argv[i]);
} /* switch (argv[i][1]) */
} /* for (i = 1; i < argc, i++) */
} /* if (argc > 1) */
/* Install isrs and init 8250. */
c = connect (rate, data, parity, stop, port, handshake);
if (c != 0)
{
switch (c)
{
case -64:
fprintf (stderr, "Bad rate %d\n", rate);
break;
case -65:
fprintf (stderr, "Bad data length %d\n", data);
break;
case -66:
fprintf (stderr, "Bad parity %d\n", parity);
break;
case -67:
fprintf (stderr, "Bad number of stop bits %d\n", stop);
break;
case -68:
fprintf (stderr, "Bad port number %d\n", port);
break;
case -69:
fprintf (stderr, "Bad handshake flag %d\n", handshake);
break;
default:
fprintf (stderr, "Unknown error code %d\n", c);
break;
} /* switch (c) */
exit (c);
} /* if (c != 0) */
/* Save SIGINT handler. */
sig_ptr = signal (SIGINT, SIG_IGN);
/* Switch off HST MNP */
send ((unsigned char *) hst_mnp_off, strlen (hst_mnp_off));
/* Main polling loop */
while (1)
{
if (mnpmode != -1 && !mnp_on)
{
/* Attempt MNP connection when carrier detected. */
if ((modemstat () & 0x80) != 0)
{
/* We have carrier - try to establish MNP link.*/
c = mnpconnect (mnpmode);
switch (c)
{
case 0: /* success */
mnp_on = TRUE;
fputs ("MNP level 2\n", stderr);
break;
case -64:
fputs ("MNP failure, unknown error\n", stderr);
break;
case -65:
fputs ("MNP failure, timeout\n", stderr);
break;
case -66:
fputs ("MNP failure, no carrier\n", stderr);
break;
case -70:
fputs ("MNP failure, incompatible ARQ\n", stderr);
break;
case -72:
fputs ("MNP failure, remote protocol error\n", stderr);
break;
default:
fprintf (stderr, "Unknown error code %d\n", c);
break;
} /* switch (c) */
} /* if ((modemstat () & 0x80) != 0) */
} /* if (mnpmode != -1 && !mnp_on) */
/* Poll characters received from remote. */
c = 0;
if (mnp_on) /* MNP connection? */
{
mnpstatus (&mnpstat); /* get MNP status */
if (mnpstat.r_count != 0)
{
c = mnpreceive (rx_buf, (mnpstat.r_count > sizeof (rx_buf))
? sizeof (rx_buf)
: mnpstat.r_count);
if (c < 0)
{
mnperror (c);
break;
}
for (i = 0; i < c; i++)
putchar (rx_buf[i]); /* and echo */
}
if (mnpstat.l_status == 0)
{
fputs ("MNP link broken\n", stderr);
mnpdisconnect ();
hangup ();
mnp_on = FALSE;
}
} /* if (mnp_on) */
else
{
bufstat (&tx_free, &rx_rdy); /* anything from remote? */
if (rx_rdy != 0)
{
c = receive (rx_buf, (rx_rdy > sizeof (rx_buf))
? sizeof (rx_buf)
: rx_rdy);
for (i = 0; i < c; i++)
putchar (rx_buf[i]); /* and echo */
}
}
/* Check for ZMODEM download. */
for (i = 0; i < c; i++)
{
if (zmatch == strlen (z_down) - 1)
{
get_files (); /* start ZMODEM download */
zmatch = 0;
}
if (rx_buf[i] != z_down[zmatch])
zmatch = 0;
else
zmatch++;
}
/* Poll user input. */
if (kbhit () != 0)
{
c = getch (); /* get user input */
if (c == '~' && !esc_flag)
{
esc_flag = TRUE; /* possible user escape */
continue;
}
/* interpret any user escape */
if (esc_flag)
{
esc_flag = FALSE;
if (c == '.')
break; /* ~. means exit */
switch (c)
{
case 'c': /* remote command */
send_command ();
break;
case 's': /* send files */
send_files ();
break;
case 'r': /* receive files */
get_files ();
break;
default:
send_char ('~'); /* not escape sequence */
send_char (c);
break;
} /* switch (c) */
} /* if (esc_flag) */
else
send_char (c); /* send data to remote */
} /* if (kbhit () != 0) */
} /* while (1) */
/* User wants to quit */
if (mnp_on)
mnpdisconnect ();
disconnect (); /* put back original state */
signal (SIGINT, sig_ptr);
return (0); /* exit */
} /* int main (int argc, char *argv[]) */
/****************************************************************************
* mnperror *
* Display MNP send/receive error message. *
****************************************************************************/
static void mnperror (errcode)
{
switch (errcode)
{
case -64:
fputs ("Link terminated, retransmission limit exceeded\n", stderr);
break;
case -65:
fputs ("Link terminated, unable to send\n", stderr);
break;
case -66:
fputs ("Link terminated, no carrier\n", stderr);
break;
case -67:
fputs ("Link terminated, remote disconnect\n", stderr);
break;
default:
fprintf (stderr, "Link terminated, unknown error %d\n", errcode);
break;
} /* switch (errcode) */
} /* static void mnperror (errcode) */
/****************************************************************************
* badarg *
* There was a bad command line argument. Print error message and exit. *
****************************************************************************/
static void badarg (char *progname, char *arg)
{
fprintf (stderr, "Bad argument %s\n", arg);
usage (progname);
} /* static void badarg (char *progname, char *arg) */
/****************************************************************************
* send_char *
* Send a character to remote. *
****************************************************************************/
static void send_char (int c)
{
int result; /* from mnpsend */
if (mnp_on) /* MNP connection? */
{
while ((result = mnpsend ((unsigned char *) &c, 1)) != 1)
{
if (result < 0)
{
mnperror (result);
break;
}
}
}
else
{
while (send ((unsigned char *) &c, 1) != 1)
;
}
} /* static void send_char (int c) */
/****************************************************************************
* usage *
* Display usage message and exit. *
****************************************************************************/
static void usage (char *progname)
{
fprintf (stderr, "Usage: %s [options]\n"
"Options are:\n"
"-o MNP originate mode\n"
"-a MNP answer mode\n"
"-p<port> Use COM<port> (default COM1)\n"
"-s<speed> Bps (default 300)\n",
progname);
exit (1);
} /* static void usage (char *progname) */
/****************************************************************************
* send_files *
* Send file(s) via ZMODEM. *
****************************************************************************/
static void send_files (void)
{
char *filenames[5]; /* max 4 files */
int i; /* loop counter */
char s[65]; /* one filename */
/* Gather filenames - wildcards not supported (use findfirst and findnext
* for wildcard support).
*/
for (i = 0; i < 4; i++)
{
printf ("\nFilename (<enter> only when done): ");
gets (s);
if (strlen (s) == 0)
{
filenames[i] = "";
break;
}
filenames[i] = malloc (strlen (s) + 1);
strcpy (filenames[i], s);
}
putc ('\n', stdout);
filenames[4] = ""; /* ensure last is "" */
/* Send the file(s) using ZMODEM, binary xfer, 32 bit CRC, debug info,
* default reporting.
*/
#ifdef __TURBOC__
openwindow ();
i = sendfile ('z', "by", filenames, reporter);
closewindow ();
switch (i)
#else
switch (i = sendfile ('z', "by", filenames, NULL))
#endif
{
case 0:
fputs ("File(s) sent ok\n", stderr);
return;
case -1:
fputs ("Invalid ZMODEM option\n", stderr);
return;
case -2:
fputs ("User abort\n", stderr);
return;
case -3:
fputs ("No carrier\n", stderr);
return;
default:
fprintf (stderr, "Unknown error code %d\n", i);
return;
} /* switch (i = sendfile ('z', "by", filenames, NULL)) */
} /* static void send_files (void) */
/****************************************************************************
* send_command *
* Send remote command via ZMODEM. *
****************************************************************************/
static void send_command (void)
{
char s[132]; /* command text */
int cmdlen; /* command length */
char *filenames[1]; /* dummy filenames parameter */
/* Enter command. */
printf ("Remote command: ");
gets (s + 2);
*s = 'i'; /* no wait for completion */
s[1] = '#'; /* turn into option string */
cmdlen = strlen (s);
s[cmdlen] = '#';
s[cmdlen + 1] = '\0';
filenames[0] = ""; /* dummy filenames parameter */
/* Send the command. */
#ifdef __TURBOC__
openwindow ();
cmdlen = sendfile ('z', s, filenames, reporter);
closewindow ();
switch (cmdlen)
#else
switch (cmdlen = sendfile ('z', s, filenames, NULL))
#endif
{
case 0:
fputs ("Command sent ok\n", stderr);
return;
case -1:
fputs ("Invalid ZMODEM option\n", stderr);
return;
case -2:
fputs ("User abort\n", stderr);
return;
case -3:
fputs ("No carrier\n", stderr);
return;
default:
fprintf (stderr, "Unknown error code %d\n", cmdlen);
return;
} /* switch (cmdlen = sendfile ('z', "by", filenames, NULL)) */
} /* static void send_command (void) */
/****************************************************************************
* get_files *
* Get file(s) using ZMODEM. *
****************************************************************************/
static void get_files (void)
{
int i;
#ifdef __TURBOC__
openwindow ();
i = getfile ('z', "b", NULL, reporter);
closewindow ();
switch (i)
#else
switch (i = getfile ('z', "b", NULL, NULL))
#endif
{
case 0:
fputs ("File(s) received ok\n", stderr);
return;
case -1:
fputs ("Invalid ZMODEM option\n", stderr);
return;
case -2:
fputs ("User abort\n", stderr);
return;
case -3:
fputs ("No carrier\n", stderr);
return;
default:
fprintf (stderr, "Unknown error code %d\n", i);
return;
} /* switch (i = sendfile ('z', "by", filenames, NULL)) */
} /* static void get_files (void) */
#ifdef __TURBOC__
static BYTE savescreen[61 * 5 * 2]; /* save area for screen window */
static struct text_info oldscr; /* old coordinates etc */
/****************************************************************************
* openwindow *
* Set up the window for the ZMODEM report function. *
****************************************************************************/
void openwindow (void)
{
gettextinfo (&oldscr); /* save old cursor etc */
gettext (11, 11, 71, 15, savescreen); /* save what's there */
window (11, 11, 70, 15); /* set window boundaries */
clrscr ();
window (11, 11, 71, 15); /* while drawing box */
gotoxy (1, 1);
cprintf ("╔══════════════════════════════════════════════════════════╗");
gotoxy (1, 2);
cprintf ("║ ║");
gotoxy (1, 3);
cprintf ("║ ║");
gotoxy (1, 4);
cprintf ("║ ║");
gotoxy (1, 5);
cprintf ("╚══════════════════════════════════════════════════════════╝");
window (12, 12, 69, 14); /* text boundaries */
} /* void openwindow (void) */
/****************************************************************************
* closewindow *
* Restore screen to its previous state. *
****************************************************************************/
void closewindow (void)
{
puttext (11, 11, 71, 15, savescreen); /* put back what was there */
window (oldscr.winleft, oldscr.wintop, oldscr.winright, oldscr.winbottom);
gotoxy (oldscr.curx, oldscr.cury);
} /* void closewindow (void) */
/****************************************************************************
* tout *
* Display <s> in the current window, filtering line feeds. *
****************************************************************************/
void tout (char *s)
{
int c;
while ((c = *s++) != '\0')
if (c != '\n')
putch (c);
} /* void tout (char *s) */
/****************************************************************************
* reporter *
* Do report functions for ZMODEM. *
****************************************************************************/
void reporter (int type, void *data)
{
char buf[128]; /* for received text */
switch (type)
{
case 0: /* filename */
gotoxy (1, 1);
clreol ();
sprintf (buf, "FILE: %s", data);
tout (buf);
return;
case 1: /* transfer count */
gotoxy (1, 2);
clreol ();
sprintf (buf, "%7ld", *((long *) data));
tout (buf);
return;
case 2: /* other text */
gotoxy (1, 3);
clreol ();
sprintf (buf, "%s", data);
tout (buf);
return;
default:
fprintf (stderr, "reporter: unknown type %d\n", type);
return;
} /* switch (type) */
} /* void reporter (int type, void *data) */
#endif