home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff330.lzh
/
Vt100
/
Src.lzh
/
Src
/
newkermit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-01
|
8KB
|
343 lines
/* :ts=8 */
/*
* These are the new interfaces between vt100 and the new Kermit protocol
* module.
*/
#include "vt100.h" /* Get defines and so on */
/*
* Here are the declarations for our communication with kermitproto.c
*/
extern int cx, cz; /* Abort flags */
extern char start; /* Start state for Kermit */
char *cmarg; /* Command argument for server */
/*
* The below variables have to do with the status of the communcation
* so far. They should be maintained over in kermitproto.w so that
* things like the number of bytes sent and the packet type can be
* printed as status.
*/
static int npackets, /* Number of packets sent so far */
naks; /* Number of naks */
static char message[80]; /* Message line to output */
/*
* Do Kermit sending. This expands wild cards into local variables for
* gnfile() below.
*/
static int nfiles, wild;
static char **lp, **list;
doksend(file,more)
char *file;
int more;
{
char *p;
list = NULL;
p = file;
while(*p && *p != '*' && *p != '?') p++;
if (*p) {
wild = 1;
list = expand(file, &nfiles);
if (list == NULL) {
InfoMsg1Line("KERMIT: No wild card match");
return FALSE;
}
}
else {
nfiles = 1;
wild = 0;
list = (char **) malloc(sizeof(char *));
*list = (char *) malloc(strlen(file) + 1);
strcpy(*list, file);
}
lp = list;
start = 's'; /* Set start state to send */
npackets = naks = 0;
message[0] = '\0';
proto(); /* Call protocol */
if (wild == 1)
free_expand(list);
else {
free((void *) *list);
free((void *) list);
}
return TRUE;
}
/*
* gnfile(s, n) char *s; int n;
*
* Returns in string s the name of the next file for Kermit to process,
* which can be up to n characters in length. Returns a positive value
* if there are more files, 0 if not.
*/
int
gnfile(s, n)
char *s;
int n;
{
if (--nfiles >= 0) {
strncpy(s, *lp, n);
lp++;
return 1;
} else
return 0;
}
/*
* Do Kermit receiving. The file and more arguments in this routine are
* for Get'ting files when the remote machine is the server.
*/
dokreceive(file,more)
char *file;
int more;
{
naks = npackets = 0;
message[0] = '\0'; /* Initialize */
if (!server)
start = 'v'; /* Start state to receive */
else {
cmarg = file; /* Files to get from remote */
start = 'r'; /* Start state to get */
}
proto();
return TRUE;
}
/* kermit_directory()--request a remote directory from a Kermit server.
*/
#define tochar(c) ((c) + 32)
void
kermit_directory(dir)
char *dir;
{
char command[80];
strcpy(command, "D"); /* Generic directory command */
command[1] = tochar(strlen(dir)); /* Length of directory name */
strcpy(&command[2], dir); /* The directory itself */
cmarg = command;
start = 'g'; /* Generic command start state */
naks = npackets = 0;
proto();
}
/*
* saybye()--send a FINISH command to a remote Kermit server. This is
* in fact what the original VT100 saybye() does. A true Kermit BYE
* command would mean changing the "F" below to "L", and it would actually
* log out the remote host as well as shut down the Kermit server.
*/
void
saybye()
{
static char bye_command[] = "F";
cmarg = &bye_command[0];
start = 'g'; /* Generic command start state */
naks = npackets = 0;
proto();
return /* TRUE */;
}
/*
* ttinl(dest, max, eol, timelimit)
*
* Read up to max characters from serial port into the array pointed
* to by dest. Return value is the number of characters received.
* If eol is greater than 0, terminate read upon first
* eol character received. If timelimit is greater than 0, wait at
* most timelimit seconds for the characters. The array is null
* terminated; in addition, if we do see an eol, we overwrite it
* with the NULL and the returned character count does not include it.
* (This behavior is required by the code in the C Kermit book but is
* not explicitly stated there.)
*
* This version is most unsatisfactory as it does I/O one character
* at a time, but extensive changes in the rest of VT100 would be
* needed in order to use a multi-character read.
*/
static int pushedser = -1; /* pushed character */
int ttinl(dest, max, eol, timelimit)
char *dest;
int max, eol, timelimit;
{
int i;
void ttflui();
if (timelimit > 0)
ttime = timelimit;
else
ttime = 30; /* Maximum timeout if not given */
for (i = 0; i < max; i++) {
dest[i] = readchar();
if (timeout != GOODREAD) {
if (timeout == USERABORT) { /* User abort requested */
if (cx == 1)
start = 'a'; /* Second escape--abort mess */
else
cx = cz = 1; /* Set abort flags */
continue; /* Continue receiving anyway */
} else {
i = -1; /* Some other error. */
break;
}
}
if (eol > 0 && dest[i] == eol)
break;
ttime = 2; /* Intrapacket timeout */
}
if (i >= 0)
dest[i] = '\0'; /* Null terminate what we got */
else
dest[0] = '\0';
return i; /* Return length or failure */
}
/*
* ttol(out, n)
*
* Send n characters pointed to by out through the serial port using
* current settings of word length, parity, and flow control. Return
*
*
* Here I bypass sendchar() and go direct to the low level.
*/
int
ttol(out, n)
char *out;
int n;
{
int retval;
Write_Request->IOSer.io_Data = (APTR) out;
Write_Request->IOSer.io_Length = n;
Write_Request->IOSer.io_Command = CMD_WRITE;
SendIO((struct IORequest *)Write_Request);
retval = WaitIO((struct IORequest *)Write_Request);
/*
* Restore old values.
*/
Write_Request->IOSer.io_Data = (APTR) rs_out;
Write_Request->IOSer.io_Length = 1;
if (retval != 0)
return -1;
else
return ((int)Write_Request->IOSer.io_Actual);
}
/*
* ttflui()
*
* Remove any pending characters from the serial port.
*
* Even worse than ttinl() and ttol(), this reads characters with a minimal
* timeout until there aren't any more. Note that I also changed readchar()
* in xmodem.c to check if ttime is 0, and if it is, to set its timeout to
* 100,000 ticks (0.1 seconds). I also removed the InfoMsg1Line call which
* warned about timeouts so this would work. Ideally, ttinl() should do
* a single CMD_READ in ReadRequest, and ttflui() should AbortIO() it.
*/
void
ttflui()
{
int c;
ttime = 0;
do {
c = readchar();
} while (timeout == GOODREAD);
}
void
sleep(seconds) int seconds;
{
if (seconds > 0)
Delay(seconds*TICKS_PER_SECOND);
}
/*
* Now here are tmsg() and tchar() for putting out warnings. What I've done
* is to use tchar()'s argument as a flag to put out whatever status we need.
* tmsg()'s argument is put out as a message line.
*/
/*
* tchar(c)--put the single character c onto the user's screen as part
* of Kermit's communication to said user.
*/
void
tchar(c)
char c;
{
char status[80];
void tmsg();
switch (c) {
case '.':
npackets++;
break;
case '%':
naks++;
break;
default:
status[0] = c;
status[1] = '\0';
tmsg(status); /* Output unknown chars */
return;
}
sprintf(status, "Packets: %4d Retries: %4d", npackets, naks);
InfoMsgNoScroll(status);
}
/*
* tmsg(s) char *s;--Put a message string onto the user's screen as part
* of the communication from Kermit.
*
* I put out a message using InfoMsg. We store it up until we get a newline,
* then we scroll and put it out.
*/
void
tmsg(more_message)
char *more_message;
{
/*
* If new message won't fit, put out message so far and copy it.
* Otherwise, just catenate new message to old.
*/
if (strlen(more_message) + strlen(message) < sizeof(message)) {
strcat(message,more_message);
} else {
InfoMsg1Line(message);
strcpy(message,more_message);
}
}
/*
* tmsgl(s) char *s;--Put out a newline-terminated message to the user's
* screen as part of Kermit communication.
*/
void
tmsgl(more_message)
char *more_message;
{
tmsg(more_message);
InfoMsg1Line(message);
message[0] = '\0';
}