# 2.11BSD#431 - /usr/src/new/kermit5.188/ckcfn2.c

##### Functions

    ack               X
    ack1              X
    ackn              X
    ackns             X
    chk1              X
    chk2              X
    chk3              X
    chktimo           X
    dopar             X
    errpkt            X
    fstats            X
    input             X
    logpkt            X
    nack              X
    nxtpkt            X
    parchk            X
    rcalcpsz          X
    resend            X
    rpack             X
    scmd              X
    spack             X
    srinit            X
    tstats            X

##### Variables

    VOID              X
    numerrs           X

##### Macros

    NP_TELNET         X

       1: /*  C K C F N 2  --  System-independent Kermit protocol support functions... */
       2:
       3: /*  ...Part 2 (continued from ckcfns.c)  */
       4:
       5: /*
       6:   Author: Frank da Cruz (fdc@watsun.cc.columbia.edu, FDCCU@CUVMA.BITNET),
       7:   Columbia University Center for Computing Activities.
       8:   First released January 1985.
       9:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
      10:   York.  Permission is granted to any individual or institution to use this
      11:   software as long as it is not sold for profit.  This copyright notice must be
      12:   retained.  This software may not be included in commercial products without
      13:   written permission of Columbia University.
      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 "ckcsym.h"         /* Compilation options */
      21: #include "ckcdeb.h"         /* Debugging and other symbols */
      22: #include "ckcasc.h"         /* ASCII symbols */
      23: #include "ckcker.h"         /* Kermit symbols */
      24: #include "ckcxla.h"         /* Translation */
      25:
      26: #ifdef TCPSOCKET            /* For TELNET business in spack() */
      27: #ifndef NP_TELNET
      28: #define NP_TELNET 1
      29: extern int tn_nlm, ttnproto;
      30: #endif /* NP_TELNET */
      31: #endif /* TCPSOCKET */
      32:
      33: #ifdef DYNAMIC
      34: extern struct pktinfo *s_pkt;       /* array of pktinfo structures */
      35: extern struct pktinfo *r_pkt;       /* array of pktinfo structures */
      36: #else
      37: extern struct pktinfo s_pkt[];      /* array of pktinfo structures */
      38: extern struct pktinfo r_pkt[];      /* array of pktinfo structures */
      39: #endif /* DYNAMIC */
      40:
      41: extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo, sbufnum;
      42:
      43: extern int ttprty;          /* from ckutio.c */
      44: extern int autopar;
      45:
      46: extern int spsiz, spmax, rpsiz, timint, timef, npad, ebq, ebqflg;
      47: extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, network, flow;
      48: extern int pktnum, sndtyp, bctr, bctu, bctl, rsn, rln, maxtry, size;
      49: extern int osize, maxsize, spktl, rpktl, nfils, stdouf, warn, parity;
      50: extern int turn, turnch,  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
      51: extern int hcflg, local, server, cxseen, czseen;
      52: extern int nakstate, quiet, success, xitsta, what;
      53: extern int spackets, rpackets, timeouts, retrans, crunched, urpsiz;
      54:
      55: extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, speed;
      56:
      57: extern char *cmarg, *cmarg2, filnam[], *hlptxt;
      58:
      59: extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;
      60: extern CHAR *recpkt, *data, encbuf[], myinit[];
      61: extern CHAR *srvptr, stchr, mystch, *rdatap;
      62: extern CHAR padbuf[];
      63: #ifdef DYNAMIC
      64:   extern CHAR *srvcmd;
      65: #else
      66:   extern CHAR srvcmd[];
      67: #endif /* DYNAMIC */
      68:
      69: int numerrs = 0;        /* (PWP) total number packet errors so far */
      70:
      71: static CHAR partab[] = {        /* Even parity table for dopar(). */
      72:     (CHAR) '\000',          /* ANSI C casts '\ooo' constants  */
      73:     (CHAR) '\201',          /* to signed char, so we have to  */
      74:     (CHAR) '\202',          /* cast back to unsigned char...  */
      75:     (CHAR) '\003',
      76:     (CHAR) '\204',
      77:     (CHAR) '\005',
      78:     (CHAR) '\006',
      79:     (CHAR) '\207',
      80:     (CHAR) '\210',
      81:     (CHAR) '\011',
      82:     (CHAR) '\012',
      83:     (CHAR) '\213',
      84:     (CHAR) '\014',
      85:     (CHAR) '\215',
      86:     (CHAR) '\216',
      87:     (CHAR) '\017',
      88:     (CHAR) '\220',
      89:     (CHAR) '\021',
      90:     (CHAR) '\022',
      91:     (CHAR) '\223',
      92:     (CHAR) '\024',
      93:     (CHAR) '\225',
      94:     (CHAR) '\226',
      95:     (CHAR) '\027',
      96:     (CHAR) '\030',
      97:     (CHAR) '\231',
      98:     (CHAR) '\232',
      99:     (CHAR) '\033',
     100:     (CHAR) '\234',
     101:     (CHAR) '\035',
     102:     (CHAR) '\036',
     103:     (CHAR) '\237',
     104:     (CHAR) '\240',
     105:     (CHAR) '\041',
     106:     (CHAR) '\042',
     107:     (CHAR) '\243',
     108:     (CHAR) '\044',
     109:     (CHAR) '\245',
     110:     (CHAR) '\246',
     111:     (CHAR) '\047',
     112:     (CHAR) '\050',
     113:     (CHAR) '\251',
     114:     (CHAR) '\252',
     115:     (CHAR) '\053',
     116:     (CHAR) '\254',
     117:     (CHAR) '\055',
     118:     (CHAR) '\056',
     119:     (CHAR) '\257',
     120:     (CHAR) '\060',
     121:     (CHAR) '\261',
     122:     (CHAR) '\262',
     123:     (CHAR) '\063',
     124:     (CHAR) '\264',
     125:     (CHAR) '\065',
     126:     (CHAR) '\066',
     127:     (CHAR) '\267',
     128:     (CHAR) '\270',
     129:     (CHAR) '\071',
     130:     (CHAR) '\072',
     131:     (CHAR) '\273',
     132:     (CHAR) '\074',
     133:     (CHAR) '\275',
     134:     (CHAR) '\276',
     135:     (CHAR) '\077',
     136:     (CHAR) '\300',
     137:     (CHAR) '\101',
     138:     (CHAR) '\102',
     139:     (CHAR) '\303',
     140:     (CHAR) '\104',
     141:     (CHAR) '\305',
     142:     (CHAR) '\306',
     143:     (CHAR) '\107',
     144:     (CHAR) '\110',
     145:     (CHAR) '\311',
     146:     (CHAR) '\312',
     147:     (CHAR) '\113',
     148:     (CHAR) '\314',
     149:     (CHAR) '\115',
     150:     (CHAR) '\116',
     151:     (CHAR) '\317',
     152:     (CHAR) '\120',
     153:     (CHAR) '\321',
     154:     (CHAR) '\322',
     155:     (CHAR) '\123',
     156:     (CHAR) '\324',
     157:     (CHAR) '\125',
     158:     (CHAR) '\126',
     159:     (CHAR) '\327',
     160:     (CHAR) '\330',
     161:     (CHAR) '\131',
     162:     (CHAR) '\132',
     163:     (CHAR) '\333',
     164:     (CHAR) '\134',
     165:     (CHAR) '\335',
     166:     (CHAR) '\336',
     167:     (CHAR) '\137',
     168:     (CHAR) '\140',
     169:     (CHAR) '\341',
     170:     (CHAR) '\342',
     171:     (CHAR) '\143',
     172:     (CHAR) '\344',
     173:     (CHAR) '\145',
     174:     (CHAR) '\146',
     175:     (CHAR) '\347',
     176:     (CHAR) '\350',
     177:     (CHAR) '\151',
     178:     (CHAR) '\152',
     179:     (CHAR) '\353',
     180:     (CHAR) '\154',
     181:     (CHAR) '\355',
     182:     (CHAR) '\356',
     183:     (CHAR) '\157',
     184:     (CHAR) '\360',
     185:     (CHAR) '\161',
     186:     (CHAR) '\162',
     187:     (CHAR) '\363',
     188:     (CHAR) '\164',
     189:     (CHAR) '\365',
     190:     (CHAR) '\366',
     191:     (CHAR) '\167',
     192:     (CHAR) '\170',
     193:     (CHAR) '\371',
     194:     (CHAR) '\372',
     195:     (CHAR) '\173',
     196:     (CHAR) '\374',
     197:     (CHAR) '\175',
     198:     (CHAR) '\176',
     199:     (CHAR) '\377'
     200: };
     201:
     202: /* CRC generation tables */
     203:
     204: static long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L,
     205:   051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L,
     206:   0153215L, 0163416L, 0173617L };
     207:
     208: static long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L,
     209:   053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L,
     210:   0155745L, 0164576L, 0174367L };
     211:
     212:
     213: /*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
     214:
     215: /*
     216:  This is the function that feeds input to Kermit's finite state machine,
     217:  in the form of a character in the range 32-126, normally a packet type
     218:  (uppercase letter) or pseudo-packet-type (lowercase letter).
     219:
     220:  If a special start state is in effect, that state is returned as if it were
     221:  the type of an incoming packet.  Otherwise:
     222:
     223:  (fill in...)
     224: */
     225:
     226: int
     227: input() {
     228:     int type;
     229:     int x = 0, y, k;
     230:
     231:     debug(F101,"input sstate","",sstate);
     232:     debug(F101," nakstate","",nakstate);
     233:     debug(F000," sndtyp","",sndtyp);
     234:
     235:     while (1) {             /* Big loop... */
     236:
     237:     if (sstate != 0) {      /* If a start state is in effect, */
     238:         type = sstate;      /* return it like a packet type, */
     239:         sstate = 0;         /* and then nullify it. */
     240:         numerrs = 0;        /* (PWP) no errors so far */
     241:         return(type);
     242:     }
     243:
     244:     if (nakstate) {         /* This section for file receiver. */
     245:
     246:         if (wslots > 1) {       /* If we're doing windows, */
     247:         x = rseqtbl[winlo]; /* see if desired packet already in. */
     248:         debug(F101," winlo","",winlo);
     249:         debug(F101," rseqtbl[winlo]","",rseqtbl[winlo]);
     250:         if (x > -1) {       /* Already there? */
     251:             if (r_pkt[x].pk_seq == winlo) { /* (double check) */
     252:             rsn = winlo;                /* Yes, return its info */
     253:             debug(F101,"input return pre-stashed packet","",rsn);
     254:             dumprbuf();
     255:             rdatap = r_pkt[x].pk_adr;   /* like rpack would do. */
     256:             rln = (int)strlen((char *) rdatap);
     257:             type = r_pkt[x].pk_typ;
     258:             break;
     259:             }
     260:         }
     261:         }
     262:         type = rpack();         /* Try to read a packet. */
     263:         debug(F111,"input recv",(char *) rdatap,(int) type);
     264:         while (type == 'e') {   /* Handle echoes */
     265:         debug(F000,"echo discarded","",type);
     266:         type = rpack();
     267:         }
     268:         if (type < -1) return('q'); /* Ctrl-C */
     269:         if (type < 0) {     /* Receive window full */
     270:         /* Another thing to do here would be to delete */
     271:         /* the highest packet and NAK winlo.  But that */
     272:         /* shouldn't be necessary since the other Kermit */
     273:         /* should not have sent a packet outside the window. */
     274:         debug(F101,"rpack receive window full","",0);
     275:         dumprbuf();
     276:         errpkt((CHAR *)"Receive window full.");
     277:         strcpy((char *)recpkt,"Receive window full.");
     278:         type = 'E';
     279:         break;
     280:         }
     281:         dumprbuf();
     282:
     283:         if (chkint() < 0) {     /* Check for console interrupts. */
     284:         errpkt((CHAR *)"User cancelled.");
     285:         strcpy((char *)recpkt,"User cancelled.");
     286:         type = 'E';
     287:         break;
     288:         }
     289:         if (type == 'E') {
     290:         debug(F101,"input got E, nakstate","",nakstate);
     291:         break;          /* Error packet */
     292:         }
     293:         if (type == 'Q') {      /* Crunched packet. */
     294:         crunched++;
     295:         numerrs++;
     296:         if (nack(winlo) < 0) {  /* Request resend of window-low.. */
     297:             debug(F101,"input sent too many naks","",winlo);
     298:             errpkt((CHAR *)"Too many retries.");
     299:             strcpy((char *)recpkt,"Sent too many NAKs.");
     300:             type = 'E';
     301:             break;
     302:         } else continue;
     303:         }
     304:         if (type == 'T') {      /* Timeout */
     305: #ifdef BULKNAKS
     306:         int z;
     307: #endif
     308:         timeouts++;
     309:         debug(F101,"input receive-state timeout, winlo","",winlo);
     310: #ifdef BULKNAKS
     311:         z = winlo + wslots; /* NAK all unACK'd packets */
     312:         if (z > 63) z -= 64;
     313:         debug(F101,"input sending bulk NAKs, winlo","",winlo);
     314:         for (x = winlo; (x != z) && ttchk() == 0; x++) {
     315:             if (x < 0 || x > 63) break;
     316:             if (rseqtbl[x] < 0) {
     317:             if (nack(x) < 0) {
     318:                 debug(F101,"input sent too many naks","",winlo);
     319:                 errpkt((CHAR *)"Too many retries.");
     320:                 strcpy(recpkt,"Sent too many NAKs.");
     321:                 type = 'E';
     322:                 break;
     323:             }
     324:             }
     325:         }
     326: #else       /* NAK only the packet at window-low */
     327:         debug(F101,"input sending NAK for winlo","",winlo);
     328:         if (nack(winlo) < 0) {
     329:             debug(F101,"input sent too many naks","",winlo);
     330:             errpkt((CHAR *)"Too many retries.");
     331:             strcpy((char *)recpkt,"Sent too many NAKs.");
     332:             type = 'E';
     333:             break;
     334:         }
     335: #endif /* BULKNAKS */
     336:         continue;
     337:         }
     338:
     339:         /* Got the packet we want, done. */
     340:
     341:         if (rsn == winlo) {
     342:         debug(F101,"input rsn=winlo","",rsn);
     343:         break;
     344:         }
     345:
     346:         /* Got a packet out of order. */
     347:
     348:         debug(F101,"input recv got packet out of order","",rsn);
     349:         k = rseqtbl[rsn];       /* Get window slot of this packet. */
     350:         debug(F101,"input recv rseqtbl[rsn]","",k);
     351:         if (k < 0) {
     352:         debug(F101,"input recv can't find index for rcvd pkt","",rsn);
     353:         errpkt((CHAR *)"internal error number 21");
     354:         strcpy((char *)recpkt,"Sliding windows protocol error.");
     355:         type = 'E';
     356:         break;
     357:         }
     358:         y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
     359:         debug(F101,"input recv chkwin","",y);
     360:         if (y == 1) {       /* Previous window. */
     361: #ifdef COMMENT
     362:         ackn(rsn);      /* Send empty ACK */
     363: #else
     364:         resend(rsn);
     365: #endif /* COMMENT */
     366:         freerpkt(rsn);      /* Get rid of received packet */
     367:         continue;
     368:         } else {            /* In this window or out of range */
     369:         if (y < 0)      /* If out of range entirely, */
     370:           freerpkt(rsn);    /* release its buffer */
     371: /*
     372:   We have received a packet, but not the one we want.  If we do nothing,
     373:   we could be in for a lengthy timeout/retry cycle.  It would seem to
     374:   make sense to send a NAK for the most desired packet (winlo).  But
     375:   consider this scenario: a packet arrived damaged so we NAK'd it above;
     376:   then packets winlo+1, winlo+2, ... winlo+n arrive, each one making us
     377:   send a NAK for winlo, so the other Kermit gets n NAKs for winlo, and
     378:   either would have to resend it n times, or if n > retry limit, give up
     379:   because of too many retries.  So we compromise: If a packet arrives
     380:   that is not the most desired packet (winlo), we NAK winlo, BUT ONLY IF
     381:   it has not been NAK'd before.
     382: */
     383:         if (s_pkt[k].pk_rtr == 0) {     /* Have we been here before? */
     384:             if (nack(winlo) < 0) {  /* No, NAK winlo. */
     385:             errpkt((CHAR *)"Too many retries."); /* Too many */
     386:             strcpy((char *)recpkt,"Timed out."); /* Give up */
     387:             type = 'E';
     388:             break;
     389:             } else continue;
     390:         } else continue;
     391:         }
     392: /*!!!*/
     393:     } else {            /* Otherwise file sender... */
     394:
     395:         if (wslots > 1) {       /* Packet at winlo already ACK'd? */
     396:         if (sacktbl[winlo]) {   /* If so,  */
     397:             sacktbl[winlo] = 0;       /* Turn off the ACK'd flag */
     398:             winlo = (winlo + 1) % 64; /* Rotate the window */
     399:             type = 'Y';     /* And return ACK */
     400:             debug(F101,
     401:               "input send returning pre-stashed ACK","",
     402:               winlo-1);
     403:             break;
     404:         }
     405:         }
     406:         type = rpack();     /* Try to read an acknowledgement */
     407:         debug(F111,"input send",(char *) rdatap,(int) type);
     408:         while (type == 'e') {   /* Handle echoes */
     409:         debug(F000,"echo discarded","",type);
     410:         type = rpack();
     411:         }
     412:         if (type == -2) return('q');
     413:         if (type == -1) {
     414:         errpkt((CHAR *)"Internal error number 18");
     415:         debug(F101," wslots","",wslots);
     416:         debug(F101," winlo","",winlo);
     417:         debug(F101," pktnum","",pktnum);
     418:         dumprbuf();
     419:         strcpy((char *)recpkt,"Can't allocate receive buffer");
     420:         type = 'E';
     421:         break;
     422:         }
     423:         dumprbuf();         /* debugging */
     424:
     425:         if (chkint() < 0) {     /* Check for console interrupts. */
     426:         errpkt((CHAR *)"User cancelled.");
     427:         strcpy((char *)recpkt,"User cancelled.");
     428:         return(type = 'E');
     429:         }
     430:
     431:         /* got a packet */
     432:
     433:         if (type == 'E') {
     434:         debug(F101,"input send got E, nakstate","",nakstate);
     435:         break;          /* Error packet */
     436:         }
     437:         if (type == 'Q') {      /* Crunched packet */
     438:         crunched++;     /* For statistics */
     439:         numerrs++;      /* For packet resizing */
     440:         x = resend(winlo);  /* Resend window-low */
     441:         if (x < 0) {
     442:             type = 'E';
     443:             errpkt(recpkt);
     444:             break;
     445:         }
     446:         continue;
     447:         }
     448:         if (type == 'T') {      /* Timeout waiting for ACKs. */
     449:         timeouts++;     /* Count it */
     450:         numerrs++;      /* Count an error too */
     451:         debug(F101,"input send state timeout, winlo","",winlo);
     452:
     453:         /* Retransmit the oldest un-ACK'd packet. */
     454:
     455:         debug(F101,"input send resending winlo","",winlo);
     456:         if (resend(winlo) < 0) { /* Check retries */
     457:             debug(F101,"input send too many resends","",maxtry);
     458:             errpkt(recpkt);
     459:             return(type = 'E');
     460:         }
     461:         continue;
     462:         }
     463:
     464:         /* Got an actual normal packet */
     465:
     466:         y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
     467:         debug(F101,"input send rsn","",rsn);
     468:         debug(F101,"input send winlo","",winlo);
     469:         debug(F101,"input send chkwin","",y);
     470:         if (type == 'Y') {      /* Got an ACK */
     471:         if (y == 0) {       /* In current window */
     472:             x = sseqtbl[rsn];   /* Mark the packet as ACK'd */
     473:             if (x > -1) s_pkt[x].pk_flg++;  /* (old way) */
     474:             sacktbl[rsn]++;             /* (new way) */
     475: /*
     476:   NOTE: The following statement frees the buffer of the ACK we just got.
     477:   But the upper layers still need the data, like if it's the ACK to an I,
     478:   S, F, D, Z, or just about any kind of packet.  So for now, freerbuf()
     479:   deallocates the buffer, but does not erase the data or destroy the pointer
     480:   to it.  There's no other single place where these receive buffers can be
     481:   correctly freed (?) ...
     482: */
     483:             freerpkt(rsn);  /* Free the ACK's buffer */
     484:             freesbuf(rsn);  /* *** Free the sent packet's buffer */
     485:             if (rsn == winlo) { /* Got the one we want */
     486:             sacktbl[winlo] = 0;
     487:             winlo = (winlo + 1) % 64;
     488:             debug(F101,"input send rotated send window","",winlo);
     489:             break;      /* Return the ACK */
     490:             } else {
     491:             debug(F101,"input send mark pkt","",rsn);
     492:             continue;   /* Otherwise go read another packet */
     493:             }
     494:         } else {        /* ACK not in window, ignore */
     495:             debug(F101,"input send ACK out of window","",rsn);
     496:             freerpkt(rsn);
     497:             continue;
     498:         }
     499:         }
     500:         if (type == 'N') {      /* NAK */
     501:         numerrs++;      /* Count an error */
     502:         debug(F101,"input send NAK","",rsn);
     503:         freerpkt(rsn);      /* Free buffer where NAK lies. */
     504:         if (y == 0) {       /* In current window */
     505:             debug(F100," in window","",0);
     506:             k = sseqtbl[rsn];   /* Get pointer to NAK'd packet. */
     507:             x = 0;
     508:             if (k < 0 || (k > -1 && s_pkt[k].pk_typ == ' ')) {
     509:             x = resend(winlo); /* Packet we haven't sent yet. */
     510:             } else {
     511:             x = resend(rsn); /* Resend requested packet. */
     512:             }
     513:             if (x < 0) {    /* Resend error is fatal.  */
     514:             type = 'E';
     515:             errpkt(recpkt);
     516:             break;
     517:             } else continue;    /* Resend ok, go read another packet */
     518:         } else if ((rsn == (pktnum + 1) % 64)) { /* NAK for next pkt */
     519:             if (wslots > 1) {
     520:             debug( F101,"NAK for next packet, windowing","",rsn);
     521:             x = resend(winlo); /* Resend window-low */
     522:             if (x < 0) {
     523:                 type = 'E';
     524:                 errpkt(recpkt);
     525:                 break;
     526:             }
     527:             continue;   /* Go back and read another pkt */
     528:             }
     529:             debug(F101,"NAK for next packet, no windowing","",rsn);
     530:             x = (rsn == 0) ? 63 : rsn - 1;
     531:             if (x == 0 && (sndtyp == 'S' || sndtyp == 'I')) {
     532:             resend(0);  /* ACK for S or I packet missing */
     533:             continue;   /* so resend it. */
     534:             }           /* Else, treat NAK(n+1) as ACK(n) */
     535:             if ((x = sseqtbl[x]) > -1) {
     536:             sacktbl[x]++;      /* (new way) */
     537:             s_pkt[x].pk_flg++; /* (old way) */
     538:             }
     539:             type = 'Y';     /* Treat it as ACK for last pkt */
     540:             break;
     541:         } else if (y > 0) { /* NAK for pkt we can't resend */
     542:             debug(F101," NAK out of window","",rsn); /* bad... */
     543:             type = 'E';
     544:             errpkt((CHAR *)"NAK out of window");
     545:             strcpy((char *)recpkt,"NAK out of window.");
     546:             break;
     547:         } else continue;    /* Ignore other NAKs */
     548:         }               /* End of file-sender NAK handler */
     549:
     550:             if (rsn == winlo) {     /* Not ACK, NAK, timeout, etc. */
     551:         debug(F000,"input send unexpected type","",type);
     552:         break;
     553:         }
     554:     }               /* End of file-sender section */
     555:     }                   /* End of input() loop */
     556:     if (wslots == 1) {
     557:     debug(F100,"input about to flush","",0);
     558:     ttflui();       /* Got what we want, clear input buffer. */
     559:     }
     560:     if (!nakstate)      /* When sending */
     561:       rcalcpsz();       /* recalculate size every packet */
     562:     debug(F000,"input returning type","",type);
     563:     return(type);       /* Success, return packet type. */
     564: }
     565:
     566: /*  D O P A R  --  Add an appropriate parity bit to a character  */
     567:
     568: /*
     569:   (PWP) this is still used in the Mac terminal emulator, so we have to keep it
     570: */
     571: CHAR
     572: #ifdef CK_ANSIC
     573: dopar(register CHAR ch)
     574: #else
     575: dopar(ch) register CHAR ch;
     576: #endif /* CK_ANSIC */
     577:     {
     578:     register unsigned int a;
     579:     if (!parity) return((CHAR) (ch & 255)); else a = ch & 127;
     580:     switch (parity) {
     581:     case 'e':  return(partab[a]);                /* Even */
     582:     case 'm':  return((CHAR) (a | 128));         /* Mark */
     583:     case 'o':  return((CHAR) (partab[a] ^ 128)); /* Odd */
     584:     case 's':  return((CHAR) a);                 /* Space */
     585:     default:   return((CHAR) a);                 /* Something illegal */
     586:     }
     587: }
     588:
     589: #ifdef PARSENSE
     590: /*  P A R C H K  --  Check if Kermit packet has parity  */
     591:
     592: /*
     593:   Call with s = pointer to packet, start = packet start character, n = length.
     594:   Returns 0 if packet has no parity, -1 on error, or, if packet has parity:
     595:     'e' for even, 'o' for odd, 'm' for mark.  Space parity cannot be sensed.
     596:   So a return value of 0 really means either space or none.
     597:   Returns -2 if parity has already been checked during this protocol operation.
     598: */
     599: int
     600: #ifdef CK_ANSIC
     601: parchk(CHAR *s, CHAR start, int n)
     602: #else
     603: parchk(s,start,n) CHAR *s, start; int n;
     604: #endif /* CK_ANSIC */
     605: /* parchk */ {
     606:     CHAR s0, s1, s2, s3;
     607:
     608:     debug(F101,"parchk n","",n);
     609:     debug(F101,"parchk start","",start);
     610:
     611:     s0 = s[0] & 0x7f;           /* Mark field (usually Ctrl-A) */
     612:
     613:     if (s0 != start || n < 5) return(-1); /* Not a valid packet */
     614:
     615: /* Look at packet control fields, which never have 8th bit set */
     616: /* First check for no parity, most common case. */
     617:
     618:     if (((s[0] | s[1] | s[2] | s[3]) & 0x80) == 0)
     619:       return(0);            /* No parity or space parity */
     620:
     621: /* Check for mark parity */
     622:
     623:     if (((s[0] & s[1] & s[2] & s[3]) & 0x80) == 0x80)
     624:       return('m');          /* Mark parity */
     625:
     626: /* Packet has some kind of parity */
     627: /* Make 7-bit copies of control fields */
     628:
     629:     s1 = s[1] & 0x7f;           /* LEN */
     630:     s2 = s[2] & 0x7f;           /* SEQ */
     631:     s3 = s[3] & 0x7f;           /* TYPE */
     632:
     633: /* Check for even parity */
     634:
     635:     if ((s[0] == partab[s0]) &&
     636:         (s[1] == partab[s1]) &&
     637:         (s[2] == partab[s2]) &&
     638:     (s[3] == partab[s3]))
     639:       return('e');
     640:
     641: /* Check for odd parity */
     642:
     643:     if ((s[0] != partab[s0]) &&
     644:         (s[1] != partab[s1]) &&
     645:         (s[2] != partab[s2]) &&
     646:     (s[3] != partab[s3]))
     647:       return('o');
     648:
     649: /* Otherwise it's probably line noise.  Let checksum calculation catch it. */
     650:
     651:     return(-1);
     652: }
     653: #endif /* PARSENSE */
     654:
     655: /*
     656:   Check to make sure timeout intervals are long enough to allow maximum
     657:   length packets to get through before the timer goes off.  If not, the
     658:   timeout interval is adjusted upwards.
     659:
     660:   This routine is called at the beginning of a transaction, before we
     661:   know anything about the delay characteristics of the line.  It works
     662:   only for serial communication devices; it trusts the speed reported by
     663:   the operating system.
     664:
     665:   Call with a timout interval.  Returns it, adjusted if necessary.
     666: */
     667: int
     668: chktimo(timo,flag) int timo, flag; {
     669:     long cps, z; int x, y;
     670:     debug(F101,"chktimo timo","",timo); /* Timeout before adjustment */
     671:     debug(F101,"chktimo flag","",flag);
     672:
     673:     if (flag)               /* Don't change timeout if user */
     674:       return(timo);         /* gave SET SEND TIMEOUT command. */
     675:     debug(F101,"chktimo spmax","",spmax);
     676:     debug(F101,"chktimo urpsiz","",urpsiz);
     677:
     678:     speed = ttgspd();           /* Get current speed. */
     679:     if (speed > 0L && !network) {
     680:     cps = speed / 10L;      /* Convert to chars per second */
     681:     if (cps > 0L) {
     682:         long plen;          /* Maximum of send and rcv pkt size */
     683:         z = cps * (long) timo;  /* Chars per timeout interval */
     684:         z -= z / 10L;       /* Less 10 percent */
     685:         plen = spmax;
     686:         if (urpsiz > spmax) plen = urpsiz;
     687:         debug(F101,"chktimo plen","",plen);
     688:         if (z < plen) {     /* Compare with packet size */
     689:         x = (int) ((long) plen / cps); /* Adjust if necessary */
     690:         y = x / 10;     /* Add 10 percent for safety */
     691:         if (y < 2) y = 2;   /* Or 2 seconds, whichever is more */
     692:         x += y;
     693:         if (x > timo)       /* If this is greater than current */
     694:           timo = x;     /* timeout, change the timeout */
     695:         debug(F101,"chktimo new timo","",timo);
     696:         }
     697:     }
     698:     }
     699:     return(timo);
     700: }
     701:
     702: /*  S P A C K  --  Construct and send a packet  */
     703:
     704: /*
     705:   spack() sends a packet of the given type, sequence number n, with len data
     706:   characters pointed to by d, in either a regular or extended- length packet,
     707:   depending on len.  Returns the number of bytes actually sent, or else -1
     708:   upon failure.  Uses global npad, padch, mystch, bctu, data.  Leaves packet
     709:   fully built and null-terminated for later retransmission by resend().
     710:   Updates global sndpktl (send-packet length).
     711:
     712:   NOTE: The global pointer "data" is assumed to point into the 7th position
     713:   of a character array (presumably in packet buffer for the current packet).
     714:   It was used by getpkt() to build the packet data field.  spack() fills in
     715:   the header to the left of the data pointer (the data pointer is defined
     716:   in getsbuf() in ckcfn3.c).  If the address "d" is the same as "data", then
     717:   the packet's data field has been built "in place" and need not be copied.
     718: */
     719: int
     720: #ifdef CK_ANSIC
     721: spack(char pkttyp, int n, int len, CHAR *d)
     722: #else
     723: spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
     724: #endif /* CK_ANSIC */
     725: /* spack */ {
     726:     register int i;
     727:     int j, k, lp, longpkt, copy;
     728:     register CHAR *cp, *mydata;
     729:     unsigned crc;
     730:
     731:     debug(F101,"spack n","",n);
     732:     debug(F111," data",data,data);
     733:     debug(F101," d","",d);
     734:     debug(F101," len","",len);
     735:
     736:     copy = (d != data);         /* Flag whether data must be copied  */
     737:     longpkt = (len + bctl + 2) > 94;    /* Decide whether it's a long packet */
     738:     mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
     739:     debug(F101," mydata","",mydata);
     740:
     741:     k = sseqtbl[n];         /* Packet structure info for pkt n */
     742:     debug(F101," sseqtbl[n]","",k);
     743:     if (k < 0) {
     744:     debug(F101,"spack sending packet out of window","",n);
     745:     } else {                /* Record packet info */
     746:     s_pkt[k].pk_adr = mydata;   /* Remember address of packet. */
     747:     s_pkt[k].pk_seq = n;        /* Record sequence number */
     748:     s_pkt[k].pk_typ = pkttyp;   /* Record packet type */
     749:     }
     750:
     751:     spktl = 0;              /* Initialize length of this packet */
     752:     i = 0;              /* and position in packet. */
     753:
     754: /* Now fill the packet */
     755:
     756:     mydata[i++] = mystch;       /* MARK */
     757:     lp = i++;               /* Position of LEN, fill in later */
     758:
     759:     mydata[i++] = tochar(n);        /* SEQ field */
     760:     mydata[i++] = pkttyp;       /* TYPE field */
     761:     j = len + bctl;         /* Length of data + block check */
     762:     if (longpkt) {          /* Long packet? */
     763:     int x;              /* Work around SCO Xenix/286 */
     764:     x = 95;             /* compiler bug... */
     765:     x = j / 95;
     766:         mydata[lp] = tochar(0);     /* Yes, set LEN to zero */
     767:         mydata[i++] = tochar(x);    /* High part */
     768:         mydata[i++] = tochar(j % 95);   /* Low part */
     769:         mydata[i] = '\0';       /* Header checksum */
     770:         mydata[i++] = tochar(chk1(mydata+lp));
     771:     } else mydata[lp] = tochar(j+2);    /* Normal LEN */
     772:
     773:     if (copy)               /* Data field built in place? */
     774:       for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */
     775:     else                /* Otherwise, */
     776:       i += len;             /* Just skip past data field. */
     777:     mydata[i] = '\0';           /* Null-terminate for checksum calc. */
     778:
     779:     switch (bctu) {         /* Block check */
     780:     case 1:             /* 1 = 6-bit chksum */
     781:         mydata[i++] = tochar(chk1(mydata+lp));
     782:         break;
     783:     case 2:             /* 2 = 12-bit chksum */
     784:         j = chk2(mydata+lp);
     785:         mydata[i++] = (unsigned)tochar((j >> 6) & 077);
     786:         mydata[i++] = (unsigned)tochar(j & 077);
     787:         break;
     788:         case 3:             /* 3 = 16-bit CRC */
     789:         crc = chk3(mydata+lp);
     790:         mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
     791:         mydata[i++] = (unsigned)tochar((crc >> 6) & 077);
     792:         mydata[i++] = (unsigned)tochar(crc & 077);
     793:         break;
     794:     case 4:             /* 2 = 12-bit chksum, blank-free */
     795:         j = chk2(mydata+lp);
     796:         mydata[i++] =
     797:           (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1)));
     798:         mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1)));
     799:         break;
     800:     }
     801:     mydata[i++] = seol;         /* End of line (packet terminator) */
     802: #ifdef TCPSOCKET
     803: /*
     804:   If TELNET connection and packet terminator is carriage return,
     805:   we must stuff either LF or NUL, according to SET TELNET NEWLINE-MODE
     806:   (tn_nlm), to meet the TELNET specification.
     807: */
     808:     if (network && ttnproto == NP_TELNET && seol == CR)
     809:       mydata[i++] = tn_nlm ? LF : NUL;
     810: #endif /* TCPSOCKET */
     811:     mydata[i] = '\0';           /* Terminate string */
     812:     logpkt('s',n,mydata);       /* Log packet */
     813:
     814:     /* (PWP) add the parity quickly at the end */
     815:     switch (parity) {
     816:       case 'e':             /* Even */
     817:     for (cp = &mydata[i-1]; cp >= mydata; cp--)
     818:       *cp = partab[*cp];
     819:     break;
     820:       case 'm':             /* Mark */
     821:     for (cp = &mydata[i-1]; cp >= mydata; cp--)
     822:       *cp |= 128;
     823:     break;
     824:       case 'o':             /* Odd */
     825:     for (cp = &mydata[i-1]; cp >= mydata; cp--)
     826:       *cp = partab[*cp] ^ 128;
     827:     break;
     828:       case 's':             /* Space */
     829:     for (cp = &mydata[i-1]; cp >= mydata; cp--)
     830:       *cp &= 127;
     831:     break;
     832:     }
     833:     if (npad) ttol(padbuf,npad);    /* Send any padding */
     834:     spktl = i;              /* Remember packet length */
     835:     s_pkt[k].pk_len = spktl;        /* also in packet info structure */
     836:     if (ttol(mydata,spktl) < 0) return(-1); /* Send the packet */
     837:     sndtyp = pkttyp;            /* Remember packet type for echos */
     838:     spackets++;             /* Count it. */
     839:     flco += spktl;          /* Count the characters */
     840:     tlco += spktl;          /* for statistics... */
     841:     dumpsbuf();             /* Dump send buffers to debug log */
     842:     screen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */
     843:     return(spktl);          /* Return length */
     844: }
     845:
     846: /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
     847:
     848: int
     849: chk1(pkt) register CHAR *pkt; {
     850:     register unsigned int chk;
     851:     chk = chk2(pkt);
     852:     chk = (((chk & 0300) >> 6) + chk) & 077;
     853:     return((int) chk);
     854: }
     855:
     856: /*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
     857:
     858: unsigned int
     859: chk2(pkt) register CHAR *pkt; {
     860:     register long chk; register unsigned int m;
     861:     m = (parity) ? 0177 : 0377;
     862:     for (chk = 0; *pkt != '\0'; pkt++)
     863:       chk += *pkt & m;
     864:     return((unsigned int) (chk & 07777));
     865: }
     866:
     867:
     868: /*  C H K 3  --  Compute a type-3 Kermit block check.  */
     869: /*
     870:  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
     871:  table.  Assumes the argument string contains no embedded nulls.
     872: */
     873: unsigned int
     874: chk3(pkt) register CHAR *pkt; {
     875:     register long c, crc;
     876:     register unsigned int m;
     877:     m = (parity) ? 0177 : 0377;
     878:     for (crc = 0; *pkt != '\0'; pkt++) {
     879:     c = crc ^ (long)(*pkt & m);
     880:     crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
     881:     }
     882:     return((unsigned int) (crc & 0xFFFF));
     883: }
     884:
     885: int
     886: nxtpkt() {              /* Called by file sender */
     887:     int j, n;
     888:
     889:     debug(F101,"nxtpkt pktnum","",pktnum);
     890:     debug(F101,"nxtpkt winlo ","",winlo);
     891:     n = (pktnum + 1) % 64;      /* Increment packet number mod 64 */
     892: #ifdef COMMENT
     893: /*
     894:   Suggested by Alan Grieg.  A packet can be sent out of window in
     895:   circumstances involving acks received out of order, ...  Have to think
     896:   about this...
     897: */
     898:     if (chkwin(n,winlo,wslots)) {
     899:     debug(F101,"nxtpkt n not in window","",n);
     900:     return(-1);
     901:     }
     902: #endif
     903:     j = getsbuf(n);         /* Get a buffer for packet n */
     904:     if (j < 0) {
     905:     debug(F101,"nxtpkt can't getsbuf","",j);
     906:     return(-1);
     907:     }
     908:     pktnum = n;
     909:     debug(F101,"nxtpkt bumped pktnum to","",pktnum);
     910:     return(0);
     911: }
     912:
     913: /* Functions for sending ACKs and NAKs */
     914:
     915: /* Note, we should only ACK the packet at window-low (winlo) */
     916: /* However, if an old packet arrives again (e.g. because the ACK we sent */
     917: /* earlier was lost), we ACK it again. */
     918:
     919: int
     920: ack() {                 /* Acknowledge the current packet. */
     921:     return(ackns(winlo,(CHAR *)""));
     922: }
     923:
     924: int
     925: ackns(n,s) int n; CHAR *s; {        /* Acknowledge packet n */
     926:     int j, k;
     927:     debug(F111,"ackns",s,n);
     928:
     929:     k = rseqtbl[n];         /* First find received packet n. */
     930:     debug(F101,"ackns k","",k);
     931: #ifdef COMMENT
     932: /* No need to set ACK'd bit, because we're gonna free the buffer now */
     933:     if (k > -1)             /* If in window */
     934:       s_pkt[k].pk_flg++;        /* mark the ack'd bit. */
     935:     else
     936:       debug(F101,"ackns can't set ack'd bit","",k);
     937: #endif
     938:     freesbuf(n);            /* Free current send-buffer, if any */
     939:     if ((j = getsbuf(n)) < 0) {
     940:     /* This can happen if we have to re-ACK an old packet that has */
     941:         /* already left the window.  It does no harm. */
     942:     debug(F101,"ackns can't getsbuf","",n);
     943:     }
     944:     spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */
     945:     debug(F101,"ackns winlo","",winlo);
     946:     debug(F101,"ackns n","",n);
     947:     if (n == winlo) {           /* If we're acking winlo */
     948:     if (k > -1)
     949:       freerbuf(k);          /* don't need it any more */
     950:     if (j > -1)
     951:       freesbuf(j);          /* and don't need to keep ACK either */
     952:     winlo = (winlo + 1) % 64;
     953:     }
     954:     return(0);
     955: }
     956:
     957: int
     958: ackn(n) int n; {            /* Send ACK for packet number n */
     959:     return(ackns(n,(CHAR *)""));
     960: }
     961:
     962: int
     963: ack1(s) CHAR *s; {          /* Send an ACK with data. */
     964:     debug(F110,"ack1",(char *) s,0);
     965:     return(ackns(winlo, s));
     966: }
     967:
     968: /* N A C K  --   Send a Negative ACKnowledgment. */
     969: /*
     970:  Call with the packet number, n, to be NAK'd.
     971:  Returns -1 if that packet has been NAK'd too many times, otherwise 0.
     972:  Btw, it is not right to return 0 under error conditions.  This is
     973:  done because the -1 code is used for cancelling the file transfer.
     974:  More work is needed here.
     975: */
     976: int
     977: nack(n) int n; {
     978:     int i;
     979:
     980:     if (n < 0 || n > 63) {
     981:     debug(F101,"nack bad pkt num","",n);
     982:     return(0);
     983:     } else debug(F101,"nack","",n);
     984:     if ((i = sseqtbl[n]) < 0) {     /* If necessary */
     985:     if (getsbuf(n) < 0) {       /* get a buffer for this NAK */
     986:         debug(F101,"nack can't getsbuf","",n);
     987:         return(0);
     988:     } else i = sseqtbl[n];      /* New slot number */
     989:     }
     990:     if (s_pkt[i].pk_rtr++ > maxtry) /* How many times have we done this? */
     991:       return(-1);           /* Too many... */
     992:
     993: /* Note, don't free this buffer.  Eventually an ACK will come, and that */
     994: /* will set it free.  If not, well, it's back to ground zero anyway...  */
     995:
     996:     spack('N',n,0,(CHAR *) "");     /* NAKs never have data. */
     997:     return(0);
     998: }
     999:
    1000: /*
    1001:  * (PWP) recalculate the optimal packet length in the face of errors.
    1002:  * This is a modified version of the algorithm by John Chandler in Kermit/370,
    1003:  * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
    1004:  *
    1005:  * This implementation minimizes the total overhead equation, which is
    1006:  *
    1007:  *   Total chars = file_chars + (header_len * num_packs)
    1008:  *                            + (errors * (header_len + packet_len))
    1009:  *
    1010:  * Differentiate with respect to number of chars, solve for packet_len, get:
    1011:  *
    1012:  *   packet_len = sqrt (file_chars * header_len / errors)
    1013:  */
    1014:
    1015: /*
    1016:  (FDC) New super-simple algorithm.  If there was an error in the most recent
    1017:  packet exchange, cut the send-packet size in half, down to a minimum of 20.
    1018:  If there was no error, increase the size by 5/4, up to the maximum negotiated
    1019:  length.  Seems to be much more responsive than previous algorithm, which took
    1020:  forever to recover the original packet length, and it also went crazy under
    1021:  certain conditions.
    1022:
    1023:  Here's another idea for packet length resizing that keeps a history of the
    1024:  last n packets.  Push a 1 into the left end of an n-bit shift register if the
    1025:  current packet is good, otherwise push a zero.  The current n-bit value, w, of
    1026:  this register is a weighted sum of the noise hits for the last n packets, with
    1027:  the most recent weighing the most.  The current packet length is some function
    1028:  of w and the negotiated packet length, like:
    1029:
    1030:    (2^n - w) / (2^n) * (negotiated length)
    1031:
    1032:  If the present resizing method causes problems, think about this one a little
    1033:  more.
    1034: */
    1035: VOID
    1036: rcalcpsz() {
    1037:
    1038: #ifdef COMMENT
    1039: /* Old way */
    1040:     register long x, q;
    1041:     if (numerrs == 0) return;   /* bounds check just in case */
    1042:
    1043:     /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
    1044:     /* an ACK is 5+bctr */
    1045:
    1046:     /* first set x = per packet overhead */
    1047:     if (wslots > 1)
    1048:     x = (long) (npad+5+bctr);    /* only the packet, don't count the ack */
    1049:     else
    1050:     x = (long) (npad+5+3+bctr+5+bctr);
    1051:
    1052:     /* then set x = packet length ** 2 */
    1053:     x = x * ( ffc / (long) numerrs);    /* careful of overflow */
    1054:
    1055:     /* calculate the long integer sqrt(x) quickly */
    1056:     q = 500;
    1057:     q = (q + x/q) >> 1;
    1058:     q = (q + x/q) >> 1;
    1059:     q = (q + x/q) >> 1;
    1060:     q = (q + x/q) >> 1;     /* should converge in about 4 steps */
    1061:     if ((q > 94) && (q < 130))  /* break-even point for long packets */
    1062:     q = 94;
    1063:     if (q > spmax) q = spmax;   /* maximum bounds */
    1064:     if (q < 10) q = 10;     /* minimum bounds */
    1065:     spsiz = q;          /* set new send packet size */
    1066:     debug(F101,"rcalcpsiz","",q);
    1067: #else
    1068: /* New way */
    1069:     if (spackets < 3) return;
    1070:     debug(F101,"rcalcpsiz numerrs","",numerrs);
    1071:     debug(F101,"rcalcpsiz spsiz","",spsiz);
    1072:     if (numerrs)
    1073:       spsiz = spsiz / 2;
    1074:     else
    1075:       spsiz = (spsiz / 4) * 5;
    1076:     if (spsiz < 20) spsiz = 20;
    1077:     if (spsiz > spmax) spsiz = spmax;
    1078:     debug(F101,"rcalcpsiz new spsiz","",spsiz);
    1079:     numerrs = 0;
    1080:     return;
    1081: #endif
    1082: }
    1083:
    1084: /*  R E S E N D  --  Retransmit packet n.  */
    1085:
    1086: /*
    1087:   Returns 0 or positive on success (the number of retries for packet n).
    1088:   On failure, returns a negative number, and an error message is placed
    1089:   in recpkt.
    1090: */
    1091: int
    1092: resend(n) int n; {          /* Send packet n again. */
    1093:     int j, k;
    1094:
    1095:     debug(F101,"resend seq","",n);
    1096:
    1097:     k = chkwin(n,winlo,wslots);     /* See if packet in current window */
    1098:     j = -1;             /* Assume it's lost */
    1099:     if (k == 0) j = sseqtbl[n];     /* See if we still have a copy of it */
    1100:     if (k != 0 || j < 0) {      /* If not.... */
    1101:     if (nakstate && k == 1) {
    1102: /*
    1103:   Packet n is in the previous window and we are the file receiver.
    1104:   We already sent the ACK and deallocated its buffer so we can't just
    1105:   retransmit the ACK.  Rather than give up, we try some tricks...
    1106: */
    1107:         if (n == 0 && spackets < 63 && myinit[0]) { /* ACK to Send-Init */
    1108: /*
    1109:   If the packet number is 0, and we're at the beginning of a protocol
    1110:   operation (spackets < 63), then we have to resend the ACK to an I or S
    1111:   packet, complete with parameters in the data field.  So we take a chance and
    1112:   send a copy of the parameters in an ACK packet with block check type 1.
    1113: */
    1114:         int bctlsav;        /* Temporary storage */
    1115:         int bctusav;
    1116:         bctlsav = bctl;     /* Save current block check length */
    1117:         bctusav = bctu;     /* and type */
    1118:         bctu = bctl = 1;    /* Set block check to 1 */
    1119:         spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
    1120:         logpkt('#',n,(CHAR *)"<reconstructed>"); /* Log it */
    1121:         bctu = bctusav;     /* Restore block check type */
    1122:         bctl = bctlsav;     /* and length */
    1123:
    1124:         } else {            /* Not the first packet */
    1125: /*
    1126:   It's not the first packet of the protocol operation.  It's some other packet
    1127:   that we have already ACK'd and forgotten about.  So we take a chance and
    1128:   send an empty ACK using the current block-check type.  Usually this will
    1129:   work out OK (like when acking Data packets), and no great harm will be done
    1130:   if it was some other kind of packet (F, etc).  If we are requesting an
    1131:   interruption of the file transfer, the flags are still set, so we'll catch
    1132:   up on the next packet.
    1133: */
    1134:         spack('Y',n,0,(CHAR *) "");
    1135:         logpkt('#',n,(CHAR *)"<faith>"); /* Log it */
    1136:         }
    1137:         retrans++;
    1138:         screen(SCR_PT,'%',(long)pktnum,"(resend)");
    1139:         return(0);
    1140:     } else {
    1141: /*
    1142:   Packet number is not in current or previous window.  We seem to hit this
    1143:   code occasionally at the beginning of a transaction, for apparently no good
    1144:   reason.  Let's just log it for debugging, send nothing, and try to proceed
    1145:   with the protocol rather than killing it.
    1146: */
    1147:         debug(F101,"RESEND PKT NOT IN WINDOW","",n);
    1148:         debug(F101,"RESEND k","",k);
    1149: #ifdef COMMENT
    1150:         sprintf((char *)recpkt,
    1151:             "   resend error: NIW, n=%d, k=%d.",n,k);
    1152:         return(-2);
    1153: #else
    1154:         return(0);
    1155: #endif /* COMMENT */
    1156:     }
    1157:     }
    1158:
    1159: /* OK, it's in the window and it's not lost. */
    1160:
    1161:     debug(F101,"resend pktinfo index","",k);
    1162:
    1163:     if (s_pkt[j].pk_rtr++ > maxtry) {   /* Found it but over retry limit */
    1164:     strcpy((char *)recpkt,"Too many retries.");
    1165:     return(-1);
    1166:     }
    1167:     debug(F101," retry","",s_pkt[j].pk_rtr); /* OK so far */
    1168:     dumpsbuf();             /* (debugging) */
    1169:     if (s_pkt[j].pk_typ == ' ') {   /* Incompletely formed packet */
    1170:     if (nakstate) {         /* (This shouldn't happen any more) */
    1171:         nack(n);
    1172:         retrans++;
    1173:         screen(SCR_PT,'%',(long)pktnum,"(resend)");
    1174:         return(s_pkt[j].pk_rtr);
    1175:     } else {            /* No packet to resend! */
    1176: #ifdef COMMENT
    1177: /*
    1178:   This happened (once) while sending a file with 2 window slots and typing
    1179:   X to the sender to cancel the file.  But since we're cancelling anyway,
    1180:   no need to give a scary message.
    1181: */
    1182:         sprintf((char *)recpkt,
    1183:             "resend logic error: NPS, n=%d, j=%d.",n,j);
    1184:         return(-2);
    1185: #else
    1186: /* Just ignore it. */
    1187:         return(0);
    1188: #endif /* COMMENT */
    1189:     }
    1190:     }
    1191:     ttol(s_pkt[j].pk_adr,s_pkt[j].pk_len); /* Everything ok, send the packet */
    1192:     retrans++;              /* Count a retransmission */
    1193:     screen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Tell user about resend */
    1194:     logpkt('S',n,s_pkt[j].pk_adr);  /* Log the resent packet */
    1195:     return(s_pkt[j].pk_rtr);        /* Return the number of retries. */
    1196: }
    1197:
    1198: int
    1199: errpkt(reason) CHAR *reason; {      /* Send an error packet. */
    1200:     int x, y;
    1201:     encstr(reason);
    1202:     y = spack('E',pktnum,size,encbuf+7);
    1203:     x = quiet; quiet = 1;       /* Close files silently. */
    1204:     clsif(); clsof(1);
    1205:     quiet = x;
    1206: #ifdef COMMENT
    1207:     screen(SCR_TC,0,0l,"");
    1208: #endif /* COMMENT */
    1209:     if (what < W_CONNECT)
    1210:       xitsta |= what;           /* Remember what failed. */
    1211:     success = 0;
    1212:     return(y);
    1213: }
    1214:
    1215: /* scmd()  --  Send a packet of the given type */
    1216:
    1217: int
    1218: #ifdef CK_ANSIC
    1219: scmd(char t, CHAR *dat)
    1220: #else
    1221: scmd(t,dat) char t; CHAR *dat;
    1222: #endif /* CK_ANSIC */
    1223: /* scmd */ {
    1224:     encstr(dat);            /* Encode the command string */
    1225:     spack(t,pktnum,size,(CHAR *)(encbuf+7));
    1226:     return(0);
    1227: }
    1228:
    1229: VOID
    1230: srinit() {              /* Send R (GET) packet */
    1231:     encstr((CHAR *)cmarg);      /* Encode the filename. */
    1232:     spack('R',pktnum,size,encbuf+7);    /* Send the packet. */
    1233: }
    1234:
    1235: /* R P A C K  --  Read a Packet */
    1236:
    1237: /*
    1238:  rpack reads a packet and returns the packet type, or else Q if the
    1239:  packet was invalid, or T if a timeout occurred.  Upon successful return, sets
    1240:  the values of global rsn (received sequence number),  rln (received
    1241:  data length), and rdatap (pointer to null-terminated data field).
    1242: */
    1243: int
    1244: rpack() {
    1245:     register int i, j, x, lp;       /* Local variables */
    1246:     int k, type, chklen;
    1247:     unsigned crc;
    1248:     CHAR pbc[4];            /* Packet block check */
    1249:     CHAR *sohp;             /* Pointer to SOH */
    1250:     CHAR e;             /* Packet end character */
    1251:
    1252:     debug(F101,"entering rpack, pktnum","",pktnum);
    1253:     k = getrbuf();          /* Get a new packet input buffer. */
    1254:     debug(F101,"rpack getrbuf","",k);
    1255:     if (k < 0) return(-1);      /* Return like this if none free. */
    1256:     recpkt = r_pkt[k].bf_adr;
    1257:     *recpkt = '\0';         /* Clear receive buffer. */
    1258:     sohp = recpkt;          /* Initialize pointers to it. */
    1259:     rdatap = recpkt;
    1260:     rsn = rln = -1;         /* In case of failure. */
    1261:     e = (turn) ? turnch : eol;      /* Use any handshake char for eol */
    1262:
    1263: /* Try to get a "line". */
    1264:
    1265: #ifdef PARSENSE
    1266: #ifdef UNIX
    1267: /*
    1268:   So far the final turn argument is only for ck[uvd]tio.c.  Should be added
    1269:   to the others too.  (turn == handshake character.)
    1270: */
    1271:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr,turn);
    1272: #else
    1273: #ifdef VMS
    1274:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr,turn);
    1275: #else
    1276: #ifdef datageneral
    1277:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr,turn);
    1278: #else
    1279:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr);
    1280: #endif /* datageneral */
    1281: #endif /* VMS */
    1282: #endif /* UNIX */
    1283:     if (parity != ttprty) autopar = 1;
    1284:     parity = ttprty;
    1285: #else
    1286:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e);
    1287: #endif /* PARSENSE */
    1288:     if (j < 0) {
    1289:     debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */
    1290:     freerbuf(k);            /* Free this buffer */
    1291:     if (j < -1) {           /* Bail out if ^C^C typed. */
    1292:         debug(F101,"rpack ^C server","",server);
    1293:         debug(F101,"rpack ^C en_fin","",en_fin);
    1294:         if (server == 0) return(j); /* But not if in server mode */
    1295:         else if (en_fin) return(j); /* with DISABLE FINISH */
    1296:     }
    1297:     if (nakstate)                  /* call it a timeout. */
    1298:       screen(SCR_PT,'T',(long)winlo,"");
    1299:     else
    1300:       screen(SCR_PT,'T',(long)pktnum,"");
    1301:     logpkt('r',-1,(CHAR *)"<timeout>");
    1302:     if (flow == 1) ttoc(XON);   /* In case of Xoff blockage. */
    1303:     return('T');
    1304:     }
    1305:     rpktl = j;
    1306:     tlci += j;              /* All OK, Count the characters. */
    1307:     flci += j;
    1308:
    1309: #ifndef PARSENSE
    1310: /* THEN eliminate this loop... */
    1311:     for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
    1312:       sohp++;               /* Find mark */
    1313:     if (i++ >= j) {         /* Didn't find it. */
    1314:     logpkt('r',-1,"<timeout>");
    1315:     freerbuf(k);
    1316:     return('T');
    1317:     }
    1318: #else
    1319:     i = 1;
    1320: #endif /* PARSENSE */
    1321:
    1322:     rpackets++;
    1323:     lp = i;             /* Remember LEN position. */
    1324:     if ((j = xunchar(recpkt[i++])) == 0) {
    1325:         if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */
    1326:     x = recpkt[j];          /* Header checksum. */
    1327:     recpkt[j] = '\0';       /* Calculate & compare. */
    1328:     if (xunchar(x) != chk1(recpkt+lp)) {
    1329:         freerbuf(k);
    1330:         logpkt('r',-1,(CHAR *)"<crunched:hdr>");
    1331:         return('Q');
    1332:     }
    1333:     recpkt[j] = x;          /* Checksum ok, put it back. */
    1334:     rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctl;
    1335:     j = 3;              /* Data offset. */
    1336:     } else if (j < 3) {
    1337:     debug(F101,"rpack packet length less than 3","",j);
    1338:     freerbuf(k);
    1339:     logpkt('r',-1,(CHAR *)"<crunched:len>");
    1340:     return('Q');
    1341:     } else {
    1342:     rln = j - bctl - 2;     /* Regular packet */
    1343:     j = 0;              /* No extended header */
    1344:     }
    1345:     rsn = xunchar(recpkt[i++]);     /* Sequence number */
    1346:     logpkt('r',rsn,sohp);
    1347:     if (rsn < 0 || rsn > 63) {
    1348:     debug(F101,"rpack bad sequence number","",rsn);
    1349:     freerbuf(k);
    1350:     logpkt('r',rsn,(CHAR *)"<crunched:seq>");
    1351:     return('Q');
    1352:     }
    1353: /*
    1354:   If this packet has the same type as the packet just sent, assume it is
    1355:   an echo and ignore it.  Don't even bother with the block check calculation:
    1356:   even if the packet is corrupted, we don't want to NAK an echoed packet.
    1357:   (And we certainly don't want to NAK an ACK or NAK!)
    1358: */
    1359:     type = recpkt[i++];         /* Get packet's TYPE field */
    1360:     if (type == sndtyp || (nakstate && (type == 'N' /* || type == 'Y' */ ))) {
    1361:     debug(F000,"rpack echo","",type); /* If it's an echo */
    1362:     freerbuf(k);            /* Free this buffer */
    1363:     logpkt('#',rsn,(CHAR *)"<echo:ignored>");
    1364:     return('e');            /* return special (lowercase) code */
    1365:     }
    1366: /*
    1367:   Separate the data from the block check, accounting for the case where
    1368:   a packet was retransmitted after the block check switched.
    1369: */
    1370:     if (type == 'I' || type == 'S') {   /* I & S packets always have type 1 */
    1371:     chklen = 1;
    1372:     rln = rln + bctl - 1;
    1373:     } else if (type == 'N') {       /* A NAK packet never has data */
    1374:     chklen = xunchar(recpkt[lp]) - 2;
    1375:     rln = rln + bctl - chklen;
    1376:     } else chklen = bctl;
    1377:     debug(F101,"rpack bctl","",bctl);
    1378:     debug(F101,"rpack chklen","",chklen);
    1379:
    1380:     i += j;             /* Buffer index of DATA field */
    1381:     rdatap = recpkt+i;          /* Pointer to DATA field */
    1382:     if ((j = rln + i) > r_pkt[k].bf_len ) { /* Make sure it fits */
    1383:     debug(F101,"packet sticks out too far","",j);
    1384:     freerbuf(k);
    1385:     logpkt('r',rsn,(CHAR *)"<overflow>");
    1386:     return('Q');
    1387:     }
    1388:
    1389:     for (x = 0; x < chklen; x++)    /* Copy the block check */
    1390:       pbc[x] = recpkt[j+x];
    1391:     pbc[x] = '\0';          /* Null-terminate block check string */
    1392:     recpkt[j] = '\0';           /*  and the packet DATA field. */
    1393:
    1394:     if (chklen == 2 && bctu == 4) { /* Adjust for Blank-Free-2 */
    1395:     chklen = 4;         /* (chklen is now a misnomer...) */
    1396:     debug(F100,"rpack block check B","",0);
    1397:     }
    1398:     switch (chklen) {           /* Check the block check */
    1399:     case 1:             /* Type 1, 6-bit checksum */
    1400:         if (xunchar(*pbc) != chk1(recpkt+lp)) {
    1401:         debug(F110,"checked chars",recpkt+lp,0);
    1402:             debug(F101,"block check","",(int) xunchar(*pbc));
    1403:         debug(F101,"should be","",chk1(recpkt+lp));
    1404:         freerbuf(k);
    1405:         logpkt('r',-1,(CHAR *)"<crunched:chk1>");
    1406:         return('Q');
    1407:         }
    1408:         break;
    1409:     case 2:             /* Type 2, 12-bit checksum */
    1410:         x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
    1411:         if (x != chk2(recpkt+lp)) { /* No match */
    1412:         if (type == 'E') {  /* Allow E packets to have type 1 */
    1413:             recpkt[j++] = pbc[0];
    1414:             recpkt[j] = '\0';
    1415:             if (xunchar(pbc[1]) == chk1(recpkt+lp))
    1416:               break;
    1417:             else
    1418:               recpkt[--j] = '\0';
    1419:         }
    1420:         debug(F110,"checked chars",recpkt+lp,0);
    1421:             debug(F101,"block check","", x);
    1422:         debug(F101,"should be","", (int) chk2(recpkt+lp));
    1423:         freerbuf(k);
    1424:         logpkt('r',-1,(CHAR *)"<crunched:chk2>");
    1425:         return('Q');
    1426:         }
    1427:         break;
    1428:     case 3:             /* Type 3, 16-bit CRC */
    1429:         crc = (xunchar(pbc[0]) << 12)
    1430:             | (xunchar(pbc[1]) << 6)
    1431:         | (xunchar(pbc[2]));
    1432:         if (crc != chk3(recpkt+lp)) {
    1433:         if (type == 'E') {  /* Allow E packets to have type 1 */
    1434:             recpkt[j++] = pbc[0];
    1435:             recpkt[j++] = pbc[1];
    1436:             recpkt[j] = '\0';
    1437:             if (xunchar(pbc[2]) == chk1(recpkt+lp))
    1438:               break;
    1439:             else { j -=2; recpkt[j] = '\0'; }
    1440:         }
    1441:         debug(F110,"checked chars",recpkt+lp,0);
    1442:             debug(F101,"block check","",xunchar(*pbc));
    1443:         debug(F101,"should be","",(int) chk3(recpkt+lp));
    1444:         freerbuf(k);
    1445:         logpkt('r',-1,(CHAR *)"<crunched:chk3>");
    1446:         return('Q');
    1447:         }
    1448:         break;
    1449:     case 4:             /* Type 4 = Type 2, no blanks. */
    1450:         x = (unsigned)((xunchar(*pbc) - 1) << 6) |
    1451:             (unsigned)(xunchar(pbc[1]) - 1);
    1452:         if (x != chk2(recpkt+lp)) {
    1453:         if (type == 'E') {  /* Allow E packets to have type 1 */
    1454:             recpkt[j++] = pbc[0];
    1455:             recpkt[j] = '\0';
    1456:             if (xunchar(pbc[1]) == chk1(recpkt+lp))
    1457:               break;
    1458:             else
    1459:               recpkt[--j] = '\0';
    1460:         }
    1461:         debug(F101,"bad type B block check","",x);
    1462:         freerbuf(k);
    1463:         logpkt('r',-1,(CHAR *)"<crunched:chkb>");
    1464:         return('Q');
    1465:         }
    1466:         break;
    1467:     default:            /* Shouldn't happen... */
    1468:         freerbuf(k);
    1469:         logpkt('r',-1,(CHAR *)"<crunched:chkx>");
    1470:         return('Q');
    1471:     }
    1472:     debug(F101,"rpack block check OK","",rsn);
    1473:
    1474: /* Now we can believe the sequence number, and other fields. */
    1475: /* Here we violate strict principles of layering, etc, and look at the  */
    1476: /* packet sequence number.  If there's already a packet with the same   */
    1477: /* number in the window, we remove this one so that the window will not */
    1478: /* fill up. */
    1479:
    1480:     if ((x = rseqtbl[rsn]) != -1) { /* Already a packet with this number */
    1481:     retrans++;          /* Count it for statistics */
    1482:     debug(F101,"rpack got dup","",rsn);
    1483:     logpkt('r',rsn,(CHAR *)"<duplicate>");
    1484:     freerbuf(x);            /* Free old buffer, keep new packet. */
    1485:     r_pkt[k].pk_rtr++;      /* Count this as a retransmission. */
    1486:     }
    1487:
    1488: /* New packet, not seen before, enter it into the receive window. */
    1489:
    1490:     rseqtbl[rsn] = k;           /* Make back pointer */
    1491:     r_pkt[k].pk_seq = rsn;      /* Record in packet info structure */
    1492:     r_pkt[k].pk_typ = type;     /* Sequence, type,... */
    1493:     r_pkt[k].pk_adr = rdatap;       /* pointer to data buffer */
    1494:     screen(SCR_PT,(char)type,(long)rsn,(char *)sohp); /* Update screen */
    1495:     return(type);           /* Return packet type */
    1496: }
    1497:
    1498: /*  L O G P K T  --  Log packet number n, pointed to by s.  */
    1499:
    1500: /* c = 's' (send) or 'r' (receive) */
    1501:
    1502: VOID
    1503: #ifdef CK_ANSIC
    1504: logpkt(char c,int n, CHAR *s)
    1505: #else
    1506: logpkt(c,n,s) char c; int n; CHAR *s;
    1507: #endif /* CK_ANSIC */
    1508: /* logpkt */ {
    1509:     char plog[20];
    1510:     if (pktlog && *s) {
    1511:     if (n < 0)
    1512:       sprintf(plog,"%c-xx-%02d-",c,(gtimer()%60));
    1513:     else
    1514:       sprintf(plog,"%c-%02d-%02d-",c,n,(gtimer()%60));
    1515:     if (zsout(ZPFILE,plog) < 0) pktlog = 0;
    1516:     else if (zsoutl(ZPFILE,(char *)s) < 0) pktlog = 0;
    1517:     }
    1518: }
    1519:
    1520: #ifdef TLOG
    1521:
    1522: /*  T S T A T S  --  Record statistics in transaction log  */
    1523:
    1524: VOID
    1525: tstats() {
    1526:     char *tp;
    1527:     ztime(&tp);             /* Get time stamp */
    1528:     tlog(F110,"End of transaction",tp,0L);  /* Record it */
    1529:
    1530:     if (filcnt < 1) return;     /* If no files, done. */
    1531:
    1532: /* If multiple files, record character totals for all files */
    1533:
    1534:     if (filcnt > 1) {
    1535:     tlog(F101," files","",filcnt);
    1536:     tlog(F101," total file characters   ","",tfc);
    1537:     tlog(F101," communication line in   ","",tlci);
    1538:     tlog(F101," communication line out  ","",tlco);
    1539:     }
    1540:
    1541: /* Record timing info for one or more files */
    1542:
    1543:     tlog(F101," elapsed time (seconds)  ","",(long) tsecs);
    1544:     if (tsecs > 0) {
    1545:     long lx;
    1546:     lx = (tfc * 10L) / (long) tsecs;
    1547:     tlog(F101," effective data rate     ","",lx/10L);
    1548:     if (speed <= 0L) speed = ttgspd();
    1549:     if (speed > 0L && speed != 8880L && network == 0) {
    1550:         lx = (lx * 100L) / speed;
    1551:         tlog(F101," efficiency (percent)    ","",lx);
    1552:     }
    1553:     }
    1554:     tlog(F100,"","",0L);        /* Leave a blank line */
    1555: }
    1556:
    1557: /*  F S T A T S  --  Record file statistics in transaction log  */
    1558:
    1559: VOID
    1560: fstats() {
    1561:     tfc += ffc;
    1562:     tlog(F100," end of file","",0L);
    1563:     tlog(F101,"  file characters        ","",ffc);
    1564:     tlog(F101,"  communication line in  ","",flci);
    1565:     tlog(F101,"  communication line out ","",flco);
    1566: }
    1567: #else /* NOTLOG */
    1568: VOID
    1569: tstats() {}
    1570:
    1571: VOID
    1572: fstats() {
    1573:     tfc += ffc;
    1574: }
    1575: #endif /* TLOG */

