home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / win100.zip / winkpr.w < prev    next >
Text File  |  1991-10-20  |  26KB  |  1,174 lines

  1. /*
  2.  * Windows Kermit
  3.  * 
  4.  * Written by William S. Hall
  5.  *          3665 Benton Street, #66
  6.  *          Santa Clara, CA 95051
  7.  *
  8.  * protocol module
  9.  */
  10.  
  11. #define NOKANJI
  12. #define NOATOM
  13. #define NOMINMAX
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <io.h>
  18. #include <stdio.h>
  19. #include <limits.h>
  20. #include <sys\types.h>
  21. #include <sys\stat.h>
  22.  
  23. #define EXTERN
  24.  
  25. #include "winasc.h"
  26. #include "winkpr.h"
  27. #include "winkpf.h"
  28.  
  29. extern cid;
  30.  
  31. /* local functions */
  32. static BOOL NEAR paritycheck(void);
  33. static int NEAR wart(void);
  34. static void NEAR ShowTransactionError(HWND, int);
  35. static void NEAR scmd(char cmd);
  36. static void NEAR ttoi(BYTE *buf, int len);
  37. static int NEAR input(void);
  38. static void NEAR errpkt(HWND hWnd, int id);
  39. static int NEAR opent(HWND);
  40. static int NEAR sinit(void);
  41. static void NEAR sipkt(char c);
  42. static int NEAR sfile(void);
  43. static void NEAR seof(char *s);
  44. static int NEAR sdata(void);
  45. static void NEAR ack(int len, BYTE *s);
  46. static int NEAR nxtpkt(void);
  47. static int NEAR canned(char *buf);
  48. static int NEAR gnfile(void);
  49. static void NEAR seot(void);
  50. static void NEAR rinit(void);
  51. static void NEAR resetc(void);
  52. static void NEAR resend(void);
  53. static int NEAR rcvfil(void);
  54. static void NEAR reot(void);
  55. static int NEAR reof(void);
  56. static void NEAR srinit(void);
  57. static void NEAR spar(BYTE *data, int len);
  58. static int NEAR rpar(BYTE *data);
  59. static void NEAR spack(BYTE type, int num, int len, BYTE *data);
  60. static int NEAR bufill(BYTE buffer[]);
  61. static int NEAR encodebuf(BYTE outbuf[], BYTE inbuf[], int *inbufsize);
  62. static int NEAR bufemp(BYTE *buffer, int len, int dest);
  63. static HANDLE NEAR GetSendFileName(char *name);
  64. static HANDLE NEAR GetReceiveFileName(HWND hWnd, BYTE *packet);
  65. static void NEAR ShowErrorPacket(HWND hWnd, char *errstr);
  66. static int NEAR getpacket(BYTE *str, int len);
  67. static int NEAR input(void);
  68. static void NEAR UpdateXferBox(void);
  69.  
  70. /* timer function */
  71. void FAR PASCAL krmDoTimeout(HWND hWnd,unsigned message,short event,DWORD time)
  72. {
  73.  
  74.     KillTimer(hWnd, event);
  75.     if (Kermit.bell)
  76.         MessageBeep(0);
  77.  
  78.     rcvpkt.state = PS_SYNCH;
  79.     Kermit.inpacket = FALSE;
  80.     switch(event) {
  81.     case KRM_WAITSEND:
  82.         Kermit.waitsend = FALSE;
  83.         break;
  84.     default:
  85.         Kermit.timeout = TRUE;
  86.         break;
  87.     }
  88. }
  89.  
  90. /* local variables */
  91. static int lclcount;
  92. static BYTE *lclbuf;
  93. static HWND lclhWnd;
  94.  
  95. /* dispatch a string from the comm port.  return when used up */
  96. void krmKermitDispatch(HWND hWnd, BYTE *buf, int count)
  97. {
  98.  
  99.  
  100.     if (Kermit.waitsend)
  101.     return;
  102.  
  103.     lclcount = count;
  104.     lclbuf = buf;
  105.     lclhWnd = hWnd;
  106.  
  107.     wart();
  108.  
  109.     if (Kermit.sstate < 0)
  110.     SendMessage(lclhWnd, WM_COMMAND, IDM_CANCELPROTOCOL, (LONG)krmState);
  111. }
  112.  
  113. /* protocol stuff */
  114. #define RESUME return(0)
  115. #define wart() static int NEAR wart()
  116. static int vstate = 0;
  117. static char vcmd = 0;
  118.  
  119. %states get rfile rdata
  120. %states ssinit ssfile ssdata sseof sseot
  121. %states ipkt rgen
  122. %%
  123.  
  124. s {                    /* send */
  125.     tinit(lclhWnd, krmState);
  126.     if (sinit())
  127.     BEGIN ssinit;
  128.     else {
  129.     Kermit.sstate = KRM_NO_SEND_FILE;
  130.     RESUME;
  131.     }
  132. }
  133.  
  134. v {                    /* receive */
  135.     tinit(lclhWnd, krmState);
  136.     BEGIN get;
  137. }
  138.  
  139. r {                    /* get */
  140.     tinit(lclhWnd, krmState);
  141.     vstate = get;
  142.     vcmd = 0;
  143.     sipkt('I');
  144.     BEGIN ipkt;
  145. }
  146.  
  147. c {                    /* host */
  148.     tinit(lclhWnd, krmState);
  149.     vstate = rgen;
  150.     vcmd = 'C';
  151.     sipkt('I');
  152.     BEGIN ipkt;
  153. }
  154.  
  155. g {                    /* generic */
  156.     tinit(lclhWnd, krmState);
  157.     vstate = rgen;
  158.     vcmd = 'G';
  159.     sipkt('I');
  160.     BEGIN ipkt;
  161. }
  162.  
  163. <rgen,get>S {                /* got send_init */
  164.     rinit();
  165.   /* note : set block check type */
  166.     resetc();
  167.     BEGIN rfile;
  168. }
  169.  
  170. <ipkt>Y {                /* got ack for I-packet */
  171.     spar(rcvpkt.data, rcvpkt.len);
  172.     if (vcmd) {
  173.     scmd(vcmd);
  174.     vcmd = 0;
  175.     }
  176.     if (vstate == get)
  177.     srinit();
  178.     BEGIN vstate;
  179. }
  180.  
  181. <ipkt>E {            /* got E for I-packet, ignore */
  182.     if (vcmd)
  183.     scmd(vcmd);
  184.     vcmd = 0;
  185.     if (vstate == get)
  186.     srinit();
  187.     BEGIN vstate;
  188. }
  189.  
  190. <rgen>Y {            /* got reply in ACK data */
  191.     bufemp(rcvpkt.data, rcvpkt.len, 2);
  192.     Kermit.sstate = KRM_COMPLETE;
  193.     RESUME;
  194. }
  195.  
  196. <rgen,rfile>F {            /* got file header */
  197.     if (rcvfil()) {
  198.         ack(strlen(Kermit.filename), Kermit.filename);
  199.     BEGIN rdata;
  200.     }
  201.     else {
  202.     Kermit.sstate = KRM_FILE_OPEN_ERROR;
  203.     errpkt(lclhWnd, Kermit.sstate);
  204.     RESUME;
  205.     }
  206. }
  207.  
  208. <rgen,rfile>X {
  209.     if (opent(lclhWnd)) {
  210.         ack(0,"");
  211.         BEGIN rdata;
  212.     }
  213.     else {
  214.     Kermit.sstate = KRM_TERM_OPEN_ERROR;
  215.     errpkt(lclhWnd, Kermit.sstate);
  216.     RESUME;
  217.     }
  218. }
  219.  
  220. <rfile>B {                 /* got eot */
  221.     ack(0,"");
  222.     reot();
  223.     Kermit.sstate = KRM_COMPLETE;
  224.     RESUME;
  225. }
  226.  
  227. <rdata>D {                /* got data */
  228.     if (Kermit.fileabort)
  229.     ack(1, "X");
  230.     else if (Kermit.batchabort)
  231.     ack(1, "Z");
  232.     else
  233.     ack(0,"");
  234.     if (bufemp(rcvpkt.data, rcvpkt.len, Kermit.displayfile) < 0) {
  235.     Kermit.sstate = KRM_FILE_WRITE_ERROR;
  236.     errpkt(lclhWnd, Kermit.sstate);
  237.     RESUME;
  238.     }
  239. }
  240.  
  241. <rdata>Z {                /* got end of file */
  242.     if (reof() < 0) {
  243.     Kermit.sstate = KRM_FILE_CLOSE_ERROR;
  244.     errpkt(lclhWnd, Kermit.sstate);
  245.     RESUME;
  246.     } else {
  247.         ack(0,"");
  248.     BEGIN rfile;
  249.     }
  250. }
  251.  
  252. <ssinit>Y {                /* got ack to send init */
  253.     spar(rcvpkt.data, rcvpkt.len);
  254.   /* note : set block check type */
  255.     if (sfile()) {
  256.     resetc();
  257.     BEGIN ssfile;
  258.     } else {
  259.     Kermit.sstate = KRM_FILE_OPEN_ERROR;
  260.     errpkt(lclhWnd, Kermit.sstate);
  261.     RESUME;
  262.     }
  263. }         
  264.  
  265. <ssfile>Y {                 /* got ack to F */
  266.     if (sdata() <= 0) {
  267.     clsif();
  268.     seof("");
  269.     BEGIN sseof;
  270.     }
  271.     else
  272.     BEGIN ssdata;
  273. }
  274.  
  275. <ssdata>Y { 
  276.     if (canned(rcvpkt.data)) {
  277.     clsif();
  278.     seof("D");
  279.     BEGIN sseof;
  280.     }
  281.     else if (sdata() <= 0) {
  282.     clsif();
  283.     seof("");
  284.     BEGIN sseof;
  285.     }
  286. }
  287.  
  288. <sseof>Y {                 /* got ack to EOF */
  289.     if (gnfile() > 0) {
  290.     if (sfile())
  291.         BEGIN ssdata;
  292.     else {
  293.          Kermit.sstate = KRM_FILE_OPEN_ERROR;
  294.         errpkt(lclhWnd, Kermit.sstate);
  295.         RESUME;
  296.     }
  297.     } else {                /* no next file */
  298.     seot();
  299.     BEGIN sseot;
  300.     }
  301. }    
  302.  
  303. <sseot>Y {                 /* got ack to EOT */
  304.     Kermit.sstate = KRM_COMPLETE;
  305.     RESUME;
  306. }
  307.       
  308. p {                    /* partial packet */
  309.     if (Kermit.numtry >= Kermit.maxtry)
  310.     Kermit.sstate = KRM_RETRY_LIMIT;
  311.     RESUME;
  312. }
  313.  
  314. E {                     /* error packet */
  315.     bufemp(rcvpkt.data, rcvpkt.len, 2);
  316.     clsif();                /* close input files */
  317.     clsof(TRUE);            /* discard any output files */
  318.     Kermit.sstate = KRM_ERROR_PKT;
  319.     RESUME; 
  320. }
  321.  
  322. $ {                    /* user abort */
  323.     Kermit.sstate = KRM_USERCNX;
  324.     errpkt(lclhWnd,Kermit.sstate);
  325.     RESUME;
  326. }
  327.  
  328. . { 
  329.     Kermit.sstate = KRM_UNKNOWN_PACKET;
  330.     errpkt(lclhWnd, Kermit.sstate);
  331.       RESUME;
  332. }
  333. %%
  334.  
  335. /* following are all support routines */
  336. static void NEAR errpkt(HWND hWnd, int id)
  337. {
  338.  
  339.     char szError[80];
  340.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  341.     int *len, datalen;
  342.  
  343.     *len = LoadString(hInstance, id, (LPSTR)szError, sizeof(szError));
  344.     datalen = encodebuf(sndpkt.data,szError,len);
  345.     spack('E', Kermit.pktnum, datalen, sndpkt.data);
  346.     clsif(); clsof(1);
  347. }
  348.  
  349. static void NEAR sipkt(char c)
  350. {
  351.  
  352.     BYTE buf[KRM_MAXPACKETSIZE];
  353.  
  354.     FlushComm(cid,1);
  355.     lclcount = 0;
  356.     spack(c,Kermit.pktnum,rpar(buf),buf);
  357.  
  358. }
  359.  
  360. static int NEAR sinit()
  361. {
  362.  
  363.     if ((Kermit.pNextFile = strtok(Kermit.pfilelist," ,")) != NULL) {
  364.         sipkt('S');
  365.         return(TRUE);
  366.     }
  367.     return(FALSE);
  368. }
  369.  
  370. static int NEAR sfile()
  371. {
  372.  
  373.     int *len;
  374.     register int datalen;
  375.     BYTE buf[20];
  376.  
  377.     Kermit.hInFile = GetSendFileName(Kermit.pNextFile);
  378.     if (Kermit.hInFile == -1)
  379.     return(0);
  380.  
  381.     strcpy(buf, Kermit.filename);
  382.     *len = strlen(Kermit.filename);
  383.     datalen = encodebuf(sndpkt.data, buf, len);
  384.  
  385.     nxtpkt();
  386.     spack('F',Kermit.pktnum, datalen, sndpkt.data);
  387.     return(1);
  388. }
  389.  
  390. static int NEAR sdata()
  391. {
  392.     register int len;
  393.  
  394.     if (rcvpkt.len) {
  395.         bufemp(rcvpkt.data, rcvpkt.len, 2);
  396.         SetDlgItemText(hWndXfer, IDD_SAVENAME,(LPSTR)rcvpkt.data);
  397.     }
  398.  
  399.     if (Kermit.fileabort || Kermit.batchabort)
  400.     return(-1);
  401.  
  402.     if ((len = bufill(sndpkt.data)) > 0) {
  403.         nxtpkt();
  404.         spack('D', Kermit.pktnum, len, sndpkt.data);
  405.     }
  406.     if (len < 0)
  407.     ShowTransactionError(lclhWnd, KRM_FILE_READ_ERROR);
  408.     return(len);
  409. }
  410.  
  411. static void NEAR seof(char *s)
  412. {
  413.  
  414.     nxtpkt();
  415.     if ((s != NULL) && (*s != NUL))
  416.     spack('Z', Kermit.pktnum, 1, s);
  417.     else
  418.     spack('Z', Kermit.pktnum, 0, "");
  419.  
  420. }
  421.  
  422. static void NEAR ack(int len, BYTE *s)
  423. {
  424.     spack('Y', Kermit.pktnum, len, s); 
  425.     nxtpkt();
  426. }
  427.  
  428. static int NEAR nxtpkt()
  429. {
  430.     Kermit.pktcount += 1;
  431.     return(Kermit.pktnum = (Kermit.pktnum + 1) & 63);
  432. }
  433.  
  434. void clsif() {
  435.     if (Kermit.hInFile) {
  436.         Kermit.hInFile = (HANDLE)close(Kermit.hInFile);
  437.     Kermit.hInFile = NULL;
  438.     }
  439.     Kermit.fileabort = FALSE;
  440. }
  441.  
  442. static int NEAR canned(char *buf)
  443. {
  444.     if (*buf == 'X')
  445.     Kermit.fileabort = TRUE;
  446.     if (*buf == 'Z')
  447.     Kermit.batchabort = TRUE;
  448.     return((Kermit.fileabort || Kermit.batchabort) ? 1 : 0);
  449. }
  450.  
  451. static int NEAR gnfile()
  452. {
  453.  
  454. /* don't do this if displaying on terminal */
  455.  
  456.     if (Kermit.batchabort || (Kermit.pNextFile = strtok(NULL, " ,")) == NULL)
  457.     return(0);
  458.  
  459.     return(1);
  460.    
  461. }
  462.  
  463. static void NEAR seot() {
  464.  
  465.     nxtpkt();
  466.     spack('B', Kermit.pktnum,0, "");
  467.     Kermit.fileabort = Kermit.batchabort = FALSE;
  468. }
  469.  
  470. static void NEAR rinit() {
  471.  
  472.     BYTE buf[100];
  473.  
  474.     spar(rcvpkt.data, rcvpkt.len);
  475.     ack(rpar(buf), buf);
  476. }
  477.  
  478. static int NEAR rcvfil() {
  479.     bufemp(rcvpkt.data, rcvpkt.len, 2);
  480.     if ((Kermit.hOutFile =
  481.         GetReceiveFileName(lclhWnd,rcvpkt.data)) == -1)
  482.     return(0);
  483.     return(1);
  484. }
  485.  
  486. static int NEAR reof() {
  487.  
  488.     register int x;
  489.  
  490.     if (Kermit.fileabort == FALSE)
  491.     Kermit.fileabort = rcvpkt.len ? (rcvpkt.data[0] == 'D') : FALSE;
  492.  
  493.     x = clsof(Kermit.fileabort | Kermit.batchabort);
  494.     
  495.     if (Kermit.fileabort || Kermit.batchabort)
  496.     Kermit.fileabort = FALSE;
  497.  
  498.     return(x);
  499. }
  500.  
  501. int clsof(int disp) {
  502.  
  503.     if (Kermit.displayfile)
  504.     return(1);
  505.  
  506.     if (Kermit.hOutFile) {
  507.         if ((Kermit.hOutFile = (HANDLE)close(Kermit.hOutFile)) != NULL)
  508.         return(-1);
  509.         if (disp && Kermit.filediscard)
  510.             unlink(myofstruct.szPathName);
  511.         return(1);
  512.     }
  513. }
  514.  
  515. static void NEAR reot() {
  516.  
  517.     Kermit.fileabort = Kermit.batchabort = FALSE;
  518.  
  519. }
  520.  
  521. static void NEAR resetc() {
  522.  
  523.     /* add appropriate code */
  524.  
  525. }
  526.  
  527. static void NEAR resend() {
  528.  
  529.     Kermit.numtry += 1;
  530.     Kermit.retrycount += 1;
  531.  
  532.     if (sndpkt.len)
  533.     ttoi(sndpkt.pktbuf, sndpkt.len);
  534.     else
  535.         spack('N', Kermit.pktnum, 0, "");
  536.  
  537.     if (IsWindow(hWndXfer))
  538.         UpdateXferBox();
  539. }
  540.  
  541. static void NEAR srinit() {
  542.  
  543.     int *len;
  544.    
  545.     *len = strlen(Kermit.pfilelist);
  546.     spack('R', Kermit.pktnum, 
  547.         encodebuf(sndpkt.data,Kermit.pfilelist,len), sndpkt.data);
  548. }
  549.  
  550. static void NEAR scmd(char cmd) {
  551.  
  552.     int *len;
  553.     register int datalen;
  554.  
  555.     switch (krmState) {
  556.     case IDM_KRM_FINISH:
  557.         datalen = 1;
  558.         sndpkt.data[0] = 'F';
  559.         break;
  560.     case IDM_KRM_BYE:
  561.     case IDM_KRM_LOGOUT:
  562.         datalen = 1;
  563.         sndpkt.data[0] = 'L';
  564.         break;
  565.        case IDM_KRM_REMOTEHOST:
  566.         *len = strlen(Kermit.pfilelist);
  567.         datalen = encodebuf(sndpkt.data, Kermit.pfilelist,len);
  568.         break;
  569.     default:
  570.             *len = strlen(Kermit.pRemoteCommand);
  571.         datalen = encodebuf(sndpkt.data, Kermit.pRemoteCommand,len);
  572.         break;
  573.     }
  574.     spack(cmd,Kermit.pktnum,datalen,sndpkt.data);
  575. }
  576.  
  577. static int NEAR opent(HWND hWnd) {
  578.  
  579.     BYTE crstring[3];
  580.  
  581.     if (krmInitMainDisplay(hWnd, Kermit.DispCharWidth, Kermit.DispCharHeight)) {
  582.         bufemp(rcvpkt.data, rcvpkt.len, 2);
  583.     krmMainStringDisplay(hWnd, rcvpkt.data, rcvpkt.len);
  584.     crstring[0] = CR;
  585.     crstring[1] = LF;
  586.         krmMainStringDisplay(hWnd, crstring,2);
  587.      Kermit.displayfile = 1;
  588.     return(TRUE);
  589.     }
  590.     return FALSE;                
  591. }
  592.  
  593. static BOOL NEAR paritycheck() {
  594.  
  595.     DCB commdata;
  596.  
  597.     GetCommState(cid, (DCB FAR *)&commdata);
  598.     if ((commdata.Parity == NOPARITY) && (commdata.ByteSize == 8))
  599.     return FALSE;
  600.     return TRUE;
  601. }
  602.  
  603. static int NEAR rpar(BYTE *data) {
  604.  
  605.     register int i = 0;
  606.  
  607.     data[i++] = (BYTE)tochar(local.maxpacketsize);
  608.     data[i++] = (BYTE)tochar(local.timeout);
  609.     data[i++] = (BYTE)tochar(local.padcount);
  610.     data[i++] = ctl(local.padchar);
  611.     data[i++] = (BYTE)tochar(local.eol);
  612.     data[i++] = local.quote;
  613.  
  614.     switch (Kermit.rqf) {
  615.     case -1 :
  616.     case  1 :
  617.         if (paritycheck())
  618.             Kermit.ebq = local.binquote = '&';
  619.         break;
  620.     case 0 :
  621.     case 2 :
  622.         break;
  623.     }        
  624.     data[i++] = local.binquote;
  625.  
  626. /* fixup: get these fields straight */
  627.  
  628.     data[i++] = (BYTE)(local.chksumtype + '0');
  629.     data[i++] = local.rptprefix;
  630.  
  631.     return(i);
  632. }
  633.  
  634. static void NEAR spar(BYTE *data, int len) {
  635.     
  636.     register int i = 0;
  637.     register int intval;
  638.     char charval;
  639.  
  640.     intval = (i < len) ? unchar(data[i++]) : KRM_DEFPACKETSIZE;
  641.     remote.maxpacketsize = (intval < KRM_MINPACKETSIZE)
  642.                          ? KRM_DEFPACKETSIZE : intval;
  643.  
  644.     intval = (i < len) ? unchar(data[i++]) : KRM_DEFTIMEOUT;
  645.     remote.timeout = ((intval < 0) || (intval > 65)) ? KRM_DEFTIMEOUT : intval;
  646.     Kermit.mstimeout = 1000 * remote.timeout;
  647.  
  648.     remote.padcount = KRM_DEFPADCOUNT;
  649.     remote.padchar = KRM_DEFPADCHAR;
  650.     if (i < len) {
  651.            remote.padcount = unchar(data[i++]);
  652.         if (i < len)
  653.         if ((((charval = ctl(data[i++])) >= 0) && (charval < SP))
  654.                  || (charval == DEL))
  655.             remote.padchar = charval;
  656.     }
  657.  
  658.     intval = (i < len) ? unchar(data[i++]) : KRM_DEFEOL;
  659.     remote.eol = ((intval > SOH) || (intval < SP)) ? intval : KRM_DEFEOL;
  660.  
  661.     charval = (i < len) ? data[i++] : KRM_DEFQUOTE;
  662.     remote.quote = ((charval > SP) && (charval < '?')) ||
  663.                ((charval > '_') && (charval < DEL)) ? 
  664.                 charval : KRM_DEFQUOTE;
  665.  
  666.     charval = remote.binquote = (i < len) ? data[i++] : 0;
  667.     if (charval == 'Y')
  668.     Kermit.rqf = 1;
  669.     else if ((charval > 32 && charval < '?') || 
  670.         (charval > '_' && charval < DEL))
  671.     Kermit.rqf = 2;
  672.     else
  673.     Kermit.rqf = 0;
  674.     switch (Kermit.rqf) {
  675.     case 0 :
  676.         Kermit.ebqflg = FALSE;
  677.         break;
  678.     case 1 :
  679.         if (paritycheck()) {
  680.         Kermit.ebqflg = TRUE;
  681.         Kermit.ebq = '&';
  682.         }
  683.         break;
  684.     case 2:
  685.         if (Kermit.ebqflg = (Kermit.ebq == local.binquote ||
  686.                     local.binquote == 'Y'))
  687.         Kermit.ebq = charval;
  688.             break;
  689.     }        
  690.  
  691. /* fixup the following code */
  692.  
  693.     intval = 1;
  694.     if (i < len) {
  695.         intval = data[i++] - '0';
  696.         if ((intval < 1) || (intval > 3))
  697.         intval = 1;
  698.     }
  699.     remote.chksumtype = intval;
  700.  
  701.     if (i < len) {
  702.     remote.rptprefix = charval = data[i++];
  703.      Kermit.rptflg = ((charval > 32 && charval < '?') || 
  704.                     (charval > '_' && charval < DEL));
  705.     }
  706.     else
  707.     Kermit.rptflg = FALSE;
  708.  
  709.     Kermit.maxsenddatalen = remote.maxpacketsize - 2 - Kermit.chksumtype;
  710.  
  711. }
  712.  
  713. static void NEAR spack(BYTE type, int num, int len, BYTE *data) {
  714.  
  715.     WORD chksum = 0;
  716.     register int i, k;
  717.  
  718.     sndpkt.len = 0;
  719.     sndpkt.data[len] = NUL;
  720.  
  721.     if (k = remote.padcount) {
  722.         memset(sndpkt.pktbuf, remote.padchar, k);
  723.     ttoi(sndpkt.pktbuf, k);
  724.     }
  725.  
  726.     k = 0;
  727.  
  728.     sndpkt.pktbuf[k++] = sndpkt.mark;
  729.     chksum += sndpkt.pktbuf[k++] = (BYTE)tochar(len + 3);
  730.     chksum += sndpkt.pktbuf[k++] = (BYTE)tochar(num);
  731.     chksum += sndpkt.pktbuf[k++] = type;
  732.  
  733.     for (i = 0; i < len; i++)
  734.         chksum += sndpkt.pktbuf[k++] = data[i];
  735.  
  736.     chksum = (((chksum & 0300) >> 6) + chksum) & 077;
  737.     sndpkt.pktbuf[k++] = (BYTE)tochar(chksum);
  738.  
  739.     sndpkt.pktbuf[k++] = (BYTE)remote.eol;
  740.     sndpkt.pktbuf[k] = NUL;
  741.     
  742.     ttoi(sndpkt.pktbuf,k);
  743.     sndpkt.len = k;
  744. }
  745.  
  746. static void NEAR ttoi(BYTE *buf, int len)
  747. {
  748.  
  749.     COMSTAT mycomstat;
  750.     register int inque;
  751.  
  752.     do {
  753.         GetCommError(cid, (COMSTAT FAR *)&mycomstat);
  754.       inque = mycomstat.cbOutQue;
  755.     } while(inque);
  756.  
  757.    WriteComm(cid, (LPSTR)buf, len);
  758.  
  759. }
  760.  
  761. static int NEAR bufill(BYTE buffer[]) {
  762.  
  763.     register int numloaded, numread;
  764.     BYTE buf[KRM_MAXPACKETSIZE];
  765.     int numrem;
  766.  
  767.     if ((numread = read(Kermit.hInFile,buf,Kermit.maxsenddatalen)) <= 0) {
  768.     numloaded = numread;
  769.     if (numread == 0)
  770.          Kermit.percentage = 100;
  771.     } else {
  772.         numrem = numread;
  773.         numloaded = encodebuf(buffer, buf, &numrem);
  774.         lseek(Kermit.hInFile, (LONG)(-numrem), SEEK_CUR);
  775.         if (Kermit.filesize) {
  776.             Kermit.bytesmoved += numread - numrem;
  777.         Kermit.percentage = (int)(Kermit.bytesmoved *100 / Kermit.filesize);
  778.         }
  779.     }
  780.     return(numloaded);
  781. }
  782.  
  783. static int NEAR encodebuf(BYTE outbuf[], BYTE inbuf[], int *inbufsize) {
  784.  
  785.     register int i,j;
  786.     BYTE t, t7;
  787.     int maxbufsize = Kermit.maxsenddatalen - 3;  /* char + prefix */
  788.     char quote = remote.quote;
  789.     char binquote = Kermit.ebq;
  790.  
  791.     if (Kermit.ebqflg) {
  792.         for (i = 0, j = 0 ; j < *inbufsize ; ) {
  793.         t = inbuf[j++];
  794.         if (t & 0x80)
  795.         outbuf[i++] = binquote;
  796.         if (((t7 = t & 0x7f) < SP) || (t7 == DEL)) {
  797.         outbuf[i++] = quote;
  798.         t7 = ctl(t7);
  799.         }
  800.         else if ((t7 == quote) || (t7 == binquote))
  801.         outbuf[i++] = quote;
  802.         outbuf[i++] = t7;
  803.         if (i > maxbufsize)
  804.             break;
  805.     }
  806.     }
  807.     else {
  808.         for (i = 0, j = 0 ; j < *inbufsize ; ) {
  809.         t = inbuf[j++];
  810.         if ((t7 = t & 0x7f) < SP || t7 == DEL || t7 == quote) {
  811.             outbuf[i++] = quote;
  812.             if (t7 != quote)
  813.             t = ctl(t);
  814.         }
  815.         outbuf[i++] = t;
  816.         if (i > maxbufsize)
  817.             break;
  818.         }
  819.     }
  820.     *inbufsize -= j;
  821.     return(i);
  822. }
  823.  
  824. static int NEAR bufemp(BYTE *buffer, int len, int dest) {
  825.  
  826.     register int i,j;
  827.     int result;
  828.     BYTE t, t7, wbuf[100];
  829.     BYTE bitset;
  830.     char quote = local.quote;
  831.     char binquote = Kermit.ebq;
  832.  
  833.     if (Kermit.ebqflg) {
  834.         for (i = 0, j = 0; i < len; i++) {
  835.         t = buffer[i];
  836.         if (t == binquote) {
  837.             t = buffer[++i];
  838.             bitset = 0x80;
  839.         }
  840.         else
  841.             bitset = 0;
  842.         if (t == quote) {
  843.             t = buffer[++i];
  844.             if (((t7 = t & 0x7f) != quote) && (t7 != binquote))
  845.             t = ctl(t);
  846.         }
  847.         wbuf[j++] = t | bitset;
  848.         }
  849.     }
  850.     else {
  851.         for (i = 0, j = 0; i < len; i++) {
  852.         t = buffer[i];
  853.         if (t == quote) {
  854.             t = buffer[++i];
  855.             if ((t & 0x7f) != quote)
  856.             t = ctl(t);
  857.         }
  858.         wbuf[j++] = t;
  859.         }
  860.     }
  861.     wbuf[j] = NUL;
  862.  
  863.     switch (dest) {
  864.     case 2 :
  865.         strcpy(rcvpkt.data, wbuf);
  866.         rcvpkt.len = j;
  867.         return (TRUE);
  868.         case 1 :
  869.             krmMainStringDisplay(lclhWnd, wbuf, j);
  870.         return (TRUE);
  871.     default:
  872.         if ((result = write(Kermit.hOutFile, wbuf, j)) >= 0)
  873.         Kermit.bytesmoved += result;
  874.             if ((result < j) || (result == -1))
  875.         return(-1);
  876.             else
  877.         return(result);
  878.     }
  879. }
  880.  
  881. static HANDLE NEAR GetSendFileName(char *name) {
  882.  
  883.     HANDLE hfile;
  884.     struct stat buf;
  885.  
  886.     hfile = OpenFile((LPSTR)name, (OFSTRUCT FAR *)&myofstruct,OF_READ);
  887.  
  888.     if (hfile != -1) {
  889.     Kermit.filename = (strrchr(myofstruct.szPathName,'\\') + 1);
  890.         SetDlgItemText(hWndXfer, IDD_FILENAME,(LPSTR)Kermit.filename);    
  891.     fstat(hfile, &buf);
  892.     Kermit.filesize = buf.st_size;
  893.     }
  894.     Kermit.bytesmoved = 0;
  895.     Kermit.percentage = 0;
  896.     return hfile;
  897. }
  898.  
  899. static HANDLE NEAR GetReceiveFileName(HWND hWnd, BYTE *packet)
  900. {
  901.  
  902.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  903.     register int i, j;
  904.     char filename[13];
  905.     char ext[5];
  906.     int numresult;
  907.     char *ptrresult;
  908.     BOOL gotextension;
  909.     HANDLE hfile;
  910.     char tempname[9], genstring[20];
  911.     int filecount;
  912.  
  913.     Kermit.newname_flag = FALSE;
  914.  
  915.     memset(filename, NUL, 13);
  916.     ext[0] = NUL;
  917.  
  918.     SetDlgItemText(hWndXfer, IDD_FILENAME,(LPSTR)packet);    
  919.  
  920.     ptrresult = strtok(packet, ".");        /* look for any extension */
  921.     numresult = strlen(ptrresult);        /* find out how long */
  922.     numresult = numresult < 8 ? numresult : 8;
  923.     strncpy(filename,ptrresult,numresult);    /* load up name */
  924.  
  925.     gotextension = FALSE;
  926.     ptrresult = strtok(NULL, ".");        /* get extension */
  927.     if (ptrresult != NULL) {
  928.     strcpy(ext,".");
  929.     strncat(ext, ptrresult,3);
  930.     ext[4] = NUL;
  931.     strcat(filename, ext);
  932.     gotextension = TRUE;
  933.     }
  934.  
  935.     if (Kermit.filewarning) {
  936.     for (filecount = 0; filecount < INT_MAX; filecount++) {
  937.             if ((hfile = OpenFile((LPSTR)filename,
  938.                 (OFSTRUCT FAR *)&myofstruct,OF_EXIST)) == -1)
  939.             break;
  940.         ptrresult = strtok(filename, ".");
  941.         strcpy(tempname, ptrresult);        
  942.         numresult = strlen(ptrresult);        
  943.         for (i = numresult; i < 8; i++)        
  944.             tempname[i] = '0';
  945.         numresult = strlen(itoa(filecount + 1, genstring,10));        
  946.  
  947.         for (i = 8 - numresult, j = 0; i < 8; i++,j++)
  948.             tempname[i] = genstring[j];        
  949.         tempname[8] = NUL;
  950.         strcpy(filename, tempname);
  951.         if (gotextension)
  952.             strcat(filename,ext);
  953.     }
  954.     if (filecount > 0)
  955.         Kermit.newname_flag = TRUE;
  956.     }
  957.  
  958.     hfile = OpenFile((LPSTR)filename,(OFSTRUCT FAR *)&myofstruct,OF_CREATE);
  959.     if (hfile != -1) {
  960.         Kermit.filename = (strrchr(myofstruct.szPathName,'\\') + 1);
  961.         SetDlgItemText(hWndXfer, IDD_SAVENAME,(LPSTR)Kermit.filename);
  962.     }
  963.     Kermit.bytesmoved = 0;
  964.     return (hfile);
  965. }
  966.  
  967. static int NEAR input() {
  968.  
  969.     int type, rsn, seq;
  970.     int startcount;
  971.  
  972.     if (Kermit.sstate > 0) {
  973.     type = Kermit.sstate;
  974.     Kermit.sstate = 0;
  975.     return(type);
  976.     }
  977.  
  978.     if (Kermit.protocolabort)
  979.     return('$');
  980.  
  981. again:
  982.     if (!Kermit.inpacket) {
  983.         if (IsWindow(hWndXfer))
  984.             UpdateXferBox();
  985.      if (Kermit.timer)
  986.         SetTimer(lclhWnd, KRM_WAITPACKET, Kermit.mstimeout, Kermit.fpTimer);
  987.     Kermit.inpacket = TRUE;
  988.     }
  989.     startcount = lclcount;
  990.     lclcount = getpacket(lclbuf, lclcount);
  991.     lclbuf += startcount - lclcount;
  992.     if (rcvpkt.state == PS_DONE) {
  993.     rcvpkt.state = PS_SYNCH;
  994.     Kermit.inpacket = FALSE;
  995.     if (Kermit.timer) {
  996.         KillTimer(lclhWnd, KRM_WAITPACKET);
  997.         Kermit.timeout = FALSE;
  998.     }
  999.     type = rcvpkt.type;
  1000.     rsn = rcvpkt.num;
  1001.     seq = Kermit.pktnum;
  1002.     if (type == sndpkt.pktbuf[3])
  1003.         goto again;
  1004.     if ((rsn != seq) || (type == 'N') || (type == 'Q')) {
  1005.         if ((type == 'N') && (rsn == (seq + 1) & 63)) {
  1006.         Kermit.numtry = 0;
  1007.         return ('Y');
  1008.         }
  1009.         else {
  1010.         resend();
  1011.         goto again;
  1012.         }
  1013.     }
  1014.     Kermit.numtry = 0;
  1015.     return (type);
  1016.     }
  1017.     else {
  1018.     if (Kermit.timeout) {
  1019.         Kermit.timeout = FALSE;
  1020.         resend();
  1021.     }
  1022.     return('p');
  1023.     }
  1024. }
  1025.  
  1026. /* get a packet, complete or partial */
  1027. static int NEAR getpacket(BYTE *str, int len) {
  1028.  
  1029.     register BYTE t;
  1030.     register int i;
  1031.  
  1032.     while (len) {
  1033.     switch (rcvpkt.state) {
  1034.         case PS_SYNCH:
  1035.             while (len) {
  1036.             if (*str != rcvpkt.mark) {
  1037.                 str++;
  1038.                 len--;
  1039.             }
  1040.                 else
  1041.                 break;
  1042.             }
  1043.         if (len) {
  1044.             str++; 
  1045.             len--;
  1046.             rcvpkt.state = PS_LEN;
  1047.             rcvpkt.cchksum = 0;
  1048.             rcvpkt.data_count = 0;
  1049.             rcvpkt.data[0] = NUL;
  1050.         }
  1051.         break;
  1052.  
  1053.         case PS_LEN:
  1054.         if ((t = *str) == rcvpkt.mark)
  1055.             rcvpkt.state = PS_SYNCH;
  1056.             else {
  1057.             rcvpkt.state = PS_NUM;
  1058.             rcvpkt.len = unchar(t) - 2 - Kermit.chksumtype;
  1059.             rcvpkt.cchksum += t;
  1060.             str++;
  1061.             len--;
  1062.         }
  1063.         break;
  1064.  
  1065.         case PS_NUM:
  1066.         if ((t = *str) == rcvpkt.mark)
  1067.             rcvpkt.state = PS_SYNCH;
  1068.             else {
  1069.             rcvpkt.state = PS_TYPE;
  1070.             rcvpkt.num = unchar(t);
  1071.             rcvpkt.cchksum += t;
  1072.             str++;
  1073.             len--;
  1074.         }
  1075.         break;
  1076.  
  1077.         case PS_TYPE:
  1078.         if ((t = *str) == rcvpkt.mark)
  1079.             rcvpkt.state = PS_SYNCH;
  1080.             else {
  1081.             if (rcvpkt.len)
  1082.                 rcvpkt.state = PS_DATA;
  1083.             else
  1084.             rcvpkt.state = PS_CHK;
  1085.             rcvpkt.type = t;
  1086.             rcvpkt.cchksum += t;
  1087.             str++;
  1088.             len--;
  1089.         }
  1090.         break;
  1091.  
  1092.         case PS_DATA:
  1093.         for (i = rcvpkt.data_count; i < rcvpkt.len; i++) {
  1094.             if ((t = *str) == rcvpkt.mark)
  1095.             break;
  1096.             else {
  1097.             rcvpkt.data[i] = t;
  1098.             rcvpkt.cchksum += t;
  1099.             rcvpkt.data_count += 1;
  1100.             str++;
  1101.             len--;
  1102.             if (len <= 0)
  1103.                 break;
  1104.             }
  1105.         }
  1106.         if (t == rcvpkt.mark)
  1107.             rcvpkt.state = PS_SYNCH;
  1108.         else if (rcvpkt.data_count == rcvpkt.len) {
  1109.             rcvpkt.data[rcvpkt.len] = NUL;
  1110.             rcvpkt.state = PS_CHK;
  1111.         }
  1112.         break;
  1113.  
  1114.         case PS_CHK:
  1115.         if ((t = *str) == rcvpkt.mark)
  1116.             rcvpkt.state = PS_SYNCH;
  1117.             else {
  1118.             rcvpkt.rchksum = unchar(t);
  1119.             str++;
  1120.             len--;
  1121.             rcvpkt.cchksum = (((rcvpkt.cchksum & 0xC0) >> 6)
  1122.                     + rcvpkt.cchksum) & 0x3f;
  1123.             if (rcvpkt.cchksum != rcvpkt.rchksum)
  1124.             rcvpkt.type = 'Q';
  1125.             rcvpkt.state = PS_DONE;
  1126.         }
  1127.         break;
  1128.         case PS_DONE:
  1129.         if ((t = *str) == (BYTE)local.eol) {
  1130.             str++;
  1131.             len--;
  1132.         }
  1133.         return len;
  1134.     } /* switch */
  1135.     } /* while */
  1136.     return len;
  1137. }
  1138.  
  1139. static void NEAR ShowTransactionError(HWND hWnd, int id)
  1140. {
  1141.  
  1142.     char szMessage[80];
  1143.     char szCaption[40];
  1144.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  1145.  
  1146.     LoadString(hInstance, IDS_KRM_KERMIT, (LPSTR)szCaption, sizeof(szCaption));
  1147.     LoadString(hInstance, id, (LPSTR)szMessage, sizeof(szMessage));
  1148.  
  1149.     if (Kermit.bell)
  1150.     MessageBeep(MB_OK | MB_ICONASTERISK);
  1151.  
  1152.     MessageBox(hWnd,(LPSTR)szMessage,(LPSTR)szCaption, MB_OK | MB_ICONASTERISK);
  1153. }
  1154.  
  1155. static void NEAR UpdateXferBox()
  1156. {
  1157.  
  1158.     char str[20];
  1159.     static int prevcount;
  1160.  
  1161.     if (IsIconic(lclhWnd))
  1162.     InvalidateRect(lclhWnd, (LPRECT)NULL, FALSE);
  1163.     else {
  1164.         SetDlgItemText(hWndXfer,IDD_BYTESMOVED,ltoa(Kermit.bytesmoved,str,10));
  1165.         SetDlgItemInt(hWndXfer,IDD_PACKETS,Kermit.pktcount,0);
  1166.         if (krmState == IDM_KRM_SEND)
  1167.             SetDlgItemInt(hWndXfer,IDD_PERCENTAGE,Kermit.percentage,0);
  1168.     if (prevcount != Kermit.retrycount) {
  1169.             SetDlgItemInt(hWndXfer,IDD_RETRIES,Kermit.retrycount,0);
  1170.         prevcount = Kermit.retrycount;
  1171.      }
  1172.     }
  1173. }
  1174.