Annotation of 43BSD/contrib/kermit/ckcfn2.c, revision 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.