#### Defined functions

ack defined in line 919; never used
ack1 defined in line 962; used 2 times

- in /usr/src/new/kermit5.188/ckcfns.c line 908, 1906

ackn defined in line 957; used 1 times

- in line 362

ackns defined in line 924; used 3 times

- in line 921, 959, 965

chk1 defined in line 848; used 8 times

- in line 770, 781, 1328, 1400-1403(2), 1415, 1437, 1456

chk2 defined in line 858; used 6 times

- in line 784, 795, 851, 1411, 1422, 1452

chk3 defined in line 873; used 3 times

- in line 789, 1432, 1443

chktimo defined in line 667; used 5 times

- in /usr/src/new/kermit5.188/ckcfns.c line 871, 1526, 1593, 1686, 2050

dopar defined in line 571; used 25 times

- in /usr/src/new/kermit5.188/ckcfns.c line 1603
- in /usr/src/new/kermit5.188/ckucon.c line 745-750(2), 826, 848, 1158, 1272, 1302
- in /usr/src/new/kermit5.188/ckuscr.c line 253, 266, 274-276(2)
- in /usr/src/new/kermit5.188/ckuus4.c line 511, 538-541(3), 548, 559-563(4), 625
- in /usr/src/new/kermit5.188/ckuus5.c line 1089-1093(2), 1107

