Article View: mod.amiga.sources
Article #32New VT100 (part 2 of 2)
From: doc
Date: Wed, 03 Sep 1986 06:53
Date: Wed, 03 Sep 1986 06:53
2095 lines
57019 bytes
57019 bytes
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# init.c
# kermit.c
# remote.c
# script.c
# This archive created: Wed Sep 3 01:51:08 1986
# By: Craig Norborg (Purdue University Computing Center)
cat << \SHAR_EOF > init.c
/***************************************************************
* vt100 - terminal emulator - initialization
*
* 860823 DBW - Integrated and rewrote lots of code
* v2.0 860809 DBW - Major rewrite
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
***************************************************************/
#define MODULE_INIT 1
#include "vt100.h"
extern char *malloc();
void InitDefaults(argc,argv)
int argc;
char **argv;
{
FILE *fd;
char line[256],scr[32],delim,macro[256],c0,*ptr;
int i,j,k;
if (((argc > 1) && (fd=fopen(argv[1],"r")) != 0) ||
(fd=fopen("vt100.init","r")) != 0 ||
(fd=fopen("c:vt100.init","r")) != 0) {
while (fgets(line,256,fd) != 0) {
if ((c0 = line[0]) == '#') continue;
if ((c0|' ') == 'e') break;
switch (c0|' ') {
case 'b':
if ((line[1]|' ') == 'o') {
/* bold color */
if (sscanf(line,"%s %x",scr,&i) == 2) p_bold = i;
break;
}
if ((line[1]|' ') != 'a') break;
switch(line[2]|' ') {
/* baud rate */
case 'u':
if (sscanf(line,"%s %d",scr,&i) == 2) p_baud = i;
break;
/* background */
case 'c':
if (sscanf(line,"%s %x",scr,&i) == 2) p_background = i;
break;
}
break;
/* screen type */
case 's':
if (sscanf(line,"%s %s",scr,scr) == 2) {
if ((scr[0]|' ') == 'w') p_screen = 0;
else p_screen = 1;
}
break;
/* number of lines */
case 'l':
if (sscanf(line,"%s %d",scr,&i) == 2) p_lines = i;
break;
/* screen depth */
case 'd':
if (sscanf(line,"%s %d",scr,&i) == 2) p_depth = i;
break;
/* cursor color */
case 'c':
if (sscanf(line,"%s %d",scr,&i) == 2) p_cursor = i;
break;
/* interlace type */
case 'i':
if (sscanf(line,"%s %s",scr,scr) == 2) {
if ((scr[1]|' ') == 'n') p_interlace = 1;
else p_interlace = 0;
}
break;
case 'f':
switch (line[1]|' ') {
/* foreground color */
case 'o':
if (sscanf(line,"%s %x",scr,&i) == 2) p_foreground = i;
break;
/* function key */
default:
if (sscanf(&line[1],"%d",&i) != 1) break;
if (i < 1 || i > 10) break;
delim = 0;
for (j=2; line[j] != 0 &&
(line[j] == ' ' || line[j] == '\t'); j++) ;
if (line[j] == 0) {
if (c0 == 'f') p_f[i-1] = NULL;
else p_F[i-1] = NULL;
break;
}
delim = line[j];
k = 0;
macro[0] = 0;
while (line[++j] != delim) {
if (line[j] == 0) {
if (fgets(line,256,fd) == 0) {
line[0] = delim;
line[1] = 0;
}
j = -1;
continue;
}
if (line[j] == '^' && line[++j] != '^')
macro[k++] = (line[j]|' ') - 0x60;
else if (line[j] != '\n') macro[k++] = line[j];
macro[k] = 0;
}
ptr = malloc(k+1);
if (c0 == 'f') p_f[i-1] = ptr;
else p_F[i-1] = ptr;
strcpy(ptr,macro);
break;
}
break;
case 'm':
if (sscanf(line,"%s %s",scr,scr) == 2) {
if ((scr[0]|' ') == 'i') p_mode = 0;
else p_mode = 1;
}
break;
case 'x':
if (sscanf(line,"%s %s",scr,scr) == 2) {
if ((scr[0]|' ') == 'd') p_xon = 0;
else p_xon = 1;
}
break;
}
}
fclose(fd);
}
/* Now set up all the screen info as necessary */
if (p_interlace == 0) {
if (p_lines > 24) p_lines = 24;
MINY = 14;
NewWindow.Height = (long)((p_lines*8)+8);
}
else {
if (p_lines > 48) p_lines = 48;
MINY = 16;
NewScreen.ViewModes |= LACE;
NewWindow.Height = (long)((p_lines*8)+10);
}
NewWindow.MinHeight = NewWindow.Height;
NewWindow.MaxHeight = NewWindow.Height;
NewWindow.TopEdge = 3L;
MAXY = ((p_lines-1)*8) + MINY;
top = MINY;
bot = MAXY;
savx = MINX;
savy = MINY;
if (p_screen == 1) {
if (p_depth > 2) p_depth = 2;
if (p_depth < 1) p_depth = 1;
NewScreen.Depth = (long)p_depth;
NewScreen.Height = (long)((p_lines*8)+15);
if (p_interlace == 1)
NewScreen.TopEdge = (long)(402 - NewScreen.Height);
else
NewScreen.TopEdge = 0L;
}
else {
p_depth = 2L;
NewWindow.TopEdge = 0L;
NewWindow.Screen = NULL;
NewWindow.Type = WBENCHSCREEN;
}
}
void InitDevs()
{
USHORT colors[4];
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV);
if( IntuitionBase == NULL )
{
puts("can't open intuition\n");
exit(TRUE);
}
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
if( GfxBase == NULL )
{
puts("can't open graphics library\n");
exit(TRUE);
}
if (p_screen == 1) {
if ((myscreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL) {
puts("can't open screen!!\n");
exit(TRUE);
}
NewWindow.Screen = myscreen;
}
if(( mywindow = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
{
puts("cant open window\n");
if (p_screen != 0) CloseScreen( myscreen );
exit(TRUE);
}
myviewport = (struct ViewPort *)ViewPortAddress(mywindow);
if (p_screen != 0) {
colors[0] = p_background;
colors[1] = p_foreground;
colors[2] = p_bold;
colors[3] = p_cursor;
if (p_depth == 1)
LoadRGB4(myviewport,(struct ColorMap *)colors,2L);
else
LoadRGB4(myviewport,(struct ColorMap *)colors,4L);
}
Read_Request = (struct IOExtSer *)
AllocMem((long)sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR);
Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS",0);
if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))
{
puts("Cant open Read device\n");
CloseWindow( mywindow );
if (p_screen != 0) CloseScreen( myscreen );
DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
FreeMem(Read_Request,(long)sizeof(*Read_Request));
exit(TRUE);
}
Read_Request->IOSer.io_Command = CMD_READ;
Read_Request->IOSer.io_Length = 1;
Read_Request->IOSer.io_Data = (APTR) &rs_in[0];
Write_Request = (struct IOExtSer *)
AllocMem((long)sizeof(*Write_Request),MEMF_PUBLIC|MEMF_CLEAR);
Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0);
if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL))
{
puts("Cant open Write device\n");
CloseDevice(Read_Request);
DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
FreeMem(Read_Request,(long)sizeof(*Read_Request));
DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
FreeMem(Write_Request,(long)sizeof(*Write_Request));
CloseWindow( mywindow );
if (p_screen != 0) CloseScreen( myscreen );
exit(TRUE);
}
Write_Request->IOSer.io_Command = CMD_WRITE;
Write_Request->IOSer.io_Length = 1;
Write_Request->IOSer.io_Data = (APTR) &rs_out[0];
Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Read_Request->io_Baud = p_baud;
Read_Request->io_ReadLen = 8;
Read_Request->io_WriteLen = 8;
Read_Request->io_CtlChar = 1L;
Read_Request->io_RBufLen = 2048;
Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(Read_Request);
Read_Request->IOSer.io_Command = CMD_READ;
Timer_Port = CreatePort("Timer Port",0);
Script_Timer_Port = CreatePort("Timer Port",0);
if (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Timer, 0) ||
OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Script_Timer, 0)) {
puts("can't open timer device");
DeletePort(Timer_Port);
DeletePort(Script_Timer_Port);
CloseDevice(Read_Request);
DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
FreeMem(Read_Request,(long)sizeof(*Read_Request));
CloseDevice(Write_Request);
DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
FreeMem(Write_Request,(long)sizeof(*Write_Request));
CloseWindow( mywindow );
if (p_screen != 0) CloseScreen( myscreen );
exit(TRUE);
}
Timer.tr_node.io_Message.mn_ReplyPort = Timer_Port;
Timer.tr_node.io_Command = TR_ADDREQUEST;
Timer.tr_node.io_Flags = 0;
Timer.tr_node.io_Error = 0;
Script_Timer.tr_node.io_Message.mn_ReplyPort = Script_Timer_Port;
Script_Timer.tr_node.io_Command = TR_ADDREQUEST;
Script_Timer.tr_node.io_Flags = 0;
Script_Timer.tr_node.io_Error = 0;
}
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the File menu topic. */
/*****************************************************************/
void InitFileItems()
{
int n;
/* initialize each menu item and IntuiText with loop */
for( n=0; n<FILEMAX; n++ )
{
FileItem[n].NextItem = &FileItem[n+1];
FileItem[n].LeftEdge = 0;
FileItem[n].TopEdge = 11 * n;
FileItem[n].Width = 135;
FileItem[n].Height = 11;
FileItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
FileItem[n].MutualExclude = 0;
FileItem[n].ItemFill = (APTR)&FileText[n];
FileItem[n].SelectFill = NULL;
FileItem[n].Command = 0;
FileItem[n].SubItem = NULL;
FileItem[n].NextSelect = 0;
FileText[n].FrontPen = 0;
FileText[n].BackPen = 1;
FileText[n].DrawMode = JAM2; /* render in fore and background */
FileText[n].LeftEdge = 0;
FileText[n].TopEdge = 1;
FileText[n].ITextFont = NULL;
FileText[n].NextText = NULL;
}
FileItem[FILEMAX-1].NextItem = NULL;
/* initialize text for specific menu items */
FileText[0].IText = (UBYTE *)"Ascii Capture";
FileText[1].IText = (UBYTE *)"Ascii Send";
FileText[2].IText = (UBYTE *)"Xmodem Receive";
FileText[3].IText = (UBYTE *)"Xmodem Send";
FileText[4].IText = (UBYTE *)"Kermit Get";
FileText[5].IText = (UBYTE *)"Kermit Receive";
FileText[6].IText = (UBYTE *)"Kermit Send";
FileText[7].IText = (UBYTE *)"Kermit BYE";
}
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the BaudRate menu topic. */
/*****************************************************************/
void InitRSItems()
{
int n;
/* initialize each menu item and IntuiText with loop */
for( n=0; n<RSMAX; n++ )
{
RSItem[n].NextItem = &RSItem[n+1];
RSItem[n].LeftEdge = 0;
RSItem[n].TopEdge = 11 * n;
RSItem[n].Width = 85;
RSItem[n].Height = 11;
RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
RSItem[n].MutualExclude = (~(1 << n));
RSItem[n].ItemFill = (APTR)&RSText[n];
RSItem[n].SelectFill = NULL;
RSItem[n].Command = 0;
RSItem[n].SubItem = NULL;
RSItem[n].NextSelect = 0;
RSText[n].FrontPen = 0;
RSText[n].BackPen = 1;
RSText[n].DrawMode = JAM2; /* render in fore and background */
RSText[n].LeftEdge = 0;
RSText[n].TopEdge = 1;
RSText[n].ITextFont = NULL;
RSText[n].NextText = NULL;
}
RSItem[RSMAX-1].NextItem = NULL;
/* select baud item chekced */
switch (p_baud) {
case 300: n = 0; break;
case 1200: n = 1; break;
case 2400: n = 2; break;
case 4800: n = 3; break;
case 9600: n = 4; break;
default: n = 2; p_baud = 2400;
}
RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | CHECKED;
/* initialize text for specific menu items */
RSText[0].IText = (UBYTE *)" 300";
RSText[1].IText = (UBYTE *)" 1200";
RSText[2].IText = (UBYTE *)" 2400";
RSText[3].IText = (UBYTE *)" 4800";
RSText[4].IText = (UBYTE *)" 9600";
}
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the Transfer Mode menu topic. */
/*****************************************************************/
void InitXFItems()
{
int n;
/* initialize each menu item and IntuiText with loop */
for( n=0; n<XFMAX; n++ )
{
XFItem[n].NextItem = &XFItem[n+1];
XFItem[n].LeftEdge = 0;
XFItem[n].TopEdge = 11 * n;
XFItem[n].Width = 85;
XFItem[n].Height = 11;
XFItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
XFItem[n].MutualExclude = (~(1 << n));
XFItem[n].ItemFill = (APTR)&XFText[n];
XFItem[n].SelectFill = NULL;
XFItem[n].Command = 0;
XFItem[n].SubItem = NULL;
XFItem[n].NextSelect = 0;
XFText[n].FrontPen = 0;
XFText[n].BackPen = 1;
XFText[n].DrawMode = JAM2; /* render in fore and background */
XFText[n].LeftEdge = 0;
XFText[n].TopEdge = 1;
XFText[n].ITextFont = NULL;
XFText[n].NextText = NULL;
}
XFItem[XFMAX-1].NextItem = NULL;
/* mode checked */
XFItem[p_mode].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | CHECKED;
/* initialize text for specific menu items */
XFText[0].IText = (UBYTE *)" image";
XFText[1].IText = (UBYTE *)" CR LF";
}
/*****************************************************************/
/* The following function initializes the structure arrays */
/* needed to provide the Script menu topic. */
/*****************************************************************/
void InitScriptItems()
{
int n;
/* initialize each menu item and IntuiText with loop */
for( n=0; n<SCRIPTMAX; n++ )
{
ScriptItem[n].NextItem = &ScriptItem[n+1];
ScriptItem[n].LeftEdge = 0;
ScriptItem[n].TopEdge = 11 * n;
ScriptItem[n].Width = 155;
ScriptItem[n].Height = 11;
ScriptItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
ScriptItem[n].MutualExclude = 0;
ScriptItem[n].ItemFill = (APTR)&ScriptText[n];
ScriptItem[n].SelectFill = NULL;
ScriptItem[n].Command = 0;
ScriptItem[n].SubItem = NULL;
ScriptItem[n].NextSelect = 0;
ScriptText[n].FrontPen = 0;
ScriptText[n].BackPen = 1;
ScriptText[n].DrawMode = JAM2; /* render in fore and background */
ScriptText[n].LeftEdge = 0;
ScriptText[n].TopEdge = 1;
ScriptText[n].ITextFont = NULL;
ScriptText[n].NextText = NULL;
}
ScriptItem[SCRIPTMAX-1].NextItem = NULL;
/* initialize text for specific menu items */
ScriptText[0].IText = (UBYTE *)"Execute file";
ScriptText[1].IText = (UBYTE *)"Abort Execution";
}
/**********************************************************************/
/* The following function initializes the Menu structure array with */
/* appropriate values for our simple menu strip. Review the manual */
/* if you need to know what each value means. */
/**********************************************************************/
void InitMenu()
{
menu[0].NextMenu = &menu[1];
menu[0].LeftEdge = 5;
menu[0].TopEdge = 0;
menu[0].Width = 50;
menu[0].Height = 10;
menu[0].Flags = MENUENABLED;
menu[0].MenuName = "File"; /* text for menu-bar display */
menu[0].FirstItem = &FileItem[0]; /* pointer to first item in list */
menu[1].NextMenu = &menu[2];
menu[1].LeftEdge = 65;
menu[1].TopEdge = 0;
menu[1].Width = 85;
menu[1].Height = 10;
menu[1].Flags = MENUENABLED;
menu[1].MenuName = "BaudRate"; /* text for menu-bar display */
menu[1].FirstItem = &RSItem[0]; /* pointer to first item in list */
menu[2].NextMenu = &menu[3];
menu[2].LeftEdge = 160;
menu[2].TopEdge = 0;
menu[2].Width = 85;
menu[2].Height = 10;
menu[2].Flags = MENUENABLED;
menu[2].MenuName = "Xfer Mode"; /* text for menu-bar display */
menu[2].FirstItem = &XFItem[0]; /* pointer to first item in list */
menu[3].NextMenu = NULL;
menu[3].LeftEdge = 255;
menu[3].TopEdge = 0;
menu[3].Width = 85;
menu[3].Height = 10;
menu[3].Flags = MENUENABLED;
menu[3].MenuName = "Script"; /* text for menu-bar display */
menu[3].FirstItem = &ScriptItem[0]; /* pointer to first item in list */
}
SHAR_EOF
cat << \SHAR_EOF > kermit.c
/*************************************************************
* vt100 terminal emulator - KERMIT protocol support
*
* 860823 DBW - Integrated and rewrote lots of code
* 860811 Steve Drew multi filexfer, bugs, status line ect..
* v2.0 860809 DBW - Major rewrite
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
*************************************************************/
#define MODULE_KERMIT 1
#include "vt100.h"
#define MAXPACKSIZ 94 /* Maximum msgpkt size */
#define CR 13 /* ASCII Carriage Return */
#define LF 10 /* ASCII line feed */
#define SP 32 /* ASCII space */
#define DEL 127 /* Delete (rubout) */
#define MAXTRY 5 /* Times to retry a msgpkt */
#define MYQUOTE '#' /* Quote character I will use */
#define MYRPTQ '~' /* Repeat quote character */
#define MYPAD 0 /* Number of padding characters I will need */
#define MYPCHAR 0 /* Padding character I need (NULL) */
#define MYEOL '\n' /* End-Of-Line character I need */
#define tochar(ch) ((ch) + ' ')
#define unchar(ch) ((ch) - ' ')
#define ctl(ch) ((ch) ^ 64 )
/* Global Variables */
int
size, /* Size of present data */
osize, /* Size of last data entry */
rpsiz, /* Maximum receive msgpkt size */
spsiz, /* Maximum send msgpkt size */
timint, /* Time interval to wait */
pad, /* How much padding to send */
n, /* Packet number */
tp, /* total packets */
numtry, /* Times this msgpkt retried */
retry, /* total retries */
oldtry, /* Times previous msgpkt retried */
rptflg, /* are we doing repeat quoting */
first, /* is this the first time in a file */
rpt, /* current repeat count */
next, /* what is the next character */
t; /* current character */
long
totbytes; /* total bytes xfered on this file */
char
state, /* Present state of the automaton */
padchar, /* Padding character to send */
eol, /* End-Of-Line character to send */
quote, /* Quote character in incoming data */
rptq, /* Quote character for repeats */
ackpkt[MAXPACKSIZ+20], /* ACK/NAK packet buffer */
msgpkt[MAXPACKSIZ+20], /* Message Packet buffer */
filnam[40]; /* remote file name */
snum[10];
void encode(), decode(), rpar(), spar();
FILE *fp; /* file for send/receive */
int shutdown = 0; /* shut down server after all xfers complete */
char *
getfname(name) /* returns pointer to start of file name from file spec */
char *name;
{
int l;
l = strlen(name);
while(l && name[l] != '/' && name[l] != ':') l--;
if (name[l] == '/' || name[l] == ':') l++;
return(name += l);
}
doksend(file,more)
char *file;
int more;
{
int retval;
ttime = TTIME_LONG;
if (!strcmp(file,"$")) { saybye(); return(2); }
if (file[strlen(file)-1] == '$') {
shutdown = 1;
file[strlen(file)-1] = '\0';
}
if ((fp = fopen(file,"r")) == NULL) {
emits("Cannot open send file\n");
return FALSE;
}
getready(file,more);
emits("SEND");
retval = sendsw();
if (retval) { x = 600; emits("DONE"); }
curmode = 0;
if (shutdown) saybye();
emits("\n");
fclose(fp);
return(retval);
}
dokreceive(file,more)
char *file;
int more;
{
int retval;
ttime = TTIME_LONG;
if (!strcmp(file,"$")) { saybye(); return(2); }
if (file[strlen(file)-1] == '$') {
shutdown = 1;
file[strlen(file)-1] = '\0';
}
if ((fp = fopen(file,"w")) == NULL) {
emits("Cannot open file\n");
return FALSE;
}
getready(file,more);
emits("RECV");
retval = recsw();
if (retval) { x = 600; emits("DONE"); }
curmode = 0;
if (shutdown) saybye();
emits("\n");
fclose(fp);
return(retval);
}
getready(file,more)
char *file;
int more;
{
if (!more) {
emits("Remote file name [");
emits(getfname(file));
emits("]: ");
filename(filnam);
if (filnam[0] == 0) strcpy(filnam,getfname(file));
emits("Type <ESC> to abort transfer\n");
}
else strcpy(filnam,getfname(file));
eatup();
tp = retry = 0; totbytes = 0L; n = numtry = 0;
want_message = FALSE; /* tell readchar no error msgs status bar instead */
statusline();
x = 600;
}
sendsw()
{
char sinit(), sfile(), sdata(), seof(), sbreak();
state = 'S';
while(TRUE) {
switch(state) {
case 'S': state = sinit(); break;
case 'F': state = sfile(); break;
case 'D': state = sdata(); break;
case 'Z': state = seof(); break;
case 'B': state = sbreak(); break;
case 'C': return(TRUE);
case 'A': x = 600;
if (timeout == USERABORT) { sabort(); return(FALSE); }
if (timeout == TIMEOUT) emits("TMOUT");
else emits("ERROR");
return(FALSE);
default: return(FALSE);
}
}
}
char sinit()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
spar(msgpkt);
spack('S',n,9,msgpkt);
switch(rpack(&len,&num,ackpkt)) {
case 'N': return(state);
case 'Y': if (n != num) return(state);
rpar(ackpkt);
if (eol == 0) eol = '\n';
if (quote == 0) quote = '#';
numtry = 0;
retry--;
n = (n+1)%64;
return('F');
case 'E': return('A');
case FALSE:if (timeout == USERABORT) state = 'A';
return(state);
default: return('A');
}
}
char sfile()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
spack('F',n,strlen(filnam),filnam);
switch(rpack(&len,&num,ackpkt)) {
case 'N':
num = (--num<0 ? 63:num);
if (n != num) return(state);
case 'Y':
if (n != num) return(state);
numtry = 0;
retry--;
n = (n+1)%64;
first = 1;
size = getpkt();
return('D');
case 'E':
return('A');
case FALSE: if (timeout == USERABORT) state = 'A';
return(state);
default: return('A');
}
}
char sdata()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
spack('D',n,size,msgpkt);
switch(rpack(&len,&num,ackpkt)) {
case 'N':
num = (--num<0 ? 63:num);
if (n != num) return(state);
case 'Y':
if (n != num) return(state);
numtry = 0;
retry--;
n = (n+1)%64;
if ((size = getpkt()) == 0) return('Z');
return('D');
case 'E':
return('A');
case FALSE: if (timeout == USERABORT) state = 'A';
return(state);
default: return('A');
}
}
char seof()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
if (timeout == USERABORT) {
timeout = GOODREAD;
spack('Z',n,1,"D"); /* tell host to discard file */
}
else spack('Z',n,0,msgpkt);
switch(rpack(&len,&num,ackpkt)) {
case 'N':
num = (--num<0 ? 63:num);
if (n != num) return(state);
case 'Y':
if (n != num) return(state);
numtry = 0;
retry--;
n = (n+1)%64;
return('B');
case 'E':
return('A');
case FALSE: return(state);
default: return('A');
}
}
char sbreak()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
spack('B',n,0,msgpkt);
switch (rpack(&len,&num,ackpkt)) {
case 'N':
num = (--num<0 ? 63:num);
if (n != num) return(state);
case 'Y':
if (n != num) return(state);
numtry = 0;
retry--;
n = (n+1)%64;
return('C');
case 'E':
return('A');
case FALSE: return(state);
default: return ('A');
}
}
/* timeout equals USERABORT so lets end the file and quit */
/* when host receives 'Z' packet with "D" in data field he */
/* should discard the file. */
sabort()
{
emits("ABORT");
n = (n+1)%64;
retry--;
state = 'Z';
while (state == 'Z') state = seof();
while (state == 'B') state = sbreak();
return(FALSE);
}
recsw()
{
char rinit(), rfile(), rdata(), rbreak();
state = 'R';
while(TRUE) {
switch(state) {
case 'R': state = rinit(); break;
case 'F': state = rfile(); break;
case 'D': state = rdata(); break;
case 'Z': state = rbreak(); break;
case 'C': return(TRUE);
case 'A': x = 600;
if (timeout == USERABORT){/* easy way to cleanly abort
should really send and ACK
with "X" in data field and
wait for host to abort but
not all kermits support
this feature. */
emits("ABORT");
spack('E',n,0,0); /* send an error packet back */
}
else if (timeout == TIMEOUT) emits("TMOUT");
else emits("ERROR");
return(FALSE);
}
}
}
char rinit()
{
int len, num;
retry++;
if (numtry++ > MAXTRY) return('A');
if (server) spack('R',n,strlen(filnam),filnam);
else spack('N',n,0,0);
switch(rpack(&len,&num,msgpkt)) {
case 'S':
rpar(msgpkt);
spar(msgpkt);
spack('Y',n,9,msgpkt);
oldtry = numtry;
numtry = 0;
retry--;
n = (n+1)%64;
return('F');
case 'E':
return('A');
case FALSE:
if (timeout == USERABORT) return('A');
spack('N',n,0,0);
return(state);
default:
return('A');
}
}
char rfile()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
switch(rpack(&len,&num,msgpkt)) {
case 'S':
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) {
spar(msgpkt);
spack('Y',num,9,msgpkt);
retry--;
numtry = 0;
return(state);
}
else return('A');
case 'Z':
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) {
spack('Y',num,0,0);
numtry = 0;
retry--;
return(state);
}
else return('A');
case 'F':
if (num != n) return('A');
spack('Y',n,0,0);
oldtry = numtry;
numtry = 0;
retry--;
n = (n+1)%64;
return('D');
case 'B':
if (num != n) return ('A');
spack('Y',n,0,0);
retry--;
return('C');
case 'E':
return('A');
case FALSE:
if (timeout == USERABORT) return('A');
spack('N',n,0,0);
return(state);
default:
return ('A');
}
}
char rdata()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
switch(rpack(&len,&num,msgpkt)) {
case 'D':
if (num != n) {
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) {
spack('Y',num,6,msgpkt);
retry--;
numtry = 0;
return(state);
}
else return('A');
}
decode();
spack('Y',n,0,0);
oldtry = numtry;
numtry = 0;
retry--;
n = (n+1)%64;
return('D');
case 'F':
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) {
spack('Y',num,0,0);
numtry = 0;
retry--;
return(state);
}
else return('A');
case 'Z':
if (num != n) return('A');
spack('Y',n,0,0);
n = (n+1)%64;
retry--;
return('Z');
case 'E':
return('A');
case FALSE:
if (timeout == USERABORT) return('A');
spack('N',n,0,0);
return(state);
default:
return('A');
}
}
char rbreak()
{
int num, len;
retry++;
if (numtry++ > MAXTRY) return('A');
switch(rpack(&len,&num,msgpkt)) {
case 'B':
spack('Y',n,0,0);
return('C');
case 'Z':
spack('Y',n,0,0);
return('Z');
case 'E':
return('A');
case FALSE:
spack('N',n,0,0);
return(state);
default:
return('A');
}
}
spack(type,num,len,data)
char type, *data;
int num, len;
{
int i;
char chksum, buffer[100];
register char *bufp;
dostats(type);
bufp = buffer;
for (i=1; i<=pad; i++) sendchar(padchar);
*bufp++ = SOH;
*bufp++ = tochar(len+3);
chksum = tochar(len+3);
*bufp++ = tochar(num);
chksum += tochar(num);
*bufp++ = type;
chksum += type;
for (i=0; i<len; i++) {
*bufp++ = data[i];
chksum += data[i];
}
chksum = (((chksum&0300) >> 6)+chksum)&077;
*bufp++ = tochar(chksum);
*bufp++ = '\r';
*bufp++ = '\n';
*bufp = 0;
sendstring(buffer);
}
rpack(len,num,data)
int *len, *num;
char *data;
{
int i, done;
char type, cchksum, rchksum;
char t = '\0';
do {
t = readchar();
if (timeout != GOODREAD) return(FALSE);
} while (t != SOH);
done = FALSE;
while (!done) {
t = readchar();
if (timeout != GOODREAD) return(FALSE);
if (t == SOH) continue;
cchksum = t;
*len = unchar(t)-3;
t = readchar();
if (timeout != GOODREAD) return(FALSE);
if (t == SOH) continue;
cchksum = cchksum + t;
*num = unchar(t);
t = readchar();
if (timeout != GOODREAD) return(FALSE);
if (t == SOH) continue;
cchksum = cchksum + t;
type = t;
for (i=0; i<*len; i++) {
t = readchar();
if (timeout != GOODREAD) return(FALSE);
if (t == SOH) continue;
cchksum = cchksum + t;
data[i] = t;
}
data[*len] = 0;
t = readchar();
if (timeout != GOODREAD) return(FALSE);
rchksum = unchar(t);
t = readchar();
if (timeout != GOODREAD) return(FALSE);
if (t == SOH) continue;
done = TRUE;
}
dostats(type);
cchksum = (((cchksum&0300) >> 6)+cchksum)&077;
if (cchksum != rchksum) return(FALSE);
return((int)type);
}
getpkt() {
int i,eof;
static char leftover[10] = { '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0' };
if (first == 1) {
first = 0;
*leftover = '\0';
t = getc(fp);
if (t == EOF) {
first = 1;
return(size = 0);
}
totbytes++;
}
else if (first == -1) {
first = 1;
return(size = 0);
}
for (size = 0; (msgpkt[size] = leftover[size]) != '\0'; size++) ;
*leftover = '\0';
rpt = 0;
eof = 0;
while (!eof) {
next = getc(fp);
if (next == EOF) {
first = -1;
eof = 1;
}
else totbytes++;
osize = size;
encode(t);
t = next;
if (size == spsiz-3) return(size);
if (size > spsiz-3) {
for (i = 0; (leftover[i] = msgpkt[osize+i]) != '\0'; i++) ;
size = osize;
msgpkt[size] = '\0';
return(size);
}
}
return(size);
}
void encode(a)
char a;
{
int a7,b8;
if (p_mode == 1 && a == '\n') {
rpt = 0;
msgpkt[size++] = quote;
msgpkt[size++] = ctl('\r');
if (size <= spsiz-3) osize = size;
msgpkt[size++] = quote;
msgpkt[size++] = ctl('\n');
msgpkt[size] = '\0';
return;
}
if (rptflg) {
if (a == next && (first == 0)) {
if (++rpt < 94) return;
else if (rpt == 94) {
msgpkt[size++] = rptq;
msgpkt[size++] = tochar(rpt);
rpt = 0;
}
}
else if (rpt == 1) {
rpt = 0;
encode(a);
if (size <= spsiz-3) osize = size;
rpt = 0;
encode(a);
return;
}
else if (rpt > 1) {
msgpkt[size++] = rptq;
msgpkt[size++] = tochar(++rpt);
rpt = 0;
}
}
a7 = a & 0177;
b8 = a & 0200;
if ((a7 < SP) || (a7==DEL)) {
msgpkt[size++] = quote;
a = ctl(a);
}
if (a7 == quote) msgpkt[size++] = quote;
if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote;
msgpkt[size++] = a;
msgpkt[size] = '\0';
}
void decode()
{
USHORT a, a7;
char *buf;
buf = msgpkt;
rpt = 0;
while ((a = *buf++) != '\0') {
if (rptflg) {
if (a == rptq) {
rpt = unchar(*buf++);
a = *buf++;
}
}
if (a == quote) {
a = *buf++;
a7 = a & 0177;
if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a);
}
if (rpt == 0) rpt = 1;
if (p_mode == 1 && a == '\r') continue;
totbytes += rpt;
for (; rpt > 0; rpt--) putc(a, fp);
}
return;
}
void spar(data)
char data[];
{
data[0] = tochar(MAXPACKSIZ);
data[1] = tochar(TTIME_LONG);
data[2] = tochar(MYPAD);
data[3] = ctl(MYPCHAR);
data[4] = tochar(MYEOL);
data[5] = MYQUOTE;
data[6] = 'N';
data[7] = '1';
data[8] = MYRPTQ;
data[9] = '\0';
}
void rpar(data)
char data[];
{
spsiz = unchar(data[0]);
timint = unchar(data[1]);
pad = unchar(data[2]);
padchar = ctl(data[3]);
eol = unchar(data[4]);
quote = data[5];
rptflg = 0;
if (data[6] == 0) return;
if (data[7] == 0) return;
if (data[8] == 0) return;
rptq = data[8];
rptflg = ((rptq > 040 && rptq < 0100) || (rptq > 0140 && rptq < 0177));
}
saybye()
{
int len,num;
shutdown = 0;
spack('G',n,1,"F"); /* shut down server no more files */
rpack(&len,&num,ackpkt);
}
statusline()
{
emits ("\nFile: Pckt: Pckt No: Retrn: Bytes: Stat: ");
x = 48;
curmode = 1;
emits (filnam);
return(0);
}
dostats(type)
char type;
{
if (type != 'Y' && type != 'N' && type != 'G') {
x = 224;
emit(type);
x = 312;
sprintf(snum,"%4d",n+(tp * 64));
emits(snum);
if (n==63) tp++;
x = 408;
sprintf(snum,"%2d",retry-1);
emits(snum);
x = 488;
sprintf(snum,"%6ld",(long)totbytes);
emits(snum);
}
}
/* allow for multi file xfers separated by commas under kermit and XMODEM */
multi_xfer(name,mode,do_send)
char *name;
int (*mode)();
int do_send;
{
int done = 0;
int status;
char *p;
p = name;
while(*p && *p != ',') p++;
if (*p == '\0') {
done = TRUE;
if (multi == 1) multi++;
}
else multi = 1;
*p = '\0';
status = ((*mode)(name, multi));
if (status == TRUE) {
if (do_send) emits("Sent File: ");
else emits("Received File: ");
emits(name);
emits("\n");
emit(8);
}
else if (status == FALSE)
{
close(fd);
if (do_send) emits("Send Failed: ");
else emits("Receive Failed: ");
emits(name);
emits("\n");
emit(8);
}
if (!done) multi_xfer(++p, mode, do_send);
server = 0;
multi = 0;
}
/* gobble up all garb that we received while getting file name strings */
eatup()
{
while(CheckIO(Read_Request)) {
WaitIO(Read_Request);
BeginIO(Read_Request);
}
}
SHAR_EOF
cat << \SHAR_EOF > remote.c
/****************************************************
* vt100 emulator - remote character interpretation
*
* 860823 DBW - Integrated and rewrote lots of code
* v2.0 860803 DRB - Rewrote the control sequence parser
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
****************************************************/
#define MODULE_REMOTE 1
#include "vt100.h"
static int p[10];
static int numpar;
static char escseq[40];
void doctrl();
void doesc(); /* force correct denomination */
void doerase();
void doindex();
/************************************************
* function to handle remote characters
*************************************************/
void doremote(c)
char c;
{
if (c == 27 || inesc >= 0) { doesc(c); return; }
if (inctrl >= 0) { doctrl(c); return; }
if (c == 10 || c == 11 || c == 12) {
if (nlmode) doindex('E'); else doindex('D');
return;
}
if (c == 13) {
if (!nlmode) emit(c);
return;
}
if (c == 15) { alt = 0; return; }
if (c == 14) { alt = 1; return; }
if (a[alt] && c > 94 && c < 127) { doalt(c); return; }
emit(c);
}
void doesc(c)
char c;
{
if (inesc < 0) { inesc = 0; return; }
if (c == 27 || c == 24) { inesc = -1; return; }
if (c < ' ' || c == 127) return; /* Ignore control chars */
if (c < '0') {escseq[inesc++] = c; return; } /* Collect intermediates */
/* by process of elimination, we have a final character. Put it in
the buffer, and dispatch on the first character in the buffer */
escseq[inesc] = c;
inesc = -1; /* No longer collecting a sequence */
switch (escseq[0]) /* Dispatch on the first received */
{
case '[': /* Control sequence introducer */
numpar = 0; /* No parameters yet */
private = 0; /* Not a private sequence (yet?) */
badseq = 0; /* Good until proven bad */
p[0] = p[1] = 0; /* But default the first parameter */
inctrl = 0; /* We are in a control sequence */
return; /* All done for now ... */
case 'D': case 'E': case 'M': /* Some kind of index */
doindex (c); /* Do the index */
return; /* Return */
case '7': /* Save cursor position */
savx = x; savy = y; savmode = curmode; savalt = alt;
sa[0] = a[0]; sa[1] = a[1];
return;
case '8': /* Restore cursor position */
x = savx; y = savy; alt = savalt; curmode = savmode;
a[0] = sa[0]; a[1] = sa[1];
return;
case 'c': /* Reset */
top = MINY; bot = MAXY; savx = MINX; savy = MINY;
a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
emit(12); return;
inesc = -1;
return;
case '(': /* Change character set */
if (c == '0' || c == '2') a[0] = 1; else a[0] = 0;
return;
case ')': /* Change the other character set */
if (c == '0' || c == '2') a[1] = 1; else a[1] = 0;
return;
/* If we didn't match anything, we can just return, happy in the
knowledge that we've at least eaten the whole sequence */
} /* End of switch */
return;
}
void doctrl(c)
char c;
{
int i;
if (c == 27 || c == 24) { inctrl = -1; return; }
if (c < ' ' || c == 127) return; /* Ignore control chars */
/* First, look for some parameter characters. If the very first
parameter character isn't a digit, then we have a private sequence */
if (c >= '0' && c < '@')
{
/* can't have parameters after intermediates */
if (inctrl > 0) {badseq++ ; return; }
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
p[numpar] = p[numpar] * 10 + (c - '0');
return;
case ';':
p[++numpar] = 0; /* Start a new parameter */
return;
case '<': case '=': case '>': case '?': /* Can only mean private */
if (inctrl = 0) private = c; /* Only allowed BEFORE parameters */
return;
/* if we come here, it's a bad sequence */
}
badseq++; /* Flag the bad sequence */
}
if (c < '0') /* Intermediate character */
{
escseq[inctrl++] = c; /* Save the intermediate character */
return;
}
/* if we get here, we have the final character. Put it in the
escape sequence buffer, then dispatch the control sequence */
numpar++; /* Reflect the real number of parameters */
escseq[inctrl++] = c; /* Store the final character */
escseq[inctrl] = '\000'; /* Tie off the buffer */
inctrl = -1; /* End of the control sequence scan */
/* Don't know how to do any private sequences right now, so just punt
them */
if (private != 0 || badseq != 0) return;
switch (escseq[0]) /* Dispatch on first intermediate or final */
{
case 'A': if (p[0]<=0) p[0] = 1;
y -= 8*p[0]; if (y<top) y = top; return;
case 'B': if (p[0]<=0) p[0] = 1;
y += 8*p[0]; if (y>bot) y = bot; return;
case 'C': if (p[0]<=0) p[0] = 1;
x += 8*p[0]; if (x>MAXX) x = MAXX; return;
case 'D': if (p[0]<=0) p[0] = 1;
x -= 8*p[0]; if (x<MINX) x = MINX; return;
case 'H': case 'f': /* Cursor position */
if (p[0] <= 0) p[0] = 1;
if (p[1] <= 0) p[1] = 1;
y = (--p[0]*8)+MINY; x = (--p[1]*8)+MINX;
if (y > MAXY) y = MAXY;
if (x > MAXX) x = MAXX;
if (y < MINY) y = MINY;
if (x < MINX) x = MINX;
return;
case 'r': /* Set scroll region */
if (p[0] <= 0) p[0] = 1;
if (p[1] <= 0) p[1] = p_lines;
top = (--p[0]*8)+MINY; bot = (--p[1]*8)+MINY;
if (top < MINY) top = MINY;
if (bot > MAXY) bot = MAXY;
if (top > bot) { top = MINY; bot = MAXY; }
x = MINX; y = MINY;
return;
case 'm': /* Set graphic rendition */
for (i=0;i<numpar;i++) {
if (p[i] < 0) p[i] = 0;
switch (p[i]) {
case 0:
curmode = 0;
break;
case 1:
case 5:
if (p_depth > 1) curmode |= BOLD;
else curmode |= REVERSE;
break;
case 4:
curmode |= UNDERLINE;
break;
default:
curmode |= REVERSE;
break;
}
}
return;
case 'K': /* Erase in line */
doerase();
return;
case 'J': /* Erase in display */
if (p[0] < 0) p[0] = 0;
SetAPen(mywindow->RPort,0L);
if (p[0] == 0) {
if (y < MAXY) RectFill(mywindow->RPort,
(long)MINX,(long)(y+2),(long)(MAXX+7),(long)(MAXY+1));
}
else if (p[0] == 1) {
if (y > MINY) RectFill(mywindow->RPort,
(long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(y-7));
}
else RectFill(mywindow->RPort,
(long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1));
SetAPen(mywindow->RPort,1L);
doerase(); return;
case 'h': /* Set parameter */
if (p[0] == 20) nlmode = 1;
return;
case 'l': /* Reset parameter */
if (p[0] == 20) nlmode = 0;
return;
case 'x':
sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return;
case 'n':
if (p[0] == 6) {
sendchar(27);
sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1);
sendstring(escseq); return;
}
sendchar(27); sendstring("[0n"); return;
case 'c':
sendchar(27); sendstring("[?1;0c"); return;
}
/* Don't know how to do this one, so punt it */
}
void doindex(c)
char c;
{
if (c != 'M') {
if (c == 'E') x = MINX;
if (y > bot) if (y < MAXY) y += 8;
if (y == bot)
ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,(long)(top-6),
(long)(MAXX+7),(long)(bot+1));
if (y < bot) y += 8;
}
else {
if (y < top) if (y > MINY) y -= 8;
if (y == top)
ScrollRaster(mywindow->RPort,0L,-8L,(long)MINX,(long)(top-6),
(long)(MAXX+7),(long)(bot+1));
if (y > top) y -= 8;
}
return;
}
doalt(c)
char c;
{
int oldx,newx;
inesc = -1;
oldx = x; emit(' '); newx = x;
x = oldx;
SetAPen(mywindow->RPort,1L);
switch (c) {
case 'j':
case 'm':
case 'v': doline(4,-8,4,-4);
if (c=='j') doline(0,-4,4,-4);
else if (c=='m') doline(4,-4,8,-4);
else doline(0,-4,8,-4);
break;
case 'k':
case 'l':
case 'w': doline(4,-4,4,0);
if (c=='k') doline(0,-4,4,-4);
else if (c=='l') doline(4,-4,8,-4);
else doline(0,-4,8,-4);
break;
case 'n':
case 'q': doline(0,-4,8,-4);
if (c=='n') doline(4,-8,4,0);
break;
case 't':
case 'u':
case 'x': doline(4,-8,4,0);
if (c=='t') doline(4,-4,8,-4);
else if (c=='u') doline(0,-4,4,-4);
break;
}
x = newx;
}
doline(x1,y1,x2,y2) {
RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1),
(long)(x+x2),(long)(y+y2));
}
void doerase()
{
if (p[0] < 0) p[0] = 0;
SetAPen(mywindow->RPort,0L);
if (p[0] == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6),
(long)(MAXX+7),(long)(y+1));
else if (p[0] == 1) RectFill(mywindow->RPort,
(long)MINX,(long)(y-6),(long)(x+7),(long)(y+1));
else RectFill(mywindow->RPort,
(long)MINX,(long)(y-6),(long)(MAXX+7),(long)(y+1));
SetAPen(mywindow->RPort,1L);
return;
}
SHAR_EOF
cat << \SHAR_EOF > script.c
/*************************************************************
* vt100 terminal emulator - Script file support
*
* 860823 DBW - Integrated and rewrote lots of code
* 860815 Steve Drew: Initial version written of SCRIPT.C
* v2.0 860809 DBW - Major rewrite
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
*************************************************************/
#define MODULE_SCRIPT 1
#include "vt100.h"
extern char *fgets(),*malloc();
extern long ftell();
struct COMMAND {
int (*func)();
char *cname;
};
struct LABEL {
struct LABEL *next;
char *name;
long pos;
};
/**************** globals needed ******************/
char on_string[20]; /* string to match on for on cmd */
char wait_string[20]; /* string to match of for wait cmd */
char golabel[20]; /* label we are looking for in goto */
char on_cmd[255]; /* command to execute when on matchs*/
int onsize; /* size of on_string */
int waitsize; /* size of wait_string */
int onpos; /* position in on string for search */
int waitpos; /* pos in wait_string for search */
int on_match; /* flag set while doing on_cmd */
FILE *sf; /* file pointer for script file */
struct LABEL *lbase = NULL; /* will point to first label */
struct LABEL *labels; /* current label pointer */
int cmd_send(), cmd_wait(), cmd_on(), cmd_goto(), cmd_delay(), cmd_done(),
cmd_ks(), cmd_kg(), cmd_kr(), cmd_xs(), cmd_xr(), cmd_cap(), cmd_as(),
cmd_null(), cmd_kb();
char *next_wrd(), *tostring();
/********************** command table **********************************/
static struct COMMAND commands[]= {
cmd_send, "SEND", /* send string to host */
cmd_wait, "WAIT", /* wait for a string from host */
cmd_on, "ON", /* on a 'string' do a cmd */
cmd_goto, "GOTO", /* goto label */
cmd_delay, "DELAY", /* delay amount of seconds */
cmd_done, "EXIT", /* exit script file */
cmd_ks, "KS", /* kermit send file */
cmd_kr, "KR", /* kermit receive file */
cmd_kg, "KG", /* kermit get file */
cmd_kb, "KB", /* kermit bye (for server) */
cmd_xs, "XS", /* xmodem send file */
cmd_xr, "XR", /* xmodem receive file */
cmd_cap, "CAPTURE", /* ascii capture on/off */
cmd_as, "ASCII_SEND", /* ascii send */
cmd_null, NULL
};
/********************************************************************/
/* checks char to see if match with on string or wait_string */
/* if on string match oncmd gets executed imediately, */
/* if wait_string match script_wait is set. */
/********************************************************************/
chk_script(c)
char c;
{
if (on_string[0] != '\0') {
if (on_string[onpos] == c) {
onpos++;
if (onpos == onsize) {
on_match = TRUE;
do_script_cmd(ONCOMMAND);
on_match = FALSE;
return(0);
}
}
else onpos = 0;
}
if (wait_string[0] != '\0') {
if (wait_string[waitpos] != c) {
waitpos = 0;
return(0);
}
waitpos++;
if (waitpos != waitsize) return(0);
wait_string[0] = '\0';
script_wait = FALSE;
}
}
script_start(file)
char *file;
{
if ((sf = fopen(file, "r")) == NULL) {
emits("Can't open script file\n");
return(0);
}
script_on = TRUE;
script_wait = FALSE;
wait_string[0] = '\0';
on_string[0] = '\0';
on_match = FALSE;
lbase = NULL;
}
/* return pointer to next word. set l to size of the word */
char *next_wrd(s,l)
char *s;
int *l;
{
char *p;
while(*s && (*s == ' ' || *s == 9)) s++;
p = s;
while(*s && (*s != ' ' && *s != 9)) s++;
*l = s-p;
return(p);
}
exe_cmd(p,l)
char *p;
int l;
{
int i;
for (i=0; commands[i].func != cmd_null; ++i)
if (strncmp(p, commands[i].cname, l) == 0) {
(*commands[i].func)(next_wrd(p+l, &l));
return(TRUE);
}
emits ("\nScript - unknown command: ");
emits (p);
emits ("\n");
}
struct LABEL *find_label(lname)
char *lname;
{
struct LABEL *label;
label = lbase;
while(label != NULL) {
if (strcmp(label->name, lname) == 0) return (label);
label = label->next;
}
return(NULL);
}
do_script_cmd(stat)
int stat;
{
int len,l;
char line[256];
char *p;
if (stat == ONCOMMAND) { /* if ON command is matched and we were */
strcpy(line,on_cmd); /* doing a DELAY then abort the delay timer,*/
p = next_wrd(line,&l); /* except if on_cmd was just a SEND. */
if (*p != 'S' && script_wait == WAIT_TIMER) {
AbortIO((char *) &Script_Timer);
Wait (1L << Script_Timer_Port->mp_SigBit);
script_wait = FALSE; /* script will proceed after on command */
}
exe_cmd(p,l);
return(0);
}
script_wait = FALSE;
while(fgets(line,256,sf) != NULL) {
len = strlen(line);
line[--len] = '\0';
p = next_wrd(&line[0], &l);
if (*(p + l - 1) == ':') { /* its a label */
*(p + l - 1) = '\0';
if (find_label(p) == NULL) { /* it's a new label */
if (lbase == NULL) { /* it's the first label */
labels = lbase = (struct LABEL *) malloc (sizeof (struct LABEL));
}
else {
labels->next =
(struct LABEL *) malloc (sizeof (struct LABEL));
labels = labels->next;
}
labels->pos = ftell(sf);
labels->name = malloc(l);
labels->next = NULL;
strcpy(labels->name, p);
if (stat == GOTOLABEL && strcmp(p, golabel) == 0)
stat = NEXTCOMMAND;
}
if (l < len) p = next_wrd(p+l+1, &l);
else return(0);
} /* end of it's a label */
if (stat == GOTOLABEL || *p == '#') continue;
if (*p) exe_cmd(p,l);
return(0);
} /* end of while */
if (stat == GOTOLABEL) {
emits("\nScript - label not found: ");
emits(golabel);
emits("\n");
}
exit_script();
}
exit_script()
{
if (script_wait == WAIT_TIMER) /* timer not done yet */
AbortIO((char *) &Script_Timer); /* so abort it */
emits("\nScript - terminated\n");
script_on = FALSE;
script_wait = TRUE;
fclose(sf);
}
/* remove quotes terminate string & return pointer to start */
char *tostring(ptr)
char *ptr;
{
char *s;
s = ptr;
if (*ptr == '"') {
while(*ptr++ && *ptr !='"');
if (*ptr == '"') {
*ptr = '\0';
ptr = s+1;
while(*s++) if (*s == '|') *s = '\r';
return(ptr);
}
}
if (*s == '^') {
*s = *(s+1)-64;
*(s+1) = '\0';
return(s);
}
*(s+1) = '\0';
return(s);
}
cmd_goto(lname)
char *lname;
{
struct LABEL *label;
/* if on_cmd was a goto kill wait state */
if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
if ((label = find_label(lname)) == NULL) { /* is it forward */
strcpy(golabel,lname);
do_script_cmd(GOTOLABEL);
}
else {
fseek(sf,(long)(label->pos),0);
}
}
cmd_send(str)
char *str;
{
sendstring(tostring(str));
}
cmd_wait(str)
char *str;
{
str = tostring(str);
*(str+20) = '\0'; /* 20 characters max */
strcpy(wait_string, str);
waitsize = strlen(str);
script_wait = WAIT_STRING;
}
cmd_on(str)
char *str;
{
char *p;
p = tostring(str);
strcpy(on_string, p);
onsize = strlen(p);
*(p+onsize+2+20) = '\0'; /* 20 characters max */
strcpy(on_cmd,p+onsize+2);
}
cmd_delay(seconds)
char *seconds;
{
script_wait = WAIT_TIMER;
Script_Timer.tr_time.tv_secs = atoi(seconds);
Script_Timer.tr_time.tv_micro = 0;
SendIO((char *) &Script_Timer.tr_node);
}
cmd_done()
{
exit_script();
}
cmd_ks(file)
char *file;
{
multi_xfer(file, doksend, 1);
}
cmd_kr(file)
char *file;
{
multi_xfer(file, dokreceive, 0);
}
cmd_kg(file)
char *file;
{
server = TRUE;
multi_xfer(file, dokreceive, 0);
}
cmd_kb()
{
saybye();
}
cmd_xs(file)
char *file;
{
multi_xfer(file, XMODEM_Send_File, 1);
}
cmd_xr(file)
char *file;
{
multi_xfer(file, XMODEM_Read_File, 1);
}
cmd_cap(file)
char *file;
{
do_capture(file);
}
cmd_as(file)
char *file;
{
do_send(file);
}
cmd_null(file)
char *file;
{
}
SHAR_EOF
# End of shell archive
exit 0
Technical Details
Message-ID:
<1965@j.cc.purdue.edu>Path:
arc1-ca.pugleaf.net!utzoo!mnetor!seismo!caip!princeton!allegra!ulysses!bellcore!whuxcc!lcuxlm!whuxl!houxm!ihnp4!inuxc!pur-ee!j.cc.purdue.edu!docShow Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!caip!princeton!allegra!ulysses!bellcore!whuxcc!lcuxlm!whuxl!houxm!ihnp4!inuxc!pur-ee!j.cc.purdue.edu!doc From: doc@pucc-j.UUCP Newsgroups: mod.amiga.sources Subject: New VT100 (part 2 of 2) Message-ID: <1965@j.cc.purdue.edu> Date: Wed, 3-Sep-86 02:53:46 EDT Article-I.D.: j.1965 Posted: Wed Sep 3 02:53:46 1986 Date-Received: Thu, 4-Sep-86 20:16:44 EDT Sender: doc@j.cc.purdue.edu Organization: Purdue University Computing Center Lines: 2095 Approved: doc@pucc-j.UUCP