home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / archimedes / arcfn2.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  15KB  |  528 lines

  1. /* -> c.ckcfn2
  2.  */
  3.  
  4. /*  C K C F N 2  --  System-independent Kermit protocol support functions... */
  5.  
  6. /*  ...Part 2 (continued from ckcfns.c)  */
  7. /*
  8.  Author: Frank da Cruz (SY.FDC@CU20B),
  9.  Columbia University Center for Computing Activities, January 1985.
  10.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  11.  Permission is granted to any individual or institution to use, copy, or
  12.  redistribute this software so long as it is not sold for profit, provided
  13.  this copyright notice is retained. 
  14. */
  15. /*
  16.  Note -- if you change this file, please amend the version number and date at
  17.  the top of ckcfns.c accordingly.
  18. */
  19.  
  20. #include "ckcker.h"
  21. #include "ckcdeb.h"
  22.  
  23. #ifdef ANSI
  24. #include <string.h>
  25. #include "ckatio.h"
  26. #include "ckafio.h"
  27. #include "ckuusr.h"
  28. #include "ckamis.h"
  29. #endif
  30.  
  31. extern int spsiz, rpsiz, timint, npad, chklen, ebq, ebqflg, rpt, rptq, rptflg,
  32.  capas;
  33. extern int pktnum, prvpkt, sndtyp, bctr, bctu,
  34.  size, osize, maxsize, spktl, nfils, stdouf, warn, timef;
  35. extern int parity, speed, turn, turnch, 
  36.  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
  37. extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize;
  38. extern int deblog, hcflg, binary, fncnv, local, server, cxseen, czseen;
  39. extern char padch, mypadc, eol, seol, ctlq, myctlq, sstate, *hlptxt;
  40. extern char filnam[], sndpkt[], recpkt[], data[], srvcmd[], *srvptr, stchr, 
  41.  mystch;
  42. extern char *cmarg, *cmarg2, **cmlist;
  43.  
  44. #ifndef ANSI
  45. char *strcpy();
  46. #endif
  47.  
  48. #ifdef ANSI
  49. extern int rpack( int *, int *, char * );
  50. extern void resend( void );
  51. extern int dopar( char );
  52. extern int chk1( char * );
  53. extern int chk2( char * );
  54. extern int chk3( char * );
  55. extern void nxtpkt( int * );
  56. extern int inlin( void );
  57.  
  58. /* Declarations for functions defined in c.ckcfns */
  59. extern void encstr( char * );
  60.  
  61.  
  62. #endif
  63.  
  64. /*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
  65.  
  66. /*
  67.  This is the function that feeds input to Kermit's finite state machine.
  68.  
  69.  If a special start state is in effect, that state is returned as if it were
  70.  the type of an incoming packet.  Otherwise:
  71.  
  72.  . If the desired packet arrives within MAXTRY tries, return its type,
  73.    with its data stored in the global 'data' array.
  74.  
  75.  . If the previous packet arrives again, resend the last packet and wait for
  76.    another to come in.
  77.  
  78.  . If the desired packet does not arrive within MAXTRY tries, return
  79.    indicating that an error packet should be sent.
  80. */
  81.  
  82. #ifdef ANSI
  83. int
  84. #endif
  85. input() {
  86.     int len, num, type, numtry;
  87.  
  88.     if (sstate != 0) {          /* If a start state is in effect, */
  89.     type = sstate;          /* return it like a packet type, */
  90.     sstate = 0;         /* and then nullify it. */
  91.     *data = '\0';
  92.     return(type);
  93.     } else type = rpack(&len,&num,data); /* Else, try to read a packet. */
  94.  
  95. /* If it's the same packet we just sent, it's an echo.  Read another. */
  96.  
  97.     if (type == sndtyp) type = rpack(&len,&num,data);
  98.  
  99.     chkint();               /* Check for console interrupts. */
  100. /*
  101.  If previous packet again, a timeout pseudopacket, or a bad packet, try again.
  102. */
  103.     for (numtry = 0;
  104.       ( (num == prvpkt) || (type == 'T') || (type == 'Q') || (type == 'N'));
  105.       numtry++) {
  106.     if (numtry > MAXTRY) {      /* If too many tries, give up */
  107.         strcpy(data,"Timed out.");  /* and send a timeout error packet. */
  108.         return('E');
  109.     }
  110.     resend();           /* Else, send last packet again, */
  111.     if (sstate != 0) {      /* If an interrupt routine has set */
  112.         type = sstate;      /* sstate behind our back, return */
  113.         sstate = 0;         /* that. */
  114.         *data = '\0';
  115.         return(type);
  116.     } else type = rpack(&len,&num,data); /* Else, try to read a packet. */
  117.     chkint();           /* Look again for interruptions. */
  118.     if (type == sndtyp) type = rpack(&len,&num,data);
  119.     }
  120.     return(type);           /* Success, return packet type. */
  121. }
  122.  
  123. /*  S P A C K  --  Construct and send a packet  */
  124.  
  125. #ifdef ANSI
  126. void
  127. #endif
  128. spack(type,num,len,dat) char type, *dat; int num, len; {
  129.     int i,j;
  130.     
  131.     j = dopar(padch);
  132.     for (i = 0; i < npad; sndpkt[i++] = j);  /* Do any requested padding */
  133.     sndpkt[i++] = dopar(mystch);    /* Start packet with the start char */
  134.     sndpkt[i++] = dopar(tochar(len+bctu+2));    /* Put in the length */
  135.     sndpkt[i++] = dopar(tochar(num));       /* The packet number */
  136.     sndpkt[i++] = sndtyp = dopar(type);     /* Packet type */
  137.  
  138.     for (j = len; j > 0; j-- ) sndpkt[i++] = dopar(*dat++); /* Data */
  139.  
  140.     sndpkt[i] = '\0';           /* Mark end for block check */
  141.     switch(bctu) {
  142.     case 1:             /* Type 1 - 6 bit checksum */
  143.         sndpkt[i++] = dopar(tochar(chk1(sndpkt+1+npad)));
  144.         break;
  145.     case 2:             /* Type 2 - 12 bit checksum*/
  146.         j = chk2(sndpkt+1+1);
  147.         sndpkt[i++] = dopar(tochar((j & 07700) >> 6));
  148.         sndpkt[i++] = dopar(tochar(j & 077));
  149.         break;
  150.         case 3:             /* Type 3 - 16 bit CRC-CCITT */
  151.         j = chk3(sndpkt+1+npad);
  152.         sndpkt[i++] = dopar(tochar(( (unsigned)(j & 0170000)) >> 12));
  153.         sndpkt[i++] = dopar(tochar((j & 07700) >> 6));
  154.         sndpkt[i++] = dopar(tochar(j & 077));
  155.         break;
  156.     }
  157.  
  158.     sndpkt[i++] = dopar(seol);      /* EOL character */
  159.     sndpkt[i] = '\0';           /* End of the packet */
  160.     ttol(sndpkt,spktl=i);       /* Send the packet just built */
  161.     flco += spktl;          /* Count the characters */
  162.     tlco += spktl;
  163.     if (pktlog) zsoutl(ZPFILE,sndpkt);  /* If logging packets, log it */
  164.     screen(SCR_PT,type,(long)num,sndpkt); /* Update screen */
  165. }
  166.  
  167. /*  D O P A R  --  Add an appropriate parity bit to a character  */
  168.  
  169. #ifdef ANSI
  170. int
  171. #endif
  172. dopar (
  173. #ifdef ANSI
  174. char ch)
  175. #else
  176. ch) char ch;
  177. #endif
  178. {
  179.     int a;
  180.     switch (parity) {
  181.     case 'm':  return(ch | 128);        /* Mark */
  182.     case 's':  return(ch & 127);        /* Space */
  183.     case 'o':  ch |= 128;           /* Odd (fall thru) */
  184.     case 'e':               /* Even */
  185.         a = (ch & 15) ^ ((ch >> 4) & 15);
  186.         a = (a & 3) ^ ((a >> 2) & 3);
  187.         a = (a & 1) ^ ((a >> 1) & 1);
  188.         return(ch | (a << 7));
  189.     default:   return(ch);
  190.     }
  191. }
  192.  
  193. /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
  194.  
  195. #ifdef ANSI
  196. int
  197. #endif
  198. chk1(pkt) char *pkt; {
  199.     int chk;
  200.     chk = chk2(pkt);
  201.     return((((chk & 0300) >> 6) + chk) & 077);
  202. }
  203.  
  204.  
  205. /*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
  206.  
  207. #ifdef ANSI
  208. int
  209. #endif
  210. chk2(pkt) char *pkt; {
  211.     unsigned int chk;
  212.     int p;
  213. #ifdef ANSI
  214.     for (chk = 0; *pkt != '\0'; pkt++) {
  215. #else
  216.     for (chk = 0; *pkt != '\0'; *pkt++) {
  217. #endif
  218.         p = (parity) ? *pkt & 0177 : *pkt;
  219.     chk += p;
  220.     }
  221.     return(chk);
  222. }
  223.  
  224. /*  C H K 3  --  Compute a type-3 Kermit block check.  */
  225. /*
  226.  Calculate the 16-bit CRC of a null-terminated string using a byte-oriented
  227.  tableless algorithm invented by Andy Lowry (Columbia University).  The
  228.  magic number 010201 is derived from the CRC-CCITT polynomial x^16+x^12+x^5+1.
  229.  Note - this function could be adapted for strings containing imbedded 0's
  230.  by including a length argument.
  231. */
  232.  
  233. #ifdef ANSI
  234. int
  235. #endif
  236. chk3(s) char *s; {
  237.     unsigned int c, q;
  238.     LONG crc = 0;
  239.  
  240.     while ((c = *s++) != '\0') {
  241.     if (parity) c &= 0177;
  242.     q = (crc ^ c) & 017;        /* Low-order nibble */
  243.     crc = (crc >> 4) ^ (q * 010201);
  244.     q = (crc ^ (c >> 4)) & 017; /* High order nibble */
  245.     crc = (crc >> 4) ^ (q * 010201);
  246.     }
  247.     return(crc);
  248. }
  249.  
  250. /* Functions for sending various kinds of packets */
  251.  
  252. #ifdef ANSI
  253. void
  254. #endif
  255. ack() {                 /* Send an ordinary acknowledgment. */
  256.     spack('Y',pktnum,0,"");     /* No data. */
  257.     nxtpkt(&pktnum);            /* Increment the packet number. */
  258. }                   /* Note, only call this once! */
  259.  
  260. #ifdef ANSI
  261. void
  262. #endif
  263. ack1(s) char *s; {          /* Send an ACK with data. */
  264.     spack('Y',pktnum,strlen(s),s);  /* Send the packet. */
  265.     nxtpkt(&pktnum);            /* Increment the packet number. */
  266. }                   /* Only call this once! */
  267.  
  268. #ifdef ANSI
  269. void
  270. #endif
  271. nack() {                /* Negative acknowledgment. */
  272.     spack('N',pktnum,0,"");     /* NAK's never have data. */
  273. }
  274.  
  275. #ifdef ANSI
  276. void
  277. #endif
  278. resend() {              /* Send the old packet again. */
  279.     int w;
  280.  
  281.     for (w = 0; w < timint - 2; w++) {  /* Be extra sure no stuff is */
  282.     ttflui();           /*  still coming in. */
  283.     sleep(1);
  284.     if (!ttchk() ) ttinc(1);    /* be extra sure no stuff in SIII/V */
  285.     if (!ttchk() ) break;
  286.     }
  287.     if (*sndpkt) ttol(sndpkt,spktl);    /* Resend if buffer not empty */
  288.  
  289.     screen(SCR_PT,'%',(long)pktnum,sndpkt); /* Display that resend occurred */
  290.     if (pktlog && *sndpkt) zsoutl(ZPFILE,sndpkt); /* Log packet if desired */
  291. }
  292.  
  293. #ifdef ANSI
  294. void
  295. #endif
  296. errpkt(reason) char *reason; {      /* Send an error packet. */
  297.     encstr(reason);
  298.     spack('E',pktnum,size,data);
  299.     screen(SCR_TC,0,0l,"");
  300. }
  301.  
  302. #ifdef ANSI
  303. void
  304. #endif
  305. scmd(t,dat) char t, *dat; {     /* Send a packet of the given type */
  306.     encstr(dat);            /* Encode the command string */
  307.     spack(t,pktnum,size,data);
  308. }
  309.  
  310. #ifdef ANSI
  311. void
  312. #endif
  313. srinit() {              /* Send R (GET) packet */
  314.     encstr(cmarg);          /* Encode the filename. */
  315.     spack('R',pktnum,size,data);    /* Send the packet. */
  316. }
  317.  
  318. #ifdef ANSI
  319. void
  320. #endif
  321. nxtpkt(num) int *num; {
  322.     prvpkt = *num;          /* Save previous */
  323.     *num = (*num + 1) % 64;     /* Increment packet number mod 64 */
  324. }
  325.  
  326. #ifdef ANSI
  327. void
  328. #endif
  329. sigint() {              /* Terminal interrupt handler */
  330.     errpkt("User typed <ESC>");
  331.     doexit(GOOD_EXIT);          /* Exit program */
  332. }
  333.  
  334. /* R P A C K  --  Read a Packet */
  335.  
  336. #ifdef ANSI
  337. int
  338. #endif
  339. rpack(l,n,dat) int *l, *n; char *dat; {
  340.     int i, j, x, done, pstart, pbl;
  341.     char chk[4], xchk[4], t, type;
  342.  
  343.     chk[3] = xchk[3] = 0;
  344.     i = inlin();            /* Read a line */
  345.     if (i != 0) {
  346.     debug(F101,"rpack: inlin","",i);
  347.     screen(SCR_PT,'T',(long)pktnum,"");
  348.     return('T');
  349.     }
  350.     debug(F110,"rpack: inlin ok, recpkt",recpkt,0);
  351.  
  352. /* Look for start of packet */
  353.  
  354.     for (i = 0; ((t = recpkt[i]) != stchr) && (i < RBUFL) ; i++);
  355.     if (++i >= RBUFL) return('Q');  /* Skip rest if not found */
  356.  
  357. /* now "parse" the packet */
  358.  
  359.     debug(F101,"entering rpack with i","",i);
  360.     done = 0;
  361.     while (!done) {
  362.     debug(F101,"rpack starting at i","",i);
  363.         pstart = i;         /* remember where packet started */
  364.  
  365. /* length */
  366.  
  367.     if ((t = recpkt[i++]) == stchr) continue; /* Resynch if SOH */
  368.     if (t == eol) return('Q');
  369.     *l = unchar(t);         /* Packet length */
  370.     debug(F101," pkt len","",*l);
  371.  
  372. /* sequence number */
  373.  
  374.     if ((t = recpkt[i++]) == stchr) continue;
  375.     if (t == eol) return('Q');
  376.     *n = unchar(t);
  377.     debug(F101,"rpack: n","",*n);
  378.  
  379. /* type */
  380.  
  381.     if ((type = recpkt[i++]) == stchr) continue;
  382.     if (type == eol) return('Q');
  383.     debug(F101,"rpack: type","",type);
  384.  
  385.     if ((type == 'S') || (type == 'I')) pbl = 1;    /* Heuristics for  */
  386.     else if (type == 'N') pbl = *l - 2;    /* syncing block check type */
  387.     else pbl = bctu;
  388.  
  389.     *l -= (pbl + 2);        /* Now compute data length */
  390.     debug(F101,"rpack: bctu","",bctu);
  391.     debug(F101," pbl","",pbl);
  392.     debug(F101," data length","",*l);
  393.  
  394. /* data */
  395.  
  396.     dat[0] = '\0';          /* Return null string if no data */
  397.     for (j=0; j<*l; i++,j++)
  398.         if ((dat[j] = recpkt[i]) == stchr) continue;
  399.         else if (dat[j] == eol) return('Q');
  400.     dat[j] = '\0';
  401.  
  402. /* get the block check */
  403.  
  404.         debug(F110," packet chk",recpkt+i,0);
  405.         for (j = 0; j < pbl; j++) {
  406.         chk[j] = recpkt[i];
  407.         debug(F101," chk[j]","",chk[j]);
  408.         if (chk[j] == stchr) break;
  409.         if (chk[j] == eol) return('Q');
  410.         recpkt[i++] = '\0';
  411.     }
  412.     chk[j] = 0;
  413.     debug(F111," chk array, j",chk,j);
  414.     if (j != pbl) continue;     /* Block check right length? */
  415.     done = 1;           /* Yes, done. */
  416.     }
  417.  
  418. /* Got packet, now check the block check */
  419.  
  420.     switch (pbl) {
  421.     case 1:
  422.         xchk[0] = tochar(chk1(&recpkt[pstart]));
  423.         if (chk[0] != xchk[0]) {
  424.         if (deblog) {
  425.             debug(F000,"rpack: chk","",chk[0]);
  426.             debug(F000," should be ","",xchk[0]);
  427.         }
  428.         screen(SCR_PT,'Q',(long)n,recpkt);
  429.         return('Q');
  430.         }
  431.         break;
  432.     case 2:
  433.         x = chk2(&recpkt[pstart]);
  434.         xchk[0] = tochar((x & 07700) >> 6);
  435.         xchk[1] = tochar(x & 077);
  436.         if (deblog) {
  437.         debug(F000," xchk[0]","=",xchk[0]);
  438.         debug(F000," xchk[1]","=",xchk[1]);
  439.         }
  440.         if ((xchk[0] != chk[0]) || (xchk[1] != chk[1])) {
  441.         debug(F100," bct2's don't compare","",0);
  442.         screen(SCR_PT,'Q',(long)n,recpkt);
  443.         return('Q');
  444.             }
  445.         break;
  446.     case 3:
  447.         x = chk3(&recpkt[pstart]);
  448.         xchk[0] = tochar(( (unsigned)(x & 0170000)) >> 12);
  449.         xchk[1] = tochar((x & 07700) >> 6);
  450.         xchk[2] = tochar(x & 077);
  451.         if (deblog) {
  452.         debug(F000," xchk[0]","=",xchk[0]);
  453.         debug(F000," xchk[1]","=",xchk[1]);
  454.         debug(F000," xchk[2]","=",xchk[2]);
  455.             }
  456.         if ((xchk[0] != chk[0]) || 
  457.             (xchk[1] != chk[1]) || 
  458.         (xchk[2] != chk[2])) {
  459.             debug(F100," bct3's don't compare","",0);
  460.             screen(SCR_PT,'Q',(long)n,recpkt);
  461.             return('Q');
  462.         }
  463.         break;
  464.         }
  465.  
  466. /* Good packet, return its type */
  467.  
  468.     ttflui();               /* Done, flush any remaining. */
  469.     screen(SCR_PT,type,(long)(*n),recpkt); /* Update screen */
  470.     return(type);
  471. }
  472.  
  473. /*  I N C H R  --  Input character from communication line, with timeout  */
  474.       
  475. #ifdef ANSI
  476. int
  477. #endif  
  478. inchr(timo) int timo; {
  479.     int c;
  480.     c = ttinc(timo);
  481.     debug(F101,"inchr ttinc","",c);
  482.     if (c < 0) return(c);       /* Get a character */
  483.     if (parity) c = c & 0177;       /* If parity on, discard parity bit.*/
  484.     debug(F101," after parity","",c);
  485.     return(c);
  486. }
  487.  
  488. /*  I N L I N  -- Input a line (up to break char) from communication line  */
  489.  
  490. /*  Returns 0 on success, nonzero on failure  */
  491.  
  492. #ifdef ANSI
  493. int
  494. #endif
  495. inlin() {
  496.     int i, j, k, maxt;
  497.     CHAR e;
  498.  
  499.     maxt = (speed >= 110) ? (MAXTRY * 9600 / speed) : MAXTRY;
  500.     debug(F101,"inlin: speed","",speed);
  501.     debug(F101," maxt","",maxt);
  502.     e = (turn) ? turnch : eol;
  503.     i = j = k = 0;
  504.     if (parity) {
  505.         while ((j != e) && (i < RBUFL) && (k < maxt)) {
  506.         j = inchr(1);       /* Get char, 1 second timeout */
  507.         debug(F101,"inlin inchr","",j);
  508.         if (j < 0) k++;     /* Timed out. */
  509.         else {
  510.         if (j) recpkt[i++] = j; /* Save it */
  511.         k = 0;          /* Reset timeout counter. */
  512.         }
  513.     }
  514.     } else {
  515.         i = ttinl(recpkt,RBUFL,timint,e);   /* Get them all at once */
  516.     if (i < 0) k = 1;
  517.     }
  518.     recpkt[i] = '\0';           /* Terminate near end of packet */
  519.     debug(F111,"inlin",recpkt,i);   /* Debug report... */
  520.     debug(F101," timeouts","",k);
  521.     if (i < 1) return(1);       /* No characters, return. */
  522.     if (pktlog) zsoutl(ZPFILE,recpkt);  /* Log any we got, if logging. */
  523.     if (k > maxt) return(1);        /* If too many tries, give up. */
  524.     tlci += i;              /* All OK, Count the characters. */
  525.     flci += i;
  526.     return(0);
  527. }
  528.