Home | History | Annotate | Line # | Download | only in dist
      1 #define KERMIT_C
      2 /*
      3   Embedded Kermit protocol module
      4   Version: 1.7
      5   Most Recent Update: Mon Jun  6 15:36:26 2011
      6 
      7   No stdio or other runtime library calls, no system calls, no system
      8   includes, no static data, and no global variables in this module.
      9 
     10   Warning: you can't use debug() in any routine whose argument list
     11   does not include "struct k_data * k".  Thus most routines in this
     12   module include this arg, even if they don't use it.
     13 
     14   Author: Frank da Cruz.
     15   As of version 1.6 of 30 March 2011, E-Kermit is Open Source software under
     16   the Revised 3-Clause BSD license which follows.  E-Kermit 1.6 is identical
     17   to version 1.51 except for the new license.
     18 
     19   Author: Frank da Cruz.
     20 
     21   Copyright (C) 1995, 2011,
     22   Trustees of Columbia University in the City of New York.
     23   All rights reserved.
     24 
     25   Redistribution and use in source and binary forms, with or without
     26   modification, are permitted provided that the following conditions are met:
     27 
     28   * Redistributions of source code must retain the above copyright notice,
     29     this list of conditions and the following disclaimer.
     30 
     31   * Redistributions in binary form must reproduce the above copyright notice,
     32     this list of conditions and the following disclaimer in the documentation
     33     and/or other materials provided with the distribution.
     34 
     35   * Neither the name of Columbia University nor the names of its contributors
     36     may be used to endorse or promote products derived from this software
     37     without specific prior written permission.
     38 
     39   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     40   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     42   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     43   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     44   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     45   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     46   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     47   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     49   POSSIBILITY OF SUCH DAMAGE.
     50 */
     51 #include "cdefs.h"			/* C language defs for all modules */
     52 #include "debug.h"			/* Debugging */
     53 #include "kermit.h"			/* Kermit protocol definitions */
     54 
     55 #define zgetc() \
     56 ((--(k->zincnt))>=0)?((int)(*(k->zinptr)++)&0xff):(*(k->readf))(k)
     57 
     58 /* See cdefs.h for meaning of STATIC, ULONG, and UCHAR */
     59 
     60 STATIC ULONG stringnum(UCHAR *, struct k_data *);
     61 STATIC UCHAR * numstring(ULONG, UCHAR *, int, struct k_data *);
     62 int STATIC spkt(char, short, int, UCHAR *, struct k_data *);
     63 int STATIC ack(struct k_data *, short, UCHAR * text);
     64 int STATIC nak(struct k_data *, short, short);
     65 int STATIC chk1(UCHAR *, struct k_data *);
     66 STATIC USHORT chk2(UCHAR *, struct k_data *);
     67 #ifdef F_CRC
     68 STATIC USHORT chk3(UCHAR *, struct k_data *);
     69 #endif /* F_CRC */
     70 void STATIC spar(struct k_data *, UCHAR *, int);
     71 int STATIC rpar(struct k_data *, char);
     72 int STATIC decode(struct k_data *, struct k_response *, short, UCHAR *);
     73 #ifdef F_AT
     74 int STATIC gattr(struct k_data *, UCHAR *, struct k_response *);
     75 int STATIC sattr(struct k_data *, struct k_response *);
     76 #endif /* F_AT */
     77 #ifndef RECVONLY
     78 int STATIC sdata(struct k_data *, struct k_response *);
     79 #endif /* RECVONLY */
     80 void STATIC epkt(char *, struct k_data *);
     81 int STATIC getpkt(struct k_data *, struct k_response *);
     82 int STATIC encstr(UCHAR *, struct k_data *, struct k_response *);
     83 void STATIC decstr(UCHAR *, struct k_data *, struct k_response *);
     84 void STATIC encode(int, int, struct k_data *);
     85 int STATIC nxtpkt(struct k_data *);
     86 int STATIC resend(struct k_data *);
     87 #ifdef DEBUG
     88 int xerror(void);
     89 #endif /* DEBUG */
     90 
     91 int					/* The kermit() function */
     92 kermit(short f,				/* Function code */
     93        struct k_data *k,		/* The control struct */
     94        short r_slot,			/* Received packet slot number */
     95        int len,				/* Length of packet in slot */
     96        char *msg,			/* Message for error packet */
     97        struct k_response *r) {		/* Response struct */
     98 
     99     int i, j, rc;			/* Workers */
    100     int datalen;                        /* Length of packet data field */
    101     UCHAR *p;                           /* Pointer to packet data field */
    102     UCHAR *q;                           /* Pointer to data to be checked */
    103     UCHAR *s;				/* Worker string pointer */
    104     UCHAR c, t;                         /* Worker chars */
    105     UCHAR pbc[4];                       /* Copy of packet block check */
    106     short seq, prev;			/* Copies of sequence numbers */
    107     short chklen;                       /* Length of packet block check */
    108 #ifdef F_CRC
    109     unsigned int crc;                   /* 16-bit CRC */
    110 #endif /* F_CRC */
    111     int ok;
    112 
    113     debug(DB_MSG,"----------",0,0);	/* Marks each entry */
    114     debug(DB_LOG,"f",0,f);
    115     debug(DB_LOG,"state",0,k->state);
    116     debug(DB_LOG,"zincnt",0,(k->zincnt));
    117 
    118     if (f == K_INIT) {			/* Initialize packet buffers etc */
    119 
    120 	k->version = (UCHAR *)VERSION;	/* Version of this module */
    121         r->filename[0] = '\0';		/* No filename yet. */
    122         r->filedate[0] = '\0';		/* No filedate yet. */
    123         r->filesize = 0L;               /* No filesize yet. */
    124 	r->sofar = 0L;			/* No bytes transferred yet */
    125 
    126         for (i = 0; i < P_WSLOTS; i++) { /* Packet info for each window slot */
    127 	    freerslot(k,i);
    128 	    freesslot(k,i);
    129 	}
    130 #ifdef F_TSW
    131         for (i = 0; i < 64; i++) {	/* Packet finder array */
    132 	    k->r_pw[i] = -1;		/* initialized to "no packets yet" */
    133 	    k->s_pw[i] = -1;		/* initialized to "no packets yet" */
    134 	}
    135 #endif /* F_TSW */
    136 
    137 /* Initialize the k_data structure */
    138 
    139 	for (i = 0; i < 6; i++)
    140 	  k->s_remain[i] = '\0';
    141 
    142         k->state    = R_WAIT;		/* Beginning protocol state */
    143 	r->status   = R_WAIT;
    144 	k->what     = W_RECV;		/* Default action */
    145 	k->s_first  = 1;		/* Beginning of file */
    146         k->r_soh    = k->s_soh = SOH;	/* Packet start */
    147         k->r_eom    = k->s_eom = CR;	/* Packet end */
    148         k->s_seq    = k->r_seq =  0;	/* Packet sequence number */
    149         k->s_type   = k->r_type = 0;	/* Packet type */
    150         k->r_timo   = P_R_TIMO;		/* Timeout interval for me to use */
    151         k->s_timo   = P_S_TIMO;		/* Timeout for other Kermit to use */
    152         k->r_maxlen = P_PKTLEN;         /* Maximum packet length */
    153         k->s_maxlen = P_PKTLEN;         /* Maximum packet length */
    154         k->window   = P_WSLOTS;		/* Maximum window slots */
    155         k->wslots   = 1;		/* Current window slots */
    156 	k->zincnt   = 0;
    157 	k->dummy    = 0;
    158 	k->filename = (UCHAR *)0;
    159 
    160         /* Parity must be filled in by the caller */
    161 
    162         k->retry  = P_RETRY;            /* Retransmission limit */
    163         k->s_ctlq = k->r_ctlq = '#';    /* Control prefix */
    164         k->ebq    = 'Y';		/* 8th-bit prefix negotiation */
    165 	k->ebqflg = 0;			/* 8th-bit prefixing flag */
    166         k->rptq   = '~';		/* Send repeat prefix */
    167         k->rptflg = 0;                  /* Repeat counts negotiated */
    168 	k->s_rpt  = 0;			/* Current repeat count */
    169         k->capas  = 0                   /* Capabilities */
    170 #ifdef F_LP
    171           | CAP_LP                      /* Long packets */
    172 #endif /* F_LP */
    173 #ifdef F_SW
    174             | CAP_SW                    /* Sliding windows */
    175 #endif /* F_SW */
    176 #ifdef F_AT
    177               | CAP_AT                  /* Attribute packets */
    178 #endif /* F_AT */
    179                 ;
    180 
    181 	k->opktbuf[0] = '\0';		/* No packets sent yet. */
    182 	k->opktlen = 0;
    183 
    184 #ifdef F_CRC
    185 /* This is the only way to initialize these tables -- no static data. */
    186 
    187         k->crcta[ 0] =       0;		/* CRC generation table A */
    188         k->crcta[ 1] =  010201;
    189         k->crcta[ 2] =  020402;
    190         k->crcta[ 3] =  030603;
    191         k->crcta[ 4] =  041004;
    192         k->crcta[ 5] =  051205;
    193         k->crcta[ 6] =  061406;
    194         k->crcta[ 7] =  071607;
    195         k->crcta[ 8] = 0102010;
    196         k->crcta[ 9] = 0112211;
    197         k->crcta[10] = 0122412;
    198         k->crcta[11] = 0132613;
    199         k->crcta[12] = 0143014,
    200         k->crcta[13] = 0153215;
    201         k->crcta[14] = 0163416;
    202         k->crcta[15] = 0173617;
    203 
    204         k->crctb[ 0] =       0;        /* CRC table B */
    205         k->crctb[ 1] =  010611;
    206         k->crctb[ 2] =  021422;
    207         k->crctb[ 3] =  031233;
    208         k->crctb[ 4] =  043044;
    209         k->crctb[ 5] =  053655;
    210         k->crctb[ 6] =  062466;
    211         k->crctb[ 7] =  072277;
    212         k->crctb[ 8] = 0106110;
    213         k->crctb[ 9] = 0116701;
    214         k->crctb[10] = 0127532;
    215         k->crctb[11] = 0137323;
    216         k->crctb[12] = 0145154;
    217         k->crctb[13] = 0155745;
    218         k->crctb[14] = 0164576;
    219         k->crctb[15] = 0174367;
    220 #endif /* F_CRC */
    221 
    222 	return(X_OK);
    223 
    224 #ifndef RECVONLY
    225     } else if (f == K_SEND) {
    226 	if (rpar(k,'S') != X_OK)	/* Send S packet with my parameters */
    227 	  return(X_ERROR);		/* I/O error, quit. */
    228 	k->state = S_INIT;		/* All OK, switch states */
    229 	r->status = S_INIT;
    230 	k->what = W_SEND;		/* Act like a sender */
    231         return(X_OK);
    232 #endif /* RECVONLY */
    233 
    234     } else if (f == K_STATUS) {         /* Status report requested. */
    235         return(X_STATUS);               /* File name, date, size, if any. */
    236 
    237     } else if (f == K_QUIT) {           /* You told me to quit */
    238         return(X_DONE);                 /* so I quit. */
    239 
    240     } else if (f == K_ERROR) {          /* Send an error packet... */
    241         epkt(msg,k);
    242 	k->closef(k,0,(k->state == S_DATA) ? 1 : 2); /* Close file */
    243         return(X_DONE);                 /* and quit. */
    244 
    245     } else if (f != K_RUN) {            /* Anything else is an error. */
    246         return(X_ERROR);
    247     }
    248     if (k->state == R_NONE)             /* (probably unnecessary) */
    249       return(X_OK);
    250 
    251 /* If we're in the protocol, check to make sure we got a new packet */
    252 
    253     debug(DB_LOG,"r_slot",0,r_slot);
    254     debug(DB_LOG,"len",0,len);
    255 
    256     if (r_slot < 0)			/* We should have a slot here */
    257       return(K_ERROR);
    258     else
    259       k->ipktinfo[r_slot].len = len;	/* Copy packet length to ipktinfo. */
    260 
    261     if (len < 4) {			/* Packet obviously no good? */
    262 #ifdef RECVONLY
    263 	return(nak(k,k->r_seq,r_slot)); /* Send NAK for the packet we want */
    264 #else
    265 	if (k->what == W_RECV)		/* If receiving */
    266 	  return(nak(k,k->r_seq,r_slot)); /* Send NAK for the packet we want */
    267 	else				/* If sending */
    268 	  return(resend(k));		/* retransmit last packet. */
    269 #endif /* RECVONLY */
    270     }
    271 
    272 /* Parse the packet */
    273 
    274     if (k->what == W_RECV) {		/* If we're sending ACKs */
    275 	switch(k->cancel) {		/* Get cancellation code if any */
    276 	  case 0: s = (UCHAR *)0;   break;
    277 	  case 1: s = (UCHAR *)"X"; break;
    278 	  case 2: s = (UCHAR *)"Z"; break;
    279 	}
    280     }
    281     p = &(k->ipktbuf[0][r_slot]);	/* Point to it */
    282 
    283     q = p;                              /* Pointer to data to be checked */
    284     k->ipktinfo[r_slot].len = xunchar(*p++); /* Length field */
    285     seq = k->ipktinfo[r_slot].seq = xunchar(*p++); /* Sequence number */
    286     t = k->ipktinfo[r_slot].typ = *p++;	/* Type */
    287 
    288     if (
    289 #ifndef RECVONLY
    290 	(k->what == W_RECV) &&		/* Echo (it happens), ignore */
    291 #endif /* RECVONLY */
    292 	(t == 'N' || t  == 'Y')) {
    293         freerslot(k,r_slot);
    294         return(X_OK);
    295     }
    296     k->ipktinfo[r_slot].dat = p;	/* Data field, maybe */
    297 #ifdef F_LP
    298     if (k->ipktinfo[r_slot].len == 0) {	/* Length 0 means long packet */
    299         c = p[2];                       /* Get header checksum */
    300         p[2] = '\0';
    301         if (xunchar(c) != chk1(p-3,k)) {  /* Check it */
    302             freerslot(k,r_slot);	/* Bad */
    303 	    debug(DB_MSG,"HDR CHKSUM BAD",0,0);
    304 #ifdef RECVONLY
    305 	    return(nak(k,k->r_seq,r_slot)); /* Send NAK */
    306 #else
    307 	    if (k->what == W_RECV)
    308 	      return(nak(k,k->r_seq,r_slot)); /* Send NAK */
    309 	    else
    310 	      return(resend(k));
    311 #endif /* RECVONLY */
    312         }
    313 	debug(DB_MSG,"HDR CHKSUM OK",0,0);
    314         p[2] = c;                       /* Put checksum back */
    315 	/* Data length */
    316         datalen = xunchar(p[0])*95 + xunchar(p[1]) - ((k->bctf) ? 3 : k->bct);
    317         p += 3;                         /* Fix data pointer */
    318         k->ipktinfo[r_slot].dat = p;	/* Permanent record of data pointer */
    319     } else {                            /* Regular packet */
    320 #endif /* F_LP */
    321         datalen = k->ipktinfo[r_slot].len - k->bct - 2; /* Data length */
    322 #ifdef F_LP
    323     }
    324 #endif /* F_LP */
    325 #ifdef F_CRC
    326     if (k->bctf) {			/* FORCE 3 */
    327 	chklen = 3;
    328     } else {
    329 	if (t == 'S' || k->state == S_INIT) { /* S-packet was retransmitted? */
    330 	    if (q[10] == '5') {		/* Block check type requested is 5 */
    331 		k->bctf = 1;		/* FORCE 3 */
    332 		chklen = 3;
    333 	    }
    334 	    chklen = 1;			/* Block check is always type 1 */
    335 	    datalen = k->ipktinfo[r_slot].len - 3; /* Data length */
    336 	} else {
    337 	    chklen = k->bct;
    338 	}
    339     }
    340 #else
    341     chklen = 1;				/* Block check is always type 1 */
    342     datalen = k->ipktinfo[r_slot].len - 3; /* Data length */
    343 #endif /* F_CRC */
    344     debug(DB_LOG,"bct",0,(k->bct));
    345     debug(DB_LOG,"datalen",0,datalen);
    346     debug(DB_LOG,"chkalen",0,chklen);
    347 
    348 #ifdef F_CRC
    349     for (i = 0; i < chklen; i++)        /* Copy the block check */
    350       pbc[i] = p[datalen+i];
    351     pbc[i] = '\0';			/* Null-terminate block check string */
    352 #else
    353     pbc[0] = p[datalen];
    354     pbc[1] = '\0';
    355 #endif /* F_CRC */
    356     p[datalen] = '\0';			/* and the packet DATA field. */
    357 #ifdef F_CRC
    358     switch (chklen) {                   /* Check the block check  */
    359       case 1:				/* Type 1, 6-bit checksum */
    360 #endif /* F_CRC */
    361 	ok = (xunchar(*pbc) == chk1(q,k));
    362 #ifdef DEBUG
    363 	if (ok && xerror()) ok = 0;
    364 #endif /* DEBUG */
    365 	if (!ok) {
    366 	    freerslot(k,r_slot);
    367 #ifdef RECVONLY
    368 	    nak(k,k->r_seq,r_slot);
    369 #else
    370 	    if (k->what == W_RECV)
    371 	      nak(k,k->r_seq,r_slot);
    372 	    else
    373 	      resend(k);
    374 #endif /* RECVONLY */
    375 	    return(X_OK);
    376 	}
    377 #ifdef F_CRC
    378 	break;
    379 
    380       case 2:                         /* Type 2, 12-bit checksum */
    381 	i = xunchar(*pbc) << 6 | xunchar(pbc[1]);
    382 	ok = (i == chk2(q,k));
    383 #ifdef DEBUG
    384 	if (ok && xerror()) ok = 0;
    385 #endif /* DEBUG */
    386 	if (!ok) {			/* No match */
    387 	    if (t == 'E') {		/* Allow E packets to have type 1 */
    388 		int j;
    389 		j = datalen;
    390 		p[j++] = pbc[0];
    391 		p[j] = '\0';
    392 		if (xunchar(pbc[1]) == chk1(q,k))
    393 		  break;
    394 		else
    395 		  p[--j] = '\0';
    396 	    }
    397 	    freerslot(k,r_slot);
    398 #ifdef RECVONLY
    399 	    nak(k,k->r_seq,r_slot);
    400 #else
    401 	    if (k->what == W_RECV)
    402 	      nak(k,k->r_seq,r_slot);
    403 	    else
    404 	      resend(k);
    405 #endif /* RECVONLY */
    406 	    return(X_OK);
    407 	}
    408 	break;
    409 
    410       case 3:				/* Type 3, 16-bit CRC */
    411 	crc = (xunchar(pbc[0]) << 12)
    412 	  | (xunchar(pbc[1]) << 6)
    413 	    | (xunchar(pbc[2]));
    414 	ok = (crc == chk3(q,k));
    415 #ifdef DEBUG
    416 	if (ok && xerror()) {
    417 	    ok = 0;
    418 	    debug(DB_MSG,"CRC ERROR INJECTED",0,0);
    419 	}
    420 #endif /* DEBUG */
    421 	if (!ok) {
    422 	    debug(DB_LOG,"CRC ERROR t",0,t);
    423 	    if (t == 'E') {		/* Allow E packets to have type 1 */
    424 		int j;
    425 		j = datalen;
    426 		p[j++] = pbc[0];
    427 		p[j++] = pbc[1];
    428 		p[j] = '\0';
    429 		if (xunchar(pbc[2]) == chk1(q,k))
    430 		  break;
    431 		else { j -=2; p[j] = '\0'; }
    432 	    }
    433 	    freerslot(k,r_slot);
    434 #ifdef RECVONLY
    435 	    nak(k,k->r_seq,r_slot);
    436 #else
    437 	    if (k->what == W_RECV)
    438 	      nak(k,k->r_seq,r_slot);
    439 	    else
    440 	      resend(k);
    441 #endif /* RECVONLY */
    442 	    return(X_OK);
    443 	}
    444     }
    445 #endif /* F_CRC */
    446     if (t == 'E')			/* (AND CLOSE FILES?) */
    447       return(X_ERROR);
    448 
    449     prev = k->r_seq - 1;		/* Get sequence of previous packet */
    450     if (prev < 0)
    451       prev = 63;
    452 
    453     debug(DB_LOG,"Seq",0,seq);
    454     debug(DB_LOG,"Prev",0,prev);
    455 
    456     if (seq == k->r_seq) {		/* Is this the packet we want? */
    457 	k->ipktinfo[r_slot].rtr = 0;	/* Yes */
    458     } else {
    459         freerslot(k,r_slot);		/* No, discard it. */
    460 
    461         if (seq == prev) {              /* If it's the previous packet again */
    462 	    debug(DB_LOG,"PREVIOUS PKT RETRIES",0,
    463 		  (long)(k->ipktinfo[r_slot].rtr));
    464             if (k->ipktinfo[r_slot].rtr++ > k->retry) { /* Count retries */
    465                 epkt("Too many retries", k); /* Too may */
    466                 return(X_ERROR);	/* Give up */
    467             } else {			/* Otherwise */
    468 		return(resend(k));	/* Send old outbound packet buffer */
    469             }
    470 #ifdef RECVONLY
    471 	} else {
    472 	    return(nak(k,k->r_seq,r_slot));
    473 #else
    474         } else if (k->what == W_RECV) {	/* Otherwise NAK the one we want */
    475 	    return(nak(k,k->r_seq,r_slot));
    476 	} else {			/* or whatever... */
    477 	    return(resend(k));
    478 #endif /* RECVONLY */
    479 	}
    480     }
    481 #ifndef RECVONLY
    482     if (k->what == W_SEND) {		/* Sending, check for ACK */
    483 	if (t != 'Y') {			/* Not an ACK */
    484 	    debug(DB_LOG,"t!=Y t",0,t);
    485 	    freerslot(k,r_slot);	/* added 2004-06-30 -- JHD */
    486 	    return(resend(k));
    487 	}
    488 	if (k->state == S_DATA) {	/* ACK to Data packet?*/
    489 	    if (k->cancel ||		/* Cancellation requested by caller? */
    490 		*p == 'X' || *p == 'Z') { /* Or by receiver? */
    491 		k->closef(k,*p,1);	  /* Close input file*/
    492 		nxtpkt(k);		  /* Next packet sequence number */
    493 		if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
    494 		  return(rc);
    495 		if (*p == 'Z' || k->cancel == I_GROUP) { /* Cancel Group? */
    496 		    debug(DB_MSG,"Group Cancel (Send)",0,0);
    497 		    while (*(k->filelist)) { /* Go to end of file list */
    498 			debug(DB_LOG,"Skip",*(k->filelist),0);
    499 			(k->filelist)++;
    500 		    }
    501 		}
    502 		k->state = S_EOF;	/* Wait for ACK to EOF */
    503 		r->status = S_EOF;
    504 		k->r_seq = k->s_seq;	/* Sequence number of packet we want */
    505 		return(X_OK);
    506 	    }
    507 	}
    508 	freerslot(k,r_slot);		/* It is, free the ACK. */
    509     }
    510 #endif /* RECVONLY */
    511 
    512 /* Now we have an incoming packet with the expected sequence number. */
    513 
    514     debug(DB_CHR,"Packet OK",0,t);
    515     debug(DB_LOG,"State",0,k->state);
    516 
    517     switch (k->state) {                 /* Kermit protocol state switcher */
    518 
    519 #ifndef RECVONLY
    520       case S_INIT:			/* Got other Kermit's parameters */
    521       case S_EOF:			/* Got ACK to EOF packet */
    522 	nxtpkt(k);			/* Get next packet number etc */
    523 	if (k->state == S_INIT) {	/* Got ACK to S packet? */
    524 	    spar(k,p,datalen);		/* Set negotiated parameters */
    525 	    debug(DB_CHR,"Parity",0,k->parity);
    526 	    debug(DB_LOG,"Ebqflg",0,(k->ebqflg));
    527 	    debug(DB_CHR,"Ebq",0,(k->ebq));
    528 	}
    529 	k->filename = *(k->filelist);	/* Get next filename */
    530 	if (k->filename) {		/* If there is one */
    531 	    int i;
    532 	    for (i = 0; i < FN_MAX; i++) { /* Copy name to result struct */
    533 		r->filename[i] = k->filename[i];
    534 		if (!(r->filename[i]))
    535 		    break;
    536 	    }
    537 	    (k->filelist)++;
    538 	    debug(DB_LOG,"Filename",k->filename,0);
    539 	    if ((rc = (k->openf)(k,k->filename,1)) != X_OK) /* Try to open */
    540 	      return(rc);
    541 	    encstr(k->filename,k,r);	/* Encode the name for transmission */
    542 	    if ((rc = spkt('F',k->s_seq,-1,k->xdata,k)) != X_OK)
    543 	      return(rc);		/* Send F packet */
    544 	    r->sofar = 0L;
    545 	    k->state = S_FILE;		/* Wait for ACK */
    546 	    r->status = S_FILE;
    547 	} else {			/* No more files - we're done */
    548 	    if ((rc = spkt('B',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
    549 	      return(rc);		/* Send EOT packet */
    550 	    k->state = S_EOT;		/* Wait for ACK */
    551 	    r->status = S_EOT;
    552 	}
    553 	k->r_seq = k->s_seq;		/* Sequence number of packet we want */
    554 	return(X_OK);			/* Return to control program */
    555 
    556       case S_FILE:			/* Got ACK to F packet */
    557 	nxtpkt(k);			/* Get next packet number etc */
    558 #ifdef F_AT
    559 	if (k->capas & CAP_AT) {	/* A-packets negotiated? */
    560 	    if ((rc = sattr(k,r)) != X_OK) /* Yes, send Attribute packet */
    561 	      return(rc);
    562 	    k->state = S_ATTR;		/* And wait for its ACK */
    563 	    r->status = S_ATTR;
    564 	} else
    565 #endif /* F_AT */
    566 	  if (sdata(k,r) == 0) {	/* No A packets - send first data */
    567 	    /* File is empty so send EOF packet */
    568 	    if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
    569 	      return(rc);
    570 	    k->closef(k,*p,1);		/* Close input file*/
    571 	    k->state = S_EOF;		/* Wait for ACK to EOF */
    572 	    r->status = S_EOF;
    573 	} else {			/* Sent some data */
    574 	    k->state = S_DATA;		/* Wait for ACK to first data */
    575 	    r->status = S_DATA;
    576 	}
    577 	k->r_seq = k->s_seq;		/* Sequence number to wait for */
    578 	return(X_OK);
    579 
    580       case S_ATTR:			/* Got ACK to A packet */
    581       case S_DATA:			/* Got ACK to D packet */
    582 	nxtpkt(k);			/* Get next packet number */
    583 	if (k->state == S_ATTR) {
    584 	    /* CHECK ATTRIBUTE RESPONSE */
    585 	    /* IF REJECTED do the right thing... */
    586 	    k->state = S_DATA;
    587 	    r->status = S_DATA;
    588 	}
    589 	rc = sdata(k,r);		/* Send first or next data packet */
    590 
    591 	debug(DB_LOG,"Seq",0,(k->s_seq));
    592 	debug(DB_LOG,"sdata()",0,rc);
    593 
    594 	if (rc == 0) {			/* If there was no data to send */
    595 	    if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
    596 	      return(rc);		/* Send EOF */
    597 	    k->closef(k,*p,1);		/* Close input file*/
    598 	    k->state = S_EOF;		/* And wait for ACK */
    599 	    r->status = S_EOF;
    600 	}				/* Otherwise stay in data state */
    601 	k->r_seq = k->s_seq;		/* Sequence number to wait for */
    602 	return(X_OK);
    603 
    604       case S_EOT:			/* Get ACK to EOT packet */
    605         return(X_DONE);			/* (or X_ERROR) */
    606 #endif /* RECVONLY */
    607 
    608       case R_WAIT:                      /* Waiting for the S packet */
    609         if (t == 'S') {                 /* Got it */
    610             spar(k,p,datalen);          /* Set parameters from it */
    611             rc = rpar(k,'Y');		/* ACK with my parameters */
    612 	    debug(DB_LOG,"rpar rc",0,rc);
    613             if (rc != X_OK)
    614               return(X_ERROR);          /* I/O error, quit. */
    615             k->state = R_FILE;          /* All OK, switch states */
    616             r->status = R_FILE;
    617         } else {                        /* Wrong kind of packet, send NAK */
    618             epkt("Unexpected packet type",k);
    619             rc = X_ERROR;
    620         }
    621         freerslot(k,r_slot);		/* Free packet slot */
    622         return(rc);
    623 
    624       case R_FILE:                      /* Want an F or B packet */
    625         if (t == 'F') {                 /* File name */
    626             if ((rc = decode(k, r, 0, p)) == X_OK) /* Decode and save */
    627               k->state = R_ATTR;        /* Switch to next state */
    628 	    r->status = k->state;
    629 	    debug(DB_LOG,"R_FILE decode rc",0,rc);
    630 	    debug(DB_LOG,"R_FILE FILENAME",r->filename,0);
    631             if (rc == X_OK) {		/* All OK so far */
    632 		r->filedate[0] = '\0';	/* No file date yet */
    633 		r->filesize = 0L;	/* Or file size */
    634 		r->sofar = 0L;		/* Or bytes transferred yet */
    635 		rc = ack(k, k->r_seq, r->filename); /* so ACK the F packet */
    636 	    } else {
    637 		epkt("Filename error",k); /* Error decoding filename */
    638 	    }
    639         } else if (t == 'B') {          /* Break, end of transaction */
    640             freerslot(k,r_slot);
    641             rc = (ack(k, k->r_seq, (UCHAR *)0) == X_OK) ? X_DONE : X_ERROR;
    642 
    643         } else {
    644             epkt("Unexpected packet type",k);
    645             rc = X_ERROR;
    646         }
    647         freerslot(k,r_slot);
    648         return(rc);
    649 
    650       case R_ATTR:                      /* Want A, D, or Z packet */
    651 #ifdef F_AT
    652         if (t == 'A') {                 /* Attribute packet */
    653 	    int x;
    654             x = gattr(k, p, r);		/* Read the attributes */
    655 	    if (x > -1)
    656 	      k->binary = x;
    657             freerslot(k,r_slot);
    658             ack(k, k->r_seq, (UCHAR *) "Y"); /* Always accept the file */
    659             return(X_OK);
    660         } else
    661 #endif /* F_AT */
    662 	  if (t == 'D') {		/* First data packet */
    663             k->obufpos = 0;             /* Initialize output buffer */
    664 	    k->filename = r->filename;
    665 	    r->sofar = 0L;
    666             if ((rc = (*(k->openf))(k,r->filename, 2)) == X_OK) {
    667                 k->state = R_DATA;      /* Switch to Data state */
    668 		r->status = k->state;
    669                 rc = decode(k, r, 1, p); /* Write out first data packet */
    670                 freerslot(k,r_slot);
    671             } else {
    672                 epkt("File refused or can't be opened", k);
    673                 freerslot(k,r_slot);
    674                 return(rc);
    675             }
    676             if (rc == X_OK)
    677               rc = ack(k, k->r_seq, s);
    678             else
    679               epkt("Error writing data", k);
    680             return(rc);
    681 	} else if (t == 'Z') {		/* Empty file */
    682 	    debug(DB_LOG,"R_ATTR empty file",r->filename,0);
    683             k->obufpos = 0;             /* Initialize output buffer */
    684 	    k->filename = r->filename;
    685 	    r->sofar = 0L;		/* Open and close the file */
    686             if ((rc = (*(k->openf))(k,r->filename, 2)) == X_OK) {
    687 		if (((rc = (*(k->closef))(k,*p,2)) == X_OK)) {
    688 		    k->state = R_FILE;
    689 		    rc = ack(k, k->r_seq, s);
    690 		} else {
    691 		    epkt("Error closing empty file", k);
    692 		    freerslot(k,r_slot);
    693 		    return(rc);
    694 		}
    695             } else {
    696                 epkt("File refused or can't be opened", k);
    697                 freerslot(k,r_slot);
    698                 return(rc);
    699             }
    700 	    r->status = k->state;
    701             freerslot(k,r_slot);
    702 
    703         } else {
    704             epkt("Unexpected packet type",k);
    705             return(X_ERROR);
    706         }
    707         break;
    708 
    709       case R_DATA:                      /* Want a D or Z packet */
    710 	debug(DB_CHR,"R_DATA t",0,t);
    711         if (t == 'D') {                 /* Data */
    712             rc = decode(k, r, 1, p);	/* Decode it */
    713             freerslot(k,r_slot);
    714         } else if (t == 'Z') {          /* End of file */
    715 	    debug(DB_CHR,"R_DATA",0,t);
    716             if (k->obufpos > 0) {       /* Flush output buffer */
    717                 rc = (*(k->writef))(k,k->obuf,k->obufpos);
    718 		debug(DB_LOG,"R_DATA writef rc",0,rc);
    719 		r->sofar += k->obufpos;
    720                 k->obufpos = 0;
    721             }
    722             if (((rc = (*(k->closef))(k,*p,2)) == X_OK) && (rc == X_OK))
    723               k->state = R_FILE;
    724 	    debug(DB_LOG,"R_DATA closef rc",0,rc);
    725 	    r->status = k->state;
    726             freerslot(k,r_slot);
    727         } else {
    728             epkt("Unexpected packet type",k);
    729             return(X_ERROR);
    730         }
    731         if (rc == X_OK)
    732           rc = ack(k, k->r_seq, s);
    733         else
    734           epkt(t == 'Z' ? "Can't close file" : "Error writing data",k);
    735         return(rc);
    736 
    737       case R_ERROR:                     /* Canceled from above */
    738       default:
    739         epkt(msg,k);
    740         return(X_ERROR);
    741     }
    742     return(X_ERROR);
    743 }
    744 
    745 /* Utility routines */
    746 
    747 UCHAR *
    748 getrslot(struct k_data *k, short *n) {   /* Find a free packet buffer */
    749     register int i;
    750 /*
    751   Note: We don't clear the retry count here.
    752   It is cleared only after the NEXT packet arrives, which
    753   indicates that the other Kermit got our ACK for THIS packet.
    754 */
    755     for (i = 0; i < P_WSLOTS; i++) {    /* Search */
    756         if (k->ipktinfo[i].len < 1) {
    757             *n = i;                     /* Slot number */
    758             k->ipktinfo[i].len = -1;	/* Mark it as allocated but not used */
    759             k->ipktinfo[i].seq = -1;
    760             k->ipktinfo[i].typ = SP;
    761             /* k->ipktinfo[i].rtr =  0; */  /* (see comment above) */
    762             k->ipktinfo[i].dat = (UCHAR *)0;
    763             return(&(k->ipktbuf[0][i]));
    764         }
    765     }
    766     *n = -1;
    767     return((UCHAR *)0);
    768 }
    769 
    770 void					/* Initialize a window slot */
    771 freerslot(struct k_data *k, short n) {
    772     k->ipktinfo[n].len = 0;		/* Packet length */
    773 #ifdef COMMENT
    774     k->ipktinfo[n].seq = 0;		/* Sequence number */
    775     k->ipktinfo[n].typ = (char)0;	/* Type */
    776     k->ipktinfo[n].rtr = 0;		/* Retry count */
    777     k->ipktinfo[n].flg = 0;		/* Flags */
    778 #endif /* COMMENT */
    779 }
    780 
    781 UCHAR *
    782 getsslot(struct k_data *k, short *n) {   /* Find a free packet buffer */
    783 #ifdef COMMENT
    784     register int i;
    785     for (i = 0; i < P_WSLOTS; i++) {    /* Search */
    786         if (k->opktinfo[i].len < 1) {
    787             *n = i;                     /* Slot number */
    788             k->opktinfo[i].len = -1;	/* Mark it as allocated but not used */
    789             k->opktinfo[i].seq = -1;
    790             k->opktinfo[i].typ = SP;
    791             k->opktinfo[i].rtr =  0;
    792             k->opktinfo[i].dat = (UCHAR *)0;
    793             return(&(k->opktbuf[0][i]));
    794         }
    795     }
    796     *n = -1;
    797     return((UCHAR *)0);
    798 #else
    799     *n = 0;
    800     return(k->opktbuf);
    801 #endif /* COMMENT */
    802 }
    803 
    804 void                                    /* Initialize a window slot */
    805 freesslot(struct k_data * k, short n) {
    806     k->opktinfo[n].len = 0;		/* Packet length */
    807     k->opktinfo[n].seq = 0;		/* Sequence number */
    808     k->opktinfo[n].typ = (char)0;	/* Type */
    809     k->opktinfo[n].rtr = 0;		/* Retry count */
    810     k->opktinfo[n].flg = 0;		/* Flags */
    811 }
    812 
    813 /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
    814 
    815 STATIC int
    816 chk1(UCHAR *pkt, struct k_data * k) {
    817     register unsigned int chk;
    818     chk = chk2(pkt,k);
    819     chk = (((chk & 0300) >> 6) + chk) & 077;
    820     return((int) chk);
    821 }
    822 
    823 /*  C H K 2  --  Numeric sum of all the bytes in the packet, 12 bits.  */
    824 
    825 STATIC USHORT
    826 chk2(UCHAR *pkt,struct k_data * k) {
    827     register USHORT chk;
    828     for (chk = 0; *pkt != '\0'; pkt++)
    829       chk += *pkt;
    830     return(chk);
    831 }
    832 
    833 #ifdef F_CRC
    834 
    835 /*  C H K 3  --  Compute a type-3 Kermit block check.  */
    836 /*
    837  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
    838  table.  Assumes the argument string contains no embedded nulls.
    839 */
    840 STATIC USHORT
    841 chk3(UCHAR *pkt, struct k_data * k) {
    842     register USHORT c, crc;
    843     for (crc = 0; *pkt != '\0'; pkt++) {
    844 #ifdef COMMENT
    845         c = crc ^ (long)(*pkt);
    846         crc = (crc >> 8) ^ (k->crcta[(c & 0xF0) >> 4] ^ k->crctb[c & 0x0F]);
    847 #else
    848 	c = crc ^ (*pkt);
    849        crc = (crc >> 8) ^ ((k->crcta[(c & 0xF0) >> 4]) ^ (k->crctb[c & 0x0F]));
    850 #endif	/*  COMMENT */
    851     }
    852     return(crc);
    853 }
    854 #endif /* F_CRC */
    855 
    856 /*   S P K T  --  Send a packet.  */
    857 /*
    858   Call with packet type, sequence number, data length, data, Kermit struct.
    859   Returns:
    860     X_OK on success
    861     X_ERROR on i/o error
    862 */
    863 STATIC int
    864 spkt(char typ, short seq, int len, UCHAR * data, struct k_data * k) {
    865 
    866     unsigned int crc;                   /* For building CRC */
    867     int i, j, lenpos, m, n, x;		/* Workers */
    868     UCHAR * s, * buf;
    869 
    870     debug(DB_LOG,"spkt len 1",0,len);
    871     if (len < 0) {			/* Calculate data length ourselves? */
    872 	len = 0;
    873 	s = data;
    874 	while (*s++) len++;
    875     }
    876     debug(DB_LOG,"spkt len 2",0,len);
    877     buf = k->opktbuf;			/* Where to put packet (FOR NOW) */
    878 
    879     i = 0;                              /* Packet buffer position */
    880     buf[i++] = k->s_soh;		/* SOH */
    881     lenpos = i++;			/* Remember this place */
    882     buf[i++] = tochar(seq);		/* Sequence number */
    883     buf[i++] = typ;			/* Packet type */
    884     j = len + k->bct;
    885 #ifdef F_LP
    886     if ((len + k->bct + 2) > 94) {	/* If long packet */
    887 	buf[lenpos] = tochar(0);	/* Put blank in LEN field */
    888 	buf[i++] = tochar(j / 95);	/* Make extended header: Big part */
    889 	buf[i++] = tochar(j % 95);	/* and small part of length. */
    890         buf[i] = NUL;			/* Terminate for header checksum */
    891         buf[i++] = tochar(chk1(&buf[lenpos],k)); /* Insert header checksum */
    892     } else {				/* Short packet */
    893 #endif /* F_LP */
    894 	buf[lenpos] = tochar(j+2);	/* Single-byte length in LEN field */
    895 #ifdef F_LP
    896     }
    897 #endif /* F_LP */
    898     if (data)                           /* Copy data, if any */
    899       for ( ; len--; i++)
    900         buf[i] = *data++;
    901     buf[i] = '\0';
    902 
    903 #ifdef F_CRC
    904     switch (k->bct) {                   /* Add block check */
    905       case 1:                           /* 1 = 6-bit chksum */
    906 	buf[i++] = tochar(chk1(&buf[lenpos],k));
    907         break;
    908       case 2:                           /* 2 = 12-bit chksum */
    909         j = chk2(&buf[lenpos],k);
    910 #ifdef XAC
    911 	/* HiTech's XAC compiler silently ruins the regular code. */
    912 	/* An intermediate variable provides a work-around. */
    913 	/* 2004-06-29 -- JHD */
    914 	{
    915 	    USHORT jj;
    916 	    jj = (j >> 6) & 077; buf[i++] = tochar(jj);
    917 	    jj = j & 077;        buf[i++] = tochar(jj);
    918 	}
    919 #else
    920         buf[i++] = (unsigned)tochar((j >> 6) & 077);
    921         buf[i++] = (unsigned)tochar(j & 077);
    922 #endif /* XAC */
    923         break;
    924       case 3:                           /* 3 = 16-bit CRC */
    925         crc = chk3(&buf[lenpos],k);
    926 #ifdef XAC
    927 	/* HiTech's XAC compiler silently ruins the above code. */
    928 	/* An intermediate variable provides a work-around. */
    929 	/* 2004-06-29 -- JHD */
    930 	{
    931 	    USHORT jj;
    932 	    jj = (crc >> 12) & 0x0f; buf[i++] = tochar(jj);
    933 	    jj = (crc >>  6) & 0x3f; buf[i++] = tochar(jj);
    934 	    jj =  crc        & 0x3f; buf[i++] = tochar(jj);
    935 	}
    936 #else
    937         buf[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
    938         buf[i++] = (unsigned)tochar((crc >> 6) & 077);
    939         buf[i++] = (unsigned)tochar(crc & 077);
    940 #endif /* XAC */
    941         break;
    942     }
    943 #else
    944     buf[i++] = tochar(chk1(&buf[lenpos],k));
    945 #endif /* F_CRC */
    946 
    947     buf[i++] = k->s_eom;		/* Packet terminator */
    948     buf[i] = '\0';			/* String terminator */
    949     k->s_seq = seq;                     /* Remember sequence number */
    950 
    951     k->opktlen = i;			/* Remember length for retransmit */
    952 
    953 #ifdef DEBUG
    954 /* CORRUPT THE PACKET SENT BUT NOT THE ONE WE SAVE */
    955     if (xerror()) {
    956 	UCHAR p[P_PKTLEN+8];
    957 	int i;
    958 	for (i = 0; i < P_PKTLEN; i++)
    959 	  if (!(p[i] = buf[i]))
    960 	    break;
    961 	p[i-2] = 'X';
    962 	debug(DB_PKT,"XPKT",(char *)&p[1],0);
    963 	return((*(k->txd))(k,p,k->opktlen)); /* Send it. */
    964     }
    965     debug(DB_PKT,"SPKT",(char *)&buf[1],0);
    966 #endif /* DEBUG */
    967 
    968     return((*(k->txd))(k,buf,k->opktlen)); /* Send it. */
    969 }
    970 
    971 /*  N A K  --  Send a NAK (negative acknowledgement)  */
    972 
    973 STATIC int
    974 nak(struct k_data * k, short seq, short slot) {
    975     int rc;
    976     rc = spkt('N', seq, 0, (UCHAR *)0, k);
    977     if (k->ipktinfo[slot].rtr++ > k->retry)
    978       rc = X_ERROR;
    979     return(rc);
    980 }
    981 
    982 /*  A C K  --  Send an ACK (positive acknowledgement)  */
    983 
    984 STATIC int
    985 ack(struct k_data * k, short seq, UCHAR * text) {
    986     int len, rc;
    987     len = 0;
    988     if (text) {                         /* Get length of data */
    989         UCHAR *p;
    990         p = text;
    991         for ( ; *p++; len++) ;
    992     }
    993     rc = spkt('Y', seq, len, text, k);  /* Send the packet */
    994     debug(DB_LOG,"ack spkt rc",0,rc);
    995     if (rc == X_OK)                     /* If OK */
    996       k->r_seq = (k->r_seq + 1) % 64;   /* bump the packet number */
    997     return(rc);
    998 }
    999 
   1000 /*  S P A R  --  Set parameters requested by other Kermit  */
   1001 
   1002 STATIC void
   1003 spar(struct k_data * k, UCHAR *s, int datalen) {
   1004     int x, y;
   1005     UCHAR c;
   1006 
   1007     s--;                                /* Line up with field numbers. */
   1008 
   1009     if (datalen >= 1)                   /* Max packet length to send */
   1010       k->s_maxlen = xunchar(s[1]);
   1011 
   1012     if (datalen >= 2)                   /* Timeout on inbound packets */
   1013       k->r_timo = xunchar(s[2]);
   1014 
   1015     /* No padding */
   1016 
   1017     if (datalen >= 5)                   /* Outbound Packet Terminator */
   1018       k->s_eom = xunchar(s[5]);
   1019 
   1020     if (datalen >= 6)                   /* Incoming control prefix */
   1021       k->r_ctlq = s[6];
   1022 
   1023     if (datalen >= 7) {                 /* 8th bit prefix */
   1024         k->ebq = s[7];
   1025         if ((s[7] > 32 && s[7] < 63) || (s[7] > 95 && s[7] < 127)) {
   1026 	    if (!k->parity)		/* They want it */
   1027 	      k->parity = 1;		/* Set parity to something nonzero */
   1028 	    k->ebqflg = 1;
   1029 	} else if (s[7] == 'Y' && k->parity) {
   1030 	    k->ebqflg = 1;
   1031 	    k->ebq = '&';
   1032 	} else if (s[7] == 'N') {
   1033 	    /* WHAT? */
   1034 	}
   1035     }
   1036     if (datalen >= 8) {                 /* Block check */
   1037         k->bct = s[8] - '0';
   1038 #ifdef F_CRC
   1039         if ((k->bct < 1) || (k->bct > 3))
   1040 #endif /* F_CRC */
   1041 	  k->bct = 1;
   1042 	if (k->bctf) k->bct = 3;
   1043     }
   1044     if (datalen >= 9) {                 /* Repeat counts */
   1045         if ((s[9] > 32 && s[9] < 63) || (s[9] > 95 && s[9] < 127)) {
   1046             k->rptq = s[9];
   1047             k->rptflg = 1;
   1048         }
   1049     }
   1050     if (datalen >= 10) {                /* Capability bits */
   1051         x = xunchar(s[10]);
   1052 
   1053 #ifdef F_LP                             /* Long packets */
   1054         if (!(x & CAP_LP))
   1055 #endif /* F_LP */
   1056           k->capas &= ~CAP_LP;
   1057 
   1058 #ifdef F_SW                             /* Sliding Windows */
   1059         if (!(x & CAP_SW))
   1060 #endif /* F_SW */
   1061           k->capas &= ~CAP_SW;
   1062 
   1063 #ifdef F_AT                             /* Attributes */
   1064         if (!(x & CAP_AT))
   1065 #endif /* F_AT */
   1066           k->capas &= ~CAP_AT;
   1067 
   1068 #ifdef F_RS                             /* Recovery */
   1069         if (!(x & CAP_RS))
   1070 #endif /* F_RS */
   1071           k->capas &= ~CAP_RS;
   1072 
   1073 #ifdef F_LS                             /* Locking shifts */
   1074         if (!(x & CAP_LS))
   1075 #endif /* F_LS */
   1076           k->capas &= ~CAP_LS;
   1077 
   1078         /* In case other Kermit sends addt'l capas fields ... */
   1079 
   1080         for (y = 10; (xunchar(s[y]) & 1) && (datalen >= y); y++) ;
   1081     }
   1082 
   1083 #ifdef F_LP                             /* Long Packets */
   1084     if (k->capas & CAP_LP) {
   1085         if (datalen > y+1) {
   1086             x = xunchar(s[y+2]) * 95 + xunchar(s[y+3]);
   1087             k->s_maxlen = (x > P_PKTLEN) ? P_PKTLEN : x;
   1088             if (k->s_maxlen < 10)
   1089               k->s_maxlen = 60;
   1090         }
   1091     }
   1092 #endif /* F_LP */
   1093 
   1094     debug(DB_LOG,"S_MAXLEN",0,k->s_maxlen);
   1095 
   1096 #ifdef F_SW
   1097     if (k->capas & CAP_SW) {
   1098         if (datalen > y) {
   1099             x = xunchar(s[y+1]);
   1100             k->window = (x > P_WSLOTS) ? P_WSLOTS : x;
   1101             if (k->window < 1)          /* Watch out for bad negotiation */
   1102               k->window = 1;
   1103             if (k->window > 1)
   1104               if (k->window > k->retry)   /* Retry limit must be greater */
   1105                 k->retry = k->window + 1; /* than window size. */
   1106         }
   1107     }
   1108 #endif /* F_SW */
   1109 }
   1110 
   1111 /*  R P A R  --  Send my parameters to other Kermit  */
   1112 
   1113 STATIC int
   1114 rpar(struct k_data * k, char type) {
   1115     UCHAR *d;
   1116     int rc, len;
   1117 #ifdef F_CRC
   1118     short b;
   1119 #endif /* F_CRC */
   1120 
   1121     d = k->ack_s;                       /* Where to put it */
   1122     d[ 0] = tochar(94);                 /* Maximum short-packet length */
   1123     d[ 1] = tochar(k->s_timo);          /* When I want to be timed out */
   1124     d[ 2] = tochar(0);                  /* How much padding I need */
   1125     d[ 3] = ctl(0);                     /* Padding character I want */
   1126     d[ 4] = tochar(k->r_eom);           /* End-of message character I want */
   1127     d[ 5] = k->s_ctlq;                  /* Control prefix I send */
   1128     if ((k->ebq == 'Y') && (k->parity)) /* 8th-bit prefix */
   1129       d[ 6] = k->ebq = '&';           /* I need to request it */
   1130     else                                /* else just agree with other Kermit */
   1131       d[ 6] = k->ebq;
   1132     if (k->bctf)			/* Block check type */
   1133       d[7] = '5';			/* FORCE 3 */
   1134     else
   1135       d[7] = k->bct + '0';		/* Normal */
   1136     d[ 8] = k->rptq;			/* Repeat prefix */
   1137     d[ 9] = tochar(k->capas);           /* Capability bits */
   1138     d[10] = tochar(k->window);          /* Window size */
   1139 
   1140 #ifdef F_LP
   1141     d[11] = tochar(k->r_maxlen / 95);   /* Long packet size, big part */
   1142     d[12] = tochar(k->r_maxlen % 95);   /* Long packet size, little part */
   1143     d[13] = '\0';			/* Terminate the init string */
   1144     len = 13;
   1145 #else
   1146     d[11] = '\0';
   1147     len = 11;
   1148 #endif /* F_LP */
   1149 
   1150 #ifdef F_CRC
   1151     if (!(k->bctf)) {			/* Unless FORCE 3 */
   1152 	b = k->bct;
   1153 	k->bct = 1;			/* Always use block check type 1 */
   1154     }
   1155 #endif /* F_CRC */
   1156     switch (type) {
   1157       case 'Y':				/* This is an ACK for packet 0 */
   1158 	rc = ack(k,0,d);
   1159 	break;
   1160       case 'S':				/* It's an S packet */
   1161 	rc = spkt('S', 0, len, d, k);
   1162 	break;
   1163       default:
   1164 	rc = -1;
   1165     }
   1166 #ifdef F_CRC
   1167     if (!(k->bctf)) {			/* Unless FORCE 3 */
   1168 	k->bct = b;
   1169     }
   1170 #endif /* F_CRC */
   1171     return(rc);                         /* Pass along return code. */
   1172 }
   1173 
   1174 /*  D E C O D E  --  Decode data field of Kermit packet - binary mode only */
   1175 /*
   1176   Call with:
   1177     k = kermit data structure
   1178     r = kermit response structure
   1179     f = function code
   1180       0 = decode filename
   1181       1 = decode file data
   1182     inbuf = pointer to packet data to be decoded
   1183   Returns:
   1184     X_OK on success
   1185     X_ERROR if output function fails
   1186 */
   1187 STATIC int
   1188 decode(struct k_data * k, struct k_response * r, short f, UCHAR *inbuf) {
   1189 
   1190     register unsigned int a, a7;        /* Current character */
   1191     unsigned int b8;                    /* 8th bit */
   1192     int rpt;                            /* Repeat count */
   1193     int rc;				/* Return code */
   1194     UCHAR *p;
   1195 
   1196     rc = X_OK;
   1197     rpt = 0;                            /* Initialize repeat count. */
   1198     if (f == 0)                         /* Output function... */
   1199       p = r->filename;
   1200 
   1201     while ((a = *inbuf++ & 0xFF) != '\0') { /* Character loop */
   1202         if (k->rptflg && a == k->rptq) { /* Got a repeat prefix? */
   1203             rpt = xunchar(*inbuf++ & 0xFF); /* Yes, get the repeat count, */
   1204             a = *inbuf++ & 0xFF;        /* and get the prefixed character. */
   1205         }
   1206         b8 = 0;                         /* 8th-bit value */
   1207         if (k->parity && (a == k->ebq)) { /* Have 8th-bit prefix? */
   1208             b8 = 0200;                  /* Yes, flag the 8th bit */
   1209             a = *inbuf++ & 0x7F;        /* and get the prefixed character. */
   1210         }
   1211         if (a == k->r_ctlq) {           /* If control prefix, */
   1212             a  = *inbuf++ & 0xFF;       /* get its operand */
   1213             a7 = a & 0x7F;              /* and its low 7 bits. */
   1214             if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Controllify */
   1215               a = ctl(a);               /* if in control range. */
   1216         }
   1217         a |= b8;                        /* OR in the 8th bit */
   1218 
   1219         if (rpt == 0) rpt = 1;          /* If no repeats, then one */
   1220 
   1221         for (; rpt > 0; rpt--) {        /* Output the char 'rpt' times */
   1222             if (f == 0) {
   1223                 *p++ = (UCHAR) a;       /* to memory */
   1224             } else {                    /* or to file */
   1225                 k->obuf[k->obufpos++] = (UCHAR) a; /* Deposit the byte */
   1226                 if (k->obufpos == k->obuflen) { /* Buffer full? */
   1227                     rc = (*(k->writef))(k,k->obuf,k->obuflen); /* Dump it. */
   1228 		    r->sofar += k->obuflen;
   1229 		    if (rc != X_OK) break;
   1230                     k->obufpos = 0;
   1231                 }
   1232             }
   1233         }
   1234     }
   1235     if (f == 0)                         /* If writing to memory */
   1236       *p = '\0';			/* terminate the string */
   1237     return(rc);
   1238 }
   1239 
   1240 STATIC ULONG				/* Convert decimal string to number  */
   1241 stringnum(UCHAR *s, struct k_data * k) {
   1242     long n;
   1243     n = 0L;
   1244     while (*s == SP)
   1245       s++;
   1246     while(*s >= '0' && *s <= '9')
   1247       n = n * 10 + (*s++ - '0');
   1248     return(n);
   1249 }
   1250 
   1251 STATIC UCHAR *				/* Convert number to string */
   1252 numstring(ULONG n, UCHAR * buf, int buflen, struct k_data * k) {
   1253     int i, x;
   1254     buf[buflen - 1] = '\0';
   1255     for (i = buflen - 2; i > 0; i--) {
   1256 	x = n % 10L;
   1257 	buf[i] = x + '0';
   1258 	n /= 10L;
   1259 	if (!n)
   1260 	  break;
   1261     }
   1262     if (n) {
   1263 	return((UCHAR *)0);
   1264     }
   1265     if (i > 0) {
   1266 	UCHAR * p, * s;
   1267 	s = &buf[i];
   1268 	p = buf;
   1269 	while ((*p++ = *s++)) ;
   1270 	*(p-1) = '\0';
   1271     }
   1272     return((UCHAR *)buf);
   1273 }
   1274 
   1275 #ifdef F_AT
   1276 
   1277 /*
   1278   G A T T R  --  Read incoming attributes.
   1279 
   1280   Returns:
   1281    -1 if no transfer mode (text/binary) was announced.
   1282     0 if text was announced.
   1283     1 if binary was announced.
   1284 */
   1285 
   1286 #define SIZEBUFL 32                     /* For number conversions */
   1287 
   1288 STATIC int
   1289 gattr(struct k_data * k, UCHAR * s, struct k_response * r) {
   1290     long fsize, fsizek;                 /* File size */
   1291     UCHAR c;                            /* Workers */
   1292     int aln, i, rc;
   1293 
   1294     UCHAR sizebuf[SIZEBUFL+1];
   1295 
   1296     rc = -1;
   1297     while ((c = *s++)) {		/* Get attribute tag */
   1298         aln = xunchar(*s++);            /* Length of attribute string */
   1299         switch (c) {
   1300           case '!':                     /* File length in K */
   1301 	  case '"':			/* File type */
   1302             for (i = 0; (i < aln) && (i < SIZEBUFL); i++) /* Copy it */
   1303               sizebuf[i] = *s++;
   1304             sizebuf[i] = '\0';           /* Terminate with null */
   1305             if (i < aln) s += (aln - i); /* If field was too long for buffer */
   1306 	    if (c == '!') {		     /* Length */
   1307 		fsizek = stringnum(sizebuf,k); /* Convert to number */
   1308 	    } else {			     /* Type */
   1309 		if (sizebuf[0] == 'A')	     /* Text */
   1310 		  rc = 0;
   1311 		else if (sizebuf[0] == 'B')  /* Binary */
   1312 		  rc = 1;
   1313 		debug(DB_LOG,"gattr rc",0,rc);
   1314 		debug(DB_LOG,"gattr size",sizebuf,0);
   1315 	    }
   1316             break;
   1317 
   1318           case '#':                     /* File creation date */
   1319             for (i = 0; (i < aln) && (i < DATE_MAX); i++)
   1320               r->filedate[i] = *s++;    /* Copy it into a static string */
   1321             if (i < aln) s += (aln - i);
   1322             r->filedate[i] = '\0';
   1323             break;
   1324 
   1325           case '1':                     /* File length in bytes */
   1326             for (i = 0; (i < aln) && (i < SIZEBUFL); i++) /* Copy it */
   1327               sizebuf[i] = *s++;
   1328             sizebuf[i] = '\0';           /* Terminate with null */
   1329             if (i < aln) s += (aln - i);
   1330             fsize = stringnum(sizebuf,k); /* Convert to number */
   1331             break;
   1332 
   1333 	  default:			/* Unknown attribute */
   1334 	    s += aln;			/* Just skip past it */
   1335 	    break;
   1336         }
   1337     }
   1338     if (fsize > -1L) {			/* Remember the file size */
   1339         r->filesize = fsize;
   1340     } else if (fsizek > -1L) {
   1341         r->filesize = fsizek * 1024L;
   1342     }
   1343     debug(DB_LOG,"gattr r->filesize",0,(r->filesize));
   1344     debug(DB_LOG,"gattr r->filedate=",r->filedate,0);
   1345     return(rc);
   1346 }
   1347 
   1348 #define ATTRLEN 48
   1349 
   1350 STATIC int
   1351 sattr(struct k_data *k, struct k_response *r) {	/* Build and send A packet */
   1352     int i, x, aln;
   1353     short tmp;
   1354     long filelength;
   1355     UCHAR datebuf[DATE_MAX], * p;
   1356 
   1357     debug(DB_LOG,"sattr k->zincnt 0",0,(k->zincnt));
   1358 
   1359     tmp = k->binary;
   1360     filelength = (*(k->finfo))
   1361 	(k,k->filename,datebuf,DATE_MAX,&tmp,k->xfermode);
   1362     k->binary = tmp;
   1363 
   1364     debug(DB_LOG,"sattr filename: ",k->filename,0);
   1365     debug(DB_LOG,"sattr filedate: ",datebuf,0);
   1366     debug(DB_LOG,"sattr filelength",0,filelength);
   1367     debug(DB_LOG,"sattr binary",0,(k->binary));
   1368 
   1369     i = 0;
   1370 
   1371     k->xdata[i++] = '"';
   1372     if (k->binary) {			/* Binary */
   1373 	k->xdata[i++] = tochar(2);	/*  Two characters */
   1374 	k->xdata[i++] = 'B';		/*  B for Binary */
   1375 	k->xdata[i++] = '8';		/*  8-bit bytes (note assumption...) */
   1376     } else {				/* Text */
   1377 	k->xdata[i++] = tochar(3);	/*  Three characters */
   1378 	k->xdata[i++] = 'A';		/*  A = (extended) ASCII with CRLFs */
   1379 	k->xdata[i++] = 'M';		/*  M for carriage return */
   1380 	k->xdata[i++] = 'J';		/*  J for linefeed */
   1381 	k->xdata[i++] = '*';		/* Encoding */
   1382 	k->xdata[i++] = tochar(1);	/* Length of value is 1 */
   1383 	k->xdata[i++] = 'A';		/* A for ASCII */
   1384     }
   1385     if (filelength > -1L) {		/* File length in bytes */
   1386 	UCHAR lenbuf[16];
   1387 	r->filesize = filelength;
   1388 	p = numstring(filelength,lenbuf,16,k);
   1389 	if (p) {
   1390 	    for (x = 0; p[x]; x++) ;	/* Get length of length string */
   1391 	    if (i + x < ATTRLEN - 3) {	/* Don't overflow buffer */
   1392 		k->xdata[i++] = '1';	/* Length-in-Bytes attribute */
   1393 		k->xdata[i++] = tochar(x);
   1394 		while (*p)
   1395 		  k->xdata[i++] = *p++;
   1396 	    }
   1397 	}
   1398     }
   1399     debug(DB_LOG,"sattr DATEBUF: ",datebuf,0);
   1400 
   1401     if (datebuf[0]) {			/* File modtime */
   1402 	p = datebuf;
   1403 	for (x = 0; p[x]; x++) ;	/* Length of modtime */
   1404 	if (i + x < ATTRLEN - 3) {	/* If it will fit */
   1405 	    k->xdata[i++] = '#';	/* Add modtime attribute */
   1406 	    k->xdata[i++] = tochar(x);	/* Its length */
   1407 	    while (*p)			/* And itself */
   1408 	      k->xdata[i++] = *p++;
   1409 	    /* Also copy modtime to result struct */
   1410 	    for (x = 0; x < DATE_MAX-1 && datebuf[x]; x++)
   1411 	      r->filedate[x] = datebuf[x];
   1412 	    r->filedate[x] = '\0';
   1413 	}
   1414     }
   1415     k->xdata[i++] = '@';		/* End of Attributes */
   1416     k->xdata[i++] = ' ';
   1417     k->xdata[i] = '\0';			/* Terminate attribute string */
   1418     debug(DB_LOG,"sattr k->xdata: ",k->xdata,0);
   1419     return(spkt('A',k->s_seq,-1,k->xdata,k));
   1420 }
   1421 #endif /* F_AT */
   1422 
   1423 STATIC int
   1424 getpkt(struct k_data *k, struct k_response *r) { /* Fill a packet from file */
   1425     int i, next, rpt, maxlen;
   1426     static int c;			/* PUT THIS IN STRUCT */
   1427 
   1428     debug(DB_LOG,"getpkt k->s_first",0,(k->s_first));
   1429     debug(DB_LOG,"getpkt k->s_remain=",k->s_remain,0);
   1430 
   1431     maxlen = k->s_maxlen - k->bct - 3;	/* Maximum data length */
   1432     if (k->s_first == 1) {		/* If first time thru...  */
   1433 	k->s_first = 0;			/* don't do this next time, */
   1434 	k->s_remain[0] = '\0';		/* discard any old leftovers. */
   1435 	if (k->istring) {		/* Get first byte. */
   1436 	    c = *(k->istring)++;	/* Of memory string... */
   1437 	    if (!c) c = -1;
   1438 	} else {			/* or file... */
   1439 #ifdef DEBUG
   1440 	    k->zincnt = -1234;
   1441 	    k->dummy = 0;
   1442 #endif /* DEBUG */
   1443 	    c = zgetc();
   1444 
   1445 #ifdef DEBUG
   1446 	    if (k->dummy) debug(DB_LOG,"DUMMY CLOBBERED (A)",0,0);
   1447 #endif /* DEBUG */
   1448 	}
   1449 	if (c < 0) {			/* Watch out for empty file. */
   1450 	    debug(DB_CHR,"getpkt first c",0,c);
   1451 	    k->s_first = -1;
   1452 	    return(k->size = 0);
   1453 	}
   1454 	r->sofar++;
   1455 	debug(DB_LOG,"getpkt first c",0,c);
   1456     } else if (k->s_first == -1 && !k->s_remain[0]) { /* EOF from last time? */
   1457         return(k->size = 0);
   1458     }
   1459     for (k->size = 0;
   1460 	 (k->xdata[k->size] = k->s_remain[k->size]) != '\0';
   1461 	 (k->size)++)
   1462       ;
   1463     k->s_remain[0] = '\0';
   1464     if (k->s_first == -1)
   1465       return(k->size);
   1466 
   1467     rpt = 0;				/* Initialize repeat counter. */
   1468     while (k->s_first > -1) {		/* Until end of file or string... */
   1469 	if (k->istring) {
   1470 	    next = *(k->istring)++;
   1471 	    if (!next) next = -1;
   1472 	} else {
   1473 #ifdef DEBUG
   1474 	    k->dummy = 0;
   1475 #endif /* DEBUG */
   1476 	    next = zgetc();
   1477 #ifdef DEBUG
   1478 	    if (k->dummy) debug(DB_LOG,"DUMMY CLOBBERED B",0,k->dummy);
   1479 #endif /* DEBUG */
   1480 	}
   1481 	if (next < 0) {			/* If none, we're at EOF. */
   1482 	    k->s_first = -1;
   1483 	} else {			/* Otherwise */
   1484 	    r->sofar++;			/* count this byte */
   1485 	}
   1486         k->osize = k->size;		/* Remember current size. */
   1487         encode(c,next,k);		/* Encode the character. */
   1488 	/* k->xdata[k->size] = '\0'; */
   1489 	c = next;			/* Old next char is now current. */
   1490 
   1491         if (k->size == maxlen)		/* Just at end, done. */
   1492 	  return(k->size);
   1493 
   1494         if (k->size > maxlen) {		/* Past end, must save some. */
   1495             for (i = 0;
   1496 		 (k->s_remain[i] = k->xdata[(k->osize)+i]) != '\0';
   1497 		 i++)
   1498 	      ;
   1499             k->size = k->osize;
   1500             k->xdata[k->size] = '\0';
   1501             return(k->size);		/* Return size. */
   1502         }
   1503     }
   1504     return(k->size);			/* EOF, return size. */
   1505 }
   1506 
   1507 #ifndef RECVONLY
   1508 STATIC int
   1509 sdata(struct k_data *k,struct k_response *r) { /* Send a data packet */
   1510     int len, rc;
   1511     if (k->cancel) {			/* Interrupted */
   1512 	debug(DB_LOG,"sdata interrupted k->cancel",0,(k->cancel));
   1513 	return(0);
   1514     }
   1515     len = getpkt(k,r);			/* Fill data field from input file */
   1516     debug(DB_LOG,"sdata getpkt",0,len);
   1517     if (len < 1)
   1518       return(0);
   1519     rc = spkt('D',k->s_seq,len,k->xdata,k); /* Send the packet */
   1520     debug(DB_LOG,"sdata spkt",0,rc);
   1521     return((rc == X_ERROR) ? rc : len);
   1522 }
   1523 #endif /* RECVONLY */
   1524 
   1525 /*  E P K T  --  Send a (fatal) Error packet with the given message  */
   1526 
   1527 STATIC void
   1528 epkt(char * msg, struct k_data * k) {
   1529     if (!(k->bctf)) {			/* Unless FORCE 3 */
   1530 	k->bct = 1;
   1531     }
   1532     (void) spkt('E', 0, -1, (UCHAR *) msg, k);
   1533 }
   1534 
   1535 STATIC int				/* Fill a packet from string s. */
   1536 encstr(UCHAR * s, struct k_data * k, struct k_response *r) {
   1537     k->s_first = 1;			/* Start lookahead. */
   1538     k->istring = s;			/* Set input string pointer */
   1539     getpkt(k,r);			/* Fill a packet */
   1540     k->istring = (UCHAR *)0;		/* Reset input string pointer */
   1541     k->s_first = 1;			/* "Rewind" */
   1542     return(k->size);			/* Return data field length */
   1543 }
   1544 
   1545 /* Decode packet data into a string */
   1546 
   1547 STATIC void
   1548 decstr(UCHAR * s, struct k_data * k, struct k_response * r) {
   1549     k->ostring = s;			/* Set output string pointer  */
   1550     (void) decode(k, r, 0, s);
   1551     *(k->ostring) = '\0';		/* Terminate with null */
   1552     k->ostring = (UCHAR *)0;		/* Reset output string pointer */
   1553 }
   1554 
   1555 STATIC void
   1556 encode(int a, int next, struct k_data * k) { /* Encode character into packet */
   1557     int a7, b8, maxlen;
   1558 
   1559     maxlen = k->s_maxlen - 4;
   1560     if (k->rptflg) {			/* Doing run-length encoding? */
   1561 	if (a == next) {		/* Yes, got a run? */
   1562 	    if (++(k->s_rpt) < 94) {	/* Yes, count. */
   1563 		return;
   1564 	    } else if (k->s_rpt == 94) { /* If at maximum */
   1565 	    	k->xdata[(k->size)++] = k->rptq; /* Emit prefix, */
   1566 		k->xdata[(k->size)++] = tochar(k->s_rpt); /* and count, */
   1567 		k->s_rpt = 0;		/* and reset counter. */
   1568 	    }
   1569 	} else if (k->s_rpt == 1) {	/* Run broken, only two? */
   1570 	    k->s_rpt = 0;		/* Yes, do the character twice */
   1571 	    encode(a,-1,k);		/* by calling self recursively. */
   1572 	    if (k->size <= maxlen)	/* Watch boundary. */
   1573 	      k->osize = k->size;
   1574 	    k->s_rpt = 0;		/* Call self second time. */
   1575 	    encode(a,-1,k);
   1576 	    return;
   1577 	} else if (k->s_rpt > 1) {	/* Run broken, more than two? */
   1578 	    k->xdata[(k->size)++] = k->rptq; /* Yes, emit prefix and count */
   1579 	    k->xdata[(k->size)++] = tochar(++(k->s_rpt));
   1580 	    k->s_rpt = 0;		/* and reset counter. */
   1581 	}
   1582     }
   1583     a7 = a & 127;			/* Get low 7 bits of character */
   1584     b8 = a & 128;			/* And "parity" bit */
   1585 
   1586     if (k->ebqflg && b8) {		/* If doing 8th bit prefixing */
   1587 	k->xdata[(k->size)++] = k->ebq; /* and 8th bit on, insert prefix */
   1588 	a = a7;				/* and clear the 8th bit. */
   1589     }
   1590     if (a7 < 32 || a7 == 127) {		   /* If in control range */
   1591         k->xdata[(k->size)++] = k->s_ctlq; /* insert control prefix */
   1592         a = ctl(a);			 /* and make character printable. */
   1593     } else if (a7 == k->s_ctlq)		 /* If data is control prefix, */
   1594       k->xdata[(k->size)++] = k->s_ctlq; /* prefix it. */
   1595     else if (k->ebqflg && a7 == k->ebq)  /* If doing 8th-bit prefixing, */
   1596       k->xdata[(k->size)++] = k->s_ctlq; /* ditto for 8th-bit prefix. */
   1597     else if (k->rptflg && a7 == k->rptq) /* If doing run-length encoding, */
   1598       k->xdata[(k->size)++] = k->s_ctlq; /* ditto for repeat prefix. */
   1599 
   1600     k->xdata[(k->size)++] = a;		/* Finally, emit the character. */
   1601     k->xdata[(k->size)] = '\0';		/* Terminate string with null. */
   1602 }
   1603 
   1604 STATIC int
   1605 nxtpkt(struct k_data * k) {		/* Get next packet to send */
   1606     k->s_seq = (k->s_seq + 1) & 63;	/* Next sequence number */
   1607     k->xdata = k->xdatabuf;
   1608     return(0);
   1609 }
   1610 
   1611 STATIC int
   1612 resend(struct k_data * k) {
   1613     UCHAR * buf;
   1614     if (!k->opktlen)			/* Nothing to resend */
   1615       return(X_OK);
   1616     buf = k->opktbuf;
   1617     debug(DB_PKT,">PKT",&buf[1],k->opktlen);
   1618     return((*(k->txd))(k,buf,k->opktlen));
   1619 }
   1620