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