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

Defined functions

ack defined in line 201; never used
ack1 defined in line 206; used 2 times
chk1 defined in line 157; used 2 times
chk2 defined in line 166; used 3 times
chk3 defined in line 185; used 2 times
dopar defined in line 137; used 23 times
errpkt defined in line 229; used 3 times
inchr defined in line 409; used 1 times
inlin defined in line 425; used 1 times
input defined in line 53; never used
nack defined in line 211; used 1 times
nxtpkt defined in line 245; used 6 times
resend defined in line 215; used 2 times
rpack defined in line 257; used 4 times
scmd defined in line 235; never used
sigint defined in line 250; never used
spack defined in line 94; used 12 times
srinit defined in line 240; never used
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1623
Valid CSS Valid XHTML 1.0 Strict