17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
23ace1a5fdp * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bdstevel@tonic-gate/*	  All Rights Reserved  	*/
297c478bdstevel@tonic-gate
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bdstevel@tonic-gate
337c478bdstevel@tonic-gate#include "uucp.h"
347c478bdstevel@tonic-gate
357c478bdstevel@tonic-gate#include "pk.h"
367c478bdstevel@tonic-gate#include <sys/buf.h>
377c478bdstevel@tonic-gate
387c478bdstevel@tonic-gateextern void pkfail(), pkzero(), pkoutput(), pkreset(), pkcntl(), pkgetpack();
397c478bdstevel@tonic-gateextern int pksack();
407c478bdstevel@tonic-gatestatic void pkdata();
417c478bdstevel@tonic-gatestatic int pkcget();
42462be47ceasthastatic void xlatestate(struct pack *, int);
43462be47ceasthavoid xlatecntl(int, int);
447c478bdstevel@tonic-gate
457c478bdstevel@tonic-gate/*
467c478bdstevel@tonic-gate * Code added to allow translation of states from numbers to
477c478bdstevel@tonic-gate * letters, to be done in such a way as to be meaningful to
487c478bdstevel@tonic-gate * John Q. Public
497c478bdstevel@tonic-gate */
507c478bdstevel@tonic-gatestruct {
517c478bdstevel@tonic-gate	int state;
527c478bdstevel@tonic-gate	char *msg;
537c478bdstevel@tonic-gate} st_trans[] = {
547c478bdstevel@tonic-gate	DEAD,	"Dead!",
557c478bdstevel@tonic-gate	INITa,	"INIT code a",
567c478bdstevel@tonic-gate	INITb,	"INIT code b",
577c478bdstevel@tonic-gate	LIVE,	"O.K.",
587c478bdstevel@tonic-gate	RXMIT,	"Rcv/Xmit",
597c478bdstevel@tonic-gate	RREJ,	"RREJ?",
607c478bdstevel@tonic-gate	PDEBUG,	"PDEBUG?",
617c478bdstevel@tonic-gate	DRAINO,	"Draino...",
627c478bdstevel@tonic-gate	WAITO,	"Waiting",
637c478bdstevel@tonic-gate	DOWN,	"Link down",
647c478bdstevel@tonic-gate	RCLOSE,	"RCLOSE?",
657c478bdstevel@tonic-gate	BADFRAME,	"Bad frame",
667c478bdstevel@tonic-gate	-1,	"End of the line",
677c478bdstevel@tonic-gate};
687c478bdstevel@tonic-gate
697c478bdstevel@tonic-gateextern char _Protocol[];	/* Protocol string with (options) */
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate#define PKMAXSTMSG 40
727c478bdstevel@tonic-gateint Connodata = 0;		/* Continuous Non Valid Data Count */
737c478bdstevel@tonic-gateint Ntimeout = 0;
747c478bdstevel@tonic-gate#define CONNODATA	20	/* Max Continuous Non Valid Data Count */
757c478bdstevel@tonic-gate#define NTIMEOUT	50	/* This is not currently used, but maybe future */
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gateextern jmp_buf Getjbuf;
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate/*
807c478bdstevel@tonic-gate * start initial synchronization.
817c478bdstevel@tonic-gate */
827c478bdstevel@tonic-gatestruct pack *
837c478bdstevel@tonic-gatepkopen(ifn, ofn)
847c478bdstevel@tonic-gateint ifn, ofn;
857c478bdstevel@tonic-gate{
86462be47ceastha	struct pack *pk;
87462be47ceastha	char **bp;
88462be47ceastha	int i;
897c478bdstevel@tonic-gate	int windows = WINDOWS;
907c478bdstevel@tonic-gate	extern int xpacksize, packsize;
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate	if ((pk = (struct pack *) calloc(1, sizeof (struct pack))) == NULL)
937c478bdstevel@tonic-gate		return(NULL);
947c478bdstevel@tonic-gate	pk->p_ifn = ifn;
957c478bdstevel@tonic-gate	pk->p_ofn = ofn;
967c478bdstevel@tonic-gate	DEBUG(7, "Setting up protocol parameters '%s'\n", _Protocol);
977c478bdstevel@tonic-gate	if ( _Protocol[1] == '(' ) {
987c478bdstevel@tonic-gate	    if (sscanf(_Protocol, "%*c(%d,%d)", &windows, &packsize) == 0)
997c478bdstevel@tonic-gate	    sscanf(_Protocol, "%*c(,%d)", &packsize);
1007c478bdstevel@tonic-gate	    windows = ( windows < MINWINDOWS ? WINDOWS :
1017c478bdstevel@tonic-gate			( windows > MAXWINDOWS ? WINDOWS : windows ) );
1027c478bdstevel@tonic-gate	    packsize = ( packsize < MINPACKSIZE ? PACKSIZE :
1037c478bdstevel@tonic-gate			( packsize > MAXPACKSIZE ? PACKSIZE : packsize ) );
1047c478bdstevel@tonic-gate	}
1057c478bdstevel@tonic-gate	if ( (_Protocol[0] == 'g') && (packsize > OLDPACKSIZE) ) {
1067c478bdstevel@tonic-gate	    /*
1077c478bdstevel@tonic-gate	     * We reset to OLDPACKSIZE to maintain compatibility
1087c478bdstevel@tonic-gate	     * with old limited implementations. Maybe we should
1097c478bdstevel@tonic-gate	     * just warn the administrator and continue?
1107c478bdstevel@tonic-gate	     */
1117c478bdstevel@tonic-gate	    packsize = OLDPACKSIZE;
1127c478bdstevel@tonic-gate	}
1137c478bdstevel@tonic-gate	pk->p_xsize = pk->p_rsize = xpacksize = packsize;
1147c478bdstevel@tonic-gate	pk->p_rwindow = pk->p_swindow = windows;
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate	/*
1177c478bdstevel@tonic-gate	 * allocate input window
1187c478bdstevel@tonic-gate	 */
1197c478bdstevel@tonic-gate	for (i = 0; i < pk->p_rwindow; i++) {
1207c478bdstevel@tonic-gate		if ((bp = (char **) malloc((unsigned) pk->p_xsize)) == NULL)
1217c478bdstevel@tonic-gate			break;
1227c478bdstevel@tonic-gate		*bp = (char *) pk->p_ipool;
1237c478bdstevel@tonic-gate		pk->p_ipool = bp;
1247c478bdstevel@tonic-gate	}
1257c478bdstevel@tonic-gate	if (i == 0)
1267c478bdstevel@tonic-gate		return(NULL);
1277c478bdstevel@tonic-gate	pk->p_rwindow = i;
1287c478bdstevel@tonic-gate
1297c478bdstevel@tonic-gate	/*
1307c478bdstevel@tonic-gate	 * start synchronization
1317c478bdstevel@tonic-gate	 */
1327c478bdstevel@tonic-gate	pk->p_msg = pk->p_rmsg = M_INITA;
1337c478bdstevel@tonic-gate	pkoutput(pk);
1347c478bdstevel@tonic-gate
1357c478bdstevel@tonic-gate	for (i = 0; i < PKMAXSTMSG; i++) {
1367c478bdstevel@tonic-gate		pkgetpack(pk);
1377c478bdstevel@tonic-gate		if ((pk->p_state & LIVE) != 0)
1387c478bdstevel@tonic-gate			break;
1397c478bdstevel@tonic-gate	}
1407c478bdstevel@tonic-gate	if (i >= PKMAXSTMSG)
1417c478bdstevel@tonic-gate		return(NULL);
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gate	pkreset(pk);
1447c478bdstevel@tonic-gate	return(pk);
1457c478bdstevel@tonic-gate}
1467c478bdstevel@tonic-gate
1477c478bdstevel@tonic-gate/*
1487c478bdstevel@tonic-gate * input framing and block checking.
1497c478bdstevel@tonic-gate * frame layout for most devices is:
1507c478bdstevel@tonic-gate *
1517c478bdstevel@tonic-gate *	S|K|X|Y|C|Z|  ... data ... |
1527c478bdstevel@tonic-gate *
1537c478bdstevel@tonic-gate *	where 	S	== initial synch byte
1547c478bdstevel@tonic-gate *		K	== encoded frame size (indexes pksizes[])
1557c478bdstevel@tonic-gate *		X, Y	== block check bytes
1567c478bdstevel@tonic-gate *		C	== control byte
1577c478bdstevel@tonic-gate *		Z	== XOR of header (K^X^Y^C)
1587c478bdstevel@tonic-gate *		data	== 0 or more data bytes
1597c478bdstevel@tonic-gate *
1607c478bdstevel@tonic-gate */
1617c478bdstevel@tonic-gate#define GETRIES 10
1627c478bdstevel@tonic-gate
1637c478bdstevel@tonic-gate/*
1647c478bdstevel@tonic-gate * Byte collection.
1657c478bdstevel@tonic-gate */
1667c478bdstevel@tonic-gatevoid
1677c478bdstevel@tonic-gatepkgetpack(ipk)
168462be47ceasthastruct pack *ipk;
1697c478bdstevel@tonic-gate{
170462be47ceastha	char *p;
171462be47ceastha	struct pack *pk;
172462be47ceastha	struct header *h;
1737c478bdstevel@tonic-gate	unsigned short sum;
1747c478bdstevel@tonic-gate	int k, tries, ifn, noise;
1757c478bdstevel@tonic-gate	char **bp, hdchk;
1767c478bdstevel@tonic-gate
1777c478bdstevel@tonic-gate	pk = ipk;
1787c478bdstevel@tonic-gate	/*
1797c478bdstevel@tonic-gate	 * If we are known to be DOWN, or if we've received too many garbage
1807c478bdstevel@tonic-gate	 * packets or timeouts, give up without a fight.
1817c478bdstevel@tonic-gate	 */
1827c478bdstevel@tonic-gate	if ((pk->p_state & DOWN) || Connodata > CONNODATA  || Ntimeout > NTIMEOUT)
1837c478bdstevel@tonic-gate		pkfail();
1847c478bdstevel@tonic-gate	ifn = pk->p_ifn;
1857c478bdstevel@tonic-gate	h = &pk->p_ihbuf;
1867c478bdstevel@tonic-gate
1877c478bdstevel@tonic-gate	/*
1887c478bdstevel@tonic-gate	 * Attempt no more than GETRIES times to read a packet.  The only valid
1897c478bdstevel@tonic-gate	 * exit from this loop is a return.  Break forces a failure.
1907c478bdstevel@tonic-gate	 */
1917c478bdstevel@tonic-gate	for (tries = 0; tries < GETRIES; tries++) {
1927c478bdstevel@tonic-gate		/*
1937c478bdstevel@tonic-gate		 * Read header.
1947c478bdstevel@tonic-gate		 * First look for SYN.  If more than 3 * packetsize characters
1957c478bdstevel@tonic-gate		 * go by w/o a SYN, request a retransmit.
1967c478bdstevel@tonic-gate		 */
1977c478bdstevel@tonic-gate		p = (caddr_t) h;
1987c478bdstevel@tonic-gate		noise = 0;
1997c478bdstevel@tonic-gate		for ( ; ; ) {
2007c478bdstevel@tonic-gate			if (pkcget(ifn, p, HDRSIZ) != SUCCESS) {
2017c478bdstevel@tonic-gate				DEBUG(7,
2027c478bdstevel@tonic-gate		"Alarm while looking for SYN -- request RXMIT\n%s", "");
2037c478bdstevel@tonic-gate				goto retransmit;
2047c478bdstevel@tonic-gate			}
2057c478bdstevel@tonic-gate			if (*p == SYN)
2067c478bdstevel@tonic-gate				break;		/* got it */
2077c478bdstevel@tonic-gate			else {
2087c478bdstevel@tonic-gate				char *pp, *pend;
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate				DEBUG(7, "first char not SYN (%x)\n", *p&0xff);
2117c478bdstevel@tonic-gate				if ((pp = memchr(p, SYN, HDRSIZ)) != NULL) {
2127c478bdstevel@tonic-gate					pend = p + HDRSIZ;
2137c478bdstevel@tonic-gate					while (pp < pend)
2147c478bdstevel@tonic-gate						*p++ = *pp++;
2157c478bdstevel@tonic-gate					/* Now look for remainder of header */
2167c478bdstevel@tonic-gate					if (pkcget(ifn, p, pend - p) !=
2177c478bdstevel@tonic-gate					    SUCCESS) {
2187c478bdstevel@tonic-gate						DEBUG(7,
2197c478bdstevel@tonic-gate		"Alarm while looking for header -- request RXMIT\n%s", "");
2207c478bdstevel@tonic-gate						goto retransmit;
2217c478bdstevel@tonic-gate					}
2227c478bdstevel@tonic-gate					p = (caddr_t) h;
2237c478bdstevel@tonic-gate					break;	/* got entire header */
2247c478bdstevel@tonic-gate				}
2257c478bdstevel@tonic-gate			}
2267c478bdstevel@tonic-gate			if ((noise += HDRSIZ) > 3 * pk->p_rsize) {
2277c478bdstevel@tonic-gate				DEBUG(7,
2287c478bdstevel@tonic-gate			"No SYN in %d characters -- request RXMIT\n", noise);
2297c478bdstevel@tonic-gate				goto retransmit;
2307c478bdstevel@tonic-gate			}
2317c478bdstevel@tonic-gate		}
2327c478bdstevel@tonic-gate		/* Validate the header */
2337c478bdstevel@tonic-gate		Connodata++;
2347c478bdstevel@tonic-gate		hdchk = p[1] ^ p[2] ^ p[3] ^ p[4];
2357c478bdstevel@tonic-gate		sum = ((unsigned) p[2] & 0377) | ((unsigned) p[3] << 8);
2367c478bdstevel@tonic-gate		h->sum = sum;
2377c478bdstevel@tonic-gate		k = h->ksize;
2387c478bdstevel@tonic-gate		if (hdchk != h->ccntl) {
2397c478bdstevel@tonic-gate			/* bad header */
2407c478bdstevel@tonic-gate			DEBUG(7, "bad header checksum\n%s", "");
2417c478bdstevel@tonic-gate			return;
2427c478bdstevel@tonic-gate		}
2437c478bdstevel@tonic-gate
2447c478bdstevel@tonic-gate		if (k == 9) {	/* control packet */
2457c478bdstevel@tonic-gate			if (((h->sum + h->cntl) & 0xffff) == CHECK) {
2467c478bdstevel@tonic-gate				pkcntl(h->cntl, pk);
2477c478bdstevel@tonic-gate				xlatestate(pk, 7);
2487c478bdstevel@tonic-gate			} else {
2497c478bdstevel@tonic-gate				/* bad header */
2507c478bdstevel@tonic-gate				DEBUG(7, "bad header (k == 9) 0%o\n", h->cntl&0xff);
2517c478bdstevel@tonic-gate				pk->p_state |= BADFRAME;
2527c478bdstevel@tonic-gate			}
2537c478bdstevel@tonic-gate			return;
2547c478bdstevel@tonic-gate		}
2557c478bdstevel@tonic-gate		/* data packet */
2567c478bdstevel@tonic-gate		if (k && pksizes[k] != pk->p_rsize)
2577c478bdstevel@tonic-gate			return;
2587c478bdstevel@tonic-gate		pk->p_rpr = h->cntl & MOD8;
2597c478bdstevel@tonic-gate		pksack(pk);
2607c478bdstevel@tonic-gate		if ((bp = pk->p_ipool) == NULL) {
2617c478bdstevel@tonic-gate			DEBUG(7, "bp NULL\n%s", "");
2627c478bdstevel@tonic-gate			return;
2637c478bdstevel@tonic-gate		}
2647c478bdstevel@tonic-gate		pk->p_ipool = (char **) *bp;
2657c478bdstevel@tonic-gate		/* Header checks out, go for data */
2667c478bdstevel@tonic-gate		if (pkcget(pk->p_ifn, (char *) bp, pk->p_rsize) == SUCCESS) {
2677c478bdstevel@tonic-gate			pkdata(h->cntl, h->sum, pk, bp);
2687c478bdstevel@tonic-gate			Ntimeout = 0;
2697c478bdstevel@tonic-gate			return;
2707c478bdstevel@tonic-gate		}
2717c478bdstevel@tonic-gate		DEBUG(7, "Alarm while reading data -- request RXMIT\n%s", "");
2727c478bdstevel@tonic-gateretransmit:
2737c478bdstevel@tonic-gate		/*
2747c478bdstevel@tonic-gate		 * Transmission error or excessive noise.  Send a RXMIT
2757c478bdstevel@tonic-gate		 * and try again.
2767c478bdstevel@tonic-gate		 */
2777c478bdstevel@tonic-gate/*
2787c478bdstevel@tonic-gate		Retries++;
2797c478bdstevel@tonic-gate*/
2807c478bdstevel@tonic-gate		pk->p_msg |= pk->p_rmsg;
2817c478bdstevel@tonic-gate		if (pk->p_msg == 0)
2827c478bdstevel@tonic-gate			pk->p_msg |= M_RR;
2837c478bdstevel@tonic-gate		if ((pk->p_state & LIVE) == LIVE)
2847c478bdstevel@tonic-gate			pk->p_state |= RXMIT;
2857c478bdstevel@tonic-gate		pkoutput(pk);
2867c478bdstevel@tonic-gate	}
2877c478bdstevel@tonic-gate	DEBUG(7, "pkgetpack failed after %d tries\n", tries);
2887c478bdstevel@tonic-gate	pkfail();
2897c478bdstevel@tonic-gate}
2907c478bdstevel@tonic-gate
2917c478bdstevel@tonic-gate/*
2927c478bdstevel@tonic-gate * Translate pk->p_state into something printable.
2937c478bdstevel@tonic-gate */
294462be47ceasthastatic void
2957c478bdstevel@tonic-gatexlatestate(pk, dbglvl)
296462be47ceasthastruct pack *pk;
297462be47ceasthaint dbglvl;
2987c478bdstevel@tonic-gate{
299462be47ceastha	int i;
3007c478bdstevel@tonic-gate	char delimc = ' ', msgline[80], *buf = msgline;
3017c478bdstevel@tonic-gate
3027c478bdstevel@tonic-gate	if (Debug < dbglvl)
3037c478bdstevel@tonic-gate		return;
3047c478bdstevel@tonic-gate	sprintf(buf, "state -");
3057c478bdstevel@tonic-gate	buf += strlen(buf);
3067c478bdstevel@tonic-gate	for(i = 0; st_trans[i].state != -1; i++) {
3077c478bdstevel@tonic-gate		if (pk->p_state&st_trans[i].state){
3087c478bdstevel@tonic-gate			sprintf(buf, "%c[%s]", delimc, st_trans[i].msg);
3097c478bdstevel@tonic-gate			buf += strlen(buf);
3107c478bdstevel@tonic-gate			delimc = '&';
3117c478bdstevel@tonic-gate		}
3127c478bdstevel@tonic-gate	}
3137c478bdstevel@tonic-gate	sprintf(buf, " (0%o)\n", pk->p_state);
3147c478bdstevel@tonic-gate	DEBUG(dbglvl, "%s", msgline);
315462be47ceastha	return;
3167c478bdstevel@tonic-gate}
3177c478bdstevel@tonic-gate
3187c478bdstevel@tonic-gatestatic void
3197c478bdstevel@tonic-gatepkdata(c, sum, pk, bp)
320462be47ceasthastruct pack *pk;
3217c478bdstevel@tonic-gateunsigned short sum;
3227c478bdstevel@tonic-gatechar c;
3237c478bdstevel@tonic-gatechar **bp;
3247c478bdstevel@tonic-gate{
325462be47ceastha	int x;
3267c478bdstevel@tonic-gate	int t;
3277c478bdstevel@tonic-gate	char m;
3287c478bdstevel@tonic-gate
3297c478bdstevel@tonic-gate	if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) {
3307c478bdstevel@tonic-gate		pk->p_msg |= pk->p_rmsg;
3317c478bdstevel@tonic-gate		pkoutput(pk);
3327c478bdstevel@tonic-gate		goto drop;
3337c478bdstevel@tonic-gate	}
3347c478bdstevel@tonic-gate	t = next[pk->p_pr];
3357c478bdstevel@tonic-gate	for(x=pk->p_pr; x!=t; x = (x-1)&7) {
3367c478bdstevel@tonic-gate		if (pk->p_is[x] == 0)
3377c478bdstevel@tonic-gate			goto slot;
3387c478bdstevel@tonic-gate	}
3397c478bdstevel@tonic-gatedrop:
3407c478bdstevel@tonic-gate	*bp = (char *)pk->p_ipool;
3417c478bdstevel@tonic-gate	pk->p_ipool = bp;
3427c478bdstevel@tonic-gate	return;
3437c478bdstevel@tonic-gate
3447c478bdstevel@tonic-gateslot:
3457c478bdstevel@tonic-gate	m = mask[x];
3467c478bdstevel@tonic-gate	pk->p_imap |= m;
3477c478bdstevel@tonic-gate	pk->p_is[x] = c;
3487c478bdstevel@tonic-gate	pk->p_isum[x] = sum;
3497c478bdstevel@tonic-gate	pk->p_ib[x] = (char *)bp;
3507c478bdstevel@tonic-gate}
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gate/*
3537c478bdstevel@tonic-gate * Start transmission on output device associated with pk.
3547c478bdstevel@tonic-gate * For asynch devices (t_line==1) framing is
3557c478bdstevel@tonic-gate * imposed.  For devices with framing and crc
3567c478bdstevel@tonic-gate * in the driver (t_line==2) the transfer is
3577c478bdstevel@tonic-gate * passed on to the driver.
3587c478bdstevel@tonic-gate */
3597c478bdstevel@tonic-gatevoid
3607c478bdstevel@tonic-gatepkxstart(pk, cntl, x)
361462be47ceasthastruct pack *pk;
3627c478bdstevel@tonic-gateint x;
3637c478bdstevel@tonic-gatechar cntl;
3647c478bdstevel@tonic-gate{
365462be47ceastha	char *p;
366462be47ceastha	short checkword;
367462be47ceastha	char hdchk;
3687c478bdstevel@tonic-gate
3697c478bdstevel@tonic-gate	p = (caddr_t) &pk->p_ohbuf;
3707c478bdstevel@tonic-gate	*p++ = SYN;
3717c478bdstevel@tonic-gate	if (x < 0) {
3727c478bdstevel@tonic-gate		*p++ = hdchk = 9;
3737c478bdstevel@tonic-gate		checkword = cntl;
3747c478bdstevel@tonic-gate	} else {
3757c478bdstevel@tonic-gate		*p++ = hdchk = pk->p_lpsize;
3767c478bdstevel@tonic-gate		checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377);
3777c478bdstevel@tonic-gate	}
3787c478bdstevel@tonic-gate	checkword = CHECK - checkword;
3797c478bdstevel@tonic-gate	*p = checkword;
3807c478bdstevel@tonic-gate	hdchk ^= *p++;
3817c478bdstevel@tonic-gate	*p = checkword>>8;
3827c478bdstevel@tonic-gate	hdchk ^= *p++;
3837c478bdstevel@tonic-gate	*p = cntl;
3847c478bdstevel@tonic-gate	hdchk ^= *p++;
3857c478bdstevel@tonic-gate	*p = hdchk;
3867c478bdstevel@tonic-gate
3877c478bdstevel@tonic-gate /*
3887c478bdstevel@tonic-gate  * writes
3897c478bdstevel@tonic-gate  */
3907c478bdstevel@tonic-gate	if (Debug >= 9)
3917c478bdstevel@tonic-gate		xlatecntl(1, cntl);
3927c478bdstevel@tonic-gate
3937c478bdstevel@tonic-gate	p = (caddr_t) & pk->p_ohbuf;
3947c478bdstevel@tonic-gate	if (x < 0) {
3957c478bdstevel@tonic-gate		if ((*Write)(pk->p_ofn, p, HDRSIZ) != HDRSIZ) {
3967c478bdstevel@tonic-gate			DEBUG(4, "pkxstart, write failed, %s\n",
397ace1a5fdp			    strerror(errno));
398ace1a5fdp			logent(strerror(errno), "PKXSTART WRITE");
3997c478bdstevel@tonic-gate			pkfail();
4007c478bdstevel@tonic-gate			/* NOT REACHED */
4017c478bdstevel@tonic-gate		}
4027c478bdstevel@tonic-gate	} else {
4037c478bdstevel@tonic-gate		char buf[MAXPACKSIZE + HDRSIZ];
4047c478bdstevel@tonic-gate
4057c478bdstevel@tonic-gate		memcpy(buf, p, HDRSIZ);
4067c478bdstevel@tonic-gate		memcpy(buf+HDRSIZ, pk->p_ob[x], pk->p_xsize);
4077c478bdstevel@tonic-gate		if ((*Write)(pk->p_ofn, buf, pk->p_xsize + HDRSIZ) !=
4087c478bdstevel@tonic-gate		    pk->p_xsize + HDRSIZ) {
4097c478bdstevel@tonic-gate			DEBUG(4, "pkxstart, write failed, %s\n",
410ace1a5fdp			    strerror(errno));
411ace1a5fdp			logent(strerror(errno), "PKXSTART WRITE");
4127c478bdstevel@tonic-gate			pkfail();
4137c478bdstevel@tonic-gate			/* NOT REACHED */
4147c478bdstevel@tonic-gate		}
4157c478bdstevel@tonic-gate		Connodata = 0;
4167c478bdstevel@tonic-gate	}
4177c478bdstevel@tonic-gate	if (pk->p_msg)
4187c478bdstevel@tonic-gate		pkoutput(pk);
4197c478bdstevel@tonic-gate}
4207c478bdstevel@tonic-gate
4217c478bdstevel@tonic-gate/*
4227c478bdstevel@tonic-gate * get n characters from input
4237c478bdstevel@tonic-gate *	b	-> buffer for characters
4247c478bdstevel@tonic-gate *	fn	-> file descriptor
4257c478bdstevel@tonic-gate *	n	-> requested number of characters
4267c478bdstevel@tonic-gate * return:
4277c478bdstevel@tonic-gate *	SUCCESS	-> n chars successfully read
4287c478bdstevel@tonic-gate *	FAIL	-> o.w.
4297c478bdstevel@tonic-gate */
4307c478bdstevel@tonic-gate
4317c478bdstevel@tonic-gatestatic int
4327c478bdstevel@tonic-gatepkcget(fn, b, n)
433462be47ceasthaint n;
434462be47ceasthachar *b;
435462be47ceasthaint fn;
4367c478bdstevel@tonic-gate{
437462be47ceastha	int ret;
4387c478bdstevel@tonic-gate#ifdef PKSPEEDUP
4397c478bdstevel@tonic-gate	extern int linebaudrate;
440462be47ceastha	int donap = (linebaudrate > 0 && linebaudrate < 4800);
4417c478bdstevel@tonic-gate#endif /*  PKSPEEDUP  */
4427c478bdstevel@tonic-gate
4437c478bdstevel@tonic-gate	if (n == 0)
4447c478bdstevel@tonic-gate		return(SUCCESS);
4457c478bdstevel@tonic-gate	if (setjmp(Getjbuf)) {
4467c478bdstevel@tonic-gate		Ntimeout++;
4477c478bdstevel@tonic-gate		DEBUG(4, "pkcget: alarm %d\n", Ntimeout);
4487c478bdstevel@tonic-gate		return(FAIL);
4497c478bdstevel@tonic-gate	}
4507c478bdstevel@tonic-gate
4517c478bdstevel@tonic-gate	(void) alarm( (unsigned) ( 10 + (n >> 7)) );
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate	for (;;) {
4547c478bdstevel@tonic-gate		ret = (*Read)(fn, b, n);
4557c478bdstevel@tonic-gate		(void) alarm(0);
4567c478bdstevel@tonic-gate		if (ret == 0) {
4577c478bdstevel@tonic-gate			DEBUG(4, "pkcget, read failed, EOF\n", 0);
4587c478bdstevel@tonic-gate			/*
4597c478bdstevel@tonic-gate			 * Device has decided that the connection has no
4607c478bdstevel@tonic-gate			 * more data to send.  Any further tries are futile...
4617c478bdstevel@tonic-gate			 * (The only other way to get a zero return value
4627c478bdstevel@tonic-gate			 * is to read a zero length message from a STREAM.
4637c478bdstevel@tonic-gate			 * However, uucp *never* sends zero length messages
4647c478bdstevel@tonic-gate			 * over any sort of channel...)
4657c478bdstevel@tonic-gate			 */
4667c478bdstevel@tonic-gate			pkfail();
4677c478bdstevel@tonic-gate			/* NOT REACHED */
4687c478bdstevel@tonic-gate		}
4697c478bdstevel@tonic-gate		if (ret < 0) {
4707c478bdstevel@tonic-gate			DEBUG(4, "pkcget, read failed, %s\n",
471ace1a5fdp			    strerror(errno));
472ace1a5fdp			logent(strerror(errno), "PKCGET READ");
4737c478bdstevel@tonic-gate			pkfail();
4747c478bdstevel@tonic-gate			/* NOT REACHED */
4757c478bdstevel@tonic-gate		}
4767c478bdstevel@tonic-gate		if ((n -= ret) <= 0)
4777c478bdstevel@tonic-gate			break;
4787c478bdstevel@tonic-gate#ifdef PKSPEEDUP
4797c478bdstevel@tonic-gate		if (donap) {
4807c478bdstevel@tonic-gate#if defined(BSD4_2) || defined(ATTSVR4)
4817c478bdstevel@tonic-gate			/* wait for more chars to come in */
4827c478bdstevel@tonic-gate			nap((n * HZ * 10) / linebaudrate); /* n char times */
4837c478bdstevel@tonic-gate#else
4847c478bdstevel@tonic-gate			sleep(1);
4857c478bdstevel@tonic-gate#endif
4867c478bdstevel@tonic-gate		}
4877c478bdstevel@tonic-gate#endif /*  PKSPEEDUP  */
4887c478bdstevel@tonic-gate		b += ret;
4897c478bdstevel@tonic-gate		(void) alarm( (unsigned) ( 10 + (n >> 7)) );
4907c478bdstevel@tonic-gate	}
4917c478bdstevel@tonic-gate	(void) alarm(0);
4927c478bdstevel@tonic-gate	return(SUCCESS);
4937c478bdstevel@tonic-gate}
4947c478bdstevel@tonic-gate
4957c478bdstevel@tonic-gate/*
4967c478bdstevel@tonic-gate * role == 0: receive
4977c478bdstevel@tonic-gate * role == 1: send
4987c478bdstevel@tonic-gate */
499462be47ceasthavoid
5007c478bdstevel@tonic-gatexlatecntl(role, cntl)
501462be47ceasthaint role;
502462be47ceasthaint cntl;
5037c478bdstevel@tonic-gate{
5047c478bdstevel@tonic-gate	static char *cntltype[4] = {"CNTL, ", "ALT, ", "DATA, ", "SHORT, "};
5057c478bdstevel@tonic-gate	static char *cntlxxx[8] = {"ZERO, ", "CLOSE, ", "RJ, ", "SRJ, ",
5067c478bdstevel@tonic-gate				   "RR, ", "INITC, ", "INITB, ", "INITA, "};
5077c478bdstevel@tonic-gate	char dbgbuf[128];
508462be47ceastha	char *ptr;
5097c478bdstevel@tonic-gate
5107c478bdstevel@tonic-gate	ptr = dbgbuf;
5117c478bdstevel@tonic-gate	strcpy(ptr, role ? "send " : "recv ");
5127c478bdstevel@tonic-gate	ptr += strlen(ptr);
5137c478bdstevel@tonic-gate
5147c478bdstevel@tonic-gate	strcpy(ptr, cntltype[(cntl&0300)>>6]);
5157c478bdstevel@tonic-gate	ptr += strlen(ptr);
5167c478bdstevel@tonic-gate
5177c478bdstevel@tonic-gate	if (cntl&0300) {
5187c478bdstevel@tonic-gate		/* data packet */
5197c478bdstevel@tonic-gate		if (role)
5207c478bdstevel@tonic-gate			sprintf(ptr, "loc %o, rem %o\n", (cntl & 070) >> 3, cntl & 7);
5217c478bdstevel@tonic-gate		else
5227c478bdstevel@tonic-gate			sprintf(ptr, "loc %o, rem %o\n", cntl & 7, (cntl & 070) >> 3);
5237c478bdstevel@tonic-gate	} else {
5247c478bdstevel@tonic-gate		/* control packet */
5257c478bdstevel@tonic-gate		strcpy(ptr, cntlxxx[(cntl&070)>>3]);
5267c478bdstevel@tonic-gate		ptr += strlen(ptr);
5277c478bdstevel@tonic-gate		sprintf(ptr, "val %o\n", cntl & 7);
5287c478bdstevel@tonic-gate	}
5297c478bdstevel@tonic-gate
5307c478bdstevel@tonic-gate	DEBUG(1, dbgbuf, 0);
5317c478bdstevel@tonic-gate}
532