home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
flex2.tar.gz
/
flex2.tar
/
fl2ker.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-08-16
|
144KB
|
4,835 lines
<<< flbuff.c >>>
#include "FLK.H"
/*
* b u f i l l
*
* Get a bufferful of data from the file that's being sent.
* Control-quoting, 8-bit & repeat count prefixes are handled.
*/
char *bptr; /* Buffer pointer */
bufill(buffer,first_time)
char buffer[]; /* Buffer */
char first_time; /* Called for the first time */
{
int new_char, /* Char read from file */
rpt_count,
max_data_size,
bufsize;
static int old_char; /* Previous character */
static char *savptr, /* Must be saved between calls */
*savbptr,
savbuf[6];
bptr = buffer; /* Init data buffer pointer */
max_data_size = spsiz - 3 - (block_check_type - 1);
if (first_time)
{
old_char = getc(fp); /* Pre-read character first time */
savbptr = savbuf;
}
if (savbptr != savbuf) /* Data left from previous call */
for (savptr = savbuf; savptr != savbptr;)
*bptr++ = *savptr++; /* Copy old data to buffer */
savbptr = savbuf; /* No more data in save buffer */
while (old_char != EOF) /* Do until no more data */
{
rpt_count = 1;
while(((new_char = getc(fp)) != EOF) && (rpt_count < 94)
&& (repeat_quote != 0) && (new_char == old_char)
&& ((new_char != '\n') || image)) /* No repeat for newline */
rpt_count++; /* Count consecutive match */
if (rpt_count > 1) /* We've had more of these */
if (rpt_count == 2)
insbuf(old_char); /* Insert twice if only 2 char's */
else
{
*bptr++ = repeat_quote; /* Setup repeat quote character */
*bptr++ = tochar(rpt_count); /* Send count */
}
transmit_chr_count += rpt_count; /* Counter for total data */
insbuf(old_char);
old_char = new_char; /* Copy next character */
bufsize = bptr - buffer; /* Current number of characters */
if (bufsize > max_data_size) /* Check length */
{
while (savptr != bptr)
*savbptr++ = *savptr++; /* Copy excess data */
return (bufsize - (savbptr - savbuf));
}
else if (bufsize == max_data_size) /* Exact fit */
return (bufsize);
savptr = bptr;
}
if (bptr == buffer) /* Wind up here only on EOF */
return(EOF);
return(bptr - buffer); /* Handle partial buffer */
}
insbuf(o_char)
int o_char;
{
char chr7;
chr7 = o_char & 0177; /* Get low order 7 bits */
if ((o_char > 127) && (eight_quote != 0))
*bptr++ = eight_quote; /* Eight_bit quoting done */
if (chr7 < SP || chr7 == DEL || chr7 == quote ||
chr7 == repeat_quote || chr7 == eight_quote)
{ /* Special handling required ? */
if (o_char == '\n' && !image)
{ /* Do LF->CRLF mapping if !image */
*bptr++ = quote;
*bptr++ = ctl('\r');
}
*bptr++ = quote; /* Quote the character */
if ((chr7 == 0) || ((chr7 != quote) &&
(chr7 != repeat_quote) && (chr7 != eight_quote)))
{
o_char = ctl(o_char); /* Uncontrolify it */
chr7 = ctl(chr7);
}
}
if (image && (eight_quote == 0))
*bptr++ = o_char; /* Deposit the character itself */
else
*bptr++ = chr7; /* Only send the low bits */
}
/*
* b u f e m p
*
* Put data from an incoming packet into a file.
* Control-quoting, 8-bit & repeat count prefixes are handled.
*/
bufemp(buffer,len)
char buffer[]; /* Buffer */
int len; /* Length */
{
int i, j, /* Counters */
rpt_count; /* Repeat counter */
char t, t7, /* Character holder */
set_bit_eight; /* flag to set bit eight */
for (i = 0; i < len; i++) /* Loop thru the data field */
{
t = buffer[i]; /* Get character */
if (t == repeat_quote) /* Repeat quoting ? */
{
rpt_count = unchar(buffer[i+1]); /* Get repeat count */
i++; /* Increment here because of compiler bug */
t = buffer[++i]; /* Get next character */
}
else
rpt_count = 1; /* No repeat quoting, count = 1 */
if (t == eight_quote) /* Eight-bit quoting ? */
{
set_bit_eight = TRUE; /* Set bit eight */
t = buffer[++i]; /* Get next character */
}
else
set_bit_eight = FALSE; /* Don't set bit eight */
if (t == quote) /* Control quote? */
{ /* Yes */
t = buffer[++i]; /* Get the quoted character */
t7 = t & 0177; /* Character without parity bit */
if ((t7 >= ctl(DEL)) && (t7 <= ctl(DEL) + 32))
t = ctl(t); /* Undo what others did to it */
}
if (set_bit_eight)
t |= 0x80; /* Set bit eight on request */
transmit_chr_count += rpt_count; /* Counter for total data */
for (j = 0; j < rpt_count; j++)
if (image)
{
if (putc(t,fp) == ERROR) /* send to file if image mode */
return(ERROR);
}
else
{
if (t == LF) /* strip LF in non-image mode */
break;
if (t == TAB) /* expand tabs to spaces */
{
while (--tabsleft >= 0)
if (putc(' ',fp) == ERROR)
return(ERROR);
tabsleft = TABSIZE; /* reset tabcounter */
}
else /* pass character */
{
if (putc(t,fp) == ERROR)
return(ERROR);
if ((--tabsleft <= 0) || (t == CR))
tabsleft = TABSIZE; /* take care of tabcount */
}
}
}
return(NULL);
}
<<< flconn.c >>>
#include "FLK.H"
/*
* c o n n e c t
*
* Establish a virtual terminal connection with the remote host
*
*/
char stop_send;
connect()
{
int save_port; /* Temp port address */
char c,
got_escape;
stop_send = FALSE; /* No stop character send yet */
save_port = ttyfd; /* Save old port address */
if (numprm > 1)
{
sscanf(params[1],"%x",&ttyfd); /* Get hex address */
if (initport(ttyfd,0) == FALSE) /* Try to init the port */
{
prterr("No such line available");
if ((ttyfd = save_port) != REMOTE) /* Restore port if not remote */
initport(ttyfd,0);
return; /* Error in port setting */
}
else
remote = FALSE;
}
if (remote)
prterr("No line to connect to\7"); /* We're remote.... */
else
{
start_remote(); /* Enable interrupt if any */
puts("Connected...\n");
cflg = TRUE; /* Put us in "connect mode" */
purgeline(ttyfd); /* eat pending input */
if (logfileopen)
logging = TRUE; /* if file available, turn log on */
plog = &logbuf[0]; /* set pointer to log data area */
got_escape = FALSE; /* no escape char received yet */
while (cflg) /* do as long as we're connected */
{
if (instat(consfd)) /* got something from the console */
{
c = inchar(consfd) & 0177; /* get character */
if ((c == escchr) || (got_escape)) /* check for escape character */
{
if (!(got_escape = ~got_escape))
{
if (c == escchr) /* maybe another one */
{
outchar(c,ttyfd); /* yes, echo it */
if (!fulldup)
{
outchar(c,consfd); /* echo if half duplex */
write_log(c,FALSE); /* send to log file as well */
}
}
else
switch (tolower(c&0177)) /* special character */
{
case '0':
outchar(NULL,ttyfd); /* send NULL */
break;
case 'b':
send_break(ttyfd); /* send BREAK */
break;
case 'c':
cflg = FALSE; /* disconnect */
write (consfd,"\r\n",0);
break;
case 'h':
write(consfd,"\r\nYes, I'm still here...\r\n",0);
break; /* tell him i'm still available */
case 'q':
if (logfileopen)
{
logging = FALSE; /* suspend logging */
write(consfd,"\r\nLogging suspended\r\n",0);
}
else
write(consfd,"\r\nLog file is not open\r\n",0);
break;
case 'r':
if (logfileopen)
{
logging = TRUE; /* resume logging */
write(consfd,"\r\nLogging resumed\r\n",0);
}
else
write(consfd,"\r\nLog file is not open\r\n",0);
break;
case 's':
write(consfd,"\r\nLog file status: ",0);
if (logfileopen)
write(consfd,"open\r\n",0);
else
write(consfd,"closed\r\n",0);
write(consfd,"Logging status: ",0);
if (logging)
write(consfd,"on\r\n",0);
else
write(consfd,"off\r\n",0);
break;
case '?': /* display commands */
write(consfd,"\r\nArguments available:\r\n\n",0);
write(consfd,"? - Show this help message\r\n",0);
write(consfd,"0 - Transmit NULL\r\n",0);
write(consfd,"B - Transmit 'BREAK'\r\n",0);
write(consfd,"C - Close connection\r\n",0);
write(consfd,"H - Report availability\r\n",0);
write(consfd,"Q - Quit logging (if started)\r\n",0);
write(consfd,"R - Resume logging\r\n",0);
write(consfd,"S - Show status of connection\r\n",0);
break;
default:
beep(); /* unknown, ring the bell */
break;
}
}
}
else
{
outchar(c,ttyfd); /* write it out */
if (!fulldup)
{
outchar(c,consfd); /* to console if half duplex */
write_log(c,FALSE); /* send to logfile */
}
}
}
else
if(instat(ttyfd)) /* see remote keyboard */
{
c = inchar(ttyfd); /* get character */
outchar(c,consfd); /* send to local screen */
write_log(c,FALSE); /* and to logfile */
wtcnt = WAITVAL; /* reset wait counter */
}
else if (stop_send) /* stop sent to remote */
if (!(--wtcnt)) /* did remote stop sending? */
flushlog(); /* yes, write buffer to disk */
}
write_log(c,TRUE); /* write buffer to disk */
puts("Disconnected.\n");
finish_remote(); /* Disable interrupts if any */
if ((ttyfd = save_port) == REMOTE) /* Restore port */
remote = TRUE;
else
initport(ttyfd,0);
}
}
/*
* Write data to log buffer
*/
write_log(chr,flush)
char chr;
int flush;
{
if (flush) /* flush buffer ? */
flushlog();
else if (logging && logfileopen && chr != CR)
{
if (chr == LF) /* convert LF to CR */
chr = CR;
if ((chr == BS) || (chr == DEL)) /* backspace or rubout */
{
if (plog > &logbuf) /* check range of pointer */
--plog;
}
else
*plog++ = chr; /* store char in buffer */
if (plog == &logbuf[LOGBUFSIZE-132]) /* time for diskwrite ? */
{
outchar(dstop, ttyfd); /* stop remote */
stop_send = TRUE; /* stop signal send to remote */
wtcnt = WAITVAL; /* set counter */
}
else if (plog == &logbuf[LOGBUFSIZE])
--plog; /* in case remote won't stop */
}
}
/*
* Write buffer to disk
*/
flushlog()
{
char *savep = &logbuf[0]; /* initial pointer */
if (logfileopen) /* only if logfile open */
{
while (savep != plog) /* if not at end of buffer */
if (putc(*savep++, lfp) == ERROR) /* write to file */
{
prterr("Error writing log file -- logging stopped");
fclose(lfp);
logging = logfileopen = FALSE; /* no more logging */
logfile[0] = '\0'; /* Zap filename */
break;
}
plog = &logbuf[0]; /* reset pointer */
if (stop_send == TRUE)
{
stop_send = FALSE;
outchar(dstart, ttyfd); /* restart remote */
}
}
}
<<< flcutl.c >>>
#include "FLK.H"
/*
* s p a r
*
* Fill the data array with my send-init parameters
*
*/
spar(data,len)
char data[],
*len;
{
data[0] = tochar(maxpacksiz); /* Biggest packet I can receive */
data[1] = tochar(mytime); /* When I want to be timed out */
data[2] = tochar(mypad); /* How much padding I need */
data[3] = ctl(mypchar); /* Padding character I want */
data[4] = tochar(myeol); /* End-Of-Line character I want */
data[5] = myquote; /* Control-Quote character I send */
if ((data[6] = eight_quote) == 0)
data[6] = 'N'; /* No eight bit quoting */
else if (config > 3) /* 8 bits link */
data[6] = 'Y'; /* 8th bit quoting on request */
data[7] = block_check_type + '0'; /* Type of block check */
if ((data[8] = repeat_quote) == 0) /* Repeat count quote character */
data[8] = ' '; /* No repeat quoting done */
*len = 9;
}
/* r p a r
*
* Get the other host's send-init parameters
*
*/
rpar(data,len)
char data[],
len;
{
char c;
if (len > 0)
spsiz = unchar(data[0]); /* Maximum send packet size */
else
spsiz = I_MYPACKSIZE; /* Use default */
if (len > 1)
timint = unchar(data[1]); /* When I should time out */
else
timint = I_MYTIME;
timecount = timint * DELAYVALUE; /* Setup new timeout counter */
if (len > 2)
pad = unchar(data[2]); /* Number of pads to send */
else
pad = I_MYPAD;
if (len > 3)
padchar = ctl(data[3]); /* Padding character to send */
else
padchar = I_MYPCHAR;
if (len > 4)
eol = unchar(data[4]); /* EOL character I must send */
else
eol = I_MYEOL;
if (len > 5)
quote = data[5]; /* Incoming data quote character */
else
quote = I_MYQUOTE;
if (len > 6)
{
if ((c = data[6]) == 'N')
eight_quote = 0; /* Don't use eight_bit quoting */
else if (c == 'Y')
{
if (config <= 3) /* 7 bits link */
eight_quote = myeightquote; /* Use default */
else
eight_quote = 0; /* Don't use it */
}
else
eight_quote = c; /* Use this char for eight bit quoting */
}
else
eight_quote = 0; /* Don't use it */
if ((len > 7) && ((c = data[7] - '0') == myblock_check_type))
block_check_type = c; /* Setup block check type */
else
block_check_type = I_BLOCKCHECKTYPE;/* Set initial value */
if ((len > 8) && ((c = data[8]) == myrptquote) && (c != ' '))
repeat_quote = c; /* Setup repeat quote character */
else
repeat_quote = 0; /* Don't use repeat quoting */
}
set_default_comm()
{
eol = myeol; /* EOL for outgoing packets */
quote = myquote; /* Standard control-quote char "#" */
pad = mypad; /* No padding */
padchar = mypchar; /* Use null if any padding wanted */
timint = mytime; /* Timeout value */
eight_quote = myeightquote; /* Set eight_bit quote character */
repeat_quote = myrptquote; /* Set repeat quote character */
block_check_type = myblock_check_type; /* Set initial value */
}
disp_size_transferred()
{
#ifdef SCREEN
float xmitted,
percentage;
if (!remote && (transmit_chr_count != 0))
{
xmitted = transmit_chr_count / 1024.; /* Size transferred so far in K */
posit(18,4);
printf("%6.2f K", xmitted);
if (image && sflg)
{
percentage = 100. * (transmit_chr_count / (file_size * 252.));
/* a FLEX data sector contains 252 bytes of data */
posit(39,4);
printf("%3.0f %%", percentage);
}
}
#endif
}
init_xfer()
{
chr_sent = datachr_sent = chr_rec = datachr_rec = 0; /* zero counters */
nak_sent = nak_rec = pack_sent = pack_rec = 0;
data_rate = 0;
#ifdef CLOCK
start_time = read_clock();
#endif
}
fin_xfer()
{
int numbits;
t_chr_sent += chr_sent; /* adjust performance counters */
t_datachr_sent += datachr_sent;
t_nak_sent += nak_sent;
t_pack_sent += pack_sent;
t_chr_rec += chr_rec;
t_datachr_rec += datachr_rec;
t_nak_rec += nak_rec;
t_pack_rec += pack_rec;
#ifdef CLOCK
end_time = read_clock(); /* Get current time */
/* calculate number of bits in transmission */
numbits = (config == 2 || config == 3 || config == 5) ? 10 : 11;
if (end_time < start_time)
end_time += 86400; /* correct for day overflow, */
/* add number of seconds for one day */
if (rflg) /* received data */
data_rate = (chr_rec / (end_time - start_time)) * (100 / numbits);
else if (sflg) /* transmitted data */
data_rate = (chr_sent / (end_time - start_time)) * (100 / numbits);
t_data_rate = (((t_data_rate == 0) ? data_rate : t_data_rate)
+ data_rate) / 2;
#endif
}
#ifdef CLOCK
long int read_clock()
{
char *clock,
c_sec,
c_min,
c_hour,
dummy;
char bcdbin();
clock = RTCADR; /* point to register 0 */
clock[15] = 0xaa; /* test pattern */
dummy = 0; /* else clock won't be read again */
if ((clock[13] & 0x80) && (clock[15] == 0xaa))
{ /* clock valid and set */
while (clock[10] & 0x80); /* check for update in progress */
c_sec = clock[0]; /* copy data */
c_min = clock[2];
c_hour = clock[4];
if (!(clock[11] & 0x02)) /* 12 hour format */
if (c_hour &= 0x80)
c_hour += 12;
if (!(clock[11] & 0x04))
{ /* BCD data format */
c_sec = bcdbin(c_sec); /* convert BCD to BIN */
c_min = bcdbin(c_min);
c_hour = bcdbin(c_hour);
}
return (long)c_hour * 3600 + (int)c_min * 60 + c_sec;
}
else
return (NULL); /* invalid clock setting */
}
/*
* convert BCD number to binary
*/
char bcdbin(value)
char value;
{
return ((value & 0x0f) + (10 * ((value & 0xf0) >> 4)));
}
#endif
<<< fldir.c >>>
#include "FLK.H"
#include "flex.h"
typedef struct fcbc FCB;
/*
* Get next file in a file group
*/
get_file_spec(firsttime)
char firsttime;
{
char *wild_file_spec(),
*status;
static char my_firsttime;
if (firsttime)
{
filenum = 1; /* First time initial values */
filecount = numprm - 1;
my_firsttime = TRUE;
}
do
{
if (rflg != 2)
{
status = wild_file_spec(params[filenum], my_firsttime);
my_firsttime = FALSE;
}
else
{
status = params[filenum++]; /* Don't parse for 'GET' */
if (filecount-- == 0)
break;
}
if (status == ERROR)
{
prterr("Error opening directory");
break;
}
else if (status) /* Got valid spec */
{
filnam = status; /* Setup pointer to spec */
if (rflg != 2) /* Don't convert for 'GET' */
cvt_case(filnam); /* Convert filename case */
return TRUE;
}
filenum++; /* Next parameter */
my_firsttime = TRUE; /* Start new directory search */
}
while (--filecount); /* More to do */
return FALSE; /* done */
}
char *wild_file_spec(mask,first)
char mask[50], first;
{
static FCB *ptr;
FCB *diropen();
static char filename[50];
if (first)
if ((ptr = diropen(mask)) == ERROR)
return (ERROR); /* Failed to open directory */
while (dirread(ptr,filename) != ERROR)
if (mskcmp(filename,mask)) /* Check match */
return(filename);
free(ptr); /* Release allocated memory */
return (FALSE); /* No more files */
}
/*
*** Compare against a mask
*
* This function compares a given string against a mask and returns
* a 1 for 'compares' or a 0 for 'does not compare'.
*
* A mask is a concatenation of the following elements:
*
* c literal character
* ? any character match except endstring null
* [..] character class (all of these characters)
* [^..] negated character class (all but these characters)
* ^c negated character (all but this character)
* * zone (match zero or more occurences)
*
* A character class consists of zero or more of the following
* surrounded by [ and ]:
*
* c1-c2 range of ascii characters
* c1-c2..c1-c3 multiple ranges
*
*/
mskcmp(string,m)
char *string,*m;
{
int k;
char *sp,*sav,string2[128];
char *n,msk[128];
strcpy(sp = string2,string);
cvt_case(sp);
strcpy(n = msk,m);
cvt_case(n);
while (*n)
{
if (*n == '*')
{
sav = sp;
if (!*++n)
return (1);
while (*sp && !mskcmp(sp,n))
++sp;
if (*sp)
continue;
sp = sav;
}
else
if (!(k = onecmp(*sp,n)))
return (0);
else
n += k;
if (*sp)
++sp;
}
return (!*sp);
}
/*
*** Compare only one character (for mskcmp)
*/
onecmp(s,m)
char s,*m;
{
char c,setfind,setflag;
char *mp;
if ((c = *(mp = m)) == '?' && s); /* Okay as it is */
else if (c == '[')
{
setfind = setflag = 0;
if (*++mp == '^')
{
setflag = 1;
++mp;
}
for (;(c = *mp) && c != ']'; ++mp)
if (*mp == '-' && s >= *(mp - 1) &&
s <= *(mp + 1) && *(mp - 1) <= *(mp + 1))
{
/* skip to trailing ']' */
while ((c = *(mp + 1)) && c != ']')
++mp;
setfind = 1;
}
if (setfind == setflag)
return (0);
else
return (mp - m + 1);
}
else if (c == '^' && *(mp + 1) != s)
return (2);
else if (c != s)
return (0);
return (1);
}
/*
*** Open disk directory
*/
int drive;
FCB *diropen(name)
char *name;
{
FCB *ptr;
int len;
char *malloc();
drive = FLEX_DATA.work_drive; /* Assume work drive */
len = strlen(name);
if (( len == 1) && isdigit(name[0]))
drive = name[0] - '0'; /* Setup single drive number */
else
{
if ((isdigit(*name)) && (name[1] == '.'))
{ /* Leading drive number */
drive = name[0] - '0';
strcpy(name,name + 2); /* Strip number */
}
else if ((isdigit(name[len - 1])) && (name[len - 2] == '.'))
{ /* Trailing drive number */
drive = name[len - 1] - '0'; /* Setup drive number */
name[len - 2] = '\0'; /* Strip number */
}
}
if ((ptr = (FCB *) malloc(sizeof(FCB))) == NULL) /* Allocate space */
return (ERROR);
ptr->f.drive = drive; /* Insert drive number in FCB */
ptr->f.function = DR_OPEN; /* Open directory for read */
if (_fms(ptr,0) == ERROR) /* Open directory */
{
free(ptr); /* Error, return memory */
return (ERROR);
}
else
return (ptr);
}
dirread(ptr,filename)
FCB *ptr;
char *filename;
{
int i,j;
ptr->f.function = GET_INF; /* Get info record function code */
while(_fms(ptr,0) != ERROR)
{
for (i = 0;i < 8;++i)
filename[i] = ptr->f.filename[i];
filename[8] = '\0';
if (!*filename)
return (ERROR); /* end of directory */
if (*filename != 0xff) /* not a deleted file */
{
strcat(filename,".");
j = strlen(filename);
for (i = 0;i < 3;++i)
filename[j + i] = ptr->f.extension[i];
filename[j + 3] = '\0';
file_size = ptr->f.size; /* fill in file size */
transmit_chr_count = 0; /* start new sequence */
return (TRUE);
}
}
return (ERROR);
}
<<< flhelp.c >>>
#include "FLK.H"
/*
* Help processing
*/
help()
{
FILE *hlpfp; /* Pointer to help file */
char str[129], /* Temporary string holder */
tmpdrv, /* Save drive number */
found, /* Found correct record flag */
match, /* One record matched flag */
quit; /* Quit if no match flag */
int i, /* Counter */
level, /* Help level */
len1, /* String length counters */
len2,
cmplen; /* Length to compare */
tmpdrv = workdrive;
workdrive = load_drive; /* Look for file on drive KERMIT came from */
if ((hlpfp = fopen(HELPFILE,"r")) == ERROR)
prterr("No help available."); /* Can't open help file */
else
{
if (numprm == 1) /* No parameters given */
{
while ((get_rec(hlpfp,str)) && (str[0] != '0'));/* Find main record */
disp_rec(hlpfp,str); /* Show it */
}
else
{
found = match = quit = FALSE;
while (!quit && !found && get_rec(hlpfp,str)) /* until found or EOF */
for (i = 1; i < numprm; i++) /* Check each parameter */
{
make_upper(params[i]); /* Force equal case */
make_upper(str);
len1 = strlen(str) - 2; /* Correct for number and space */
len2 = strlen(params[i]);
cmplen = len2 < len1 ? len2 : len1; /* Find length to match */
level = atoi(str); /* Get current level */
if (match && (level < i))
{
quit = TRUE; /* New level, quit */
break;
}
if ((i == level) && (strncmp(&str[1],params[i],cmplen) == 0))
{ /* This one is ok */
match = TRUE;
if (i == numprm - 1) /* At the end ? */
found = TRUE; /* Done */
break;
}
if (!match) /* Stop if first string does'nt match */
break;
}
if (found)
disp_rec(hlpfp,str); /* Show record */
else
prterr("No such topic"); /* No match */
}
fclose(hlpfp);
workdrive = tmpdrv; /* Restore work drive */
}
}
get_rec(fp,str)
FILE *fp;
char str[];
{
while (fgets(str,128,fp) != NULL) /* Until EOF */
if (isdigit(str[0])) /* Or no more digits */
return (TRUE);
return (FALSE); /* End of file */
}
disp_rec(fp,topic)
FILE *fp;
char *topic;
{
char string[129];
printf("\n%s\n",&topic[1]); /* Print current topic */
while ((fgets(string,128,fp) != NULL) && (!isdigit(string[0])))
puts(string); /* Print it as long as no digit */
puts("\n");
}
<<< flio.c >>>
#include "FLK.H"
#ifdef VIDIS
int v_speed_6850[] = /* valid speed settings for VIDIS 6850 */
{
75, 0,
300, 1,
600, 2,
1200, 3,
2400, 4,
#ifdef INTERRUPT
4800, 5,
9600, 6,
19200, 7,
#endif
0, 0
};
int v_speed_6551[] = /* valid speed settings for 6551 acia */
{
50, 1,
75, 2,
110, 3,
135, 4,
150, 5,
300, 6,
600, 7,
1200, 8,
1800, 9,
2400, 10,
#ifdef INTERRUPT
3600, 11,
4800, 12,
7200, 13,
9600, 14,
19200, 15,
#endif
0, 0
};
#else
int v_speed_6850[] = /* valid speed settings for normal 6850 acia */
{
300, 2,
1200, 1,
0, 0
};
#endif
char port_err, /* Flag to indicate error in port initialize */
*old_port,
lastchar,
irq_on = FALSE;
/*
* Initialize an acia type port
*/
initport(port,first_time)
char port[];
char first_time;
{
int *p;
if (!first_time)
cleanup(); /* Reset old port */
#ifdef INTERRUPT
save_vector = -1; /* Dummy vector */
#endif
old_port = port;
if (!get_acia_type(port))
return (FALSE); /* no such port available */
#ifdef INTERRUPT
save_nmi = *dmem(NMIVEC); /* Save old NMI vector */
*dmem(NMIVEC) = &nmihdr; /* Setup NMI handler address */
inptr = outptr = &input_buffer[0]; /* Setup buffer pointers */
setirq_on(); /* Enable interrupts */
#endif
#ifdef VIDIS
if (use_6850)
{
port[0] = RESET_6850; /* reset the acia */
#ifdef INTERRUPT
if (irq_on)
{
save_vector = *dmem(IRQVEC_6850);
*dmem(IRQVEC_6850) = &irqprp; /* Setup interrupt vector */
port[0] = (config << 2) | 0x81; /* clock / 16, irq enable */
}
else
port[0] = (config << 2) | 0x01; /* clock / 16 */
#else
port[0] = (config << 2) | 0x01; /* clock / 16 */
#endif
p = v_speed_6850; /* point to speed table */
while (*p++ != speed) /* get valid speed */
p++;
port[2] = *p; /* set hardware */
}
else /* use 6551 */
{
port[1] = RESET_6551;
#ifdef INTERRUPT
if (irq_on)
{
save_vector = *dmem(IRQVEC_6551);
*dmem(IRQVEC_6551) = &irqprp; /* Setup interrupt vector */
port[2] = INITCMND_6551 & 0xfd; /* Enable interrupt */
}
else
port[2] = INITCMND_6551;
#else
port[2] = INITCMND_6551;
#endif
port[3] = INITCTRL_6551;
switch(config) /* set configuration */
{
case 0:
port[2] |= 0x60;
port[3] |= 0xa0;
break;
case 1:
port[2] |= 0x20;
port[3] |= 0xa0;
break;
case 2:
port[2] |= 0x60;
port[3] |= 0x20;
break;
case 3:
port[2] |= 0x20;
port[3] |= 0x20;
break;
case 4:
port[3] |= 0x80;
break;
case 5:
break;
case 6:
port[2] |= 0x60;
break;
case 7:
port[2] |= 0x20;
break;
}
p = v_speed_6551; /* point to valid speed table */
while (*p++ != speed) /* get valid speed */
p++;
port[3] |= *p; /* set hardware */
}
#else
port[0] = RESET_6850; /* reset the acia */
p = v_speed_6850; /* point to valid speed table */
while (*p++ != speed) /* get valid speed */
p++;
#ifdef INTERRUPT
if (irq_on)
{
save_vector = *dmem(IRQVEC_6850);
*dmem(IRQVEC_6850) = &irqprp; /* Setup interrupt vector */
port[0] = (config << 2) | *p | 0x80;/* set hardware, enable interrupt */
}
else
port[0] = (config << 2) | *p; /* set hardware */
#else
port[0] = (config << 2) | *p; /* set hardware */
#endif
#endif
purgeline(port); /* eat old input */
return (TRUE); /* valid port found */
}
/*
* get acia type
* return TRUE if port found, use_6850 = true if 6850, else 6551
*/
get_acia_type(port)
char port[];
{
int dummy;
char savep1, savep2, savep3;
savep1 = port[0]; /* Save memory in case of failure */
savep2 = port[1];
savep3 = port[3];
port_err = FALSE;
port[3] = 0; /* set initial value */
dummy = 0; /* else acia won't be read again */
if (port[3] != 0) /* still zero ? */
{
port[0] = RESET_6850; /* no, reset special acia */
dummy = 0; /* else acia won't be read again */
if ((port[0] & 0xf3) == 0) /* check if 6850 available */
{
use_6850 = TRUE; /* it's there */
return (TRUE);
}
}
#ifdef VIDIS
port[1] = RESET_6551;
port[3] = 0;
dummy = 0; /* else acia won't be read again */
if ((port[3] == 0) && (port[1] & 0x10))/* check if 6551 available */
{
use_6850 = FALSE; /* 6551 found */
return (TRUE);
}
#endif
port[0] = savep1; /* Restore memory in case of failure */
port[1] = savep2;
port[3] = savep3;
port_err = TRUE; /* Flag port error for cleanup */
return (FALSE); /* No such port there */
}
/*
* Setup line for remote connection
*/
start_remote()
{
if (remote)
ttyfd = consfd; /* Must use this port */
irq_on = TRUE;
initport(ttyfd,0);
aborted = FALSE;
}
/*
* Finish line for remote connection
*/
finish_remote()
{
if (remote)
ttyfd = REMOTE; /* Restore setting */
irq_on = FALSE;
initport(ttyfd,0); /* Re-init old port */
if (aborted)
puts("\n");
}
/*
* read data from port
*/
read(dev,data,count)
int dev,count;
char *data;
{
int i;
long int time;
for (i = 0; i < count; i++) /* do it for the requested count */
{
time = timecount; /* get timeout value */
while (!instat(dev)) /* no response yet */
if (--time == 0)
{
check_abort(); /* check for user abort after timeout */
return TIMEOUT;
}
lastchar = data[i] = inchar(dev); /* get character */
}
if (rflg || sflg)
chr_rec += count; /* count chars if sending or receiving */
return NULL; /* normal termination */
}
/*
* write characters to port
*/
write(dev,data,count)
int dev,count;
char *data;
{
int i;
if (count == 0) /* determine count if not given */
count = strlen(data);
for (i = 0; i < count; i++)
outchar(data[i],dev); /* send to output port */
if (rflg || sflg)
chr_sent += count; /* count chars if sending or receiving */
}
/*
* check for user abort
*/
check_abort()
{
char c;
if (!cflg && !stopped) /* only when connect is inactive */
{ /* and no stop character is sent */
if (instat(consfd)) /* if character available */
c = inchar(consfd);
else
{
if (remote)
c = lastchar; /* Only check typed character */
else /* if remote */
c = 0;
}
c &= 0177; /* strip parity */
lastchar = 0;
if ((c == ABORTX) || (c == ABORTZ))
{ /* and if it's the abort char */
aborted = c; /* flag abort */
return c;
}
else if (c == TOGDBG) /* Toggle debug ? */
{
if (debug)
{
debug = FALSE; /* Switch off debug */
if (dbgfil != ERROR)
{
fclose(dbgfil); /* Close debug output file if open */
dbgfil = ERROR;
}
}
else
debug = TRUE; /* Switch on debug */
set_frame(); /* Make new display frame */
}
else if (c == dstop) /* Wait.... */
while ((c = inchar(ttyfd) & 0177) != dstart); /* Wait for start */
}
return NULL; /* no abort */
}
/*
* test for input character
*/
instat(port)
char port[];
{
#ifdef VIDIS
if (port_err || ((port == consfd) && !remote))
return constat(); /* buffer status */
#ifdef INTERRUPT
if (irq_on)
return (inptr != outptr);
#endif
else if (use_6850)
return(port[0] & 0x01); /* rcv ready bit 6850 */
else
return(port[1] & 0x08); /* rcv ready bit 6551 */
#else
#ifdef INTERRUPT
if (irq_on)
return (inptr != outptr);
#endif
return(port[0] & 0x01); /* rcv ready bit 6850 */
#endif
}
/*
* get an input character
*/
inchar(port)
char port[];
{
char get_in_buf();
while (!instat(port)); /* wait for input */
#ifdef VIDIS
if (port_err || ((port == consfd) && !remote))
return inchne(); /* use FLEX "input no echo" */
#ifdef INTERRUPT
if (irq_on)
return (get_in_buf());
#endif
else if (use_6850)
return port[1]; /* get data from 6850 */
else
return port[0]; /* get data from 6551 */
#else
#ifdef INTERRUPT
if (irq_on)
return (get_in_buf());
#endif
return port[1]; /* get data from 6850 */
#endif
}
/*
* test for output ready
*/
outstat(port)
char port[];
{
check_abort(); /* maybe he's aborting this */
#ifdef VIDIS
if (port_err || ((port == consfd) && !remote))
return TRUE; /* console always ready in VIDIS */
else if (use_6850)
return(port[0] & 0x02); /* xmit ready bit 6850 */
else
return(port[1] & 0x10); /* xmit ready bit 6551 */
#else
return (port[0] & 0x02); /* xmit ready bit 6850 */
#endif
}
/*
* send a character
*/
outchar(c,port)
char c,port[];
{
long int time;
time = timecount;
while(!outstat(port)) /* wait for ready */
if ((--time == 0) && aborted) /* Acia not ready ? */
return; /* return in case of abort */
#ifdef VIDIS
if (port == consfd)
_putchr(c); /* use FLEX */
else if (use_6850)
port[1] = c; /* send to 6850 */
else
port[0] = c; /* send to 6551 */
#else
port[1] = c; /* send to 6850 */
#endif
}
/*
* purge a line of input data
*/
purgeline(port)
char port[];
{
while(instat(port)) /* eat characters */
inchar(port);
}
/*
* send a break
*/
send_break(port)
char port[];
{
#ifdef VIDIS
if (use_6850)
{
port[0] = 0x60; /* set line */
wait(300); /* delay 300 Ms */
initport(port,0); /* re-initialize */
}
else
{
port[2] |= 0x0c; /* set line */
wait(300); /* delay 300 Ms */
initport(port,0); /* re-initialize */
}
#else
port[0] = 0x60; /* set line */
wait(300); /* delay 300 Ms */
initport(port,0); /* re-initialize */
#endif
}
/*
* delay 'n' Ms
*/
wait(delay)
int delay;
{
long int del_count;
if (delay != 0) /* Only if we have to */
{
del_count = (delay / 1000.) * DELAYVALUE * 3; /* Calculate value */
while (--del_count); /* Ordinary wait loop */
}
}
#ifdef INTERRUPT
/*
* Interrupt handler
*/
irqhdr()
{
char status;
char *port;
port = ttyfd;
if (use_6850)
{
status = port[0];
if (status & 0x80) /* This port issued interrupt */
if (status & 0x01) /* Data available */
put_in_buf(port[1]);
else if (status & 0x04) /* DCD lost interrupt */
status = port[1]; /* Dummy read */
}
#ifdef VIDIS
else /* 6551 */
{
status = port[1];
if (status & 0x80) /* This port issued interrupt */
if (status & 0x08) /* Data available */
put_in_buf(port[0]);
else if (status & 0x20) /* DCD lost interrupt */
status = port[0]; /* Dummy read */
}
#endif
}
/*
* Stuff character in data buffer
* Use handshake if buffer becomes full
*/
put_in_buf(ch)
char ch;
{
int numchar;
*inptr++ = ch; /* Insert character */
if (inptr >= &input_buffer[INBUFSIZE]) /* Adjust pointer */
inptr = &input_buffer;
numchar = calc_bsize(inptr,outptr); /* Calculate number of characters */
if (!stopped && (numchar > FULL_LIMIT)) /* Take care of pending overflow */
{
stopped = TRUE; /* Flag stop character sent */
outchar(dstop,ttyfd); /* Stop remote */
}
}
/*
* Get character from data buffer
* Take care of handshake
*/
char get_in_buf()
{
int numchar;
char ch;
ch = *outptr++; /* Get character from buffer */
if (outptr >= &input_buffer[INBUFSIZE]) /* Adjust buffer pointer */
outptr = &input_buffer;
numchar = calc_bsize(inptr,outptr); /* Calculate number of characters */
if (stopped && (numchar < EMPTY_LIMIT)) /* Take care of underflow */
{
outchar(dstart,ttyfd); /* Re-start remote */
stopped = FALSE; /* Flag stop character sent */
}
return ch;
}
/*
* Calculate number of characters in buffer
*/
calc_bsize(i,o)
char *i,*o;
{
if (i < o)
return ((i + INBUFSIZE) - o);
else
return (i - o);
}
#endif
/*
* Cleanup interrupt vectors
*/
cleanup()
{
#ifdef INTERRUPT
char *port;
int *p;
port = old_port;
if (!port_err) /* Only restore if no error */
{
if (use_6850)
{
port[0] = RESET_6850; /* reset the acia */
#ifdef VIDIS
port[0] = (config << 2) | 0x01;
#else
p = v_speed_6850; /* point to valid speed table */
while (*p++ != speed) /* get valid speed */
p++;
port[0] = (config << 2) | *p; /* set hardware */
#endif
if (save_vector != -1)
*dmem(IRQVEC_6850) = save_vector;
}
#ifdef VIDIS
else
{
port[2] |= 0x02; /* Turn off interrupt enable */
if (save_vector != -1)
*dmem(IRQVEC_6551) = save_vector;
}
#endif
*dmem(NMIVEC) = save_nmi;
}
#endif
}
<<< flkerm.c >>>
/*
* K e r m i t File Transfer Utility
*
* FLEX Kermit... Adapted from UNIX version by
*
* Jur van der Burg
* Nettelhorst 56
* 2402 LS Alphen aan den Rijn
* The Netherlands
*
* Telephone: (0)1720 - 34057
*
* Last update: 12 September 1986
*
* This program runs under almost any FLEX-09 version.
* Hardware dependent things are in the files FLK.H and FLIO.C
*
* Compiled with INTROL C (c) V 1.5
*
*/
#include "FLK.H"
/*
* Main command table
*/
TABLE command_table[] =
{
"send", 1,
"receive", 2,
"connect", 3,
"get", 4,
"set", 5,
"show", 6,
"server", 7,
"help", 8,
"exit", 9,
"quit", 10,
"bye", 11,
"finish", 12,
"transmit", 13,
"flex", 14,
"statistics", 15,
"take", 16,
"", 0
};
/*
* Start of main program
*/
main(argc,argv)
int argc;
char **argv;
{
char input[257], /* Command input */
*s, /* Options pointer */
do_startup, /* Start file flag */
echo; /* Echo startup file */
do_startup = TRUE; /* Use startup command file */
echo = FALSE; /* Don't echo startup file */
while (--argc > 0 && (*++argv)[0] == '-')
for (s = argv[0] + 1; *s != '\0'; s++)
switch(tolower(*s))
{
case 'n':
do_startup = FALSE; /* Don't get commands from file */
break;
case 'e':
echo = TRUE; /* Echo startup file */
break;
default:
usage();
}
init_par(do_startup,echo); /* Init all parameters */
for (;;) /* Do this forever */
{
do
{
puts(prompt); /* Prompt user */
if (gets(input,256) == NULL) /* Get response */
kerm_exit(); /* E O F */
}
while (!input[0]); /* Blank command line */
kerm_command(input); /* Process command */
}
}
init_par(autostart,echo)
char autostart, echo;
{
char data[257]; /* Command input */
FILE *inifp;
/* Initialize these values and hope the first packet will get across OK */
mypackstart = I_MYPACKSTART; /* Start of packet character */
maxpacksiz = I_MAXPACKSIZ; /* Maximum packet size */
maxtry = I_MAXTRY; /* Times to retry a packet */
myquote = I_MYQUOTE; /* Quote character I will use */
mypad = I_MYPAD; /* Number of padding chars I need */
mypchar = I_MYPCHAR; /* Padding character I need (NULL) */
myeol = I_MYEOL; /* End-Of-Line character I need */
mytime = I_MYTIME; /* My timeout in seconds */
myblock_check_type = I_BLOCKCHECKTYPE; /* Block check type */
myrptquote = I_MYRPTQUOTE; /* Repeat count quote character */
myeightquote = I_MYEIGHTQUOTE; /* Eight bit quote character */
send_delay = I_SEND_DELAY; /* Delay before sending */
load_drive = system_fcb_drive; /* Save drive KERMIT came from */
strcpy(prompt,DEFPROMPT); /* Setup prompt */
logfile[0] = '\0'; /* No log filename yet */
logfileopen = FALSE; /* No logging done yet */
speed = 1200; /* Default line speed */
config = 5; /* 8 bits, 1 stop, no parity */
image = FALSE; /* Translation */
save_file = FALSE; /* Don't save file on abort */
escchr = ESCCHR; /* Default escape character */
fulldup = TRUE; /* Default is full duplex */
warning = TRUE; /* File conflict warning */
t_chr_sent = t_datachr_sent = t_nak_sent = 0; /* reset counters */
t_chr_rec = t_datachr_rec = t_nak_rec = 0;
dstop = XOFF; /* Init handshake characters */
dstart = XON;
dbgfil = ERROR; /* No debug file */
remote = FALSE; /* No remote line */
stopped = FALSE; /* Not stopped with handshake */
init_crc_table(); /* Setup table for CRC calculation */
consfd = CONSOLE; /* Setup console port address */
#ifdef VIDIS
ttyfd = ADDRESS_6850;
if (initport(ttyfd,1) == FALSE) /* Look for a 6850 acia */
{
ttyfd = ADDRESS_6551; /* No 6850 present */
initport(ttyfd,0); /* Use default 6551 acia */
}
#else
ttyfd = TTYPORT; /* tty is the communications line */
initport(ttyfd,1); /* Initialize 6850 acia */
#endif
puts(IDENT); /* Tell him we're on the air! */
puts(VERSION); /* With this version */
puts("\n\n");
if (autostart) /* Startup with command file */
take(TRUE,echo);
}
/*
* Process kermit command
*/
kerm_command(instrng)
char *instrng;
{
int funcpoint;
char *free();
if (split(instrng, params)) /* Split command line */
{ /* into seperate strings */
cflg = sflg = rflg = 0; /* Turn off all flags */
tabsleft = TABSIZE; /* Default tab setting */
aborted = FALSE; /* Not yet aborted */
timint = I_MYTIME; /* Setup timeout value */
timecount = mytime * DELAYVALUE; /* Setup timeout counter */
funcpoint = parse(params[0], command_table);/* Find routine address */
if (funcpoint == NULL) /* Ambiguous */
prterr("Ambiguous command");
else if (funcpoint == ERROR) /* Unknown */
prterr("Unknown command");
else
switch(funcpoint) /* Process command */
{
case 1:
sendfile();
break;
case 2:
recfile();
break;
case 3:
connect();
break;
case 4:
getfile();
break;
case 5:
set();
break;
case 6:
show();
break;
case 7:
server();
break;
case 8:
help();
break;
case 9:
case 10:
kerm_exit();
break;
case 11:
bye();
break;
case 12:
finish();
break;
case 13:
transmit();
break;
case 14:
do_flex();
break;
case 15:
statistics();
break;
case 16:
take(FALSE,TRUE);
break;
}
fclose(fp); /* Close file if we're aborted */
fp = ERROR; /* Indicate no file open yet */
}
while (numprm)
free(params[--numprm]); /* Free command string memory */
}
usage()
{
puts("Usage: KERMIT -n Disable startup command file\n");
puts(" -e Echo startup command file\n");
exit();
}
kerm_exit()
{
cleanup(); /* Restore interrupt vectors if any */
exit();
}
<<< flpack.c >>>
#include "FLK.H"
/*
* s p a c k
*
* Send a Packet
*/
spack(type,num,len,data,check)
char type, *data, len,
num, check;
{
int i; /* Character loop counter */
char buffer[100]; /* Packet buffer */
int crc, chksum, ck1, ck2, ck3; /* CRC value and checksum */
register char *bufp; /* Buffer pointer */
prtdbgf("Packet transmitted: %d, Type: %c, Length: %d\n",num,type,len);
if (!remote)
{
#ifdef SCREEN
posit(20,7);
printf("%d ",num);
#else
printf("Packet transmitted: %d\n",num);
#endif
}
if (debug) /* Display outgoing packet */
{
#ifdef SCREEN
disp(0,12,CLREOL);
disp(20,11,CLREOL);
#endif
if ((debug >= 1) && !remote)
{
#ifdef SCREEN
posit(33,7);
printf("%c",type);
posit(45,7);
printf("%d ",len);
#else
printf("Type: %c Length: %d\n",type,len);
#endif
}
if (len != 0)
{
data[len] = '\0'; /* Null terminate data to print it */
if ((debug >= 1) && !remote)
{
#ifdef SCREEN
posit(20,11);
putchar('"');
puts(data);
putchar('"');
#else
printf("Data transmitted: \"%s\"\n",data);
#endif
}
prtdbgf("Data transmitted: \"%s\"\n",data);
}
}
pack_sent++; /* Count packet */
bufp = buffer; /* Set up buffer pointer */
write(ttyfd,&padchar,pad); /* Issue any padding */
init_crc(); /* Initialize CRC calculation */
*bufp++ = mypackstart; /* Packet marker */
*bufp++ = tochar(len + check + 2); /* Send the character count */
chksum = tochar(len + check + 2); /* Initialize the checksum */
calc_crc(tochar(len + check + 2)); /* Calculate CRC */
*bufp++ = tochar(num); /* Packet number */
chksum += tochar(num); /* Update checksum */
calc_crc(tochar(num)); /* Calculate CRC */
*bufp++ = type; /* Packet type */
chksum += type; /* Update checksum */
crc = calc_crc(type); /* Calculate CRC */
if (type == 'N')
nak_sent++; /* Count nak */
for (i=0; i<len; i++) /* Loop for all data characters */
{
*bufp++ = data[i]; /* Get a character */
chksum += data[i]; /* Update checksum */
crc = calc_crc(data[i]); /* Calculate CRC */
}
if (check == 1) /* One character checksum */
{
chksum = (((chksum & 0300) >> 6) + chksum) & 077;
*bufp++ = (ck1 = tochar(chksum)); /* Put it in the packet */
}
else if (check == 2) /* Two character checksum */
{
*bufp++ = (ck1 = tochar((chksum >> 6) & 077));
*bufp++ = (ck2 = tochar(chksum & 077));
}
else if (check == 3) /* Three character CRC */
{
*bufp++ = (ck1 = tochar((crc >> 12) & 017));
*bufp++ = (ck2 = tochar((crc >> 6) & 077));
*bufp++ = (ck3 = tochar(crc & 077));
}
if (debug)
{
if (debug >= 1)
#ifdef SCREEN
posit(59,7);
#else
puts("Checksum: ");
#endif
prtdbgf("Checksum: ");
switch(check)
{
case 1:
prtdbg("%02x\n",unchar(ck1));
break;
case 2:
prtdbg("%02x%02x\n",unchar(ck1),unchar(ck2));
break;
case 3:
prtdbg("%02x%02x%02x\n",unchar(ck1),unchar(ck2),unchar(ck3));
}
}
*bufp++ = eol; /* Extra-packet line terminator */
datachr_sent += len; /* Adjust character counters */
write(ttyfd, buffer,bufp-buffer); /* Send the packet */
if (sflg)
disp_size_transferred(); /* Show how far we've got */
}
/*
* r p a c k
*
* Read a Packet
*/
rpack(len,num,data,check)
char *num, check, /* length, number, checksum type */
*len, *data; /* Packet data */
{
int i, done, /* Data char number, loop exit */
numtry, /* retry counter */
cchksum, /* Our (computed) checksum */
ck1, ck2, ck3, /* Temporary save */
rchksum, /* Checksum received from host */
crc; /* CRC value */
char t, /* Current input character */
type; /* Packet type */
do /* Wait for packet header */
{
if (read(ttyfd,&t,1) == TIMEOUT)
return ('T'); /* Return timeout */
t &= 0177; /* Handle parity */
}
while (t != mypackstart);
done = FALSE; /* Got packet start, init loop */
while (!done) /* Loop to get a packet */
{
init_crc(); /* Start new CRC calculation */
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
t &= 0177; /* Handle parity */
if (t == mypackstart) /* Resynch if start of packet */
continue;
cchksum = t; /* Start the checksum */
calc_crc(t); /* Calculate CRC */
*len = unchar(t)-check-2; /* Character count */
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
t &= 0177; /* Handle parity */
if (t == mypackstart) /* Resynch if start of packet */
continue;
cchksum += t; /* Update checksum */
calc_crc(t); /* Calculate CRC */
*num = unchar(t); /* Packet number */
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
t &= 0177; /* Handle parity */
if (t == mypackstart) /* Resynch if start of packet */
continue;
cchksum += t; /* Update checksum */
crc = calc_crc(t); /* Calculate CRC */
type = t; /* Packet type */
if (type == 'N')
nak_rec++; /* Count received nak */
for (i = 0; i < (*len); i++) /* The data itself, if any */
{ /* Loop for character count */
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
if (!image) /* Handle parity */
t &= 0177;
if (t == mypackstart) /* Resynch if start of packet */
continue;
cchksum += t; /* Update checksum */
crc = calc_crc(t); /* Calculate CRC */
data[i] = t; /* Put it in the data buffer */
}
data[*len] = '\0'; /* Mark the end of the data */
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
if (check == 1)
rchksum = (ck1 = unchar(t)); /* Convert to numeric */
else if (check == 2)
{
rchksum = (ck1 = unchar(t)) << 6;
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
rchksum += (ck2 = unchar(t));
}
else if (check == 3)
{
rchksum = (ck1 = unchar(t)) << 12;
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
rchksum += (ck2 = unchar(t)) << 6;
if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
return ('T');
rchksum += (ck3 = unchar(t));
}
if (read(ttyfd,&t,1) == TIMEOUT) /* get EOL character and toss it */
return ('T');
t &= 0177; /* Handle parity */
if (t == mypackstart) /* Resynch if start of packet */
continue;
done = TRUE; /* Got checksum, done */
}
datachr_rec += *len; /* Count received data characters */
pack_rec++; /* Count packet */
if (check == 3)
cchksum = crc; /* Set calculated value */
else if (check == 2)
cchksum &= 07777; /* Strip result to 12 bits */
if (check == 1)
cchksum = (((cchksum & 0300) >> 6) + cchksum) & 077; /* Final checksum */
prtdbgf("Packet received: %d, Type: %c, Length: %d\n",*num,type,*len);
if (!remote)
{
#ifdef SCREEN
posit(20,6);
printf("%d ",*num);
#else
printf("Packet received: %d\n",*num);
#endif
}
if (debug) /* Display incoming packet */
{
if ((debug >= 1) && !remote)
{
#ifdef SCREEN
posit(33,6);
printf("%c",type);
posit(45,6);
printf("%d ",*len);
posit(59,6);
#else
printf("Type: %c Length: %d\n",type,*len);
#endif
}
prtdbgf("Checksum: ");
#ifndef SCREEN
puts("Checksum: ");
#endif
switch(check)
{
case 1:
prtdbg("%02x\n",ck1);
break;
case 2:
prtdbg("%02x%02x\n",ck1,ck2);
break;
case 3:
prtdbg("%02x%02x%02x\n",ck1,ck2,ck3);
}
#ifdef SCREEN
disp(20,9,CLREOL);
disp(0,10,CLREOL);
#endif
if (*len != 0)
{
data[*len] = '\0'; /* Null terminate data to print it */
if ((debug >= 1) && !remote)
{
#ifdef SCREEN
posit(20,9);
putchar('"');
puts(data);
putchar('"');
#else
printf("Data received: \"%s\"\n",data);
#endif
}
prtdbgf("Data received: \"%s\"\n",data);
}
}
if (rflg)
disp_size_transferred(); /* Show how far we've got */
if (cchksum != rchksum)
return(FALSE); /* Checksum error */
else
return(type); /* All OK, return packet type */
}
<<< flrecs.c >>>
#include "FLK.H"
char rec_filnam[50], stopflag;
recfile()
{
if (numprm > 2)
prterr("Only one filename allowed");
else
{
if (numprm == 2)
strcpy(rec_filnam,params[1]); /* Get filename to use */
else
rec_filnam[0] = '\0'; /* Use default name */
rflg++; /* Receive command */
n = 0; /* Init packet number */
set_frame();
start_remote(); /* Setup port if remote */
purgeline(ttyfd); /* Eat old input */
if (!recsw('R')) /* Receive the file(s) */
disp(0,16,"Receive failed.");
disp(0,20,CURSON);
beep();
finish_remote();
}
}
getfile()
{
char status, i;
if (numprm <= 1) /* check for parameter */
prterr("Filespec(s) required");
else
{
rec_filnam[0] = '\0'; /* Use default name */
rflg = 2; /* 'GET' command */
n = 0; /* Init packet number */
set_frame();
start_remote(); /* Setup port if remote */
i = TRUE;
while (get_file_spec(i)) /* Get filespec */
{
i = FALSE;
if (!(status = get())) /* Get the file */
break;
}
if (!status)
disp(0,16,"Get failed."); /* Report failure */
disp(0,20,CURSON);
beep();
finish_remote();
}
}
/*
* get file from remote server
*/
get()
{
char len, num;
n = 0;
numtry = 0;
set_default_comm(); /* Set default communication */
aborted = FALSE;
while(TRUE)
{
len = strlen(filnam);
strcpy(packet,filnam); /* Setup filename */
if (debug)
{
prtdbgf("Receive state: ");
#ifndef SCREEN
puts("Receice state: ");
#endif
disp_state(20,13,'R');
}
purgeline(ttyfd); /* Eat old input */
spack('R',n,len,packet,1); /* Receiver init */
switch(rpack(&len,&num,recpkt,1))
{
case 'S':
rpar(recpkt,len); /* Get the other side's init data */
spar(packet,&len); /* Fill up packet with my init info */
spack('Y',n,len,packet,1); /* ACK with my parameters */
oldtry = numtry; /* Save old try count */
numtry = 0; /* Start a new counter */
n = (n + 1) % 64; /* Bump packet number, mod 64 */
return(recsw('F')); /* Enter File-Receive state */
case 'E':
prerrpkt(recpkt); /* error return */
return(FALSE);
case 'T':
if (aborted) /* user abort */
return(FALSE);
default:
if (numtry++ >= maxtry)
return (FALSE); /* max try's exceeded */
}
}
}
/*
* r e c s w
*
* This is the state table switcher for receiving files.
*/
recsw(istate)
char istate;
{
char rinit(), rfile(), rdata(); /* Use these procedures */
init_xfer(); /* reset character counters */
if (istate != 'F') /* if not already done */
set_default_comm(); /* Set default communication */
state = istate; /* set start state 'R' or 'F' */
numtry = 0; /* Say no tries yet */
stopflag = FALSE; /* Not stopped yet */
aborted = FALSE; /* Not aborted yet */
while(TRUE)
{
if (debug)
{
prtdbgf("Receive state: ");
#ifndef SCREEN
puts("Receive state: ");
#endif
disp_state(20,13,state);
}
switch(state) /* Do until done */
{
case 'R': /* Receive-Init */
state = rinit();
break;
case 'F': /* Receive-File */
state = rfile();
break;
case 'D': /* Receive-Data */
state = rdata();
break;
case 'C': /* Complete state */
fin_xfer();
return(TRUE);
default: /* Unknown or abort */
fin_xfer();
return(FALSE);
}
}
}
/*
* r i n i t
*
* Receive Initialization
*/
char rinit()
{
char len, num; /* Packet length, number */
if (numtry++ >= maxtry) /* If too many tries, "abort" */
return('A');
switch(rpack(&len,&num,packet,1)) /* Get a packet */
{
case 'S': /* Send-Init */
rpar(packet,len); /* Get the other side's init data */
spar(packet,&len); /* Fill packet with my init info */
spack('Y',n,len,packet,1); /* ACK with my parameters */
oldtry = numtry; /* Save old try count */
numtry = 0; /* Start a new counter */
n = (n + 1) % 64; /* Bump packet number, mod 64 */
return('F'); /* Enter File-Receive state */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
return('A'); /* aborted by user */
case FALSE: /* Didn't get packet */
spack('N',n,0,0,1); /* Return a NAK */
return(state); /* Keep trying */
default: /* Some other packet type, "abort" */
return('A');
}
}
/*
* r f i l e
*
* Receive File Header
*/
char rfile()
{
char num, len, /* Packet number, length */
*w;
if (numtry++ >= maxtry) /* "abort" if too many tries */
return('A');
switch(rpack(&len,&num,packet,block_check_type)) /* Get a packet */
{
case 'S': /* Send-Init, maybe our ACK lost */
if (oldtry++ >= maxtry) /* If too many tries "abort" */
return('A');
if (num == ((n == 0) ? 63 : n-1)) /* Previous packet, mod 64? */
{ /* Yes, ACK it again with */
spar(packet,&len); /* our Send-Init parameters */
spack('Y',num,len,packet,1);
numtry = 0; /* Reset try counter */
return(state); /* Stay in this state */
}
else /* Not previous packet, "abort" */
return('A');
case 'Z': /* End-Of-File */
if (oldtry++ >= maxtry)
return('A');
if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
{ /* Yes, ACK it again. */
spack('Y',num,0,0,block_check_type);
numtry = 0;
return(state); /* Stay in this state */
}
else /* Not previous packet, "abort" */
return('A');
case 'F': /* File Header (just what we want) */
if (num != n) /* The packet number must be right */
return('A');
if (!rec_filnam[0]) /* Copy filename if not given */
strcpy(rec_filnam, packet);
cvt_case(rec_filnam); /* Convert case */
transmit_chr_count = 0; /* Counter for total data size */
if(image)
w = "bw"; /* open binary file */
else
w = "w"; /* open text file */
while ((fp = fopen(rec_filnam,"r")) != ERROR)
{ /* File already there */
fclose(fp);
if (warning) /* File warning on ? */
{
if (!remote)
{
posit(0,18);
printf("%sWarning: File %s already exists, creating new name",
CLREOL,rec_filnam);
beep();
#ifndef SCREEN
puts("\n");
#endif
}
new_name(rec_filnam); /* Create new filename */
}
else
break; /* Leave it as it is */
}
if ((fp = fopen(rec_filnam,w)) == ERROR)/* Try to open new file */
{
error(4,"%s",rec_filnam); /* Give up if error */
return('A');
}
else /* OK, give message */
{
disp(0,2,"Receiving: ");
disp(20,2,rec_filnam);
puts(CLREOL);
prtdbgf("New file name: %s\n",rec_filnam);
}
purgeline(ttyfd); /* Eat old input */
spack('Y',n,0,0,block_check_type); /* Acknowledge file header */
oldtry = numtry; /* Reset try counters */
numtry = 0; /* ... */
stopflag = FALSE; /* In case we're aborted */
aborted = FALSE;
n = (n + 1) % 64; /* Bump packet number, mod 64 */
return('D'); /* Switch to Data state */
case 'B': /* Break transmission (EOT) */
if (num != n) /* Need right packet number here */
return ('A');
spack('Y',n,0,0,block_check_type); /* Say OK */
return('C'); /* Go to complete state */
case 'E': /* Error packet received */
prerrpkt(packet); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Didn't get packet */
spack('N',n,0,0,block_check_type); /* Return a NAK */
return(state); /* Keep trying */
default: /* Some other packet, "abort" */
return ('A');
}
}
/*
* r d a t a
*
* Receive Data
*/
char rdata()
{
char num, len, tlen; /* Packet number, length */
if (numtry++ >= maxtry) /* "abort" if too many tries */
return('A');
switch(rpack(&len,&num,packet,block_check_type)) /* Get packet */
{
case 'D': /* Got Data packet */
if (num != n) /* Right packet? */
{ /* No */
if (oldtry++ >= maxtry)
return('A'); /* If too many tries, abort */
if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
{ /* Previous packet again? */
spack('Y',num,0,0,block_check_type); /* Yes, re-ACK it */
numtry = 0; /* Reset try counter */
return(state); /* Don't write out data! */
}
else /* sorry, wrong number */
return('A');
}
if (stopflag) /* Other side still sending ? */
{
error(0); /* Transfer aborted */
return('A');
}
/* Got data with right packet number */
if (bufemp(packet,len) == ERROR) /* Write the data to the file */
{
error(3,"%d",errno); /* FLEX error */
return('A'); /* enter abort state */
}
tlen = 1; /* Assume aborted */
stopflag = TRUE;
if (aborted == ABORTX) /* Abort current file ? */
packet[0] = 'X';
else if (aborted == ABORTZ) /* Abort whole batch ? */
{
packet[0] = 'Z';
filecount = 0; /* No more files for 'GET' */
}
else
{
tlen = 0; /* Nothing to abort, length = 0 */
stopflag = FALSE;
}
spack('Y',n,tlen,packet,block_check_type); /* Acknowledge packet */
oldtry = numtry; /* Reset the try counters */
numtry = 0; /* ... */
n = (n + 1) % 64; /* Bump packet number, mod 64 */
return('D'); /* Remain in data state */
case 'F': /* Got a File Header */
case 'X':
if (oldtry++ >= maxtry)
return('A'); /* If too many tries, "abort" */
if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
{ /* It was the previous one */
spack('Y',num,0,0,block_check_type); /* ACK it again */
numtry = 0; /* Reset try counter */
return(state); /* Stay in Data state */
}
else /* Not previous packet, "abort" */
return('A');
case 'Z': /* End-Of-File */
if (num != n) /* Must have right packet number */
return('A');
spack('Y',n,0,0,block_check_type); /* OK, ACK it. */
fclose(fp); /* Close the file */
if (len == 1) /* Interrupt */
{
#ifdef SCREEN
disp(0,18,CLREOL);
disp(0,18,"Transfer aborted.");
#else
puts("Transfer aborted.\n");
#endif
beep();
if ((packet[0] == 'D') && !save_file)
unlink(rec_filnam); /* Discard input file */
}
rec_filnam[0] = '\0'; /* Use default for next transfer */
n = (n + 1) % 64; /* Bump packet number */
return('F'); /* Go back to Receive File state */
case 'E': /* Error packet received */
prerrpkt(packet); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Didn't get packet */
spack('N',n,0,0,block_check_type); /* Return a NAK */
return(state); /* Keep trying */
default: /* Some other packet, "abort" */
return('A');
}
}
<<< flsend.c >>>
#include "FLK.H"
sendfile()
{
if (numprm <= 1) /* check parameter */
prterr("Filespec(s) required");
else if (!get_file_spec(TRUE)) /* Get filespec for send */
prterr("No files selected");
else
{
sflg++;
set_frame();
start_remote(); /* Setup port if remote */
if (!sendsw()) /* Send the file(s) */
disp(0,16,"Send failed."); /* Report failure */
disp(0,20,CURSON);
beep();
finish_remote();
}
}
/*
* s e n d s w
*
* Sendsw is the state table switcher for sending files. It loops until
* either it finishes, or an error is encountered. The routines called
* by sendsw are responsible for changing the state.
*
*/
sendsw()
{
char sinit(), sfile(), sdata(), seof(), sbreak();
init_xfer(); /* Reset counters */
set_default_comm(); /* Set communication parameters */
state = 'S'; /* Send initiate is start state */
n = 0; /* Initialize message number */
numtry = 0; /* Say no tries yet */
if (remote)
wait(send_delay * 1000); /* Wait before sending if remote */
purgeline(ttyfd); /* Eat old input */
while(TRUE) /* Do this as long as necessary */
{
if (debug)
{
prtdbgf("Send state: ");
#ifndef SCREEN
puts("Send state: ");
#endif
disp_state(20,14,state);
}
switch(state)
{
case 'S': /* Send-init */
state = sinit();
break;
case 'F': /* Send-file */
state = sfile();
break;
case 'D': /* Send-data */
state = sdata();
break;
case 'Z': /* Send-End-of-File */
state = seof();
break;
case 'B': /* Send-Break */
state = sbreak();
break;
case 'C': /* Complete */
fin_xfer();
return (TRUE);
default: /* Unknown or abort, fail */
fin_xfer();
return (FALSE);
}
}
}
/*
* s i n i t
*
* Send Initiate: send this host's parameters and get other side's back.
*/
char sinit()
{
char num, len; /* Packet number, length */
if (numtry++ >= maxtry) /* If too many tries, give up */
return('A');
spar(packet,&len); /* Fill up init info packet */
spack('S',n,len,packet,1); /* Send an S packet */
switch(rpack(&len,&num,recpkt,1)) /* What was the reply? */
{
case 'N': /* NAK, try it again */
return(state);
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, stay in S state */
return(state); /* and try again */
rpar(recpkt,len); /* Get other side's init info */
numtry = 0; /* Reset try counter */
n = ( n + 1) % 64; /* Bump packet count */
return('F'); /* OK, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* Abort */
case 'T': /* Timeout */
if (aborted)
return('A'); /* aborted by user */
case FALSE: /* Receive failure, try again */
return(state);
default: /* Anything else, just "abort" */
return('A');
}
}
/*
* s f i l e
*
* Send File Header.
*/
char sfile()
{
char num, len, /* Packet number, length */
fnm[50];
extern int drive;
if (numtry++ >= maxtry) /* If too many tries, give up */
return('A');
aborted = FALSE;
if (fp == ERROR) /* If not already open, */
{
fnm[0] = drive + '0'; /* Insert drive in spec */
fnm[1] = '.';
strcpy(&fnm[2],filnam);
if (image)
fp = fopen(fnm,"br"); /* open the file to be sent */
else
fp = fopen(fnm,"r"); /* open the file to be sent */
if (fp == ERROR) /* If bad file pointer, give up */
{
error(5,"%s",fnm); /* Can't open file */
if (!get_file_spec(FALSE))
return('C'); /* No more files to do */
else
return('S'); /* Try next file */
}
}
disp(0,2,"Sending: ");
disp(20,2,fnm);
puts(CLREOL);
len = strlen(filnam);
spack('F',n,len,filnam,block_check_type); /* Send an F packet */
switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, stay in F state */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* Bump packet count */
size = bufill(packet,TRUE); /* Get first data from file */
return('D'); /* Switch state to D */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in F */
return(state);
default: /* Something else, just "abort" */
return('A');
}
}
/*
* s d a t a
*
* Send File Data
*/
char sdata()
{
char num, len, /* Packet number, length */
tmpc;
if (numtry++ >= maxtry) /* If too many tries, give up */
return('A');
spack('D',n,(char)size,packet,block_check_type); /* Send a D packet */
switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, fail */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* Bump packet count */
if ((size = bufill(packet,FALSE)) == EOF) /* Get data from file */
return('Z'); /* If EOF set state to that */
tmpc = recpkt[0];
if (len == 1) /* Data on ack */
{
if (tmpc == 'Z') /* Stop entire batch */
filecount = 0; /* No more files to send */
if ((tmpc == 'X') || (tmpc == 'Z'))
aborted = tmpc - 64; /* Make binary */
}
if ((aborted == ABORTX) || (aborted == ABORTZ))
{
#ifdef SCREEN
disp(0,18,"Transfer interrupted.");
#else
puts("Transfer interrupted.\n");
#endif
beep();
return('Z'); /* Send abort */
}
return('D'); /* Got data, stay in state D */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in D */
return(state);
default: /* Anything else, "abort" */
return('A');
}
}
/*
* s e o f
*
* Send End-Of-File.
*/
char seof()
{
char num, len, tlen; /* Packet number, length */
if (numtry++ >= maxtry) /* If too many tries, "abort" */
return('A');
tlen = 0; /* Assume no abort */
if ((aborted == ABORTX) || (aborted == ABORTZ))
{
packet[0] = 'D'; /* Discard file on abort */
tlen = 1;
}
spack('Z',n,tlen,packet,block_check_type); /* Send a 'Z' packet */
switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, hold out */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* and bump packet count */
fclose(fp); /* Close the input file */
fp = ERROR; /* flag no file open */
if (!get_file_spec(FALSE))
return ('B'); /* Stop if no more files */
if (aborted == ABORTZ) /* Abort the rest ? */
{
while (get_file_spec(FALSE)); /* FLush directory buffer */
return ('B');
}
return('F'); /* More files, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in Z */
return(state);
default: /* Something else, "abort" */
return('A');
}
}
/*
* s b r e a k
*
* Send Break (EOT)
*/
char sbreak()
{
char num, len; /* Packet number, length */
if (numtry++ >= maxtry) /* If too many tries "abort" */
return('A');
spack('B',n,0,packet,block_check_type);/* Send a B packet */
switch (rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, fail */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* and bump packet count */
return('C'); /* Switch state to Complete */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('A'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(0); /* send error packet */
return('A'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in B */
return(state);
default: /* Other, "abort" */
return ('A');
}
}
<<< flserv.c >>>
#include "FLK.H"
/*
* s e r v e r
*/
server()
{
char num, len, i;
extern char rec_filnam[];
char filename[50];
n = 0; /* initialize message number */
numtry = 0; /* say no tries yet */
set_frame();
posit(0,20);
puts("Server running... Type your kermit 'BYE' or 'FINISH'\n");
puts("commands, or ctrl-X to quit the server.\n");
set_default_comm(); /* Set default communication */
start_remote(); /* Setup port if remote */
while(TRUE)
{
switch(rpack(&len,&num,packet,1))/* do this for as long as necessary */
{
case 'S':
set_frame();
n = num;
rpar(packet,len); /* setup receive parameters */
spar(packet,&len); /* setup transmit parameters */
spack('Y',n,len,packet,1);
oldtry = numtry;
numtry = 0;
rec_filnam[0] = '\0'; /* Use default name */
n = (n + 1) % 64;
rflg++; /* Flag receive file */
recsw('F'); /* switch to 'F' state */
break;
case 'I':
set_frame();
n = num;
rpar(packet,len); /* setup receive parameters */
spar(packet,&len); /* setup transmit parameters */
spack('Y',n,len,packet,1);
break;
case 'R':
i = 0;
do
filename[i] = packet[i]; /* copy filename */
while((packet[i++] != '\0') && (i < len));
filename[i] = '\0'; /* Mark end of string */
numprm = 2;
params[1] = &filename; /* Setup pointer to filename */
get_file_spec(TRUE); /* Parse filespec */
sflg++; /* Flag end file */
sendsw(); /* Send file */
n = 0;
break;
case 'G': /* 'general' command */
set_frame();
switch(packet[0])
{
case 'L': /* logout */
spack('Y',num,0,0,1); /* acknowledge */
disp(0,23,CURSON);
finish_remote();
kerm_exit();
case 'F': /* finish */
spack('Y',num,0,0,1); /* acknowledge */
disp(0,23,CURSON);
finish_remote();
return;
default:
error(1); /* Not implemented */
}
break;
case 'T': /* timeout */
if (aborted)
{
disp(0,23,CURSON);
finish_remote();
return; /* aborted by user */
}
spack('N',n,0,0,1); /* send NAK */
break;
case 'N':
case 'E':
break; /* Eat NAK and error packet */
case FALSE:
error(2); /* Packet error */
break;
default:
if (aborted)
{
disp(0,23,CURSON);
finish_remote();
return;
}
error(1); /* Not implemented */
}
rflg = sflg = 0;
set_default_comm(); /* Set default communication */
}
}
/*
* stop remote server
*/
finish()
{
if (remote)
prterr("Not allowed if REMOTE");
else
{
if (!do_generic('F'))
{
disp(0,16,"Finish failed\n");
beep();
}
disp(0,23,CURSON);
finish_remote();
}
}
/*
* log out remote server and local kermit
*/
bye()
{
if (remote)
prterr("Not allowed if REMOTE");
else
{
if (!do_generic('L'))
{
disp(0,16,"Bye failed\n");
disp(0,23,CURSON);
beep();
}
else
{
disp(0,23,CURSON);
kerm_exit(); /* stop program if successful */
}
finish_remote();
}
}
/*
* send server function
*/
do_generic(function)
char function;
{
char len, num,
status;
n = 0; /* initialize message number */
numtry = 0; /* say no tries yet */
set_frame();
set_default_comm(); /* setup default communication */
start_remote(); /* Setup port if remote */
packet[0] = function; /* insert GENERIC command */
while(TRUE)
{
num = 0;
spack('G',num,1,packet,1); /* send GENERIC packet */
switch(rpack(&len,&num,recpkt,1))
{
case 'Y':
return(TRUE); /* valid response */
case 'E':
prerrpkt(recpkt);
return(FALSE); /* received an error */
case 'T':
if (aborted)
return(FALSE); /* aborted by user */
default:
if (numtry++ > maxtry)
return(FALSE); /* too many errors */
}
}
}
<<< flset.c >>>
#include "FLK.H"
TABLE set_table[] =
{
"debug", 1,
"escape", 2,
"line", 3,
"baud", 4,
"configuration", 5,
"timeout", 6,
"prompt", 7,
"filetype", 8,
"log", 9,
"duplex", 10,
"handshake", 11,
"block_check_type", 12,
"repeat_quote", 13,
"retry", 14,
"packet_length", 15,
"padding", 16,
"padchar", 17,
"start_of_packet", 18,
"end_of_line", 19,
"quote", 20,
"eight_bit_quote", 21,
"incomplete", 22,
"delay", 23,
"warning", 24,
"", 0
};
set()
{
int fpoint;
fpoint = parse(params[1], set_table); /* Parse 'set' command */
if (fpoint == NULL) /* Ambiguous */
prterr("Ambiguous 'set' command");
else if (fpoint == ERROR) /* Unknown */
prterr("Unknown 'set' command");
else if (!synerr(3)) /* Dispatch to command if no error */
switch(fpoint)
{
case 1:
set_debug();
break;
case 2:
set_escape();
break;
case 3:
set_line();
break;
case 4:
set_baud();
break;
case 5:
set_config();
break;
case 6:
set_timeout();
break;
case 7:
set_prompt();
break;
case 8:
set_filetype();
break;
case 9:
set_log();
break;
case 10:
set_dup();
break;
case 11:
set_hsh();
break;
case 12:
set_block_check_type();
break;
case 13:
set_repeat_quote();
break;
case 14:
set_retry();
break;
case 15:
set_packet_length();
break;
case 16:
set_padding();
break;
case 17:
set_padchar();
break;
case 18:
set_start_of_packet();
break;
case 19:
set_end_of_line();
break;
case 20:
set_quote();
break;
case 21:
set_eight_bit_quote();
break;
case 22:
set_incomplete();
break;
case 23:
set_delay();
break;
case 24:
set_warning();
}
}
set_debug()
{
int temp;
if ((temp = set_onoff(2)) != ERROR)
{
debug = temp;
if (dbgfil != ERROR) /* Close file */
fclose(dbgfil);
dbgfil = ERROR;
}
else if (tolower(*params[2]) == 'l') /* Open debug log file */
{
if (numprm < 4)
prterr("Filespec required");
else
if (dbgfil != ERROR)
prterr("Debug log file already open");
else
{
strcpy(dbgfname,params[3]);
cvt_case(params[3]);
if ((dbgfil = fopen(params[3],"w")) == ERROR)
prterr("Error opening debug log file %s, error number is %d",
params[3], errno);
else
debug = 2;
}
}
else
synerr(0);
}
set_escape()
{
escchr = *params[2]; /* Get escape character */
}
set_line()
{
if (tolower(*params[2]) == 'r')
{
cleanup(); /* Reset port */
ttyfd = REMOTE; /* Remote connection */
remote = TRUE;
}
else
{
sscanf(params[2],"%x",&ttyfd); /* Get hex address */
if (initport(ttyfd,0) == FALSE) /* Try to init the port */
prterr("No such line available");
else
remote = FALSE;
}
}
set_baud()
{
int temp,
speed_value,
found,
*p;
extern int v_speed_6850[];
#ifdef VIDIS
extern int v_speed_6551[];
#endif
#ifdef VIDIS
if (use_6850)
p = v_speed_6850;
else
p = v_speed_6551;
#else
p = v_speed_6850;
#endif
temp = atoi(params[2]); /* Get speed value */
found = FALSE;
while (*p) /* Do until end of table */
{
if (temp == *p++)
{ /* Match! */
speed_value = *p;
found = TRUE;
break;
}
p++; /* Skip speed value */
}
if (found)
{
speed = temp; /* Set new speed value */
initport(ttyfd,0); /* Init the port */
}
else
prterr("Invalid speed");
}
set_config()
{
int temp;
temp = atoi(params[2]); /* Get configuration */
if ((temp < 0) || (temp > 7)) /* Check range */
prterr("Improper value");
else
{
config = temp; /* Set new value */
initport(ttyfd,0); /* Init the port */
}
}
set_timeout()
{
int temp;
temp = atoi(params[2]); /* Get timeout value */
if ((temp <= 0) || (temp > 100)) /* Check range */
prterr("Improper value");
else
mytime = temp; /* Set new value */
}
set_prompt()
{
if (strlen(params[2]) > 20)
params[2][20] = '\0'; /* Truncate string */
strcpy(prompt, params[2]); /* Setup new prompt */
}
set_filetype()
{
char temp;
temp = tolower(*params[2]);
if (temp == 'a') /* ASCII */
image = FALSE;
else if (temp == 'b') /* BINARY */
image = TRUE;
else
synerr(0);
}
set_log()
{
if ((params[2][0] == '-') && logfileopen)
{ /* Close file */
if (fclose(lfp) == ERROR)
prterr("Error closing log file %s", logfile);
logfile[0] = '\0'; /* Zap filename */
logfileopen = logging = FALSE;
}
else
{
if (logfileopen)
prterr("Log file already open");
else
{
if (strlen(params[2]) > 20)
params[2][20] = '\0'; /* Truncate string */
strcpy(logfile,params[2]);
cvt_case(logfile); /* Take care of case mapping */
if ((lfp = fopen(logfile, "w")) == ERROR)
{
prterr("Error opening log file %s", logfile);
logfile[0] = '\0'; /* Zap filename */
logfileopen = logging = FALSE;
}
else
logfileopen = TRUE;
}
}
}
set_dup()
{
char ch;
ch = tolower(*params[2]);
if (ch == 'f')
fulldup = TRUE;
else if (ch == 'h')
fulldup = FALSE;
else
synerr(0);
}
set_hsh()
{
char start_tmp, stop_tmp;
if (!synerr(4)) /* Be sure there are enough parameters */
{
start_tmp = atoi(params[2]); /* Set data start character */
stop_tmp = atoi(params[3]); /* Set data stop character */
if ((start_tmp < 0) || (start_tmp > 127)
|| (stop_tmp < 0) || (stop_tmp > 127))
prterr("Illegal value");
else
dstart = start_tmp;
dstop = stop_tmp;
}
}
set_quote()
{
char c;
if (check_quote(c = *params[2]))
{
if ((c != myeightquote) && (c != myrptquote))
myquote = c;
else
prterr("Character already in use");
}
}
set_eight_bit_quote()
{
char c;
if (toupper(c = *params[2]) == 'N')
myeightquote = 0; /* No eight bit quoting done */
else if (check_quote(c))
{
if ((c != myquote) && (c != myrptquote))
myeightquote = c;
else
prterr("Character already in use");
}
}
set_repeat_quote()
{
char c;
if (toupper(c = *params[2]) == 'N')
myrptquote = 0; /* No repeat quoting done */
else if (check_quote(c))
{
if ((c != myquote) && (c != myeightquote))
myrptquote = c;
else
prterr("Character already in use");
}
}
set_packet_length()
{
char size;
size = atoi(params[2]);
if ((size < 10) || (size > 94))
prterr("Invalid length");
else
maxpacksiz = size;
}
set_padding()
{
int ptmp;
ptmp = atoi(params[2]);
if (ptmp > 94)
prterr("Value out of range");
else
mypad = ptmp;
}
set_padchar()
{
int ptmp;
sscanf(params[2], "%x", &ptmp);
mypchar = ptmp;
}
set_retry()
{
maxtry = atoi(params[2]);
}
set_end_of_line()
{
int etmp;
sscanf(params[2], "%x", &etmp);
if (etmp == mypackstart)
prterr("End of line must be different of start of packet");
else
myeol = etmp;
}
set_start_of_packet()
{
int ptmp;
sscanf(params[2], "%x", &ptmp);
if (ptmp == myeol)
prterr("Start of packet must be different of end of line");
else
mypackstart = ptmp;
}
set_block_check_type()
{
char c;
c = atoi(params[2]);
if ((c >= 1) && (c <= 3))
myblock_check_type = c;
else
prterr("Invalid check type");
}
set_incomplete()
{
char c;
c = toupper(*params[2]);
if (c == 'K')
save_file = TRUE; /* Keep file */
else if (c == 'D')
save_file = FALSE; /* Discard file */
else
synerr(0);
}
set_delay()
{
send_delay = atoi(params[2]);
}
set_warning()
{
int temp;
temp = set_onoff(2);
if (temp != ERROR)
warning = temp;
else
synerr(0);
}
check_quote(qchar)
char qchar;
{
if (((qchar >= '!') && (qchar <= '>')) ||
((qchar >= '{') && (qchar <= '~')) ||
(qchar == '`'))
return (TRUE); /* Valid character */
else
{
prterr("Invalid character");
return (FALSE); /* Invalid character */
}
}
set_onoff(i)
int i;
{
make_lower(params[i]);
if (strcmp(params[i], "on") == 0)
return TRUE;
else
if ((strcmp(params[i], "of") == 0) ||
(strcmp(params[i], "off") == 0))
return FALSE;
else return ERROR;
}
<<< flshow.c >>>
#include "FLK.H"
TABLE show_table[] =
{
"all", 1,
"debug", 2,
"escape", 3,
"line", 4,
"baud", 5,
"configuration", 6,
"timeout", 7,
"filetype", 8,
"log", 9,
"duplex", 10,
"handshake", 11,
"block_check_type", 12,
"repeat_quote", 13,
"retry", 14,
"packet_length", 15,
"padding", 16,
"padchar", 17,
"start_of_packet", 18,
"end_of_line", 19,
"quote", 20,
"eight_bit_quote", 21,
"incomplete", 22,
"delay", 23,
"warning", 24,
"", 0
};
show()
{
int fpoint;
fpoint = parse(params[1], show_table); /* Parse 'show' command */
if (fpoint == NULL) /* Ambiguous */
prterr("Ambiguous 'show' command");
else if (fpoint == ERROR) /* Unknown */
prterr("Unknown 'show' command");
else /* Dispatch to command if no error */
switch(fpoint)
{
case 1:
show_all();
break;
case 2:
show_debug();
break;
case 3:
show_escape();
break;
case 4:
show_line();
break;
case 5:
show_baud();
break;
case 6:
show_config();
break;
case 7:
show_timeout();
break;
case 8:
show_filetype();
break;
case 9:
show_log();
break;
case 10:
show_dup();
break;
case 11:
show_hsh();
break;
case 12:
show_block_check_type();
break;
case 13:
show_repeat_quote();
break;
case 14:
show_retry();
break;
case 15:
show_packet_length();
break;
case 16:
show_padding();
break;
case 17:
show_padchar();
break;
case 18:
show_start_of_packet();
break;
case 19:
show_end_of_line();
break;
case 20:
show_quote();
break;
case 21:
show_eight_bit_quote();
break;
case 22:
show_incomplete();
break;
case 23:
show_delay();
break;
case 24:
show_warning();
}
}
/*
* Show various parameters
*/
show_all()
{
show_line();
show_baud();
show_config();
show_escape();
show_filetype();
show_warning();
show_log();
show_dup();
show_debug();
show_incomplete();
show_hsh();
show_retry();
show_timeout();
show_delay();
show_start_of_packet();
show_end_of_line();
show_quote();
show_eight_bit_quote();
show_repeat_quote();
show_packet_length();
show_padding();
show_padchar();
show_block_check_type();
}
show_debug()
{
puts("Debug:\t\t\t\t");
if (debug != 2)
show_onoff(debug);
else
printf("File: %s\n",dbgfname);
}
show_dup()
{
puts("Duplex:\t\t\t\t");
if (fulldup)
puts("Full\n");
else
puts("Half\n");
}
show_escape()
{
printf("Escape character:\t\t%c\n", escchr);
}
show_line()
{
puts("Line:\t\t\t\t");
if (remote)
puts("Remote\n");
else
printf("%x\n", ttyfd);
}
show_baud()
{
printf("Baudrate:\t\t\t%d baud\n", speed);
}
show_config()
{
static int *conftab[] =
{
"7 bits, even parity, 2 stop bits",
"7 bits, odd parity, 2 stop bits",
"7 bits, even parity, 1 stop bit",
"7 bits, odd parity, 1 stop bit",
"8 bits, no parity, 2 stop bits",
"8 bits, no parity, 1 stop bit",
"8 bits, even parity, 1 stop bit",
"8 bits, odd parity, 1 stop bit"
};
printf("Configuration:\t\t\t%s\n", conftab[config]);
}
show_timeout()
{
printf("Timeout:\t\t\t%d seconds\n", mytime);
}
show_filetype()
{
puts("Filetype:\t\t\t", image);
if (image)
puts("Binary\n");
else
puts("Ascii\n");
}
show_log()
{
puts("Log file:\t\t\t");
if (logfile[0])
printf("%s\n", logfile);
else
puts("None\n");
}
show_hsh()
{
printf("Handshake start:\t\t%d (dec)\n", dstart);
printf("Handshake stop: \t\t%d (dec)\n", dstop);
}
show_quote()
{
printf("Quote character:\t\t%c\n", myquote);
}
show_repeat_quote()
{
puts("Repeat quote character:\t\t");
if (myrptquote == 0)
puts("None\n");
else
printf("%c\n",myrptquote);
}
show_eight_bit_quote()
{
puts("Eight-bit quote character:\t");
if (myeightquote == 0)
puts("None\n");
else
printf("%c\n",myeightquote);
}
show_start_of_packet()
{
printf("Start of packet:\t\t%02.2x (hex)\n", mypackstart);
}
show_retry()
{
printf("Maximum retry's:\t\t%d (dec)\n", maxtry);
}
show_packet_length()
{
printf("Packet length:\t\t\t%d (dec)\n", maxpacksiz);
}
show_end_of_line()
{
printf("End of line character:\t\t%02.2x (hex)\n", myeol);
}
show_padding()
{
printf("Padding count:\t\t\t%d (dec)\n", mypad);
}
show_padchar()
{
printf("Padding character:\t\t%02.2x (hex)\n", mypchar);
}
show_block_check_type()
{
puts("Blockcheck type:\t\t");
switch (myblock_check_type)
{
case 1:
puts("One character checksum\n");
break;
case 2:
puts("Two character checksum\n");
break;
case 3:
puts("Three character CRC-CCITT\n");
break;
}
}
show_incomplete()
{
puts("Incomplete file disposition:\t");
if (save_file)
puts("Keep\n");
else
puts("Discard\n");
}
show_delay()
{
printf("Delay before sending:\t\t%d seconds\n",send_delay);
}
show_warning()
{
puts("File conflict warning:\t\t");
show_onoff(warning);
}
show_onoff(flag)
int flag;
{
if (flag)
puts("On\n");
else
puts("Off\n");
}
<<< flutil.c >>>
#include "FLK.H"
/*
* split command line into seperate strings
*/
split(cmd_str, cmds)
char *cmd_str[],
*cmds[];
{
char *malloc();
char *p,
*q,
result[128];
numprm = 0; /* no parameters yet */
p = cmd_str; /* setup pointer to input string */
while (*p) /* do till end of string */
{
if (numprm == MAXPRM) /* no more space */
{
prterr("Too many command parameters");
return(FALSE);
}
while (isspace(*p)) /* strip leading white space */
p++;
sscanf(p, "%s", result); /* get part of input string */
if ((q = malloc(strlen(result) + 1)) == NULL) /* allocate string space */
{
prterr("Fatal error allocating memory");
kerm_exit();
}
strcpy(q, result); /* copy part to allocated memory */
cmds[numprm++] = q; /* save pointer to string */
while ((!isspace(*p)) && *p) /* skip to end of this string */
p++;
}
return (TRUE);
}
/*
* parse command components
*/
parse(command_string, table)
char *command_string;
TABLE table[];
{
char i = 0,
j;
int mstat,
cmd_num = 0,
tv = 0,
unique = FALSE;
make_lower(command_string); /* convert to lower case */
while (*table[i].string) /* do until end of command table */
{
mstat = match(table[i].string, command_string); /* do compare */
if (mstat == -1)
return (table[i].funcadr); /* exact match found */
if (mstat != 0) /* some characters did match */
{
if (mstat > tv) /* longer than so far ? */
{
tv = mstat; /* save longest length */
cmd_num = i; /* remember which command */
unique = TRUE; /* it's unique so far */
}
j = i;
while (*table[++j].string) /* start new search from next entry */
{
mstat = match(table[j].string, command_string); /* other match ? */
if (mstat == -1)
return (table[j].funcadr); /* exact match */
if (mstat != 0) /* some characters did match */
{
if (mstat > tv) /* longer than so far ? */
{
tv = mstat; /* save greatest length */
cmd_num = i; /* remember which command */
unique = TRUE; /* it's unique so far */
}
if (mstat == tv) /* another one of the same length ? */
unique = FALSE; /* yes, it's not unique anymore */
}
}
if (!unique) /* if it was'nt unique it's ambiguous */
return (NULL);
else
return (table[cmd_num].funcadr); /* else it's a valid command */
}
i++; /* try next entry */
}
if (cmd_num == 0)
return (ERROR); /* no such command */
else return (table[cmd_num].funcadr); /* return command number */
}
match(s, t)
char *s, *t;
{
int len = 0,
inputlen;
inputlen = strlen(t); /* length of input command */
while (*s) /* do until end of string */
{
if (*s++ != *t++) /* if no match */
{
if (inputlen == 0) /* total command checked */
return (len); /* return matched length */
else
return (0); /* no match for this command */
}
len++; /* one more character done */
--inputlen; /* count down input string length */
}
return (-1); /* full match found */
}
/*
* m a k e _ u p p e r
*
* Convert string to upper case
*/
make_upper(p)
char *p;
{
while (*p)
*p++ = toupper(*p);
}
/*
* m a k e _ l o w e r
*
* Convert string to lower case
*/
make_lower(p)
char *p;
{
while (*p)
*p++ = tolower(*p);
}
prterr(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
printf(fmt,a1,a2,a3,a4,a5);
printf("\n");
beep();
}
/*
* e r r o r
*
* Print error message.
*
* send an error packet with the message.
*/
error(number,fmt, a1, a2, a3, a4, a5)
int number;
char *fmt;
{
char msg1[80], msg2[80];
char len;
static char *errmsg[] =
{
"Aborted by user",
"Unimplemented server command",
"Packet error",
"FLEX error writing data, error number is ",
"Cannot create file ",
"Cannot open file "
};
strcpy(msg1,prompt); /* Start with prompt */
strcat(msg1,": ");
strcat(msg1,errmsg[number]); /* Append error string */
if (number > 2)
{
sprintf(msg2,fmt,a1,a2,a3,a4,a5); /* Make it a string */
strcat(msg1,msg2); /* Form one string */
}
len = strlen(msg1);
spack('E',n,len,msg1,block_check_type); /* Send the error packet */
#ifdef SCREEN
disp(0,18,CLREOL);
disp(0,18,"Error:");
disp(20,18,msg1);
#else
printf("Error: %s\n",msg1);
#endif
beep();
}
/*
* p r e r r p k t
*
* Print contents of error packet received from remote host.
*/
prerrpkt(msg)
char *msg;
{
disp(0,18,"Kermit aborting with following error from remote host:");
disp(0,19,msg);
beep();
}
/*
* send ASCII file to remote without protocol.
* handshake is used.
*/
transmit()
{
FILE *xmitfp;
char xmitfilename[20];
int c;
if (numprm <= 1) /* check for parameters */
prterr("Filespec required");
else
{
strcpy(xmitfilename, params[1]);
cvt_case(xmitfilename); /* take care of filename mapping */
if ((xmitfp = fopen(xmitfilename, "r")) == ERROR)
prterr("Error opening %s", xmitfilename);
else
{
while ((c = getc(xmitfp)) != EOF)/* get character from file */
{
if (debug)
{
outchar(c, consfd); /* send to console as well */
if (c == LF)
outchar(CR, consfd);
}
if (instat(ttyfd)) /* Check if character received */
if (inchar(ttyfd) == dstop) /* Stop character ? */
do /* Yes */
while (!instat(ttyfd)) /* Wait for next character */
if (aborted) /* Check user abort */
{
puts("\n");
return; /* User abort */
}
while (inchar(ttyfd) != dstart); /* Wait for start char */
if (aborted) /* Check user abort */
{
puts("\n");
return; /* User abort */
}
if (c == LF) /* Convert LF to CR */
c = CR;
outchar(c, ttyfd); /* Send to output port */
}
fclose(xmitfp);
}
}
}
/*
* Read KERMIT commands from file
*/
take(startup,echo)
char startup, echo;
{
FILE *tfp;
char data[257], /* Command input */
fname[50];
if (startup)
strcpy(fname, INITFILE); /* Use default name at startup */
else
{
if (numprm <= 1) /* Filename must be given */
{
prterr("Filespec required");
return;
}
else
strcpy(fname, params[1]);
}
cvt_case(fname); /* Take care of filename mapping */
if ((tfp = fopen(fname,"r")) != ERROR) /* Look for command file */
{ /* Found file, read commands */
while (fgets(data,256,tfp))
{
if (echo)
{
puts(prompt); /* Echo prompt */
puts(data); /* Echo command */
}
if (data[0] != '\n') /* Not a blank line */
kerm_command(data); /* Do command */
}
fclose(tfp);
}
else
if (!startup)
prterr("Error opening %s as input",fname);
}
/*
* call FLEX to perform external command
*/
do_flex()
{
char *cp1, *cp2;
int i;
if (numprm <= 1) /* no command given */
{
printf("Enter FLEX command: ");
call(inbuff); /* use FLEX */
}
else
{
cp1 = *flinepointer = flinebuffer;
for(i = 1; i < numprm; i++)
{ /* copy command parameters to
FLEX command buffer */
cp2 = params[i];
while (*cp2) /* copy string */
*cp1++ = *cp2++;
*cp1++ = ' '; /* parameter seperator */
}
*--cp1 = '\r'; /* required by flex */
}
call(docmd); /* call FLEX */
puts("\n");
}
/*
* show statistics about connection
*/
statistics()
{
static char s1[] = "Characters sent:\t\t%ld\n";
static char s2[] = "Data characters sent:\t\t%ld\n";
static char s3[] = "NAK's sent:\t\t\t%d\n";
static char s4[] = "Packets sent:\t\t\t%d\n";
static char s5[] = "Characters received:\t\t%ld\n";
static char s6[] = "Data characters received:\t%ld\n";
static char s7[] = "NAK's received:\t\t\t%d\n";
static char s8[] = "Packets received:\t\t%d\n";
printf("Totals for the last transfer:\n\n");
printf(s1, chr_sent);
printf(s2, datachr_sent);
printf(s3, nak_sent);
printf(s4, pack_sent);
printf(s5, chr_rec);
printf(s6, datachr_rec);
printf(s7, nak_rec);
printf(s8, pack_rec);
#ifdef CLOCK
printf("Effective data rate:\t\t%d baud\n", data_rate);
#endif
printf("\nTotals since KERMIT was started:\n\n");
printf(s1, t_chr_sent);
printf(s2, t_datachr_sent);
printf(s3, t_nak_sent);
printf(s4, t_pack_sent);
printf(s5, t_chr_rec);
printf(s6, t_datachr_rec);
printf(s7, t_nak_rec);
printf(s8, t_pack_rec);
#ifdef CLOCK
printf("Mean effective data rate:\t%d baud\n", t_data_rate);
#endif
}
#define POLYIT 0x8408 /* Polynomial for CRC-CCITT */
#define POLY16 0xa001 /* Polynomial for CRC-16 (not used here) */
int crc_value, crc[256]; /* Global accessible variables */
init_crc_table()
{
int count, nr;
unsigned int accum, crcch;
for (count = 0; count < 256; count++) /* Build CRC lookup table */
{
accum = 0;
crcch = count;
for (nr = 0; nr < 8; nr++)
{
if (((accum & 0xff) ^ crcch) & 1)
accum = (accum / 2) ^ POLYIT;
else
accum = (accum / 2);
crcch = (crcch / 2);
}
crc[count] = accum; /* Save calculated value in table */
}
}
init_crc()
{
crc_value = 0; /* Initial value is zero */
}
calc_crc(value)
char value;
{
crc_value = crc[value ^ (crc_value & 0xff)] ^ ((crc_value >> 8) & 0xff);
return crc_value; /* Return accumulated value so far */
}
/*
* Convert string case if mapping is off
*/
cvt_case(p)
char *p;
{
if (mapup == 0x60) /* refer to flag in FLEX memory */
make_upper(p);
}
beep()
{
if (!remote)
_putchr(BELL);
}
disp(x,y,string)
int x,y;
char *string;
{
if (!remote)
{
posit(x,y);
#ifndef SCREEN
puts("\n");
#endif
puts(string);
}
}
posit(x,y)
int x,y;
{
#ifdef SCREEN
if (!remote)
{
_putchr(ESC);
_putchr(POSCUR);
_putchr(y + CHROFS);
_putchr(x + CHROFS);
}
#endif
}
set_frame()
{
#ifdef SCREEN
if (!remote)
{
puts(CLRSCR); /* Clear screen */
puts(CURSOFF); /* Disable cursor */
puts(INVBEG); /* Start inverse screen */
puts(" KERMIT version ");
puts(VERSION);
puts(" ");
puts(INVEND); /* End inverse screen */
if (sflg || rflg)
{
disp(0,4,"Transferred:");
if (image && sflg)
disp(27,4,"Percentage:");
}
disp(0,6,"Packet received:");
disp(0,7,"Packet transmitted:");
if (debug >= 1)
{
disp(0,9,"Data received:");
disp(0,11,"Data transmitted:");
disp(0,13,"Receive state:");
disp(0,14,"Send state:");
disp(27,6,"Type:");
disp(27,7,"Type:");
disp(37,6,"Length:");
disp(37,7,"Length:");
disp(49,6,"Checksum:");
disp(49,7,"Checksum:");
}
}
#endif
}
disp_state(x,y,state)
int x,y;
char state;
{
static char sa[] = "Abort ";
static char sb[] = "Break ";
static char sc[] = "Complete ";
static char sd[] = "Data ";
static char sf[] = "Filename ";
static char sr[] = "Receive init";
static char ss[] = "Send init ";
static char st[] = "Timeout ";
static char sz[] = "End of file ";
static char un[] = "Unknown ";
static char dsc[] = "%s\n";
posit(x,y);
switch(state)
{
case 'A':
prtdbg(dsc,sa);
break;
case 'B':
prtdbg(dsc,sb);
break;
case 'C':
prtdbg(dsc,sc);
break;
case 'D':
prtdbg(dsc,sd);
break;
case 'F':
prtdbg(dsc,sf);
break;
case 'R':
prtdbg(dsc,sr);
break;
case 'S':
prtdbg(dsc,ss);
break;
case 'T':
prtdbg(dsc,st);
break;
case 'Z':
prtdbg(dsc,sz);
break;
default:
prtdbg(dsc,un);
}
}
prtdbg(fmt, a1, a2, a3, a4, a5, a6)
char *fmt;
{
if ((debug >= 1) && !remote)
printf(fmt,a1,a2,a3,a4,a5,a6);
if (debug == 2)
fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
}
prtdbgf(fmt, a1, a2, a3, a4, a5, a6)
char *fmt;
{
if (debug == 2)
fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
}
new_name(s)
char *s;
{
s += strlen(s) - 1; /* Point to last character */
if (isdigit(*s))
{ /* Already a digit */
if (*s == '9') /* Test for wrap */
*s = '0';
else
(*s)++; /* Form new number */
}
else /* It was no digit, make one */
if (*--s == '.') /* Only one char in extension */
{
s++;
*++s = '0'; /* Append zero */
*++s = '\0'; /* Mark end of string */
}
else
*++s = '0'; /* More than one chr in extension */
}
synerr(threshold)
int threshold;
{
if ((threshold != 0) && (numprm >= threshold))
return FALSE;
prterr("Syntax error");
return TRUE;
}
<<<flk.h >>>
/*
* KERMIT09 - flex version header file
*/
#include "stdio.h"
#define VERSION "V 3.1"
#define IDENT "KERMIT FLEX 6809 version "
#define DEFPROMPT "Kermit-09>"
#define INITFILE "KERMIT.INI"
#define HELPFILE "KERMIT.HLP"
/*
* The VIDIS system normally only has a 6551 type acia available,
* and optionally an 6850 acia.
* At startup the program looks for an 6850 at address ADDRESS_6850.
* If it's there, that one will be used initially. If not,
* the 6551 acia at address ADDRESS_6551 will be used.
* When issueing an SET LINE command, the program automatically
* determines the acia type (6850 or 6551).
* The speed setting depends on the acia. In case of a 6551, all
* the values of the 6551 can be used. In case of a 6850, 1200 baud
* will be selected by a clock divider of 16, and 300 baud by
* a divider of 64.
*/
#ifdef VIDIS
#define CLOCK /* Real time clock available (MC 146818) */
#endif
/*
* The clock will be used for determination of the effective data rate
*/
#ifdef VIDIS
#define CLOCKSPEED 1.33333333 /* Clock speed in MHz */
#else
#define CLOCKSPEED 1 /* Clock speed in MHz */
#endif
#define DELAYVALUE (4300 * CLOCKSPEED) /* Count for 1 second delay */
/* Symbol Definitions */
#define SOH 1 /* Start of header */
#define BELL 7 /* ASCII Bell */
#define BS 8 /* ASCII Backspace */
#define TAB 9 /* ASCII Tab */
#define LF 10 /* ASCII Linefeed */
#define CR 13 /* ASCII Carriage Return */
#define ESC 27 /* ASCII Escape */
#define SP 32 /* ASCII space */
#define DEL 127 /* Delete (rubout) */
#define XON 17 /* Start output */
#define XOFF 19 /* Stop output */
#define ESCCHR '^' /* Default escape char for CONNECT */
#define TOGDBG 'D' - 64 /* Toggle debug on/off */
#define ABORTX 'X' - 64 /* Ctrl-X to abort transfer */
#define ABORTZ 'Z' - 64 /* Ctrl-Z to abort transfer */
#define TABSIZE 8 /* Tabstop every eight places */
#define I_MYPACKSTART SOH /* Start of packet character */
#define I_MAXPACKSIZ 94 /* Maximum packet size */
#define I_MYPACKSIZE 80 /* Default value if no 'S' packet */
#define I_MAXTRY 10 /* Times to retry a packet */
#define I_MYQUOTE '#' /* Quote character I will use */
#define I_MYPAD 0 /* Number of padding char's I need */
#define I_MYPCHAR 0 /* Padding character I need (NULL) */
#define I_MYEOL '\r' /* End-Of-Line character I need */
#define I_MYTIME 5 /* My timeout in seconds */
#define I_MYRPTQUOTE '~' /* Repeat quote character */
#define I_MYEIGHTQUOTE '&' /* Eight_bit quote character */
#define I_BLOCKCHECKTYPE 1 /* Initial checksum type */
#define I_SEND_DELAY 5 /* Delay time before sending */
#define MAXPRM 20 /* Max. number of command line parameters */
#define LOGBUFSIZE 5000 /* Size of log buffer */
#define WAITVAL 800 * CLOCKSPEED /* Wait counter in connect */
#define TIMEOUT 1 /* Internal codes */
#define REMOTE -1
#ifdef VIDIS
#define CONSOLE 0 /* Dummy for console */
#define ADDRESS_6850 0xec24 /* Default modem acia address */
#define ADDRESS_6551 0xec00 /* VIDIS modem acia address */
#define INIT_6850 0x15 /* Port init 8 bits 1 stop clk/16 */
#define RESET_6850 0x03
#define RESET_6551 0x00
#define INITCMND_6551 0x0b /* Init for command register of 6551 acia */
#define INITCTRL_6551 0x10 /* Init for control register */
#define IRQVEC_6850 0xe810
#define IRQVEC_6551 0xe816
#define NMIVEC 0xe80c
#else
#define CONSOLE 0xe004 /* Console acia address */
#define TTYPORT 0xe000 /* Modem acia address */
#define INIT_6850 0x15 /* Port init 8 bits 1 stop clk/16 */
#define RESET_6850 0x03
#define IRQVEC_6850 0xdfc8
#define NMIVEC 0xdfca
#endif
#ifdef SCREEN
#define POSCUR 'A' /* Cursor positioning character */
#define CHROFS 1 /* Character offset */
#define CLRSCR "\033D\f" /* Clear screen string */
#define INVBEG "\033U\033K" /* Start underline */
#define INVEND "\033U\033K" /* End underline */
#define CLREOL "\025" /* Clear till end of line */
#define CURSOFF "\033B" /* Cursor off */
#define CURSON "\033C" /* Cursor on */
#else
#define CURSON "" /* Dummy's if no screen */
#define CURSOFF ""
#define CLREOL ""
#endif
/* Macro Definitions */
/*
* tochar: converts a control character to a printable one by adding a space.
*
* unchar: undoes tochar.
*
* ctl: converts between control characters and printable characters by
* toggling the control bit (ie. ^A becomes A and A becomes ^A).
*/
#define tochar(ch) ((ch) + ' ')
#define unchar(ch) ((ch) - ' ')
#define ctl(ch) ((ch) ^ 64 )
#define callind(p1) (*(char (*)())*((int *)(&p1)))()
#define call(p1) (*(char (*)())p1)()
#define dmem(adr) ((int *)(adr))
#define mem(adr) ((char *)(adr))
/*
* FLEX constants
*/
#define mapup (*mem(0xcc49)) /* place to find filename mapping flag */
#define inchne(p1) ((*(int (*)())*((int *)(0xd3e5)))(p1) >> 8) /* input char
without echo */
#define workdrive (*mem(0xcc0c)) /* Work drive number */
#define system_fcb_drive (*mem(0xc843)) /* Drive KERMIT came from */
#define flinebuffer ((char *)0xc080) /* Line input buffer */
#define flinepointer ((unsigned *)0xcc14) /* Line buffer pointer */
#define inbuff 0xcd1b /* Get input buffer routine */
#define docmd 0xcd4b /* Call flex routine */
/* Global Variables */
/* Structure used by command parser */
typedef struct table_point
{
char *string; /* Command name */
int funcadr; /* Function address */
} TABLE;
#ifdef CLOCK
#define RTCADR 0xee20 /* Address of MC 146818 */
long int read_clock(),
start_time,
end_time;
#endif
int send_delay, /* Start sending delay time */
ttyfd, /* I/O port address */
consfd, /* Console port address */
wtcnt, /* stop time counter */
speed, /* line speed */
tabsleft, /* Tab counter */
file_size, /* Size of current file in blocks */
size, /* Size of present data */
nak_sent, /* nak's sent */
pack_sent, /* packets sent */
nak_rec, /* nak's received */
pack_rec, /* packets received */
data_rate, /* effective data rate */
t_nak_sent, /* total naks sent */
t_pack_sent, /* total packets sent */
t_nak_rec, /* total nak's received */
t_pack_rec, /* total packets received */
t_data_rate; /* total effective data rate */
long int chr_sent, /* characters sent */
datachr_sent, /* data characters sent */
chr_rec, /* characters received */
datachr_rec, /* data characters received */
t_chr_sent, /* total characters sent */
t_datachr_sent, /* total data characters sent */
t_chr_rec, /* total characters received */
t_datachr_rec, /* total data characters received */
timecount, /* Timeout counter */
transmit_chr_count; /* Character count for data size calculation */
char state, /* Present state of the automaton */
padchar, /* Padding character to send */
eol, /* End-Of-Line character to send */
escchr, /* Connect command escape character */
quote, /* Quote character in incoming data */
block_check_type, /* Checksum type */
eight_quote, /* eight_bit quote character */
repeat_quote, /* repeat quote character */
timint, /* Timeout for foreign host on sends */
spsiz, /* Maximum send packet size */
pad, /* How much padding to send */
n, /* Packet number */
numtry, /* Times this packet retried */
oldtry, /* Times previous packet retried */
image, /* TRUE means 8-bit mode */
warning, /* File conflict warning flag */
debug, /* indicates debugging output done (0=none) */
fulldup, /* TRUE means full duples in connect */
logfileopen, /* TRUE means log file open */
logging, /* TRUE means loggin active */
dstop, /* stop character for remote */
dstart, /* start character for remote */
stopped, /* TRUE if dstop sent */
filecount, /* Number of files left to send */
filenum, /* current filenumber */
config, /* initialize value */
numprm, /* number of command parameters */
aborted, /* TRUE means we're aborted */
save_file, /* keep/discard file on abort */
sflg, /* send active flag */
rflg, /* receive active flag */
cflg, /* connect active flag */
*filnam, /* Current file name */
use_6850, /* 6850 acia in use */
remote, /* Remote line in use */
*params[MAXPRM], /* parameter list */
prompt[21], /* prompt string */
logfile[21], /* filename for logfile */
recpkt[I_MAXPACKSIZ+5], /* Receive packet buffer */
packet[I_MAXPACKSIZ+5], /* Packet buffer */
logbuf[LOGBUFSIZE], /* buffer for log */
*plog, /* pointer for logbuffer */
dbgfname[50], /* Filename for debug file */
load_drive, /* Drive KERMIT came from */
mypackstart, /* Start of packet character */
maxpacksiz, /* Maximum packet size */
maxtry, /* Times to retry a packet */
myquote, /* Quote character I will use */
mypad, /* Number of padding characters I will need */
mypchar, /* Padding character I need (NULL) */
myeol, /* End-Of-Line character I need */
mytime, /* Seconds after which I should be timed out */
myrptquote, /* Repeat quote character */
myeightquote, /* Eight_bit quote character */
myblock_check_type; /* My checksum type */
FILE *fp, /* File pointer for current disk file */
*lfp, /* File pointer for log file */
*dbgfil; /* File pointer for debug file output */
#ifdef INTERRUPT
#define INBUFSIZE 500
#define FULL_LIMIT (INBUFSIZE - 250)
#define EMPTY_LIMIT 10
int irqhdr(),
irqprp(),
nmihdr(),
save_vector,
save_nmi;
char input_buffer[INBUFSIZE],
*inptr,
*outptr;
#endif