xref: /titanic_53/usr/src/cmd/bnu/fio.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  *
31*7c478bd9Sstevel@tonic-gate  * flow control protocol.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * This protocol relies on flow control of the data stream.
34*7c478bd9Sstevel@tonic-gate  * It is meant for working over links that can (almost) be
35*7c478bd9Sstevel@tonic-gate  * guaranteed to be errorfree, specifically X.25/PAD links.
36*7c478bd9Sstevel@tonic-gate  * A sumcheck is carried out over a whole file only. If a
37*7c478bd9Sstevel@tonic-gate  * transport fails the receiver can request retransmission(s).
38*7c478bd9Sstevel@tonic-gate  * This protocol uses a 7-bit datapath only, so it can be
39*7c478bd9Sstevel@tonic-gate  * used on links that are not 8-bit transparent.
40*7c478bd9Sstevel@tonic-gate  *
41*7c478bd9Sstevel@tonic-gate  * When using this protocol with an X.25 PAD:
42*7c478bd9Sstevel@tonic-gate  * Although this protocol uses no control chars except CR,
43*7c478bd9Sstevel@tonic-gate  * control chars NULL and ^P are used before this protocol
44*7c478bd9Sstevel@tonic-gate  * is started; since ^P is the default char for accessing
45*7c478bd9Sstevel@tonic-gate  * PAD X.28 command mode, be sure to disable that access
46*7c478bd9Sstevel@tonic-gate  * (PAD par 1). Also make sure both flow control pars
47*7c478bd9Sstevel@tonic-gate  * (5 and 12) are set. The CR used in this proto is meant
48*7c478bd9Sstevel@tonic-gate  * to trigger packet transmission, hence par 3 should be
49*7c478bd9Sstevel@tonic-gate  * set to 2; a good value for the Idle Timer (par 4) is 10.
50*7c478bd9Sstevel@tonic-gate  * All other pars should be set to 0.
51*7c478bd9Sstevel@tonic-gate  *
52*7c478bd9Sstevel@tonic-gate  * Normally a calling site will take care of setting the
53*7c478bd9Sstevel@tonic-gate  * local PAD pars via an X.28 command and those of the remote
54*7c478bd9Sstevel@tonic-gate  * PAD via an X.29 command, unless the remote site has a
55*7c478bd9Sstevel@tonic-gate  * special channel assigned for this protocol with the proper
56*7c478bd9Sstevel@tonic-gate  * par settings.
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  * Additional comments for hosts with direct X.25 access:
59*7c478bd9Sstevel@tonic-gate  * - the global variable IsTcpIp, when set, excludes the ioctl's,
60*7c478bd9Sstevel@tonic-gate  *   so the same binary can run on X.25 and non-X.25 hosts;
61*7c478bd9Sstevel@tonic-gate  * - reads are done in small chunks, which can be smaller than
62*7c478bd9Sstevel@tonic-gate  *   the packet size; your X.25 driver must support that.
63*7c478bd9Sstevel@tonic-gate  *
64*7c478bd9Sstevel@tonic-gate  *
65*7c478bd9Sstevel@tonic-gate  * Author:
66*7c478bd9Sstevel@tonic-gate  *	Piet Beertema, CWI, Amsterdam, Sep 1984
67*7c478bd9Sstevel@tonic-gate  * Modified for X.25 hosts:
68*7c478bd9Sstevel@tonic-gate  *	Robert Elz, Melbourne Univ, Mar 1985
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #include "uucp.h"
72*7c478bd9Sstevel@tonic-gate #ifdef F_PROTOCOL
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate extern unsigned msgtime;
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* privates */
77*7c478bd9Sstevel@tonic-gate static int frdblk(), fwrblk();
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate #define FIBUFSIZ	4096	/* for X.25 interfaces: set equal to packet size,
80*7c478bd9Sstevel@tonic-gate 				 * but see comment above
81*7c478bd9Sstevel@tonic-gate 				 */
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate #define FOBUFSIZ	4096	/* for X.25 interfaces: set equal to packet size;
84*7c478bd9Sstevel@tonic-gate 				 * otherwise make as large as feasible to reduce
85*7c478bd9Sstevel@tonic-gate 				 * number of write system calls
86*7c478bd9Sstevel@tonic-gate 				 */
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate #ifndef MAXMSGLEN
89*7c478bd9Sstevel@tonic-gate #define MAXMSGLEN	BUFSIZ
90*7c478bd9Sstevel@tonic-gate #endif MAXMSGLEN
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static int fchksum;
93*7c478bd9Sstevel@tonic-gate static jmp_buf Ffailbuf;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
96*7c478bd9Sstevel@tonic-gate static void
97*7c478bd9Sstevel@tonic-gate falarm(sig)
98*7c478bd9Sstevel@tonic-gate 	int sig;
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	signal(SIGALRM, falarm);
101*7c478bd9Sstevel@tonic-gate 	longjmp(Ffailbuf, 1);
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate static void (*fsig)();
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate static int ioctlok;
107*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
108*7c478bd9Sstevel@tonic-gate static struct termio ttbuf;
109*7c478bd9Sstevel@tonic-gate #else
110*7c478bd9Sstevel@tonic-gate static struct sgttyb ttbuf;
111*7c478bd9Sstevel@tonic-gate #endif
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate fturnon()
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate 	int ret;
116*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
117*7c478bd9Sstevel@tonic-gate 	struct termio save_ttbuf;
118*7c478bd9Sstevel@tonic-gate #else
119*7c478bd9Sstevel@tonic-gate 	struct sgttyb save_ttbuf;
120*7c478bd9Sstevel@tonic-gate #endif
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
123*7c478bd9Sstevel@tonic-gate 	if (ioctl(Ifn, TCGETA, &ttbuf) >= 0) {
124*7c478bd9Sstevel@tonic-gate 		ioctlok = 1;
125*7c478bd9Sstevel@tonic-gate 		save_ttbuf = ttbuf;
126*7c478bd9Sstevel@tonic-gate 		ioctl(Ifn, TCGETA, &ttbuf);
127*7c478bd9Sstevel@tonic-gate 		ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
128*7c478bd9Sstevel@tonic-gate 		ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
129*7c478bd9Sstevel@tonic-gate 		ttbuf.c_cc[VTIME] = 5;
130*7c478bd9Sstevel@tonic-gate 		ret = ioctl(Ifn, TCSETA, &ttbuf);
131*7c478bd9Sstevel@tonic-gate 		ASSERT(ret >= 0, "STTY FAILED", "", ret);
132*7c478bd9Sstevel@tonic-gate 		ttbuf = save_ttbuf;
133*7c478bd9Sstevel@tonic-gate 	}
134*7c478bd9Sstevel@tonic-gate #else /* !ATTSVTTY */
135*7c478bd9Sstevel@tonic-gate 	if (ioctl(Ifn, TIOCGETP, &ttbuf) >= 0) {
136*7c478bd9Sstevel@tonic-gate 		ioctlok = 1;
137*7c478bd9Sstevel@tonic-gate 		save_ttbuf = ttbuf;
138*7c478bd9Sstevel@tonic-gate 		ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
139*7c478bd9Sstevel@tonic-gate 		ret = ioctl(Ifn, TIOCSETP, &ttbuf);
140*7c478bd9Sstevel@tonic-gate 		ASSERT(ret >= 0, "STTY FAILED", "", ret);
141*7c478bd9Sstevel@tonic-gate 		ttbuf = save_ttbuf;
142*7c478bd9Sstevel@tonic-gate 	}
143*7c478bd9Sstevel@tonic-gate #endif /* ATTSVTTY */
144*7c478bd9Sstevel@tonic-gate 	fsig = signal(SIGALRM, falarm);
145*7c478bd9Sstevel@tonic-gate 	/* give the other side time to perform its ioctl;
146*7c478bd9Sstevel@tonic-gate 	 * otherwise it may flush out the first data this
147*7c478bd9Sstevel@tonic-gate 	 * side is about to send.
148*7c478bd9Sstevel@tonic-gate 	 */
149*7c478bd9Sstevel@tonic-gate 	sleep(2);
150*7c478bd9Sstevel@tonic-gate 	return SUCCESS;
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate fturnoff()
154*7c478bd9Sstevel@tonic-gate {
155*7c478bd9Sstevel@tonic-gate 	if (ioctlok) {
156*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
157*7c478bd9Sstevel@tonic-gate 		(void) ioctl(Ifn, TCSETA, &ttbuf);
158*7c478bd9Sstevel@tonic-gate #else
159*7c478bd9Sstevel@tonic-gate 		(void) ioctl(Ifn, TIOCSETP, &ttbuf);
160*7c478bd9Sstevel@tonic-gate #endif
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGALRM, fsig);
163*7c478bd9Sstevel@tonic-gate 	sleep(2);
164*7c478bd9Sstevel@tonic-gate 	return SUCCESS;
165*7c478bd9Sstevel@tonic-gate }
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate fwrmsg(type, str, fn)
168*7c478bd9Sstevel@tonic-gate register char *str;
169*7c478bd9Sstevel@tonic-gate int fn;
170*7c478bd9Sstevel@tonic-gate char type;
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	register char *s;
173*7c478bd9Sstevel@tonic-gate 	char bufr[MAXMSGLEN];
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	s = bufr;
176*7c478bd9Sstevel@tonic-gate 	*s++ = type;
177*7c478bd9Sstevel@tonic-gate 	while (*str)
178*7c478bd9Sstevel@tonic-gate 		*s++ = *str++;
179*7c478bd9Sstevel@tonic-gate 	if (*(s-1) == '\n')
180*7c478bd9Sstevel@tonic-gate 		s--;
181*7c478bd9Sstevel@tonic-gate 	*s++ = '\r';
182*7c478bd9Sstevel@tonic-gate 	*s = 0;
183*7c478bd9Sstevel@tonic-gate 	(void) write(fn, bufr, s - bufr);
184*7c478bd9Sstevel@tonic-gate 	return SUCCESS;
185*7c478bd9Sstevel@tonic-gate }
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate frdmsg(str, fn)
188*7c478bd9Sstevel@tonic-gate register char *str;
189*7c478bd9Sstevel@tonic-gate register int fn;
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	register char *smax;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	if (setjmp(Ffailbuf))
194*7c478bd9Sstevel@tonic-gate 		return FAIL;
195*7c478bd9Sstevel@tonic-gate 	smax = str + MAXMSGLEN - 1;
196*7c478bd9Sstevel@tonic-gate 	(void) alarm(msgtime);
197*7c478bd9Sstevel@tonic-gate 	for (;;) {
198*7c478bd9Sstevel@tonic-gate 		if (read(fn, str, 1) <= 0)
199*7c478bd9Sstevel@tonic-gate 			goto msgerr;
200*7c478bd9Sstevel@tonic-gate 		*str &= 0177;
201*7c478bd9Sstevel@tonic-gate 		if (*str == '\r')
202*7c478bd9Sstevel@tonic-gate 			break;
203*7c478bd9Sstevel@tonic-gate 		if (*str < ' ') {
204*7c478bd9Sstevel@tonic-gate 			continue;
205*7c478bd9Sstevel@tonic-gate 		}
206*7c478bd9Sstevel@tonic-gate 		if (str++ >= smax)
207*7c478bd9Sstevel@tonic-gate 			goto msgerr;
208*7c478bd9Sstevel@tonic-gate 	}
209*7c478bd9Sstevel@tonic-gate 	*str = '\0';
210*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
211*7c478bd9Sstevel@tonic-gate 	return SUCCESS;
212*7c478bd9Sstevel@tonic-gate msgerr:
213*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
214*7c478bd9Sstevel@tonic-gate 	return FAIL;
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate fwrdata(fp1, fn)
218*7c478bd9Sstevel@tonic-gate FILE *fp1;
219*7c478bd9Sstevel@tonic-gate int fn;
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate 	register int alen, ret;
222*7c478bd9Sstevel@tonic-gate 	char ack, ibuf[MAXMSGLEN];
223*7c478bd9Sstevel@tonic-gate 	int flen, retries = 0;
224*7c478bd9Sstevel@tonic-gate 	long fbytes;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	ret = FAIL;
227*7c478bd9Sstevel@tonic-gate retry:
228*7c478bd9Sstevel@tonic-gate 	fchksum = 0xffff;
229*7c478bd9Sstevel@tonic-gate 	fbytes = 0L;
230*7c478bd9Sstevel@tonic-gate 	ack = '\0';
231*7c478bd9Sstevel@tonic-gate 	do {
232*7c478bd9Sstevel@tonic-gate 		alen = fwrblk(fn, fp1, &flen);
233*7c478bd9Sstevel@tonic-gate 		fbytes += flen;
234*7c478bd9Sstevel@tonic-gate 		if (alen <= 0) {
235*7c478bd9Sstevel@tonic-gate 			goto acct;
236*7c478bd9Sstevel@tonic-gate 		}
237*7c478bd9Sstevel@tonic-gate 	} while (!feof(fp1) && !ferror(fp1));
238*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "\nchecksum: %04x\n", fchksum);
239*7c478bd9Sstevel@tonic-gate 	if (frdmsg(ibuf, fn) != FAIL) {
240*7c478bd9Sstevel@tonic-gate 		if ((ack = ibuf[0]) == 'G')
241*7c478bd9Sstevel@tonic-gate 			ret = SUCCESS;
242*7c478bd9Sstevel@tonic-gate 		DEBUG(4, "ack - '%c'\n", ack);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate acct:
245*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "%d retries\n", retries);
246*7c478bd9Sstevel@tonic-gate 	if (ack == 'R') {
247*7c478bd9Sstevel@tonic-gate 		DEBUG(4, "RETRY:\n", 0);
248*7c478bd9Sstevel@tonic-gate 		fseek(fp1, 0L, 0);
249*7c478bd9Sstevel@tonic-gate 		retries++;
250*7c478bd9Sstevel@tonic-gate 		goto retry;
251*7c478bd9Sstevel@tonic-gate 	}
252*7c478bd9Sstevel@tonic-gate 	return ret;
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate /* max. attempts to retransmit a file: */
256*7c478bd9Sstevel@tonic-gate #define MAXRETRIES	(fbytes < 10000L ? 2 : 1)
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate frddata(fn, fp2)
259*7c478bd9Sstevel@tonic-gate register int fn;
260*7c478bd9Sstevel@tonic-gate register FILE *fp2;
261*7c478bd9Sstevel@tonic-gate {
262*7c478bd9Sstevel@tonic-gate 	register int flen;
263*7c478bd9Sstevel@tonic-gate 	register char eof;
264*7c478bd9Sstevel@tonic-gate 	char ibuf[FIBUFSIZ];
265*7c478bd9Sstevel@tonic-gate 	int ret, retries = 0;
266*7c478bd9Sstevel@tonic-gate 	long alen, fbytes;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	ret = FAIL;
269*7c478bd9Sstevel@tonic-gate retry:
270*7c478bd9Sstevel@tonic-gate 	fchksum = 0xffff;
271*7c478bd9Sstevel@tonic-gate 	fbytes = 0L;
272*7c478bd9Sstevel@tonic-gate 	do {
273*7c478bd9Sstevel@tonic-gate 		flen = frdblk(ibuf, fn, &alen);
274*7c478bd9Sstevel@tonic-gate 		if (flen < 0)
275*7c478bd9Sstevel@tonic-gate 			goto acct;
276*7c478bd9Sstevel@tonic-gate 		if (eof = flen > FIBUFSIZ)
277*7c478bd9Sstevel@tonic-gate 			flen -= FIBUFSIZ + 1;
278*7c478bd9Sstevel@tonic-gate 		fbytes += flen;
279*7c478bd9Sstevel@tonic-gate 		if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
280*7c478bd9Sstevel@tonic-gate 			goto acct;
281*7c478bd9Sstevel@tonic-gate 	} while (!eof);
282*7c478bd9Sstevel@tonic-gate 	ret = SUCCESS;
283*7c478bd9Sstevel@tonic-gate acct:
284*7c478bd9Sstevel@tonic-gate 	DEBUG(7, "%d retries\n", retries);
285*7c478bd9Sstevel@tonic-gate 	if (ret == FAIL) {
286*7c478bd9Sstevel@tonic-gate 		if (retries++ < MAXRETRIES) {
287*7c478bd9Sstevel@tonic-gate 			DEBUG(8, "send ack: 'R'\n", 0);
288*7c478bd9Sstevel@tonic-gate 			fwrmsg('R', "", fn);
289*7c478bd9Sstevel@tonic-gate 			fseek(fp2, 0L, 0);
290*7c478bd9Sstevel@tonic-gate 			DEBUG(4, "RETRY:\n", 0);
291*7c478bd9Sstevel@tonic-gate 			goto retry;
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 		DEBUG(8, "send ack: 'Q'\n", 0);
294*7c478bd9Sstevel@tonic-gate 		fwrmsg('Q', "", fn);
295*7c478bd9Sstevel@tonic-gate 	}
296*7c478bd9Sstevel@tonic-gate 	else {
297*7c478bd9Sstevel@tonic-gate 		DEBUG(8, "send ack: 'G'\n", 0);
298*7c478bd9Sstevel@tonic-gate 		fwrmsg('G', "", fn);
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate 	return ret;
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate static
304*7c478bd9Sstevel@tonic-gate frdbuf(blk, len, fn)
305*7c478bd9Sstevel@tonic-gate register char *blk;
306*7c478bd9Sstevel@tonic-gate register int len;
307*7c478bd9Sstevel@tonic-gate register int fn;
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate 	static int ret = FIBUFSIZ / 2;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	if (setjmp(Ffailbuf))
312*7c478bd9Sstevel@tonic-gate 		return FAIL;
313*7c478bd9Sstevel@tonic-gate 	(void) alarm(msgtime);
314*7c478bd9Sstevel@tonic-gate 	ret = read(fn, blk, len);
315*7c478bd9Sstevel@tonic-gate 	alarm(0);
316*7c478bd9Sstevel@tonic-gate 	return ret <= 0 ? FAIL : ret;
317*7c478bd9Sstevel@tonic-gate }
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
320*7c478bd9Sstevel@tonic-gate /* call ultouch every TC calls to either frdblk or fwrblk  */
321*7c478bd9Sstevel@tonic-gate #define TC	20
322*7c478bd9Sstevel@tonic-gate static int tc = TC;
323*7c478bd9Sstevel@tonic-gate #endif !defined(ATTSVKILL)
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate /* Byte conversion:
326*7c478bd9Sstevel@tonic-gate  *
327*7c478bd9Sstevel@tonic-gate  *   from	 pre	   to
328*7c478bd9Sstevel@tonic-gate  * 000-037	 172	 100-137
329*7c478bd9Sstevel@tonic-gate  * 040-171		 040-171
330*7c478bd9Sstevel@tonic-gate  * 172-177	 173	 072-077
331*7c478bd9Sstevel@tonic-gate  * 200-237	 174	 100-137
332*7c478bd9Sstevel@tonic-gate  * 240-371	 175	 040-171
333*7c478bd9Sstevel@tonic-gate  * 372-377	 176	 072-077
334*7c478bd9Sstevel@tonic-gate  */
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate static
337*7c478bd9Sstevel@tonic-gate fwrblk(fn, fp, lenp)
338*7c478bd9Sstevel@tonic-gate int fn;
339*7c478bd9Sstevel@tonic-gate register FILE *fp;
340*7c478bd9Sstevel@tonic-gate int *lenp;
341*7c478bd9Sstevel@tonic-gate {
342*7c478bd9Sstevel@tonic-gate 	register char *op;
343*7c478bd9Sstevel@tonic-gate 	register int c, sum, nl, len;
344*7c478bd9Sstevel@tonic-gate 	char obuf[FOBUFSIZ + 8];
345*7c478bd9Sstevel@tonic-gate 	int ret;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
348*7c478bd9Sstevel@tonic-gate 	/* call ultouch occasionally */
349*7c478bd9Sstevel@tonic-gate 	if (--tc < 0) {
350*7c478bd9Sstevel@tonic-gate 		tc = TC;
351*7c478bd9Sstevel@tonic-gate 		ultouch();
352*7c478bd9Sstevel@tonic-gate 	}
353*7c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/
354*7c478bd9Sstevel@tonic-gate 	op = obuf;
355*7c478bd9Sstevel@tonic-gate 	nl = 0;
356*7c478bd9Sstevel@tonic-gate 	len = 0;
357*7c478bd9Sstevel@tonic-gate 	sum = fchksum;
358*7c478bd9Sstevel@tonic-gate 	while ((c = getc(fp)) != EOF) {
359*7c478bd9Sstevel@tonic-gate 		len++;
360*7c478bd9Sstevel@tonic-gate 		if (sum & 0x8000) {
361*7c478bd9Sstevel@tonic-gate 			sum <<= 1;
362*7c478bd9Sstevel@tonic-gate 			sum++;
363*7c478bd9Sstevel@tonic-gate 		} else
364*7c478bd9Sstevel@tonic-gate 			sum <<= 1;
365*7c478bd9Sstevel@tonic-gate 		sum += c;
366*7c478bd9Sstevel@tonic-gate 		sum &= 0xffff;
367*7c478bd9Sstevel@tonic-gate 		if (c & 0200) {
368*7c478bd9Sstevel@tonic-gate 			c &= 0177;
369*7c478bd9Sstevel@tonic-gate 			if (c < 040) {
370*7c478bd9Sstevel@tonic-gate 				*op++ = '\174';
371*7c478bd9Sstevel@tonic-gate 				*op++ = c + 0100;
372*7c478bd9Sstevel@tonic-gate 			} else
373*7c478bd9Sstevel@tonic-gate 			if (c <= 0171) {
374*7c478bd9Sstevel@tonic-gate 				*op++ = '\175';
375*7c478bd9Sstevel@tonic-gate 				*op++ = c;
376*7c478bd9Sstevel@tonic-gate 			}
377*7c478bd9Sstevel@tonic-gate 			else {
378*7c478bd9Sstevel@tonic-gate 				*op++ = '\176';
379*7c478bd9Sstevel@tonic-gate 				*op++ = c - 0100;
380*7c478bd9Sstevel@tonic-gate 			}
381*7c478bd9Sstevel@tonic-gate 			nl += 2;
382*7c478bd9Sstevel@tonic-gate 		} else {
383*7c478bd9Sstevel@tonic-gate 			if (c < 040) {
384*7c478bd9Sstevel@tonic-gate 				*op++ = '\172';
385*7c478bd9Sstevel@tonic-gate 				*op++ = c + 0100;
386*7c478bd9Sstevel@tonic-gate 				nl += 2;
387*7c478bd9Sstevel@tonic-gate 			} else
388*7c478bd9Sstevel@tonic-gate 			if (c <= 0171) {
389*7c478bd9Sstevel@tonic-gate 				*op++ = c;
390*7c478bd9Sstevel@tonic-gate 				nl++;
391*7c478bd9Sstevel@tonic-gate 			} else {
392*7c478bd9Sstevel@tonic-gate 				*op++ = '\173';
393*7c478bd9Sstevel@tonic-gate 				*op++ = c - 0100;
394*7c478bd9Sstevel@tonic-gate 				nl += 2;
395*7c478bd9Sstevel@tonic-gate 			}
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 		if (nl >= FOBUFSIZ - 1) {
398*7c478bd9Sstevel@tonic-gate 			/*
399*7c478bd9Sstevel@tonic-gate 			 * peek at next char, see if it will fit
400*7c478bd9Sstevel@tonic-gate 			 */
401*7c478bd9Sstevel@tonic-gate 			c = getc(fp);
402*7c478bd9Sstevel@tonic-gate 			if (c == EOF)
403*7c478bd9Sstevel@tonic-gate 				break;
404*7c478bd9Sstevel@tonic-gate 			(void) ungetc(c, fp);
405*7c478bd9Sstevel@tonic-gate 			if (nl >= FOBUFSIZ || c < 040 || c > 0171)
406*7c478bd9Sstevel@tonic-gate 				goto writeit;
407*7c478bd9Sstevel@tonic-gate 		}
408*7c478bd9Sstevel@tonic-gate 	}
409*7c478bd9Sstevel@tonic-gate 	/*
410*7c478bd9Sstevel@tonic-gate 	 * At EOF - append checksum, there is space for it...
411*7c478bd9Sstevel@tonic-gate 	 */
412*7c478bd9Sstevel@tonic-gate 	sprintf(op, "\176\176%04x\r", sum);
413*7c478bd9Sstevel@tonic-gate 	nl += strlen(op);
414*7c478bd9Sstevel@tonic-gate writeit:
415*7c478bd9Sstevel@tonic-gate 	*lenp = len;
416*7c478bd9Sstevel@tonic-gate 	fchksum = sum;
417*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "%d/", len);
418*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "%d,", nl);
419*7c478bd9Sstevel@tonic-gate 	ret = write(fn, obuf, nl);
420*7c478bd9Sstevel@tonic-gate 	return ret == nl ? nl : ret < 0 ? 0 : -ret;
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate static
424*7c478bd9Sstevel@tonic-gate frdblk(ip, fn, rlen)
425*7c478bd9Sstevel@tonic-gate register char *ip;
426*7c478bd9Sstevel@tonic-gate int fn;
427*7c478bd9Sstevel@tonic-gate long *rlen;
428*7c478bd9Sstevel@tonic-gate {
429*7c478bd9Sstevel@tonic-gate 	register char *op, c;
430*7c478bd9Sstevel@tonic-gate 	register int sum, len, nl;
431*7c478bd9Sstevel@tonic-gate 	char buf[5], *erbp = ip;
432*7c478bd9Sstevel@tonic-gate 	int i;
433*7c478bd9Sstevel@tonic-gate 	static char special = 0;
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
436*7c478bd9Sstevel@tonic-gate 	/* call ultouch occasionally */
437*7c478bd9Sstevel@tonic-gate 	if (--tc < 0) {
438*7c478bd9Sstevel@tonic-gate 		tc = TC;
439*7c478bd9Sstevel@tonic-gate 		ultouch();
440*7c478bd9Sstevel@tonic-gate 	}
441*7c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/
442*7c478bd9Sstevel@tonic-gate 	if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
443*7c478bd9Sstevel@tonic-gate 		*rlen = 0;
444*7c478bd9Sstevel@tonic-gate 		goto dcorr;
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 	*rlen = len;
447*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "%d/", len);
448*7c478bd9Sstevel@tonic-gate 	op = ip;
449*7c478bd9Sstevel@tonic-gate 	nl = 0;
450*7c478bd9Sstevel@tonic-gate 	sum = fchksum;
451*7c478bd9Sstevel@tonic-gate 	do {
452*7c478bd9Sstevel@tonic-gate 		if ((*ip &= 0177) >= '\172') {
453*7c478bd9Sstevel@tonic-gate 			if (special) {
454*7c478bd9Sstevel@tonic-gate 				DEBUG(8, "%d", nl);
455*7c478bd9Sstevel@tonic-gate 				special = 0;
456*7c478bd9Sstevel@tonic-gate 				op = buf;
457*7c478bd9Sstevel@tonic-gate 				if (*ip++ != '\176' || (i = --len) > 5)
458*7c478bd9Sstevel@tonic-gate 					goto dcorr;
459*7c478bd9Sstevel@tonic-gate 				while (i--)
460*7c478bd9Sstevel@tonic-gate 					*op++ = *ip++ & 0177;
461*7c478bd9Sstevel@tonic-gate 				while (len < 5) {
462*7c478bd9Sstevel@tonic-gate 					i = frdbuf(&buf[len], 5 - len, fn);
463*7c478bd9Sstevel@tonic-gate 					if (i == FAIL) {
464*7c478bd9Sstevel@tonic-gate 						len = FAIL;
465*7c478bd9Sstevel@tonic-gate 						goto dcorr;
466*7c478bd9Sstevel@tonic-gate 					}
467*7c478bd9Sstevel@tonic-gate 					DEBUG(8, ",%d", i);
468*7c478bd9Sstevel@tonic-gate 					len += i;
469*7c478bd9Sstevel@tonic-gate 					*rlen += i;
470*7c478bd9Sstevel@tonic-gate 					while (i--)
471*7c478bd9Sstevel@tonic-gate 						*op++ &= 0177;
472*7c478bd9Sstevel@tonic-gate 				}
473*7c478bd9Sstevel@tonic-gate 				if (buf[4] != '\r')
474*7c478bd9Sstevel@tonic-gate 					goto dcorr;
475*7c478bd9Sstevel@tonic-gate 				sscanf(buf, "%4x", &fchksum);
476*7c478bd9Sstevel@tonic-gate 				DEBUG(8, "\nchecksum: %04x\n", sum);
477*7c478bd9Sstevel@tonic-gate 				if (fchksum == sum)
478*7c478bd9Sstevel@tonic-gate 					return FIBUFSIZ + 1 + nl;
479*7c478bd9Sstevel@tonic-gate 				else {
480*7c478bd9Sstevel@tonic-gate 					DEBUG(8, "\n", 0);
481*7c478bd9Sstevel@tonic-gate 					DEBUG(4, "Bad checksum\n", 0);
482*7c478bd9Sstevel@tonic-gate 					return FAIL;
483*7c478bd9Sstevel@tonic-gate 				}
484*7c478bd9Sstevel@tonic-gate 			}
485*7c478bd9Sstevel@tonic-gate 			special = *ip++;
486*7c478bd9Sstevel@tonic-gate 		} else {
487*7c478bd9Sstevel@tonic-gate 			if (*ip < '\040') {
488*7c478bd9Sstevel@tonic-gate 				/* error: shouldn't get control chars */
489*7c478bd9Sstevel@tonic-gate 				goto dcorr;
490*7c478bd9Sstevel@tonic-gate 			}
491*7c478bd9Sstevel@tonic-gate 			switch (special) {
492*7c478bd9Sstevel@tonic-gate 			case 0:
493*7c478bd9Sstevel@tonic-gate 				c = *ip++;
494*7c478bd9Sstevel@tonic-gate 				break;
495*7c478bd9Sstevel@tonic-gate 			case '\172':
496*7c478bd9Sstevel@tonic-gate 				c = *ip++ - 0100;
497*7c478bd9Sstevel@tonic-gate 				break;
498*7c478bd9Sstevel@tonic-gate 			case '\173':
499*7c478bd9Sstevel@tonic-gate 				c = *ip++ + 0100;
500*7c478bd9Sstevel@tonic-gate 				break;
501*7c478bd9Sstevel@tonic-gate 			case '\174':
502*7c478bd9Sstevel@tonic-gate 				c = *ip++ + 0100;
503*7c478bd9Sstevel@tonic-gate 				break;
504*7c478bd9Sstevel@tonic-gate 			case '\175':
505*7c478bd9Sstevel@tonic-gate 				c = *ip++ + 0200;
506*7c478bd9Sstevel@tonic-gate 				break;
507*7c478bd9Sstevel@tonic-gate 			case '\176':
508*7c478bd9Sstevel@tonic-gate 				c = *ip++ + 0300;
509*7c478bd9Sstevel@tonic-gate 				break;
510*7c478bd9Sstevel@tonic-gate 			}
511*7c478bd9Sstevel@tonic-gate 			*op++ = c;
512*7c478bd9Sstevel@tonic-gate 			if (sum & 0x8000) {
513*7c478bd9Sstevel@tonic-gate 				sum <<= 1;
514*7c478bd9Sstevel@tonic-gate 				sum++;
515*7c478bd9Sstevel@tonic-gate 			} else
516*7c478bd9Sstevel@tonic-gate 				sum <<= 1;
517*7c478bd9Sstevel@tonic-gate 			sum += c & 0377;
518*7c478bd9Sstevel@tonic-gate 			sum &= 0xffff;
519*7c478bd9Sstevel@tonic-gate 			special = 0;
520*7c478bd9Sstevel@tonic-gate 			nl++;
521*7c478bd9Sstevel@tonic-gate 		}
522*7c478bd9Sstevel@tonic-gate 	} while (--len);
523*7c478bd9Sstevel@tonic-gate 	fchksum = sum;
524*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "%d,", nl);
525*7c478bd9Sstevel@tonic-gate 	return nl;
526*7c478bd9Sstevel@tonic-gate dcorr:
527*7c478bd9Sstevel@tonic-gate 	DEBUG(8, "\n", 0);
528*7c478bd9Sstevel@tonic-gate 	DEBUG(4, "Data corrupted\n", 0);
529*7c478bd9Sstevel@tonic-gate 	while (len != FAIL) {
530*7c478bd9Sstevel@tonic-gate 		if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
531*7c478bd9Sstevel@tonic-gate 			*rlen += len;
532*7c478bd9Sstevel@tonic-gate 	}
533*7c478bd9Sstevel@tonic-gate 	return FAIL;
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate #endif /* F_PROTOCOL */
536