Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: 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 # 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 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 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> 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 (ybot) 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 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 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