errpkt defined in line 1198; used 15 times

- in line 276, 284, 298, 319, 330, 353, 385, 414, 426, 443, 458, 515, 524, 544
- in /usr/src/new/kermit5.188/ckcfns.c line 1014

fstats defined in line 1571; used 3 times

- in /usr/src/new/kermit5.188/ckcfn3.c line 1378, 1418, 1426

input defined in line 226; never used
logpkt defined in line 1502; used 18 times

- in line 812, 1120, 1135, 1194, 1301, 1314, 1330, 1339, 1346-1350(2), 1363, 1385, 1405, 1424, 1445, 1463, 1469, 1483

nack defined in line 976; used 5 times

- in line 296, 317, 328, 384, 1171

nxtpkt defined in line 885; used 5 times

- in /usr/src/new/kermit5.188/ckcfn3.c line 645
- in /usr/src/new/kermit5.188/ckcfns.c line 1299, 1403, 1493, 1505

parchk defined in line 599; used 2 times

- in /usr/src/new/kermit5.188/ckcnet.c line 1682
- in /usr/src/new/kermit5.188/ckutio.c line 4615

rcalcpsz defined in line 1035; used 1 times

- in line 561

resend defined in line 1091; used 9 times

- in line 364, 440, 456, 509-511(2), 521, 532
- in /usr/src/new/kermit5.188/ckcfns.c line 1069
- in /usr/src/new/kermit5.188/ckuusx.c line 758

