Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!decvax!ucbvax!ucbcad!nike!lll-crg!lll-lcc!qantel!ihnp4!inuxc!pur-ee!j.cc.purdue.edu!doc From: doc@j.cc.purdue.edu Newsgroups: mod.amiga.sources Subject: VT100 (V2.2 861012 DBW) Part 3 of 3 Message-ID: <2293@j.cc.purdue.edu> Date: Tue, 14-Oct-86 14:03:00 EDT Article-I.D.: j.2293 Posted: Tue Oct 14 14:03:00 1986 Date-Received: Thu, 16-Oct-86 08:42:17 EDT Sender: doc@j.cc.purdue.edu Organization: Purdue University Computing Center Lines: 1632 Approved: doc@j.cc.purdue.edu # 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 # This archive created: Tue Oct 14 12:58:51 1986 # By: Craig Norborg (Purdue University Computing Center) cat << \SHAR_EOF > init.c /*************************************************************** * vt100 - terminal emulator - initialization * * v2.2 861012 DBW - more of the same * v2.1 860915 DBW - new features (see README) * 860901 ACS - Added Parity and Word Length and support code * 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" char line[256]; char *InitDefaults(argc,argv) int argc; char **argv; { FILE *fd; char scr[32],delim,macro[256],c0,*ptr,*ptr2; int i,j,k; long li; if (((argc > 1) && (fd=fopen(argv[1],"r")) != 0) || (fd=fopen("vt100.init","r")) != 0 || (fd=fopen("s: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]|' ') == 'u') { /* buffer size */ if (sscanf(line,"%s %d",scr,&i) == 2) p_buffer = i; if (p_buffer < 512) p_buffer = 512; break; } if ((line[1]|' ') == 'r') { /* break time */ if (sscanf(line,"%s %ld",scr,&li) == 2) p_break = li; break; } if ((line[1]|' ') != 'a') break; switch(line[2]|' ') { /* baud rate */ case 'u': if (sscanf(line,"%s %d",scr,&i) == 2) switch (i) { case 300: case 1200: case 2400: case 4800: case 9600: p_baud = i; break; } 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 %x",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=(i==10?3: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 'k': /*keyscript*/ if (sscanf(line,"%s %x",scr,&i) == 2) p_keyscript = i & 0x7F; break; case 'm': if (sscanf(line,"%s %s",scr,scr) == 2) { if ((scr[0]|' ') == 'i') p_mode = 0; else p_mode = 1; } break; case 'p': /*parity*/ if (sscanf(line,"%s %s",scr,scr) == 2) switch(*scr|' ') { case 'n': p_parity = 0; break; case 'm': p_parity = 1; break; case 's': p_parity = 2; break; case 'e': p_parity = 3; break; case 'o': p_parity = 4; break; } break; case 'v': /*volume*/ if (sscanf(line,"%s %d",scr,&i) == 2) if (i > 0) p_volume = i; break; case 'w': /*wrap*/ if (sscanf(line,"%s %s",scr,scr) == 2) { if ((scr[1]|' ') == 'n') p_wrap = 1; else p_wrap = 0; } 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; } /* see if we exit with a startup script */ if ((c0|' ') == 'e') { ptr = &line[0]; while (*ptr != '\000' && *ptr != ' ' && *ptr != '\t') ptr++; if (*ptr == '\000') return(NULL); while (*ptr != '\000' && (*ptr == ' ' || *ptr == '\t')) ptr++; if (*ptr == '\000') return(NULL); ptr2 = ptr; while (*ptr2 != '\000' && *ptr2 != ' ' && *ptr2 != '\t' && *ptr2 != '\n') ptr2++; *ptr2 = '\000'; return(ptr); } else return(NULL); } void InitDevs() { USHORT colors[4]; int i; BYTE *b,*c; IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV); if( IntuitionBase == NULL ) cleanup("can't open intuition",1); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV); if( GfxBase == NULL ) cleanup("can't open graphics library",2); if (p_screen == 1) { if ((myscreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL) cleanup("can't open screen",3); NewWindow.Screen = myscreen; } if(( mywindow = (struct Window *)OpenWindow(&NewWindow) ) == NULL) cleanup("can't open window",4); 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 = 0L; Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort(0,0); if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL)) cleanup("Cant open Read device",5); rs_in = malloc(p_buffer+1); Read_Request->io_SerFlags = 0L; Read_Request->io_Baud = p_baud; Read_Request->io_ReadLen = 8L; Read_Request->io_WriteLen = 8L; Read_Request->io_CtlChar = 0x11130000L; Read_Request->io_RBufLen = p_buffer; Read_Request->io_BrkTime = p_break; Read_Request->IOSer.io_Command = SDCMD_SETPARAMS; DoIO(Read_Request); 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); b = (BYTE *)Read_Request; c = (BYTE *)Write_Request; for (i=0;iIOSer.io_Message.mn_ReplyPort = CreatePort(0,0); Write_Request->IOSer.io_Command = CMD_WRITE; Write_Request->IOSer.io_Length = 1; Write_Request->IOSer.io_Data = (APTR) &rs_out[0]; 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)) cleanup("can't open timer device",7); 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; BeepWave = (UBYTE *)AllocMem(BEEPSIZE,(long)(MEMF_CHIP|MEMF_CLEAR)); if (BeepWave != 0) BeepWave[0] = 100; Audio_Port = CreatePort("Audio Port",0); Audio_Request.ioa_Request.io_Message.mn_ReplyPort = Audio_Port; Audio_Request.ioa_Request.io_Message.mn_Node.ln_Pri = 85; Audio_Request.ioa_Data = Audio_AllocMap; Audio_Request.ioa_Length = (ULONG) sizeof(Audio_AllocMap); if (OpenDevice(AUDIONAME, NULL, (char *) &Audio_Request, NULL)) cleanup("can't open audio device",8); Audio_Request.ioa_Request.io_Command = CMD_WRITE; Audio_Request.ioa_Request.io_Flags = ADIOF_PERVOL; Audio_Request.ioa_Data = BeepWave; Audio_Request.ioa_Length = BEEPSIZE; Audio_Request.ioa_Period = COLORCLOCK / (BEEPSIZE * BEEPFREQ); Audio_Request.ioa_Volume = p_volume; Audio_Request.ioa_Cycles = 100; } /*****************************************************************/ /* 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 * * v2.2 861012 DBW - more of the same * v2.1 860915 DBW - new features (see README) * 860901 ACS - Added eight bit quoting * 860830 Steve Drew Wild card support, error recovery, bugs. * 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 CONVERTNAME TRUE /* convert file name to lower case for receive */ #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 MYEBQ '&' /* 8th bit prefix 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 */ sendabort, /* flag for aborting send file */ rptflg, /* are we doing repeat quoting */ ebqflg, /* are we doing 8th bit quoting */ notfirst, /* is this the first file received */ 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 */ ebq, /* Quote character for 8th bit quoting */ 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 */ 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 amount, c, wild; char *p, **list = NULL; if (!strcmp(file,"$")) { saybye(); return(2); } want_message = FALSE; /* tell readchar no error msgs */ p = file; while(*p && *p != '*' && *p != '?') p++; if (*p) { wild = TRUE; list = expand(file, &amount); if (list == NULL) emits("No wild card match\n"); } else { wild = FALSE; amount = 1; } for (c = 0; c < amount; c++) { if (wild == TRUE) p = list[c]; else p = file; strcpy(filnam,getfname(p)); ttime = TTIME_KERMIT; tp = retry = n = numtry = 0; totbytes = 0L; statusline(); if ((fp = fopen(p,"r")) == NULL) { emits("ERROR"); emits("\nVT100 - Kermit - Cannot open send file: "); emits(p); curmode = FS_NORMAL; continue; } emits("SEND"); ClearBuffer(); if (sendsw()) { x = 600; emits("DONE"); } fclose(fp); curmode = FS_NORMAL; } free_expand(list); return TRUE; } dokreceive(file,more) char *file; int more; { int retval; ttime = TTIME_KERMIT; if (!strcmp(file,"$")) { saybye(); return(2); } strcpy(filnam, file); statusline(); if (server) emits("GET "); else emits("RECV"); tp = retry = n = numtry = notfirst = 0; totbytes = 0L; want_message = FALSE; /* tell readchar no error msgs status bar instead */ ClearBuffer(); retval = recsw(); curmode = FS_NORMAL; return(retval); } sendsw() { char sinit(), sfile(), sdata(), seof(), sbreak(); sendabort = 0; 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': if (sendabort) return FALSE; else return TRUE; case 'E': x = 600; /* host sent us error packet */ emits("ERROR"); /* so print the error and abort */ print_host_err(ackpkt); return(FALSE); case 'A': x = 600; if (timeout == USERABORT) { timeout = GOODREAD; n = (n+1)%64; sendabort = 1; emits("ABORT"); strcpy(msgpkt, "D"); state = 'Z'; break; } if (timeout == TIMEOUT) emits("TMOUT"); else { /* protocol error dectected by us */ emits("ERROR"); print_our_err(); } 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 = MYQUOTE; numtry = 0; retry--; n = (n+1)%64; return('F'); case 'E': return('E'); 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('E'); 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('E'); 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) { /* tell host to discard file */ /* timeout = GOODREAD; spack('Z',n,1,"D"); } else */ spack('Z',n,sendabort,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('E'); 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('E'); 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(); state = 'R'; while(TRUE) { switch(state) { case 'R': state = rinit(); break; case 'Z': case 'F': state = rfile(); break; case 'D': state = rdata(); break; case 'C': return(TRUE); case 'E': 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"); /* send an error packet back */ spack('E',n,12,"User aborted"); } else if (timeout == TIMEOUT) { /* we timed out waiting */ /* will we need to spack here ?*/ emits("TMOUT"); } else emits("ERROR"); /* must be 'E' from host or we detected a protocol error */ if (state == 'E') print_host_err(msgpkt); else if (timeout == GOODREAD) /* tell host why */ print_our_err(); /* will this kill all files ?*/ do { ttime = 2; readchar(); } while (timeout == GOODREAD); fclose(fp); sendstring("\r"); return(FALSE); default: 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('E'); 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); 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; return(state); } else return('A'); case 'F': if (num != n) return('A'); strcpy(filnam,msgpkt); if (CONVERTNAME) { char *p; p = &filnam[0]; while (*p) { *p = tolower(*p); p++; } } if (notfirst) { curmode = FS_NORMAL; totbytes = 0L; statusline(); emits("RECV"); } else { /* is the first file so emit actual file name from host */ x = 48; emits(" "); x = 48; emits(filnam); notfirst++; } if ((fp = fopen(filnam,"w")) == NULL) { strcpy(msgpkt,"VT100 - Kermit - Unable to create file: "); strcat(msgpkt,filnam); spack('E',n,strlen(msgpkt),msgpkt); /* let host know */ x = 600; emits("ERROR"); emits("\n"); emits(msgpkt); /* let user know */ return ('\0'); /* abort everything */ } spack('Y',n,0,0); oldtry = numtry; numtry = 0; retry--; n = (n+1)%64; return('D'); case 'B': /* totaly done server sending no more */ if (num != n) return ('A'); spack('Y',n,0,0); retry--; return('C'); case 'E': return('E'); 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); 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 'Z': if (num != n) return('A'); spack('Y',n,0,0); n = (n+1)%64; retry--; x = 600; emits("DONE"); fclose(fp); return('Z'); case 'F': if (oldtry++ > MAXTRY) return('A'); if (num == ((n==0) ? 63:n-1)) { spack('Y',num,0,0); numtry = 0; return(state); } case 'E': return('E'); case FALSE: if (timeout == USERABORT) return('A'); 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; ClearBuffer(); 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 (ebqflg && b8) { /* Do 8th bit prefix if necessary. */ msgpkt[size++] = ebq; a = a7; } if ((a7 < SP) || (a7==DEL)) { msgpkt[size++] = quote; a = ctl(a); } if (a7 == quote) msgpkt[size++] = quote; if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote; if ((ebqflg) && (a7 == ebq)) /* Prefix the 8th bit prefix */ msgpkt[size++] = quote; /* if doing 8th-bit prefixes */ msgpkt[size++] = a; msgpkt[size] = '\0'; } void decode() { USHORT a, a7, b8; char *buf; buf = msgpkt; rpt = 0; while ((a = *buf++) != '\0') { if (rptflg) { if (a == rptq) { rpt = unchar(*buf++); a = *buf++; } } b8 = 0; if (ebqflg) { /* 8th-bit prefixing? */ if (a == ebq) { /* Yes, got an 8th-bit prefix? */ b8 = 0200; /* Yes, remember this, */ a = *buf++; /* and get the prefixed character. */ } } if (a == quote) { a = *buf++; a7 = a & 0177; if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a); } a |= b8; 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_KERMIT); data[2] = tochar(MYPAD); data[3] = ctl(MYPCHAR); data[4] = tochar(MYEOL); data[5] = MYQUOTE; if ((p_parity >= 0) || ebqflg) { /* 8-bit quoting... */ data[6] = MYEBQ; /* If parity or flag on, send &. */ if ((ebq > 0040 && ebq < 0100) || /* If flag off, then turn it on */ (ebq > 0140 && ebq < 0177) || /* if other side has asked us to */ (ebq == 'Y')) ebqflg = 1; } else /* Normally, */ data[6] = 'Y'; /* just say we're willing. */ data[7] = '1'; data[8] = MYRPTQ; data[9] = '\0'; } void rpar(data) char data[]; { spsiz = unchar(data[0]); ttime = unchar(data[1]); pad = unchar(data[2]); padchar = ctl(data[3]); eol = unchar(data[4]); quote = data[5]; rptflg = 0; ebqflg = 0; if (data[6] == 0) return; ebq = data[6]; if ((ebq > 040 && ebq < 0100) || (ebq > 0140 && ebq < 0177)) ebqflg = 1; else if (((p_parity >= 0) || ebqflg) && (ebq == 'Y')) { ebqflg = 1; ebq = '&'; } else ebqflg = 0; 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; spack('G',n,1,"F"); /* shut down server no more files */ rpack(&len,&num,ackpkt); } print_our_err() { if (retry > MAXTRY || oldtry > MAXTRY) strcpy(msgpkt,"VT100 - Kermit - Too many retries for packet"); else strcpy(msgpkt,"VT100 - Kermit - Protocol Error"); spack('E',n,strlen(msgpkt)); emits("\n"); emits(msgpkt); } print_host_err(msg) char *msg; { curmode = FS_NORMAL; emits("\n"); emits("Host Error: "); curmode = FSF_BOLD; emits(msg); } statusline() { emits ("\nFile: Pckt: Pckt No: Retrn: Bytes: Stat: "); x = 48; curmode = FSF_BOLD; emits (filnam); x = 600; 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++; while(*p && *p != ',' && *p != ' ') p++; if (*p == '\0') done = TRUE; else multi = 1; *p = '\0'; status = ((*mode)(name, multi)); if (status == TRUE && want_message) { if (do_send) emits("Sent File: "); else emits("Received File: "); emits(name); emits("\n"); } else if (status == FALSE && want_message) { close(fd); if (do_send) emits("Send Failed: "); else emits("Receive Failed: "); emits(name); emits("\n"); } if (!done && timeout != USERABORT) multi_xfer(++p, mode, do_send); else emits("\n"); server = 0; multi = 0; } ClearBuffer() { AbortIO(Read_Request); Read_Request->IOSer.io_Command = CMD_CLEAR; DoIO(Read_Request); Read_Request->IOSer.io_Command = CMD_READ; SendIO(Read_Request); } SHAR_EOF # End of shell archive exit 0