home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
STerm_src.lzh
/
sterm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1984-12-20
|
18KB
|
671 lines
/*
* STERM Ver 1.5 - A terminal emulator & minimal file xfer program.
*
* Original source code - Smod9.c by Carl Kreider
*
* Modified by Mark Griffith for the OS9 Forum's Simple
* Terminal program for new users
*
* Originally released as STERM Ver. 1.0
* Version 1.1 was a maintenance release
* Version 1.2 Added B+ protocol file transfers
*
* Summary of additional changes by various hackers since version 1.2
*
* 08-13-88 CRK changed signal handling and a bunch of other stuff (ver 1.3)
* 08-27-88 MDG added XMODEM file transfers (ver 1.3)
* 08-28-88 MDG added termcap capability (ver 1.3)
* 06-17-89 SrT Modified for use with OSK, fixed filename bug,
* standard termcap code incorporated, fixed
* filename with xmodem routine, and some other things.
* (ver 1.4)
* 08-22-89 PWL added append/overwrite to capture buffer saves (ver 1.4)
* 08-22-89 MDG fixed logic error in bplus.c when changing default
* B protocol packet sizes. (ver 1.4)
* 10-17-89 MDG fixed dropping of ENQ and DLE characters to external terminals
* and false B protocol starts. (ver 1.4)
* -------- MDG Version 1.4 never released - started on 1.5
* 07-23-90 crk Change to getopt for arg parsing. (ver 1.5)
* Maximum timeout error user settable.
* DEbug code in bplus.
* Failsafe timer on signals.
* Clean exit on fatal signal (helps debug).
* Move termcap stuff to io.c
* 01-27-91 MDG Fixed stupid mistake of mine (not telling where *8^)
* 02-02-91 MDG Added usage() for OSK Help utility and some cosmetic stuff
* 02-08-91 MDG Fixed a bug in Sterm for 3 years....not all characters rcvd
* from the modem were displayed on the screen because of NULLS
* in the stream. Using tputs() caused all chars UP TO THE NULL
* to be written to the screen. Changed to a direct write()
* and viola!
* 02-08-91 MDG Made some small changes to allow the code to compile in both
* the 6809/OS-9 and _OSK environments
*
* 12-18-94 EG Hacked (rather ungracefully) by Ed Gresick to compile under
* Ultra-C. Changing the CPU entry in the makefile will permit
* compiling and execution under either the OS9/68K or OS9000/386
* environments.
* Xmodem was tested with DELPHI downloading files as large as
* 900K. B+ protocol was tested with CIS with files in the
* mid 20k range.
* Important - this version will not compile in the 6809/OS-9
* environment.
* Changed version number to 2.0 (20).
*/
#include <stdio.h>
#include <ctype.h>
#include <modes.h>
#include <errno.h>
#ifdef _OSK
extern char *optarg;
#endif
#include "common.h"
#include "sterm.h"
#include <strings.h>
#ifdef _OSK
void opendsk(), xmodem();
#else
extern opterr, optind;
extern char *optarg;
#endif
extern int max_err;
main(argc, argv)
int argc;
char **argv;
{
int option;
register int c;
int lastchar;
int cistate = CIDLE;
int trap();
char *p;
/* #ifdef _OSK */
to_floppy = FALSE;
/* #else
to_floppy = TRUE; /* Initially floppy xfer is TRUE to */
/* prevent new users from having */
/* transfer problems to disk */
/* #endif */
while ((option = getopt(argc, argv, "defl:?")) != EOF)
switch (tolower(option))
{
case 'd' :
bug_on++; /* may use debug levels later */
break;
case 'e' :
max_err = atoi(optarg);
break;
case 'f' :
to_floppy = FALSE;
break;
case 'l' :
mport = optarg;
break;
case '?' :
usage();
exit(0);
default :
help();
}
intercept(trap); /* set up interrupt handler */
termsetup(); /* configure stdin for terminal action */
modsetup(mport); /* open and set up modem path */
tputs0(CL);
help();
show_baud(cur_baud);
t_puts("\n\012\012***** STERM is online *****\n\012\012");
/*
* Loop forever reading the modem port and perfoming functions as needed
*/
for ( ; ; )
{
if (m_rdy())
{
switch (cistate)
{
case CIDLE : /* idle state */
sbp = sbuf;
while (m_rdy() && ((sbp - sbuf) < 10))
switch (c = (m_getc() & 0x7f))
{
case ENQ : /* Starting B+ transfer */
lastchar = c; /* save last rcvd char */
bp_ENQ();
break;
case DLE :
if (lastchar == ENQ)
{ /* MUST follow an ENQ */
up_priority();
c = bp_DLE(to_floppy);
cistate = CIDLE; /* Return to normal */
down_priority();
}
else
{
*sbp++ = lastchar; /* nothing is missed */
*sbp++ = c; /* save char */
}
break;
default :
*sbp++ = c; /* save the character */
lastchar = c; /* set lastchar */
if (capflg) /* if a file is open */
dskout(c); /* save received data */
}
write(1, sbuf, (sbp - sbuf)); /* changed from tputs() */
break; /* to make sure EVERY */
/* char (including nulls */
/* gets written */
} /* End of Switch */
} /* End of if m_rdy */
if (t_rdy())
{ /* if there is something there */
c = t_getc(); /* go get it */
if (echoflg && isprint(c)) /* if half-duplex echo to screen */
t_putc(c);
if (escflg) /* if ESC was pressed previously */
internal(c); /* check for command */
else
if (c == ESC) /* if it is an ESC key press */
escflg = TRUE; /* set the flag */
else
m_putc(c);
} /* End of if t_rdy */
} /* End of Loop Forever */
} /* End of Main */
/*page*/
/*
* handler for internal operations
*/
static
internal(c)
register int c;
{
escflg = FALSE;
switch (tolower(c))
{
case CAPTURE :
if (capflg)
closdsk();
else
opendsk();
break;
case ECHO :
toggleduplex();
break;
case SHELL :
shell();
break;
case XMODEM :
xmodem();
break;
case TRANSMIT :
xmit();
break;
case DIR :
cwd();
break;
case QUIT :
if (getans("\n\012QUIT - are you sure? ") == TRUE)
{
tputs0(CL);
cleanup();
exit(0);
}
break;
case HELP :
help();
break;
case ESC :
m_putc(ESC);
break;
case STATS :
stats();
break;
default :
m_putc(ESC); /* Send ESC char if no commands */
m_putc(c); /* and then send the next char */
}
}
/*page*/
static
char *hlpmsg[] = {
"\n\012",
" The OS-9 Forum's\012\n",
" Simple Terminal Ver 2.0\n\012\012",
" Esc A - ABORT Transfer Esc S - Execute OS9 Shell\n\012",
" Esc C - Capture ON/OFF Esc T - Transmit a file\n\012",
" Esc D - Change Directory Esc Q - Quit to OS9\n\012",
" Esc E - Echo ON/OFF Esc X - XMODEM transfers\n\012",
" Esc H - Show this help Esc Z - Show transfer stats\n\012",
" Esc Esc - Send an ESC\n\012\012",
""
};
static
help()
{
register char **hscan;
for (hscan = hlpmsg; **hscan; hscan++)
t_puts(*hscan);
}
usage()
{
fprintf(stderr, "\nSterm Ver. 2.0\n\n");
fprintf(stderr, "Usage: sterm [-df? -l'p' -e'x']\n");
fprintf(stderr, " -d Debug mode on (displays during downloads)\n");
fprintf(stderr, " -f NOT downloading to floppy disks (CoCo only)\n");
fprintf(stderr, " -? Print this usage message\n");
fprintf(stderr, " -l p Link to modem port 'p' (Default /t2)\n");
fprintf(stderr, " -e x Set B+ MAXERRS to 'x' (default 10)\n\n");
}
close_file() /* close any capture file opened before exiting */
{
/* if (cp_pn != NULL) /* if a file is opend */
if (cp_pn != 0x00) /* bloop */
{
wrt_dbuf(); /* write out the remaining buffer */
close(cp_pn); /* and close it */
}
}
static
closdsk() /* close a disk capture file */
{
t_puts("\nCapture OFF - ");
/* if (cp_pn == NULL) */
if (cp_pn == 0x00) /* bloop */
{
t_puts(" FILE NOT OPENED\n\012");
capflg = FALSE;
}
else
{
wrt_dbuf();
capflg = FALSE;
if (getans(" Close File? ") == TRUE)
{
close(cp_pn);
cp_pn = 0;
t_puts("\n\012File CLOSED\n/012");
}
else
t_puts("\n\012File REMAINS OPEN\n\012");
}
}
/* open capture file - modified for appending [PWL] */
#ifdef _OSK
void
#else
static
#endif
opendsk()
{
if (cp_pn)
{
t_puts("\n\012Capture ON - File already opened\n\012");
capflg = TRUE;
return (0);
}
else
if (!getfile())
{
t_puts(" No filename given\n\012");
return (0);
}
if (access(filename, 0) == 0)
{
t_puts("\n\012FILE EXISTS - [O]verwrite, [A]ppend, or [RETURN]: ");
{
int ansok = FALSE;
char cz;
while(ansok == FALSE)
{
sig_off();
cz = t_getc();
sig_on();
switch (tolower(cz))
{
case 0x0d:
t_puts("\n\012ABORTED\n\012");
return (0);
case 'o':
t_puts("\012\nOverwriting ...\n\012");
cp_pn = creat(filename, S_IWRITE);
ansok = TRUE;
break;
case 'a':
t_puts("\012\nAppending ...\n");
if((cp_pn = open(filename, S_IWRITE)) >= 0)
lseek(cp_pn, 0L, 2);
ansok = TRUE;
break;
}
}
}
}
else
cp_pn = creat(filename, S_IWRITE);
if (cp_pn == -1)
{
char errstr[200];
sprintf(errstr,"Can't open '%s' - error %d %c!\n\012",
filename, errno, 7);
t_puts(errstr);
cp_pn = 0;
capflg = FALSE;
}
else
{
dbp = dbuf;
t_puts("\n\012Capture ON - File Opened\n\012");
capflg = TRUE;
}
}
static
xmit()
{
int ch, c, i;
t_puts("\012\nTransmit");
if (!getfile())
t_puts("ABORTED - No Filename given\n\012");
else
if ((xmf = fopen(filename, "r")) == NULL)
{
t_puts("CAN'T OPEN ");
t_puts(filename);
t_putc(BELL);
t_puts("\n\012");
}
else
{
tputs0(CL);
while (fgets(sbuf, MAXLIN, xmf) != NULL)
{ /* Get line to xmit */
m_puts(sbuf); /* and send it out */
tsleep(10); /* wait one-sixth of a second */
while (m_rdy())
t_putc(_toascii(m_getc()));
if (t_rdy())
{ /* check for terminal input */
ch = t_getc();
if (ch == BREAK) /* ABORT if it's a CNTL-C */
break;
}
}
fclose(xmf);
for (i = 0; i < 5; i++)
{
while (m_rdy())
{ /* catch any dribbles */
c = m_getc();
t_putc(c);
}
tsleep(5);
}
if (ch == BREAK)
t_puts("\012\nABORTED");
t_puts("\n\012Transmit File Closed\n\012");
}
}
getans(s) /* Get a single character response from the keyboard */
char *s;
{
char c;
t_puts(s);
while (!t_rdy())
tsleep(1);
t_putc(c = tolower(t_getc()));
return (c == 'y');
}
static
getfile() /* Get a filename -- CR by itself aborts */
{
t_puts("\n\012Filename ? ");
t_gets(filename);
return (filename[0] != '\0');
}
/* use cr to abort */
static
cwd()
{
t_puts("\n\012New Directory ? ");
t_gets(filename);
if (filename[0] == '\0')
t_puts("ABORTED\n\012");
else
if (chdir(filename) == -1)
t_puts("Can't CHD\n\012");
else
t_puts("OK!\n\012");
}
/*
** Write what is received to disk using buffering and XOFF/XON
** flow control to the host.
*/
static
dskout(c)
char c;
{
if ((isspace(c) && (c != 0x0a)) || c == BACKSP || isprint(c))
{
*dbp++ = c; /* store the char */
if ((dbp - dbuf) > (CAP_SIZ - 100)) /* If the buffer is full */
{
m_putc(XOFF); /* Shutup the host */
wrt_dbuf(); /* And write out the buffer */
m_putc(XON); /* Return to receiving */
}
}
}
static
wrt_dbuf()
{
if ((write(cp_pn, dbuf, dbp - dbuf)) < 0)
{
t_putc(BELL); /* If an error occurs */
t_puts("\012\nERROR during write!!\n\012");
}
dbp = dbuf;
}
static
shell()
{
t_puts("OS9: ");
t_gets(sbuf);
cook_io();
system(sbuf);
raw_io();
t_puts("\n\012**** STERM back online ****\n\012");
}
/* Do an XMODEM file transfer */
#ifdef _OSK
void
#else
static
#endif
xmodem()
{
int c;
t_puts("\n\012XMODEM: <S>end or <R>eceive? ");
while (!t_rdy())
tsleep(1);
t_putc(c = tolower(t_getc()));
if ((c == 's') || (c == 'r'))
{
if (!getfile())
t_puts("\n\012ABORTED");
else
{
show_box(5, 55, 8, 20);
if (c == 's')
{
show_at(13, 9, "Uploading");
c = XMODEM_Send(filename);
}
else
{
show_at(10, 9, "Downloading");
c = XMODEM_Read(filename);
}
}
}
else
{
t_puts("\012\nABORTED");
return (0);
}
t_puts("\n\012");
}
/* Toggle echo mode (duplex) */
static
toggleduplex()
{
if (echoflg)
{
t_puts("\012\nFull duplex\012\n");
echoflg = FALSE;
}
else
{
t_puts("\012\nHalf duplex\012\n");
echoflg = TRUE;
}
}
/*
** Function to increase STERM's priority while running and insure no
** errors are generated do to background processes. (used only with OS9/6809)
*/
static
up_priority()
{
#ifndef _OSK
setpr(getpid(), 132); /* bump process priority up */
#endif
}
static
down_priority()
{
#ifndef _OSK
setpr(getpid(), 128); /* bring process priority back down */
#endif
}
/*
** Routine to print the statistics on the last file transfer.
*/
static
stats()
{
int realbaud;
long totime;
totime = endtime - startime;
/* Prevent division by Zero ++SrT */
if (!totime)
totime = 1L;
realbaud = get_baud(cur_baud);
t_puts("\n\012Last file transfer statistics\n\012");
sprintf(tmp, " Transfer Time: %-6ld seconds\n\012", totime);
t_puts(tmp);
sprintf(tmp, " Bytes transfered: %-6ld\n\012", totalbytes);
t_puts(tmp);
sprintf(tmp, " Baud rate: %-4d\n\012", realbaud);
t_puts(tmp);
sprintf(tmp, " Total Errors: %d\n\012", errors);
t_puts(tmp);
sprintf(tmp, " Timeouts: %d\n\012", timeouts);
t_puts(tmp);
sprintf(tmp, " Actual bps: %-4.0f\n\012",
(double)((totalbytes / totime))*8);
t_puts(tmp);
sprintf(tmp, "Efficiency Rating: %2.1f%%\n\012",
(((double) totalbytes * 800) / totime) / realbaud);
t_puts(tmp);
}