Annotation of 43BSDTahoe/new/kermit/ckcfn2.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.