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