static char sccsid
[] = "@(#)fio.c 5.3 (Berkeley) %G%";
* This protocol relies on flow control of the data stream.
* It is meant for working over links that can (almost) be
* guaranteed to be errorfree, specifically X.25/PAD links.
* A sumcheck is carried out over a whole file only. If a
* transport fails the receiver can request retransmission(s).
* This protocol uses a 7-bit datapath only, so it can be
* used on links that are not 8-bit transparent.
* When using this protocol with an X.25 PAD:
* Although this protocol uses no control chars except CR,
* control chars NULL and ^P are used before this protocol
* is started; since ^P is the default char for accessing
* PAD X.28 command mode, be sure to disable that access
* (PAD par 1). Also make sure both flow control pars
* (5 and 12) are set. The CR used in this proto is meant
* to trigger packet transmission, hence par 3 should be
* set to 2; a good value for the Idle Timer (par 4) is 10.
* All other pars should be set to 0.
* Normally a calling site will take care of setting the
* local PAD pars via an X.28 command and those of the remote
* PAD via an X.29 command, unless the remote site has a
* special channel assigned for this protocol with the proper
* Additional comments for hosts with direct X.25 access:
* - the global variable IsTcpIp, when set, excludes the ioctl's,
* so the same binary can run on X.25 and non-X.25 hosts;
* - reads are done in small chunks, which can be smaller than
* the packet size; your X.25 driver must support that.
* Piet Beertema, CWI, Amsterdam, Sep 1984
* Modified for X.25 hosts:
* Robert Elz, Melbourne Univ, Mar 1985
#define FIBUFSIZ 256 /* for X.25 interfaces: set equal to packet size,
#define FOBUFSIZ 256 /* for X.25 interfaces: set equal to packet size;
* otherwise make as large as feasible to reduce
* number of write system calls
ioctl(Ifn
, TCGETA
, &ttbuf
);
ttbuf
.c_iflag
= IXOFF
|IXON
|ISTRIP
;
ttbuf
.c_cc
[VMIN
] = FIBUFSIZ
> 64 ? 64 : FIBUFSIZ
;
ttbuf
.sg_flags
= ANYP
|CBREAK
|TANDEM
;
ret
= ioctl(Ifn
, TCSETA
, &ttbuf
);
ASSERT(ret
>= 0, "STTY FAILED", "", ret
);
fsig
= signal(SIGALRM
, falarm
);
/* give the other side time to perform its ioctl;
* otherwise it may flush out the first data this
(void) signal(SIGALRM
, fsig
);
(void) write(fn
, bufr
, s
- bufr
);
smax
= str
+ MAXMSGLEN
- 1;
(void) alarm(2*MAXMSGTIME
);
if (read(fn
, str
, 1) <= 0)
char ack
, ibuf
[MAXMSGLEN
];
int flen
, mil
, retries
= 0;
alen
= fwrblk(fn
, fp1
, &flen
);
} while (!feof(fp1
) && !ferror(fp1
));
DEBUG(8, "\nchecksum: %04x\n", fchksum
);
if (frdmsg(ibuf
, fn
) != FAIL
) {
if ((ack
= ibuf
[0]) == 'G')
DEBUG(4, "ack - '%c'\n", ack
);
mil
= t2
.millitm
- t1
.millitm
;
sprintf(ibuf
, "sent data %ld bytes %ld.%02d secs",
fbytes
, (long)t2
.time
, mil
/ 10);
sysacct(abytes
, t2
.time
);
sprintf(&ibuf
[strlen(ibuf
)], ", %d retries", retries
);
sysaccf(NULL
); /* force accounting */
/* max. attempts to retransmit a file: */
#define MAXRETRIES (fbytes < 10000L ? 2 : 1)
int ret
, mil
, retries
= 0;
long alen
, abytes
, fbytes
;
flen
= frdblk(ibuf
, fn
, &alen
);
if (eof
= flen
> FIBUFSIZ
)
if (fwrite(ibuf
, sizeof (char), flen
, fp2
) != flen
)
mil
= t2
.millitm
- t1
.millitm
;
sprintf(ibuf
, "received data %ld bytes %ld.%02d secs",
fbytes
, (long)t2
.time
, mil
/10);
sprintf(&ibuf
[strlen(ibuf
)]," %d retries", retries
);
sysacct(abytes
, t2
.time
);
if (retries
++ < MAXRETRIES
) {
DEBUG(8, "send ack: 'R'\n", 0);
DEBUG(8, "send ack: 'Q'\n", 0);
sysaccf(NULL
); /* force accounting */
DEBUG(8, "send ack: 'G'\n", 0);
static int ret
= FIBUFSIZ
/ 2;
(void) alarm(MAXMSGTIME
);
ret
= read(fn
, blk
, len
);
return ret
<= 0 ? FAIL
: ret
;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch every TC calls to either frdblk or fwrblk */
#endif !defined(BSD4_2) && !defined(USG)
register int c
, sum
, nl
, len
;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
#endif !defined(BSD4_2) && !defined(USG)
while ((c
= getc(fp
)) != EOF
) {
if (nl
>= FOBUFSIZ
- 1) {
* peek at next char, see if it will fit
if (nl
>= FOBUFSIZ
|| c
< 040 || c
> 0171)
* At EOF - append checksum, there is space for it...
sprintf(op
, "\176\176%04x\r", sum
);
ret
= write(fn
, obuf
, nl
);
return ret
== nl
? nl
: ret
< 0 ? 0 : -ret
;
register int sum
, len
, nl
;
#if !defined(BSD4_2) && !defined(USG)
/* call ultouch occasionally */
#endif !defined(BSD4_2) && !defined(USG)
if ((len
= frdbuf(ip
, FIBUFSIZ
, fn
)) == FAIL
) {
if ((*ip
&= 0177) >= '\172') {
if (*ip
++ != '\176' || (i
= --len
) > 5)
i
= frdbuf(&buf
[len
], 5 - len
, fn
);
sscanf(buf
, "%4x", &fchksum
);
DEBUG(8, "\nchecksum: %04x\n", sum
);
return FIBUFSIZ
+ 1 + nl
;
DEBUG(4, "Bad checksum\n", 0);
/* error: shouldn't get control chars */
DEBUG(4, "Data corrupted\n", 0);
if ((len
= frdbuf(erbp
, FIBUFSIZ
, fn
)) != FAIL
)