home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
atarist.zip
/
astutl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-06-19
|
15KB
|
542 lines
/*
* astutl.c Packet handling and misc. routines for ATARI ST kermit
*/
#include <osbind.h>
#include <stdio.h>
#include "astinc.h"
#include "astobj.h"
extern *msg_string();
/*
* KERMIT utilities.
*/
/*
* s p a c k
*
* Send a Packet
*/
spack(type,num,len,data)
char type, *data;
int num, len;
{
int i; /* Character loop counter */
char chksum, buffer[100]; /* Checksum, packet buffer */
register char *bufp; /* Buffer pointer */
if (ibmmode)
wait_handshake(); /* if ibm mode wait for handshake */
if(type != 'Y' && type != 'N')
flushinput(); /* dump any leftovers */
len=len & 0x7f; /* Make sure len is not > 127 */
if (len > MAXPACKSIZ ) /* Make sure not larger than buffer */
len = MAXPACKSIZ-4; /* IF so limit it */
msgdeb(MSGTLNPS,type,len,num);
/* Display outgoing packet */
if (data != NIL)
data[len] = '\0'; /* Null-terminate data to print it */
if (data != NIL)
msgdeb(MSGDATPS,data);
bufp = buffer; /* Set up buffer pointer */
if (padding) /* Do padding */
for (i=1; i<=spad; i++)
Cauxout(spadc);
if (debug && (debug > 1)) msgdeb(MSGCHPAD,spad,spadc);
*bufp++ = spcks; /* Packet marker, usally SOH */
*bufp++ = tochar(len+3); /* Send the character count */
chksum = tochar(len+3); /* Initialize the checksum */
*bufp++ = tochar(num); /* Packet number */
chksum += tochar(num); /* Update checksum */
*bufp++ = type; /* Packet type */
chksum += type; /* Update checksum */
for (i=0; i<len; i++) /* Loop for all data characters */
{
*bufp++ = data[i]; /* Get a character */
chksum += data[i]; /* Update checksum */
}
chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum */
*bufp++ = tochar(chksum); /* Put it in the packet */
*bufp++ = seol; /* Extra-packet line terminator */
*bufp = '\0';
auxsend(buffer); /* Send the packet */
return(TRUE);
}
/*
* r p a c k
*
* Read a Packet
*/
char rpack(len,num,data)
int *len, *num; /* Packet length, number */
char *data; /* Packet data */
{
int i,j, eolwc, done; /* Data character number, loop exit */
int read_abort; /* 0 = timeout, 'A' = abort requested */
int abort; /* restart current packet */
char t, /* Current input character */
type, /* Packet type */
cchksum, /* Our (computed) checksum */
rchksum; /* Checksum received from other host */
start_timer(&startpckt);
if (testat(&read_abort)) return(read_abort);
do {
if (readtimed(&t,&read_abort)) return(read_abort);
}
while ((t&127) != rpcks); /* Wait for packet header */
done = FALSE; /* Got SOH, init loop */
while (!done) /* Loop to get a packet */
{
if(readtimed(&t,&read_abort))
return(read_abort); /* read character, or timeout */
/* if (!image) I guess, that's nonsense! */
t &= 0177; /* Handle parity */
if (t == rpcks) continue; /* Resynchronize if SOH */
cchksum = t; /* Start the checksum */
*len = unchar(t)-3; /* Character count */
if(readtimed(&t, &read_abort))
return(read_abort); /* read character, or timeout */
/* if (!image) nonsense ? */
t &= 0177; /* Handle parity */
if (t == rpcks) continue; /* Resynchronize if SOH */
cchksum = cchksum + t; /* Update checksum */
*num = unchar(t); /* Packet number */
if(readtimed(&t, &read_abort))
return(read_abort); /* read character, or timeout */
/* if (!image) nonsense ? */
t &= 0177; /* Handle parity */
if (t == rpcks) continue; /* Resynchronize if SOH */
cchksum = cchksum + t; /* Update checksum */
type = t; /* Packet type */
abort=FALSE;
for (i=0; i<*len; i++) /* The data itself, if any */
{ /* Loop for character count */
if(readtimed(&t, &read_abort))
return(read_abort); /* read character, or timeout */
if (!image || ebq)
t &= 0177; /* Handle parity */
if (t == rpcks) { /* Resynch if SOH */
abort=TRUE;
break;
}
cchksum = cchksum + t; /* Update checksum */
data[i] = t; /* Put it in the data buffer */
}
if(abort)continue;
data[*len] = 0; /* Mark the end of the data */
if(readtimed(&t, &read_abort))
return(read_abort); /* read character, or timeout */
t &= 0177; /* do not use parity bit of checksum */
rchksum = unchar(t); /* Convert to numeric */
if (t == rpcks) continue; /* Resynchronize if SOH */
done = TRUE; /* Got checksum, done */
}
if (data != NIL)
data[*len] = '\0'; /* Null-terminate data to print it */
msgdeb(MSGTLNPR,type,*len,*num);
if (data != NIL)
msgdeb(MSGDATPR,data);
/* Fold in bits 7,8 to compute */
cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
if (cchksum != rchksum)
{
msgdeb(MSGCHKERR,rchksum,cchksum);
return(FALSE);
}
/* wait for eol to avoid lost packages */
for (eolwc=0; eolwc<100; eolwc++)
if (Cauxis())
break;
else
evnt_timer(1,0);
return(type); /* All OK, return packet type */
}
/*
* compute 'universal time'
*/
long univ_time(t)
int t;
{
long int res;
res = 60 * ((t >> 11) & 0x1FL);
res = 60 * (res + ((t >> 5) & 0x3FL));
res = res + ((t & 0x1FL) << 1);
return (res);
}
/*
* start timer
*/
start_timer(t0)
long int *t0;
{*t0 = univ_time(Tgettime());
}
/*
* compute difference to start time
*/
int timer(t0)
long int t0;
{long int t1;
t1 = univ_time(Tgettime());
if (t1 < t0)
return ((int) (t1+(24*60*69)-t0));
else
return ((int) max((t1 - t0),1));
}
/* readtimed: read a character or timeout
* timeout is relative to start of waiting for packet
*/
readtimed(c,flag)
char *c; /* character received */
int *flag; /* flag showing reason for abort: 0=timeout,'A'=user aborted */
{
while(!Cauxis())
{
*flag = sleepwait(50);
if (*flag == 'A') /* abort requested */
{
msgdeb(MSGUSRABO);
return(TRUE);
};
if (state == 'W')
start_timer(&startpckt); /* no timeout in server wait */
if ((*flag == 'T') ||
(stimint && dotimout && (timer(startpckt) >= stimint)))
{
msgdeb(MSGTIMOUT);
timcnt += 1;
*flag = 0;
return(TRUE);
};
};
*c = Cauxin();
if (debug && (deblevel > 1))
msgdeb(MSGCHRD,timer(startpckt),*c,(*c & 0x7F));
return(FALSE);
}
/*
* test for abort or timeout request
*/
int testat(flag)
int *flag;
{
*flag = sleepwait(0);
if (*flag == 'A') /* abort requested */
{
msgdeb(MSGUSRABO);
return(TRUE);
};
if (*flag == 'T')
{
msgdeb(MSGTIMOUT);
timcnt += 1;
*flag = FALSE;
return(TRUE);
};
return(FALSE);
}
/*
* b u f i l l
*
* Get a bufferful of data from the file that's being sent.
* Only control-quoting is done; 8-bit & repeat count prefixes are
* not handled. The last sentence is obsolete!
*/
bufill(buffer)
char buffer[]; /* Buffer */
{
int i, /* Loop index */
t; /* Char read from file */
char t7; /* 7-bit version of above */
char t9; /* dup of data char t */
char b8; /* 8th bit */
i = 0; /* Init data buffer pointer */
while(TRUE)
{
t = getc(fp); /* Get the next character */
bytecnt++;
if (feof(fp)) break;
t9=t; /* Keep original pattern */
t7 = t & 0177; /* Get low order 7 bits */
b8 = t & 0200; /* Get MSB */
if (ebq && b8 && image)
buffer[i++] = ebq;
if ((t7 < SP) || (t7==DEL) || (t7==squote)
|| ((t7 == ebq) && ebq))
/* Does this char require */
{ /* special handling? */
if (t=='\n' && !image)
{ /* Do LF->CRLF mapping if !image */
buffer[i++] = squote;
buffer[i++] = ctl('\r');
}
buffer[i++] = squote; /* Quote the character */
if ((t7 != squote) && ((t7 != ebq) || !ebq))
{
t = ctl(t); /* and uncontrolify */
t7 = ctl(t7);
};
};
if (image && !ebq)
buffer[i++] = t; /* Deposit the character itself */
else
buffer[i++] = t7;
if (i >= spsiz-8) return(i); /* Check length */
}
if (i==0) return(EOF); /* Wind up here only on EOF */
return(i); /* Handle partial buffer */
}
/*
* b u f e m p
*
* Put data from an incoming packet into a file.
*/
bufemp(buffer,len)
char buffer[]; /* Buffer */
int len; /* Length */
{
int i; /* Counter */
char t; /* Character holder */
int b8; /* 8th bit flag */
for (i=0; i<len; i++) /* Loop thru the data field */
{
b8 = FALSE;
t = buffer[i]; /* Get character */
if (ebq && image && (ebq == (t & 0177)))
{b8 = TRUE; t = buffer[++i];
};
if (t == rquote) /* Control quote? */
{
t = buffer[++i]; /* Get the quoted character */
if (((t & 0177) != rquote) &&
(((t & 0177) != ebq) || !ebq))
/* Low order bits match quote char? */
t = ctl(t); /* No, uncontrollify it */
};
if (b8) t |= 0200;
putc(t,fp);
bytecnt++;
};
}
/*
* s p a r
*
* Fill the data array with my send-init parameters
*
*/
spar(data)
char data[];
{
data[0] = tochar(rpsiz); /* Biggest packet I can receive */
data[1] = tochar(rtimint); /* 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(reol); /* End-Of-Line character I want */
data[5] = squote; /* Control-Quote character I send */
data[6] = (image ? MYEBQ : MYNOEBQ); /* 8 bit quoting */
}
/* r p a r
*
* Get the other host's send-init parameters
*
*/
rpar(data)
char data[];
{ if((data[0]) != 0)
spsiz = unchar(data[0]); /* Maximum send packet size */
if (data[1] != 0)
stimint = unchar(data[1]); /* When I should time out */
if (data[2] != 0)
padding = spad = unchar(data[2]); /* Number of pads to send */
else
padding = spad = 0;
spadc = ctl(data[3]); /* Padding character to send */
if ((data[4]) != 0)
seol = unchar(data[4]); /* EOL character I must send */
else
seol = MYEOL;
if (data[5] != 0)
rquote = data[5]; /* Incoming data quote character */
else
rquote = MYQUOTE;
if (!image || (data[6] == 0) || (data[6] == 'N') || (data[6] == 'Y'))
ebq = FALSE;
else
ebq = data[6];
}
/*
* f l u s h i n p u t
*
* Dump all pending input to clear stacked up NACK's.
*/
flushinput()
{char c;
/* TOS Clear AUX receive buffer */
while (Cauxis())
{c = Cauxin();
if (debug && (deblevel > 1))
msgdeb(MSGCHFLU,c,(c & 0x7F));
};
}
/*
* send one string to the aux port
*/
auxsend(str)
char *str;
{
while (*str != '\0')
{if (debug && (deblevel > 1)) msgdeb(MSGCHSND,*str,(*str & 0x7F));
Cauxout(*str++);
};
}
/*
* wait for handshake character
*/
wait_handshake()
/*
* wait for turnchar
* if received wait another 100 msecs and if no char received return.
* if no char received within 1000 msecs assume we missed turnchar
* otherwise return after a maximum of 4 secs
*/
{
int waitc; /* wait counter */
char c; /* last char read */
int nochrec; /* no char received */
long int starthw; /* start time for wait */
waitc = 0;
start_timer(&starthw);
while (TRUE)
{if (timer(starthw) >= 4) break;
if ((waitc >= 10) && !Cauxis()) break;
if (Cauxis())
{waitc = 0;
while (Cauxis())
{c = Cauxin() & 0x7F;
if (debug && (deblevel > 1)) msgdeb(MSGCHWHC,c,c);
};
};
evnt_timer(100,0);
if ((c == rturnchar) && !Cauxis())
{msgdeb(MSGHNDOK);
return(FALSE);
};
waitc++;
};
msgdeb(MEGHNDFA);
return(FALSE);
}
/*
* Kermit printing routines:
*
*/
/*
* Print message on DEBUG file
* First arg is object index of the KRMESSS object
*/
msgdeb(fmtix, a1, a2, a3, a4, a5)
int fmtix;
long a1,a2,a3,a4,a5;
{
if (debug)
{
fprintf(deb,msg_string(fmtix),a1,a2,a3,a4,a5);
putc('\n',deb);
};
}
/*
* Print message on LOG file
* if first arg >= 0 then display an alert box too
*/
msglog(alertix,fmtix,a1,a2,a3,a4,a5)
int fmtix, alertix;
long a1, a2, a3, a4, a5;
{
if (translog)
{
fprintf(log,msg_string(fmtix),a1,a2,a3,a4,a5);
putc('\n',log);
};
if (alertix >= 0)
displ_alert(1,alertix);
}
/*
* Print message on DEBUG and LOG file
* and perhaps display an alert box
*/
msgall(alertix,fmtix,a1,a2,a3,a4,a5)
int fmtix, alertix;
{
msgdeb(fmtix,a1,a2,a3,a4,a5);
msglog(alertix,fmtix,a1,a2,a3,a4,a5);
}
/*
* p r e r r p k t
*
* Print contents of error packet received from remote host.
*/
prerrpkt(msg)
char *msg;
{
msgall(-1,MSGERRPK,msg);
displ_pckerr(msg);
}