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*462be471Sceastha * 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 #pragma ident "%Z%%M% %I% %E% SMI"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * flow control protocol.
327c478bd9Sstevel@tonic-gate *
337c478bd9Sstevel@tonic-gate * This protocol relies on flow control of the data stream.
347c478bd9Sstevel@tonic-gate * It is meant for working over links that can (almost) be
357c478bd9Sstevel@tonic-gate * guaranteed to be errorfree, specifically X.25/PAD links.
367c478bd9Sstevel@tonic-gate * A sumcheck is carried out over a whole file only. If a
377c478bd9Sstevel@tonic-gate * transport fails the receiver can request retransmission(s).
387c478bd9Sstevel@tonic-gate * This protocol uses a 7-bit datapath only, so it can be
397c478bd9Sstevel@tonic-gate * used on links that are not 8-bit transparent.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * When using this protocol with an X.25 PAD:
427c478bd9Sstevel@tonic-gate * Although this protocol uses no control chars except CR,
437c478bd9Sstevel@tonic-gate * control chars NULL and ^P are used before this protocol
447c478bd9Sstevel@tonic-gate * is started; since ^P is the default char for accessing
457c478bd9Sstevel@tonic-gate * PAD X.28 command mode, be sure to disable that access
467c478bd9Sstevel@tonic-gate * (PAD par 1). Also make sure both flow control pars
477c478bd9Sstevel@tonic-gate * (5 and 12) are set. The CR used in this proto is meant
487c478bd9Sstevel@tonic-gate * to trigger packet transmission, hence par 3 should be
497c478bd9Sstevel@tonic-gate * set to 2; a good value for the Idle Timer (par 4) is 10.
507c478bd9Sstevel@tonic-gate * All other pars should be set to 0.
517c478bd9Sstevel@tonic-gate *
527c478bd9Sstevel@tonic-gate * Normally a calling site will take care of setting the
537c478bd9Sstevel@tonic-gate * local PAD pars via an X.28 command and those of the remote
547c478bd9Sstevel@tonic-gate * PAD via an X.29 command, unless the remote site has a
557c478bd9Sstevel@tonic-gate * special channel assigned for this protocol with the proper
567c478bd9Sstevel@tonic-gate * par settings.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate * Additional comments for hosts with direct X.25 access:
597c478bd9Sstevel@tonic-gate * - the global variable IsTcpIp, when set, excludes the ioctl's,
607c478bd9Sstevel@tonic-gate * so the same binary can run on X.25 and non-X.25 hosts;
617c478bd9Sstevel@tonic-gate * - reads are done in small chunks, which can be smaller than
627c478bd9Sstevel@tonic-gate * the packet size; your X.25 driver must support that.
637c478bd9Sstevel@tonic-gate *
647c478bd9Sstevel@tonic-gate *
657c478bd9Sstevel@tonic-gate * Author:
667c478bd9Sstevel@tonic-gate * Piet Beertema, CWI, Amsterdam, Sep 1984
677c478bd9Sstevel@tonic-gate * Modified for X.25 hosts:
687c478bd9Sstevel@tonic-gate * Robert Elz, Melbourne Univ, Mar 1985
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate #include "uucp.h"
727c478bd9Sstevel@tonic-gate #ifdef F_PROTOCOL
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate extern unsigned msgtime;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /* privates */
777c478bd9Sstevel@tonic-gate static int frdblk(), fwrblk();
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate #define FIBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size,
807c478bd9Sstevel@tonic-gate * but see comment above
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate #define FOBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size;
847c478bd9Sstevel@tonic-gate * otherwise make as large as feasible to reduce
857c478bd9Sstevel@tonic-gate * number of write system calls
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate #ifndef MAXMSGLEN
897c478bd9Sstevel@tonic-gate #define MAXMSGLEN BUFSIZ
90*462be471Sceastha #endif /* MAXMSGLEN */
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static int fchksum;
937c478bd9Sstevel@tonic-gate static jmp_buf Ffailbuf;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate /* ARGSUSED */
967c478bd9Sstevel@tonic-gate static void
falarm(sig)977c478bd9Sstevel@tonic-gate falarm(sig)
987c478bd9Sstevel@tonic-gate int sig;
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate signal(SIGALRM, falarm);
1017c478bd9Sstevel@tonic-gate longjmp(Ffailbuf, 1);
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate static void (*fsig)();
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate static int ioctlok;
1077c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
1087c478bd9Sstevel@tonic-gate static struct termio ttbuf;
1097c478bd9Sstevel@tonic-gate #else
1107c478bd9Sstevel@tonic-gate static struct sgttyb ttbuf;
1117c478bd9Sstevel@tonic-gate #endif
1127c478bd9Sstevel@tonic-gate
113*462be471Sceastha int
fturnon(void)114*462be471Sceastha fturnon(void)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate int ret;
1177c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
1187c478bd9Sstevel@tonic-gate struct termio save_ttbuf;
1197c478bd9Sstevel@tonic-gate #else
1207c478bd9Sstevel@tonic-gate struct sgttyb save_ttbuf;
1217c478bd9Sstevel@tonic-gate #endif
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
1247c478bd9Sstevel@tonic-gate if (ioctl(Ifn, TCGETA, &ttbuf) >= 0) {
1257c478bd9Sstevel@tonic-gate ioctlok = 1;
1267c478bd9Sstevel@tonic-gate save_ttbuf = ttbuf;
1277c478bd9Sstevel@tonic-gate ioctl(Ifn, TCGETA, &ttbuf);
1287c478bd9Sstevel@tonic-gate ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
1297c478bd9Sstevel@tonic-gate ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
1307c478bd9Sstevel@tonic-gate ttbuf.c_cc[VTIME] = 5;
1317c478bd9Sstevel@tonic-gate ret = ioctl(Ifn, TCSETA, &ttbuf);
1327c478bd9Sstevel@tonic-gate ASSERT(ret >= 0, "STTY FAILED", "", ret);
1337c478bd9Sstevel@tonic-gate ttbuf = save_ttbuf;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate #else /* !ATTSVTTY */
1367c478bd9Sstevel@tonic-gate if (ioctl(Ifn, TIOCGETP, &ttbuf) >= 0) {
1377c478bd9Sstevel@tonic-gate ioctlok = 1;
1387c478bd9Sstevel@tonic-gate save_ttbuf = ttbuf;
1397c478bd9Sstevel@tonic-gate ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
1407c478bd9Sstevel@tonic-gate ret = ioctl(Ifn, TIOCSETP, &ttbuf);
1417c478bd9Sstevel@tonic-gate ASSERT(ret >= 0, "STTY FAILED", "", ret);
1427c478bd9Sstevel@tonic-gate ttbuf = save_ttbuf;
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate #endif /* ATTSVTTY */
1457c478bd9Sstevel@tonic-gate fsig = signal(SIGALRM, falarm);
1467c478bd9Sstevel@tonic-gate /* give the other side time to perform its ioctl;
1477c478bd9Sstevel@tonic-gate * otherwise it may flush out the first data this
1487c478bd9Sstevel@tonic-gate * side is about to send.
1497c478bd9Sstevel@tonic-gate */
1507c478bd9Sstevel@tonic-gate sleep(2);
1517c478bd9Sstevel@tonic-gate return SUCCESS;
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate
154*462be471Sceastha int
fturnoff(void)155*462be471Sceastha fturnoff(void)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate if (ioctlok) {
1587c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
1597c478bd9Sstevel@tonic-gate (void) ioctl(Ifn, TCSETA, &ttbuf);
1607c478bd9Sstevel@tonic-gate #else
1617c478bd9Sstevel@tonic-gate (void) ioctl(Ifn, TIOCSETP, &ttbuf);
1627c478bd9Sstevel@tonic-gate #endif
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, fsig);
1657c478bd9Sstevel@tonic-gate sleep(2);
1667c478bd9Sstevel@tonic-gate return SUCCESS;
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate
169*462be471Sceastha int
fwrmsg(type,str,fn)1707c478bd9Sstevel@tonic-gate fwrmsg(type, str, fn)
171*462be471Sceastha char *str;
1727c478bd9Sstevel@tonic-gate int fn;
1737c478bd9Sstevel@tonic-gate char type;
1747c478bd9Sstevel@tonic-gate {
175*462be471Sceastha char *s;
1767c478bd9Sstevel@tonic-gate char bufr[MAXMSGLEN];
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate s = bufr;
1797c478bd9Sstevel@tonic-gate *s++ = type;
1807c478bd9Sstevel@tonic-gate while (*str)
1817c478bd9Sstevel@tonic-gate *s++ = *str++;
1827c478bd9Sstevel@tonic-gate if (*(s-1) == '\n')
1837c478bd9Sstevel@tonic-gate s--;
1847c478bd9Sstevel@tonic-gate *s++ = '\r';
1857c478bd9Sstevel@tonic-gate *s = 0;
1867c478bd9Sstevel@tonic-gate (void) write(fn, bufr, s - bufr);
1877c478bd9Sstevel@tonic-gate return SUCCESS;
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
190*462be471Sceastha int
frdmsg(str,fn)1917c478bd9Sstevel@tonic-gate frdmsg(str, fn)
192*462be471Sceastha char *str;
193*462be471Sceastha int fn;
1947c478bd9Sstevel@tonic-gate {
195*462be471Sceastha char *smax;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate if (setjmp(Ffailbuf))
1987c478bd9Sstevel@tonic-gate return FAIL;
1997c478bd9Sstevel@tonic-gate smax = str + MAXMSGLEN - 1;
2007c478bd9Sstevel@tonic-gate (void) alarm(msgtime);
2017c478bd9Sstevel@tonic-gate for (;;) {
2027c478bd9Sstevel@tonic-gate if (read(fn, str, 1) <= 0)
2037c478bd9Sstevel@tonic-gate goto msgerr;
2047c478bd9Sstevel@tonic-gate *str &= 0177;
2057c478bd9Sstevel@tonic-gate if (*str == '\r')
2067c478bd9Sstevel@tonic-gate break;
2077c478bd9Sstevel@tonic-gate if (*str < ' ') {
2087c478bd9Sstevel@tonic-gate continue;
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate if (str++ >= smax)
2117c478bd9Sstevel@tonic-gate goto msgerr;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate *str = '\0';
2147c478bd9Sstevel@tonic-gate (void) alarm(0);
2157c478bd9Sstevel@tonic-gate return SUCCESS;
2167c478bd9Sstevel@tonic-gate msgerr:
2177c478bd9Sstevel@tonic-gate (void) alarm(0);
2187c478bd9Sstevel@tonic-gate return FAIL;
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate
221*462be471Sceastha int
fwrdata(fp1,fn)2227c478bd9Sstevel@tonic-gate fwrdata(fp1, fn)
2237c478bd9Sstevel@tonic-gate FILE *fp1;
2247c478bd9Sstevel@tonic-gate int fn;
2257c478bd9Sstevel@tonic-gate {
226*462be471Sceastha int alen, ret;
2277c478bd9Sstevel@tonic-gate char ack, ibuf[MAXMSGLEN];
2287c478bd9Sstevel@tonic-gate int flen, retries = 0;
2297c478bd9Sstevel@tonic-gate long fbytes;
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate ret = FAIL;
2327c478bd9Sstevel@tonic-gate retry:
2337c478bd9Sstevel@tonic-gate fchksum = 0xffff;
2347c478bd9Sstevel@tonic-gate fbytes = 0L;
2357c478bd9Sstevel@tonic-gate ack = '\0';
2367c478bd9Sstevel@tonic-gate do {
2377c478bd9Sstevel@tonic-gate alen = fwrblk(fn, fp1, &flen);
2387c478bd9Sstevel@tonic-gate fbytes += flen;
2397c478bd9Sstevel@tonic-gate if (alen <= 0) {
2407c478bd9Sstevel@tonic-gate goto acct;
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate } while (!feof(fp1) && !ferror(fp1));
2437c478bd9Sstevel@tonic-gate DEBUG(8, "\nchecksum: %04x\n", fchksum);
2447c478bd9Sstevel@tonic-gate if (frdmsg(ibuf, fn) != FAIL) {
2457c478bd9Sstevel@tonic-gate if ((ack = ibuf[0]) == 'G')
2467c478bd9Sstevel@tonic-gate ret = SUCCESS;
2477c478bd9Sstevel@tonic-gate DEBUG(4, "ack - '%c'\n", ack);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate acct:
2507c478bd9Sstevel@tonic-gate DEBUG(7, "%d retries\n", retries);
2517c478bd9Sstevel@tonic-gate if (ack == 'R') {
2527c478bd9Sstevel@tonic-gate DEBUG(4, "RETRY:\n", 0);
2537c478bd9Sstevel@tonic-gate fseek(fp1, 0L, 0);
2547c478bd9Sstevel@tonic-gate retries++;
2557c478bd9Sstevel@tonic-gate goto retry;
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate return ret;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate /* max. attempts to retransmit a file: */
2617c478bd9Sstevel@tonic-gate #define MAXRETRIES (fbytes < 10000L ? 2 : 1)
2627c478bd9Sstevel@tonic-gate
263*462be471Sceastha int
frddata(fn,fp2)2647c478bd9Sstevel@tonic-gate frddata(fn, fp2)
265*462be471Sceastha int fn;
266*462be471Sceastha FILE *fp2;
2677c478bd9Sstevel@tonic-gate {
268*462be471Sceastha int flen;
269*462be471Sceastha char eof;
2707c478bd9Sstevel@tonic-gate char ibuf[FIBUFSIZ];
2717c478bd9Sstevel@tonic-gate int ret, retries = 0;
2727c478bd9Sstevel@tonic-gate long alen, fbytes;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate ret = FAIL;
2757c478bd9Sstevel@tonic-gate retry:
2767c478bd9Sstevel@tonic-gate fchksum = 0xffff;
2777c478bd9Sstevel@tonic-gate fbytes = 0L;
2787c478bd9Sstevel@tonic-gate do {
2797c478bd9Sstevel@tonic-gate flen = frdblk(ibuf, fn, &alen);
2807c478bd9Sstevel@tonic-gate if (flen < 0)
2817c478bd9Sstevel@tonic-gate goto acct;
2827c478bd9Sstevel@tonic-gate if (eof = flen > FIBUFSIZ)
2837c478bd9Sstevel@tonic-gate flen -= FIBUFSIZ + 1;
2847c478bd9Sstevel@tonic-gate fbytes += flen;
2857c478bd9Sstevel@tonic-gate if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
2867c478bd9Sstevel@tonic-gate goto acct;
2877c478bd9Sstevel@tonic-gate } while (!eof);
2887c478bd9Sstevel@tonic-gate ret = SUCCESS;
2897c478bd9Sstevel@tonic-gate acct:
2907c478bd9Sstevel@tonic-gate DEBUG(7, "%d retries\n", retries);
2917c478bd9Sstevel@tonic-gate if (ret == FAIL) {
2927c478bd9Sstevel@tonic-gate if (retries++ < MAXRETRIES) {
2937c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'R'\n", 0);
2947c478bd9Sstevel@tonic-gate fwrmsg('R', "", fn);
2957c478bd9Sstevel@tonic-gate fseek(fp2, 0L, 0);
2967c478bd9Sstevel@tonic-gate DEBUG(4, "RETRY:\n", 0);
2977c478bd9Sstevel@tonic-gate goto retry;
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'Q'\n", 0);
3007c478bd9Sstevel@tonic-gate fwrmsg('Q', "", fn);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate else {
3037c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'G'\n", 0);
3047c478bd9Sstevel@tonic-gate fwrmsg('G', "", fn);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate return ret;
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
309*462be471Sceastha static int
frdbuf(blk,len,fn)3107c478bd9Sstevel@tonic-gate frdbuf(blk, len, fn)
311*462be471Sceastha char *blk;
312*462be471Sceastha int len;
313*462be471Sceastha int fn;
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate static int ret = FIBUFSIZ / 2;
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate if (setjmp(Ffailbuf))
3187c478bd9Sstevel@tonic-gate return FAIL;
3197c478bd9Sstevel@tonic-gate (void) alarm(msgtime);
3207c478bd9Sstevel@tonic-gate ret = read(fn, blk, len);
3217c478bd9Sstevel@tonic-gate alarm(0);
3227c478bd9Sstevel@tonic-gate return ret <= 0 ? FAIL : ret;
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
3267c478bd9Sstevel@tonic-gate /* call ultouch every TC calls to either frdblk or fwrblk */
3277c478bd9Sstevel@tonic-gate #define TC 20
3287c478bd9Sstevel@tonic-gate static int tc = TC;
329*462be471Sceastha #endif /* !defined(ATTSVKILL) */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /* Byte conversion:
3327c478bd9Sstevel@tonic-gate *
3337c478bd9Sstevel@tonic-gate * from pre to
3347c478bd9Sstevel@tonic-gate * 000-037 172 100-137
3357c478bd9Sstevel@tonic-gate * 040-171 040-171
3367c478bd9Sstevel@tonic-gate * 172-177 173 072-077
3377c478bd9Sstevel@tonic-gate * 200-237 174 100-137
3387c478bd9Sstevel@tonic-gate * 240-371 175 040-171
3397c478bd9Sstevel@tonic-gate * 372-377 176 072-077
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate
342*462be471Sceastha static int
fwrblk(fn,fp,lenp)3437c478bd9Sstevel@tonic-gate fwrblk(fn, fp, lenp)
3447c478bd9Sstevel@tonic-gate int fn;
345*462be471Sceastha FILE *fp;
3467c478bd9Sstevel@tonic-gate int *lenp;
3477c478bd9Sstevel@tonic-gate {
348*462be471Sceastha char *op;
349*462be471Sceastha int c, sum, nl, len;
3507c478bd9Sstevel@tonic-gate char obuf[FOBUFSIZ + 8];
3517c478bd9Sstevel@tonic-gate int ret;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
3547c478bd9Sstevel@tonic-gate /* call ultouch occasionally */
3557c478bd9Sstevel@tonic-gate if (--tc < 0) {
3567c478bd9Sstevel@tonic-gate tc = TC;
3577c478bd9Sstevel@tonic-gate ultouch();
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/
3607c478bd9Sstevel@tonic-gate op = obuf;
3617c478bd9Sstevel@tonic-gate nl = 0;
3627c478bd9Sstevel@tonic-gate len = 0;
3637c478bd9Sstevel@tonic-gate sum = fchksum;
3647c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) {
3657c478bd9Sstevel@tonic-gate len++;
3667c478bd9Sstevel@tonic-gate if (sum & 0x8000) {
3677c478bd9Sstevel@tonic-gate sum <<= 1;
3687c478bd9Sstevel@tonic-gate sum++;
3697c478bd9Sstevel@tonic-gate } else
3707c478bd9Sstevel@tonic-gate sum <<= 1;
3717c478bd9Sstevel@tonic-gate sum += c;
3727c478bd9Sstevel@tonic-gate sum &= 0xffff;
3737c478bd9Sstevel@tonic-gate if (c & 0200) {
3747c478bd9Sstevel@tonic-gate c &= 0177;
3757c478bd9Sstevel@tonic-gate if (c < 040) {
3767c478bd9Sstevel@tonic-gate *op++ = '\174';
3777c478bd9Sstevel@tonic-gate *op++ = c + 0100;
3787c478bd9Sstevel@tonic-gate } else
3797c478bd9Sstevel@tonic-gate if (c <= 0171) {
3807c478bd9Sstevel@tonic-gate *op++ = '\175';
3817c478bd9Sstevel@tonic-gate *op++ = c;
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate else {
3847c478bd9Sstevel@tonic-gate *op++ = '\176';
3857c478bd9Sstevel@tonic-gate *op++ = c - 0100;
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate nl += 2;
3887c478bd9Sstevel@tonic-gate } else {
3897c478bd9Sstevel@tonic-gate if (c < 040) {
3907c478bd9Sstevel@tonic-gate *op++ = '\172';
3917c478bd9Sstevel@tonic-gate *op++ = c + 0100;
3927c478bd9Sstevel@tonic-gate nl += 2;
3937c478bd9Sstevel@tonic-gate } else
3947c478bd9Sstevel@tonic-gate if (c <= 0171) {
3957c478bd9Sstevel@tonic-gate *op++ = c;
3967c478bd9Sstevel@tonic-gate nl++;
3977c478bd9Sstevel@tonic-gate } else {
3987c478bd9Sstevel@tonic-gate *op++ = '\173';
3997c478bd9Sstevel@tonic-gate *op++ = c - 0100;
4007c478bd9Sstevel@tonic-gate nl += 2;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate if (nl >= FOBUFSIZ - 1) {
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate * peek at next char, see if it will fit
4067c478bd9Sstevel@tonic-gate */
4077c478bd9Sstevel@tonic-gate c = getc(fp);
4087c478bd9Sstevel@tonic-gate if (c == EOF)
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate (void) ungetc(c, fp);
4117c478bd9Sstevel@tonic-gate if (nl >= FOBUFSIZ || c < 040 || c > 0171)
4127c478bd9Sstevel@tonic-gate goto writeit;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate * At EOF - append checksum, there is space for it...
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate sprintf(op, "\176\176%04x\r", sum);
4197c478bd9Sstevel@tonic-gate nl += strlen(op);
4207c478bd9Sstevel@tonic-gate writeit:
4217c478bd9Sstevel@tonic-gate *lenp = len;
4227c478bd9Sstevel@tonic-gate fchksum = sum;
4237c478bd9Sstevel@tonic-gate DEBUG(8, "%d/", len);
4247c478bd9Sstevel@tonic-gate DEBUG(8, "%d,", nl);
4257c478bd9Sstevel@tonic-gate ret = write(fn, obuf, nl);
4267c478bd9Sstevel@tonic-gate return ret == nl ? nl : ret < 0 ? 0 : -ret;
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
429*462be471Sceastha static int
frdblk(ip,fn,rlen)4307c478bd9Sstevel@tonic-gate frdblk(ip, fn, rlen)
431*462be471Sceastha char *ip;
4327c478bd9Sstevel@tonic-gate int fn;
4337c478bd9Sstevel@tonic-gate long *rlen;
4347c478bd9Sstevel@tonic-gate {
435*462be471Sceastha char *op, c;
436*462be471Sceastha int sum, len, nl;
4377c478bd9Sstevel@tonic-gate char buf[5], *erbp = ip;
4387c478bd9Sstevel@tonic-gate int i;
4397c478bd9Sstevel@tonic-gate static char special = 0;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL)
4427c478bd9Sstevel@tonic-gate /* call ultouch occasionally */
4437c478bd9Sstevel@tonic-gate if (--tc < 0) {
4447c478bd9Sstevel@tonic-gate tc = TC;
4457c478bd9Sstevel@tonic-gate ultouch();
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/
4487c478bd9Sstevel@tonic-gate if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
4497c478bd9Sstevel@tonic-gate *rlen = 0;
4507c478bd9Sstevel@tonic-gate goto dcorr;
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate *rlen = len;
4537c478bd9Sstevel@tonic-gate DEBUG(8, "%d/", len);
4547c478bd9Sstevel@tonic-gate op = ip;
4557c478bd9Sstevel@tonic-gate nl = 0;
4567c478bd9Sstevel@tonic-gate sum = fchksum;
4577c478bd9Sstevel@tonic-gate do {
4587c478bd9Sstevel@tonic-gate if ((*ip &= 0177) >= '\172') {
4597c478bd9Sstevel@tonic-gate if (special) {
4607c478bd9Sstevel@tonic-gate DEBUG(8, "%d", nl);
4617c478bd9Sstevel@tonic-gate special = 0;
4627c478bd9Sstevel@tonic-gate op = buf;
4637c478bd9Sstevel@tonic-gate if (*ip++ != '\176' || (i = --len) > 5)
4647c478bd9Sstevel@tonic-gate goto dcorr;
4657c478bd9Sstevel@tonic-gate while (i--)
4667c478bd9Sstevel@tonic-gate *op++ = *ip++ & 0177;
4677c478bd9Sstevel@tonic-gate while (len < 5) {
4687c478bd9Sstevel@tonic-gate i = frdbuf(&buf[len], 5 - len, fn);
4697c478bd9Sstevel@tonic-gate if (i == FAIL) {
4707c478bd9Sstevel@tonic-gate len = FAIL;
4717c478bd9Sstevel@tonic-gate goto dcorr;
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate DEBUG(8, ",%d", i);
4747c478bd9Sstevel@tonic-gate len += i;
4757c478bd9Sstevel@tonic-gate *rlen += i;
4767c478bd9Sstevel@tonic-gate while (i--)
4777c478bd9Sstevel@tonic-gate *op++ &= 0177;
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate if (buf[4] != '\r')
4807c478bd9Sstevel@tonic-gate goto dcorr;
4817c478bd9Sstevel@tonic-gate sscanf(buf, "%4x", &fchksum);
4827c478bd9Sstevel@tonic-gate DEBUG(8, "\nchecksum: %04x\n", sum);
4837c478bd9Sstevel@tonic-gate if (fchksum == sum)
4847c478bd9Sstevel@tonic-gate return FIBUFSIZ + 1 + nl;
4857c478bd9Sstevel@tonic-gate else {
4867c478bd9Sstevel@tonic-gate DEBUG(8, "\n", 0);
4877c478bd9Sstevel@tonic-gate DEBUG(4, "Bad checksum\n", 0);
4887c478bd9Sstevel@tonic-gate return FAIL;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate special = *ip++;
4927c478bd9Sstevel@tonic-gate } else {
4937c478bd9Sstevel@tonic-gate if (*ip < '\040') {
4947c478bd9Sstevel@tonic-gate /* error: shouldn't get control chars */
4957c478bd9Sstevel@tonic-gate goto dcorr;
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate switch (special) {
4987c478bd9Sstevel@tonic-gate case 0:
4997c478bd9Sstevel@tonic-gate c = *ip++;
5007c478bd9Sstevel@tonic-gate break;
5017c478bd9Sstevel@tonic-gate case '\172':
5027c478bd9Sstevel@tonic-gate c = *ip++ - 0100;
5037c478bd9Sstevel@tonic-gate break;
5047c478bd9Sstevel@tonic-gate case '\173':
5057c478bd9Sstevel@tonic-gate c = *ip++ + 0100;
5067c478bd9Sstevel@tonic-gate break;
5077c478bd9Sstevel@tonic-gate case '\174':
5087c478bd9Sstevel@tonic-gate c = *ip++ + 0100;
5097c478bd9Sstevel@tonic-gate break;
5107c478bd9Sstevel@tonic-gate case '\175':
5117c478bd9Sstevel@tonic-gate c = *ip++ + 0200;
5127c478bd9Sstevel@tonic-gate break;
5137c478bd9Sstevel@tonic-gate case '\176':
5147c478bd9Sstevel@tonic-gate c = *ip++ + 0300;
5157c478bd9Sstevel@tonic-gate break;
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate *op++ = c;
5187c478bd9Sstevel@tonic-gate if (sum & 0x8000) {
5197c478bd9Sstevel@tonic-gate sum <<= 1;
5207c478bd9Sstevel@tonic-gate sum++;
5217c478bd9Sstevel@tonic-gate } else
5227c478bd9Sstevel@tonic-gate sum <<= 1;
5237c478bd9Sstevel@tonic-gate sum += c & 0377;
5247c478bd9Sstevel@tonic-gate sum &= 0xffff;
5257c478bd9Sstevel@tonic-gate special = 0;
5267c478bd9Sstevel@tonic-gate nl++;
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate } while (--len);
5297c478bd9Sstevel@tonic-gate fchksum = sum;
5307c478bd9Sstevel@tonic-gate DEBUG(8, "%d,", nl);
5317c478bd9Sstevel@tonic-gate return nl;
5327c478bd9Sstevel@tonic-gate dcorr:
5337c478bd9Sstevel@tonic-gate DEBUG(8, "\n", 0);
5347c478bd9Sstevel@tonic-gate DEBUG(4, "Data corrupted\n", 0);
5357c478bd9Sstevel@tonic-gate while (len != FAIL) {
5367c478bd9Sstevel@tonic-gate if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
5377c478bd9Sstevel@tonic-gate *rlen += len;
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate return FAIL;
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate #endif /* F_PROTOCOL */
542