rpack defined in line 1243; used 4 times

- in line 262-266(2), 406-410(2)

scmd defined in line 1217; never used
spack defined in line 719; used 15 times

- in line 944, 996, 1119, 1134, 1202, 1225, 1232
- in /usr/src/new/kermit5.188/ckcfn3.c line 745-749(2)
- in /usr/src/new/kermit5.188/ckcfns.c line 1051, 1326, 1430, 1459-1462(2), 1506

srinit defined in line 1229; never used
tstats defined in line 1568; used 2 times

- in /usr/src/new/kermit5.188/ckcfns.c line 1280, 1508

#### Defined variables

VOID defined in line 1502; never used
crcta defined in line 204; used 1 times

- in line 880

crctb defined in line 208; used 1 times

- in line 880

numerrs defined in line 69; used 13 times

- in line 240, 295, 439, 450, 501, 1041, 1053, 1070-1072(2), 1079
- in /usr/src/new/kermit5.188/ckcfns.c line 867, 1731
- in /usr/src/new/kermit5.188/ckuusx.c line 757

partab defined in line 71; used 12 times

- in line 581-583(2), 635-646(8), 818, 826

#### Defined macros

NP_TELNET defined in line 28; used 2 times

- in line 27, 808

Last modified: 1992-11-24 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3250 |