/* * Windows Kermit * * Written by William S. Hall * 3665 Benton Street, #66 * Santa Clara, CA 95051 * * protocol module */ #define NOKANJI #define NOATOM #define NOMINMAX #include #include #include #include #include #include #include #include #define EXTERN #include "winasc.h" #include "winkpr.h" #include "winkpf.h" extern cid; /* local functions */ static BOOL NEAR paritycheck(void); static int NEAR wart(void); static void NEAR ShowTransactionError(HWND, int); static void NEAR scmd(char cmd); static void NEAR ttoi(BYTE *buf, int len); static int NEAR input(void); static void NEAR errpkt(HWND hWnd, int id); static int NEAR opent(HWND); static int NEAR sinit(void); static void NEAR sipkt(char c); static int NEAR sfile(void); static void NEAR seof(char *s); static int NEAR sdata(void); static void NEAR ack(int len, BYTE *s); static int NEAR nxtpkt(void); static int NEAR canned(char *buf); static int NEAR gnfile(void); static void NEAR seot(void); static void NEAR rinit(void); static void NEAR resetc(void); static void NEAR resend(void); static int NEAR rcvfil(void); static void NEAR reot(void); static int NEAR reof(void); static void NEAR srinit(void); static void NEAR spar(BYTE *data, int len); static int NEAR rpar(BYTE *data); static void NEAR spack(BYTE type, int num, int len, BYTE *data); static int NEAR bufill(BYTE buffer[]); static int NEAR encodebuf(BYTE outbuf[], BYTE inbuf[], int *inbufsize); static int NEAR bufemp(BYTE *buffer, int len, int dest); static HANDLE NEAR GetSendFileName(char *name); static HANDLE NEAR GetReceiveFileName(HWND hWnd, BYTE *packet); static void NEAR ShowErrorPacket(HWND hWnd, char *errstr); static int NEAR getpacket(BYTE *str, int len); static int NEAR input(void); static void NEAR UpdateXferBox(void); /* timer function */ void FAR PASCAL krmDoTimeout(HWND hWnd,unsigned message,short event,DWORD time) { KillTimer(hWnd, event); if (Kermit.bell) MessageBeep(0); rcvpkt.state = PS_SYNCH; Kermit.inpacket = FALSE; switch(event) { case KRM_WAITSEND: Kermit.waitsend = FALSE; break; default: Kermit.timeout = TRUE; break; } } /* local variables */ static int lclcount; static BYTE *lclbuf; static HWND lclhWnd; /* dispatch a string from the comm port. return when used up */ void krmKermitDispatch(HWND hWnd, BYTE *buf, int count) { if (Kermit.waitsend) return; lclcount = count; lclbuf = buf; lclhWnd = hWnd; wart(); if (Kermit.sstate < 0) SendMessage(lclhWnd, WM_COMMAND, IDM_CANCELPROTOCOL, (LONG)krmState); } /* protocol stuff */ #define RESUME return(0) #define wart() static int NEAR wart() static int vstate = 0; static char vcmd = 0; %states get rfile rdata %states ssinit ssfile ssdata sseof sseot %states ipkt rgen %% s { /* send */ tinit(lclhWnd, krmState); if (sinit()) BEGIN ssinit; else { Kermit.sstate = KRM_NO_SEND_FILE; RESUME; } } v { /* receive */ tinit(lclhWnd, krmState); BEGIN get; } r { /* get */ tinit(lclhWnd, krmState); vstate = get; vcmd = 0; sipkt('I'); BEGIN ipkt; } c { /* host */ tinit(lclhWnd, krmState); vstate = rgen; vcmd = 'C'; sipkt('I'); BEGIN ipkt; } g { /* generic */ tinit(lclhWnd, krmState); vstate = rgen; vcmd = 'G'; sipkt('I'); BEGIN ipkt; } S { /* got send_init */ rinit(); /* note : set block check type */ resetc(); BEGIN rfile; } Y { /* got ack for I-packet */ spar(rcvpkt.data, rcvpkt.len); if (vcmd) { scmd(vcmd); vcmd = 0; } if (vstate == get) srinit(); BEGIN vstate; } E { /* got E for I-packet, ignore */ if (vcmd) scmd(vcmd); vcmd = 0; if (vstate == get) srinit(); BEGIN vstate; } Y { /* got reply in ACK data */ bufemp(rcvpkt.data, rcvpkt.len, 2); Kermit.sstate = KRM_COMPLETE; RESUME; } F { /* got file header */ if (rcvfil()) { ack(strlen(Kermit.filename), Kermit.filename); BEGIN rdata; } else { Kermit.sstate = KRM_FILE_OPEN_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } } X { if (opent(lclhWnd)) { ack(0,""); BEGIN rdata; } else { Kermit.sstate = KRM_TERM_OPEN_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } } B { /* got eot */ ack(0,""); reot(); Kermit.sstate = KRM_COMPLETE; RESUME; } D { /* got data */ if (Kermit.fileabort) ack(1, "X"); else if (Kermit.batchabort) ack(1, "Z"); else ack(0,""); if (bufemp(rcvpkt.data, rcvpkt.len, Kermit.displayfile) < 0) { Kermit.sstate = KRM_FILE_WRITE_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } } Z { /* got end of file */ if (reof() < 0) { Kermit.sstate = KRM_FILE_CLOSE_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } else { ack(0,""); BEGIN rfile; } } Y { /* got ack to send init */ spar(rcvpkt.data, rcvpkt.len); /* note : set block check type */ if (sfile()) { resetc(); BEGIN ssfile; } else { Kermit.sstate = KRM_FILE_OPEN_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } } Y { /* got ack to F */ if (sdata() <= 0) { clsif(); seof(""); BEGIN sseof; } else BEGIN ssdata; } Y { if (canned(rcvpkt.data)) { clsif(); seof("D"); BEGIN sseof; } else if (sdata() <= 0) { clsif(); seof(""); BEGIN sseof; } } Y { /* got ack to EOF */ if (gnfile() > 0) { if (sfile()) BEGIN ssdata; else { Kermit.sstate = KRM_FILE_OPEN_ERROR; errpkt(lclhWnd, Kermit.sstate); RESUME; } } else { /* no next file */ seot(); BEGIN sseot; } } Y { /* got ack to EOT */ Kermit.sstate = KRM_COMPLETE; RESUME; } p { /* partial packet */ if (Kermit.numtry >= Kermit.maxtry) Kermit.sstate = KRM_RETRY_LIMIT; RESUME; } E { /* error packet */ bufemp(rcvpkt.data, rcvpkt.len, 2); clsif(); /* close input files */ clsof(TRUE); /* discard any output files */ Kermit.sstate = KRM_ERROR_PKT; RESUME; } $ { /* user abort */ Kermit.sstate = KRM_USERCNX; errpkt(lclhWnd,Kermit.sstate); RESUME; } . { Kermit.sstate = KRM_UNKNOWN_PACKET; errpkt(lclhWnd, Kermit.sstate); RESUME; } %% /* following are all support routines */ static void NEAR errpkt(HWND hWnd, int id) { char szError[80]; HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE); int *len, datalen; *len = LoadString(hInstance, id, (LPSTR)szError, sizeof(szError)); datalen = encodebuf(sndpkt.data,szError,len); spack('E', Kermit.pktnum, datalen, sndpkt.data); clsif(); clsof(1); } static void NEAR sipkt(char c) { BYTE buf[KRM_MAXPACKETSIZE]; FlushComm(cid,1); lclcount = 0; spack(c,Kermit.pktnum,rpar(buf),buf); } static int NEAR sinit() { if ((Kermit.pNextFile = strtok(Kermit.pfilelist," ,")) != NULL) { sipkt('S'); return(TRUE); } return(FALSE); } static int NEAR sfile() { int *len; register int datalen; BYTE buf[20]; Kermit.hInFile = GetSendFileName(Kermit.pNextFile); if (Kermit.hInFile == -1) return(0); strcpy(buf, Kermit.filename); *len = strlen(Kermit.filename); datalen = encodebuf(sndpkt.data, buf, len); nxtpkt(); spack('F',Kermit.pktnum, datalen, sndpkt.data); return(1); } static int NEAR sdata() { register int len; if (rcvpkt.len) { bufemp(rcvpkt.data, rcvpkt.len, 2); SetDlgItemText(hWndXfer, IDD_SAVENAME,(LPSTR)rcvpkt.data); } if (Kermit.fileabort || Kermit.batchabort) return(-1); if ((len = bufill(sndpkt.data)) > 0) { nxtpkt(); spack('D', Kermit.pktnum, len, sndpkt.data); } if (len < 0) ShowTransactionError(lclhWnd, KRM_FILE_READ_ERROR); return(len); } static void NEAR seof(char *s) { nxtpkt(); if ((s != NULL) && (*s != NUL)) spack('Z', Kermit.pktnum, 1, s); else spack('Z', Kermit.pktnum, 0, ""); } static void NEAR ack(int len, BYTE *s) { spack('Y', Kermit.pktnum, len, s); nxtpkt(); } static int NEAR nxtpkt() { Kermit.pktcount += 1; return(Kermit.pktnum = (Kermit.pktnum + 1) & 63); } void clsif() { if (Kermit.hInFile) { Kermit.hInFile = (HANDLE)close(Kermit.hInFile); Kermit.hInFile = NULL; } Kermit.fileabort = FALSE; } static int NEAR canned(char *buf) { if (*buf == 'X') Kermit.fileabort = TRUE; if (*buf == 'Z') Kermit.batchabort = TRUE; return((Kermit.fileabort || Kermit.batchabort) ? 1 : 0); } static int NEAR gnfile() { /* don't do this if displaying on terminal */ if (Kermit.batchabort || (Kermit.pNextFile = strtok(NULL, " ,")) == NULL) return(0); return(1); } static void NEAR seot() { nxtpkt(); spack('B', Kermit.pktnum,0, ""); Kermit.fileabort = Kermit.batchabort = FALSE; } static void NEAR rinit() { BYTE buf[100]; spar(rcvpkt.data, rcvpkt.len); ack(rpar(buf), buf); } static int NEAR rcvfil() { bufemp(rcvpkt.data, rcvpkt.len, 2); if ((Kermit.hOutFile = GetReceiveFileName(lclhWnd,rcvpkt.data)) == -1) return(0); return(1); } static int NEAR reof() { register int x; if (Kermit.fileabort == FALSE) Kermit.fileabort = rcvpkt.len ? (rcvpkt.data[0] == 'D') : FALSE; x = clsof(Kermit.fileabort | Kermit.batchabort); if (Kermit.fileabort || Kermit.batchabort) Kermit.fileabort = FALSE; return(x); } int clsof(int disp) { if (Kermit.displayfile) return(1); if (Kermit.hOutFile) { if ((Kermit.hOutFile = (HANDLE)close(Kermit.hOutFile)) != NULL) return(-1); if (disp && Kermit.filediscard) unlink(myofstruct.szPathName); return(1); } } static void NEAR reot() { Kermit.fileabort = Kermit.batchabort = FALSE; } static void NEAR resetc() { /* add appropriate code */ } static void NEAR resend() { Kermit.numtry += 1; Kermit.retrycount += 1; if (sndpkt.len) ttoi(sndpkt.pktbuf, sndpkt.len); else spack('N', Kermit.pktnum, 0, ""); if (IsWindow(hWndXfer)) UpdateXferBox(); } static void NEAR srinit() { int *len; *len = strlen(Kermit.pfilelist); spack('R', Kermit.pktnum, encodebuf(sndpkt.data,Kermit.pfilelist,len), sndpkt.data); } static void NEAR scmd(char cmd) { int *len; register int datalen; switch (krmState) { case IDM_KRM_FINISH: datalen = 1; sndpkt.data[0] = 'F'; break; case IDM_KRM_BYE: case IDM_KRM_LOGOUT: datalen = 1; sndpkt.data[0] = 'L'; break; case IDM_KRM_REMOTEHOST: *len = strlen(Kermit.pfilelist); datalen = encodebuf(sndpkt.data, Kermit.pfilelist,len); break; default: *len = strlen(Kermit.pRemoteCommand); datalen = encodebuf(sndpkt.data, Kermit.pRemoteCommand,len); break; } spack(cmd,Kermit.pktnum,datalen,sndpkt.data); } static int NEAR opent(HWND hWnd) { BYTE crstring[3]; if (krmInitMainDisplay(hWnd, Kermit.DispCharWidth, Kermit.DispCharHeight)) { bufemp(rcvpkt.data, rcvpkt.len, 2); krmMainStringDisplay(hWnd, rcvpkt.data, rcvpkt.len); crstring[0] = CR; crstring[1] = LF; krmMainStringDisplay(hWnd, crstring,2); Kermit.displayfile = 1; return(TRUE); } return FALSE; } static BOOL NEAR paritycheck() { DCB commdata; GetCommState(cid, (DCB FAR *)&commdata); if ((commdata.Parity == NOPARITY) && (commdata.ByteSize == 8)) return FALSE; return TRUE; } static int NEAR rpar(BYTE *data) { register int i = 0; data[i++] = (BYTE)tochar(local.maxpacketsize); data[i++] = (BYTE)tochar(local.timeout); data[i++] = (BYTE)tochar(local.padcount); data[i++] = ctl(local.padchar); data[i++] = (BYTE)tochar(local.eol); data[i++] = local.quote; switch (Kermit.rqf) { case -1 : case 1 : if (paritycheck()) Kermit.ebq = local.binquote = '&'; break; case 0 : case 2 : break; } data[i++] = local.binquote; /* fixup: get these fields straight */ data[i++] = (BYTE)(local.chksumtype + '0'); data[i++] = local.rptprefix; return(i); } static void NEAR spar(BYTE *data, int len) { register int i = 0; register int intval; char charval; intval = (i < len) ? unchar(data[i++]) : KRM_DEFPACKETSIZE; remote.maxpacketsize = (intval < KRM_MINPACKETSIZE) ? KRM_DEFPACKETSIZE : intval; intval = (i < len) ? unchar(data[i++]) : KRM_DEFTIMEOUT; remote.timeout = ((intval < 0) || (intval > 65)) ? KRM_DEFTIMEOUT : intval; Kermit.mstimeout = 1000 * remote.timeout; remote.padcount = KRM_DEFPADCOUNT; remote.padchar = KRM_DEFPADCHAR; if (i < len) { remote.padcount = unchar(data[i++]); if (i < len) if ((((charval = ctl(data[i++])) >= 0) && (charval < SP)) || (charval == DEL)) remote.padchar = charval; } intval = (i < len) ? unchar(data[i++]) : KRM_DEFEOL; remote.eol = ((intval > SOH) || (intval < SP)) ? intval : KRM_DEFEOL; charval = (i < len) ? data[i++] : KRM_DEFQUOTE; remote.quote = ((charval > SP) && (charval < '?')) || ((charval > '_') && (charval < DEL)) ? charval : KRM_DEFQUOTE; charval = remote.binquote = (i < len) ? data[i++] : 0; if (charval == 'Y') Kermit.rqf = 1; else if ((charval > 32 && charval < '?') || (charval > '_' && charval < DEL)) Kermit.rqf = 2; else Kermit.rqf = 0; switch (Kermit.rqf) { case 0 : Kermit.ebqflg = FALSE; break; case 1 : if (paritycheck()) { Kermit.ebqflg = TRUE; Kermit.ebq = '&'; } break; case 2: if (Kermit.ebqflg = (Kermit.ebq == local.binquote || local.binquote == 'Y')) Kermit.ebq = charval; break; } /* fixup the following code */ intval = 1; if (i < len) { intval = data[i++] - '0'; if ((intval < 1) || (intval > 3)) intval = 1; } remote.chksumtype = intval; if (i < len) { remote.rptprefix = charval = data[i++]; Kermit.rptflg = ((charval > 32 && charval < '?') || (charval > '_' && charval < DEL)); } else Kermit.rptflg = FALSE; Kermit.maxsenddatalen = remote.maxpacketsize - 2 - Kermit.chksumtype; } static void NEAR spack(BYTE type, int num, int len, BYTE *data) { WORD chksum = 0; register int i, k; sndpkt.len = 0; sndpkt.data[len] = NUL; if (k = remote.padcount) { memset(sndpkt.pktbuf, remote.padchar, k); ttoi(sndpkt.pktbuf, k); } k = 0; sndpkt.pktbuf[k++] = sndpkt.mark; chksum += sndpkt.pktbuf[k++] = (BYTE)tochar(len + 3); chksum += sndpkt.pktbuf[k++] = (BYTE)tochar(num); chksum += sndpkt.pktbuf[k++] = type; for (i = 0; i < len; i++) chksum += sndpkt.pktbuf[k++] = data[i]; chksum = (((chksum & 0300) >> 6) + chksum) & 077; sndpkt.pktbuf[k++] = (BYTE)tochar(chksum); sndpkt.pktbuf[k++] = (BYTE)remote.eol; sndpkt.pktbuf[k] = NUL; ttoi(sndpkt.pktbuf,k); sndpkt.len = k; } static void NEAR ttoi(BYTE *buf, int len) { COMSTAT mycomstat; register int inque; do { GetCommError(cid, (COMSTAT FAR *)&mycomstat); inque = mycomstat.cbOutQue; } while(inque); WriteComm(cid, (LPSTR)buf, len); } static int NEAR bufill(BYTE buffer[]) { register int numloaded, numread; BYTE buf[KRM_MAXPACKETSIZE]; int numrem; if ((numread = read(Kermit.hInFile,buf,Kermit.maxsenddatalen)) <= 0) { numloaded = numread; if (numread == 0) Kermit.percentage = 100; } else { numrem = numread; numloaded = encodebuf(buffer, buf, &numrem); lseek(Kermit.hInFile, (LONG)(-numrem), SEEK_CUR); if (Kermit.filesize) { Kermit.bytesmoved += numread - numrem; Kermit.percentage = (int)(Kermit.bytesmoved *100 / Kermit.filesize); } } return(numloaded); } static int NEAR encodebuf(BYTE outbuf[], BYTE inbuf[], int *inbufsize) { register int i,j; BYTE t, t7; int maxbufsize = Kermit.maxsenddatalen - 3; /* char + prefix */ char quote = remote.quote; char binquote = Kermit.ebq; if (Kermit.ebqflg) { for (i = 0, j = 0 ; j < *inbufsize ; ) { t = inbuf[j++]; if (t & 0x80) outbuf[i++] = binquote; if (((t7 = t & 0x7f) < SP) || (t7 == DEL)) { outbuf[i++] = quote; t7 = ctl(t7); } else if ((t7 == quote) || (t7 == binquote)) outbuf[i++] = quote; outbuf[i++] = t7; if (i > maxbufsize) break; } } else { for (i = 0, j = 0 ; j < *inbufsize ; ) { t = inbuf[j++]; if ((t7 = t & 0x7f) < SP || t7 == DEL || t7 == quote) { outbuf[i++] = quote; if (t7 != quote) t = ctl(t); } outbuf[i++] = t; if (i > maxbufsize) break; } } *inbufsize -= j; return(i); } static int NEAR bufemp(BYTE *buffer, int len, int dest) { register int i,j; int result; BYTE t, t7, wbuf[100]; BYTE bitset; char quote = local.quote; char binquote = Kermit.ebq; if (Kermit.ebqflg) { for (i = 0, j = 0; i < len; i++) { t = buffer[i]; if (t == binquote) { t = buffer[++i]; bitset = 0x80; } else bitset = 0; if (t == quote) { t = buffer[++i]; if (((t7 = t & 0x7f) != quote) && (t7 != binquote)) t = ctl(t); } wbuf[j++] = t | bitset; } } else { for (i = 0, j = 0; i < len; i++) { t = buffer[i]; if (t == quote) { t = buffer[++i]; if ((t & 0x7f) != quote) t = ctl(t); } wbuf[j++] = t; } } wbuf[j] = NUL; switch (dest) { case 2 : strcpy(rcvpkt.data, wbuf); rcvpkt.len = j; return (TRUE); case 1 : krmMainStringDisplay(lclhWnd, wbuf, j); return (TRUE); default: if ((result = write(Kermit.hOutFile, wbuf, j)) >= 0) Kermit.bytesmoved += result; if ((result < j) || (result == -1)) return(-1); else return(result); } } static HANDLE NEAR GetSendFileName(char *name) { HANDLE hfile; struct stat buf; hfile = OpenFile((LPSTR)name, (OFSTRUCT FAR *)&myofstruct,OF_READ); if (hfile != -1) { Kermit.filename = (strrchr(myofstruct.szPathName,'\\') + 1); SetDlgItemText(hWndXfer, IDD_FILENAME,(LPSTR)Kermit.filename); fstat(hfile, &buf); Kermit.filesize = buf.st_size; } Kermit.bytesmoved = 0; Kermit.percentage = 0; return hfile; } static HANDLE NEAR GetReceiveFileName(HWND hWnd, BYTE *packet) { HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE); register int i, j; char filename[13]; char ext[5]; int numresult; char *ptrresult; BOOL gotextension; HANDLE hfile; char tempname[9], genstring[20]; int filecount; Kermit.newname_flag = FALSE; memset(filename, NUL, 13); ext[0] = NUL; SetDlgItemText(hWndXfer, IDD_FILENAME,(LPSTR)packet); ptrresult = strtok(packet, "."); /* look for any extension */ numresult = strlen(ptrresult); /* find out how long */ numresult = numresult < 8 ? numresult : 8; strncpy(filename,ptrresult,numresult); /* load up name */ gotextension = FALSE; ptrresult = strtok(NULL, "."); /* get extension */ if (ptrresult != NULL) { strcpy(ext,"."); strncat(ext, ptrresult,3); ext[4] = NUL; strcat(filename, ext); gotextension = TRUE; } if (Kermit.filewarning) { for (filecount = 0; filecount < INT_MAX; filecount++) { if ((hfile = OpenFile((LPSTR)filename, (OFSTRUCT FAR *)&myofstruct,OF_EXIST)) == -1) break; ptrresult = strtok(filename, "."); strcpy(tempname, ptrresult); numresult = strlen(ptrresult); for (i = numresult; i < 8; i++) tempname[i] = '0'; numresult = strlen(itoa(filecount + 1, genstring,10)); for (i = 8 - numresult, j = 0; i < 8; i++,j++) tempname[i] = genstring[j]; tempname[8] = NUL; strcpy(filename, tempname); if (gotextension) strcat(filename,ext); } if (filecount > 0) Kermit.newname_flag = TRUE; } hfile = OpenFile((LPSTR)filename,(OFSTRUCT FAR *)&myofstruct,OF_CREATE); if (hfile != -1) { Kermit.filename = (strrchr(myofstruct.szPathName,'\\') + 1); SetDlgItemText(hWndXfer, IDD_SAVENAME,(LPSTR)Kermit.filename); } Kermit.bytesmoved = 0; return (hfile); } static int NEAR input() { int type, rsn, seq; int startcount; if (Kermit.sstate > 0) { type = Kermit.sstate; Kermit.sstate = 0; return(type); } if (Kermit.protocolabort) return('$'); again: if (!Kermit.inpacket) { if (IsWindow(hWndXfer)) UpdateXferBox(); if (Kermit.timer) SetTimer(lclhWnd, KRM_WAITPACKET, Kermit.mstimeout, Kermit.fpTimer); Kermit.inpacket = TRUE; } startcount = lclcount; lclcount = getpacket(lclbuf, lclcount); lclbuf += startcount - lclcount; if (rcvpkt.state == PS_DONE) { rcvpkt.state = PS_SYNCH; Kermit.inpacket = FALSE; if (Kermit.timer) { KillTimer(lclhWnd, KRM_WAITPACKET); Kermit.timeout = FALSE; } type = rcvpkt.type; rsn = rcvpkt.num; seq = Kermit.pktnum; if (type == sndpkt.pktbuf[3]) goto again; if ((rsn != seq) || (type == 'N') || (type == 'Q')) { if ((type == 'N') && (rsn == (seq + 1) & 63)) { Kermit.numtry = 0; return ('Y'); } else { resend(); goto again; } } Kermit.numtry = 0; return (type); } else { if (Kermit.timeout) { Kermit.timeout = FALSE; resend(); } return('p'); } } /* get a packet, complete or partial */ static int NEAR getpacket(BYTE *str, int len) { register BYTE t; register int i; while (len) { switch (rcvpkt.state) { case PS_SYNCH: while (len) { if (*str != rcvpkt.mark) { str++; len--; } else break; } if (len) { str++; len--; rcvpkt.state = PS_LEN; rcvpkt.cchksum = 0; rcvpkt.data_count = 0; rcvpkt.data[0] = NUL; } break; case PS_LEN: if ((t = *str) == rcvpkt.mark) rcvpkt.state = PS_SYNCH; else { rcvpkt.state = PS_NUM; rcvpkt.len = unchar(t) - 2 - Kermit.chksumtype; rcvpkt.cchksum += t; str++; len--; } break; case PS_NUM: if ((t = *str) == rcvpkt.mark) rcvpkt.state = PS_SYNCH; else { rcvpkt.state = PS_TYPE; rcvpkt.num = unchar(t); rcvpkt.cchksum += t; str++; len--; } break; case PS_TYPE: if ((t = *str) == rcvpkt.mark) rcvpkt.state = PS_SYNCH; else { if (rcvpkt.len) rcvpkt.state = PS_DATA; else rcvpkt.state = PS_CHK; rcvpkt.type = t; rcvpkt.cchksum += t; str++; len--; } break; case PS_DATA: for (i = rcvpkt.data_count; i < rcvpkt.len; i++) { if ((t = *str) == rcvpkt.mark) break; else { rcvpkt.data[i] = t; rcvpkt.cchksum += t; rcvpkt.data_count += 1; str++; len--; if (len <= 0) break; } } if (t == rcvpkt.mark) rcvpkt.state = PS_SYNCH; else if (rcvpkt.data_count == rcvpkt.len) { rcvpkt.data[rcvpkt.len] = NUL; rcvpkt.state = PS_CHK; } break; case PS_CHK: if ((t = *str) == rcvpkt.mark) rcvpkt.state = PS_SYNCH; else { rcvpkt.rchksum = unchar(t); str++; len--; rcvpkt.cchksum = (((rcvpkt.cchksum & 0xC0) >> 6) + rcvpkt.cchksum) & 0x3f; if (rcvpkt.cchksum != rcvpkt.rchksum) rcvpkt.type = 'Q'; rcvpkt.state = PS_DONE; } break; case PS_DONE: if ((t = *str) == (BYTE)local.eol) { str++; len--; } return len; } /* switch */ } /* while */ return len; } static void NEAR ShowTransactionError(HWND hWnd, int id) { char szMessage[80]; char szCaption[40]; HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE); LoadString(hInstance, IDS_KRM_KERMIT, (LPSTR)szCaption, sizeof(szCaption)); LoadString(hInstance, id, (LPSTR)szMessage, sizeof(szMessage)); if (Kermit.bell) MessageBeep(MB_OK | MB_ICONASTERISK); MessageBox(hWnd,(LPSTR)szMessage,(LPSTR)szCaption, MB_OK | MB_ICONASTERISK); } static void NEAR UpdateXferBox() { char str[20]; static int prevcount; if (IsIconic(lclhWnd)) InvalidateRect(lclhWnd, (LPRECT)NULL, FALSE); else { SetDlgItemText(hWndXfer,IDD_BYTESMOVED,ltoa(Kermit.bytesmoved,str,10)); SetDlgItemInt(hWndXfer,IDD_PACKETS,Kermit.pktcount,0); if (krmState == IDM_KRM_SEND) SetDlgItemInt(hWndXfer,IDD_PERCENTAGE,Kermit.percentage,0); if (prevcount != Kermit.retrycount) { SetDlgItemInt(hWndXfer,IDD_RETRIES,Kermit.retrycount,0); prevcount = Kermit.retrycount; } } }