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