home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i050: UUCP X.25 'f' protocol and PAD dialer
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!mnetor!spectrix!clewis
- Mod.sources: Volume 8, Issue 50
- Archive-name: uucp.x25pad
-
- [ A Makefile and manpage wouldn't be sensible for this posting.
- I haven't tested this code; heck, it usually takes strong medicine
- to get me to even _look_ at UUCP code. Still and all, this may
- be useful, given the recent increase in net interest in writing
- a public-domain UUCP. --r$ ]
-
- I mentioned on the net that I had written a PAD dialer for UUCP, and
- I've had a fair number of requests for it. I spoke to Rick Adams about
- it, and he said that I can post it along with the "f" protocol source
- itself.
- -Chris Lewis
-
- #!/bin/sh
- echo 'Start of pack.out, part 01 of 01:'
- echo 'x - READMEfio'
- sed 's/^X//' > READMEfio << '/'
- X F protocol (X.25 PAD)
- X Installation hints
- X
- X"F" protocol is a UUCP protocol used to communicate over X.25 networks.
- XThe PAD dialer is a "real" dialer that can be used to set up connections
- Xto remote X.25 destinations using MICOM or Motorola PADS - and will probably
- Xwork with most other PADS. fio.c was originally distributed with various
- X"alpha-test" versions of the UUCP in BSD4.3 and has been posted several
- Xtimes. I wrote the PAD dialer. This readme gives some pointers on how
- Xto install this into your UUCP.
- X
- XApplicability: if you already have "f" protocol (eg: you already have BSD4.3
- XUUCP), fio.c is likely to be a little older than the one you have, so don't
- Xbother using it. However, Rick Adams has told me that the PAD dialer
- Xdidn't make it into real BSD4.3, so the dialer should be really useful to you
- Xwithout any changes. If you have an older UUCP (eg: BSD4.2 or previous,
- XSystem V, XENIX) you may be able to install both of these files.
- X
- XNote: I have never tried to install either of these into non-4.3 UUCP,
- Xso your mileage may vary - greatly. The pad dialer in particular makes use
- Xof "generic" facilities (ABORT sequences, chat scripts etc.) that are not
- Xlikely to be accessible in older UUCPs. So you may have to do some carving
- Xjust to get your new UUCP to compile and link. I'm afraid you're on your
- Xown in that case.
- X
- XInstallation:
- X 1) Make copies of cntrl.c and condevs.c
- X 2) Insert into cntrl.c, near the beginning:
- X #ifdef PAD
- X extern int fturnon(), fturnoff();
- X extern int frdmsg(), frddata();
- X extern int fwrmsg(), fwrdata();
- X #endif PAD
- X 3) in cntrl.c, inside the "struct Proto Ptbl[] =" initialization,
- X insert the following just before the "g" proto definition:
- X #ifdef PAD
- X 'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff,
- X #endif PAD
- X 4) In cntrl.c, inside the fptcl(str) function,
- X you will see something like:
- X for (p = Ptbl; p->P_id != '\0'; p++) {
- X ...
- X if (index(str, p->P_id) != NULL) {
- X return p->P_id;
- X }
- X }
- X Insert the following code just before the "index" line:
- X #ifdef PAD
- X /* only use 'f' protocol on PAD */
- X if (p->P_id == 'f' && strcmp("PAD", Flds[F_LINE]))
- X continue;
- X #endif PAD
- X
- X 5) in condevs.c, insert the following into the
- X "struct condev condevs[]=" initialization:
- X #ifdef PAD
- X { "PAD", "PAD", padopn, nulldev, padcls },
- X #endif
- X 6) insert "#define PAD 1" into your uucp.h
- X 7) copy pad.c into the directory containing the rest of the dialers
- X and modify the makefile to compile it.
- X 8) copy fio.c into the main UUCP directory and modify the makefile
- X to compile it.
- X 9) run your UUCP make.
- X
- XYou may encounter a number of undefined things. If "dochat" is undefined,
- Xremove it from pad.c. Ditto the stuff about ABORT sequences.
- X
- XTypical L.sys entry:
- X
- X<system> Any PAD <speed> <seq>
- X
- XWhere <speed> is the baud rate between your computer and your pad. <seq>
- Xis the "dial number" to dial the destination. Eg: if you have to type
- X"c 12345555" to reach that destination, place "12345555" here. You may
- Xencounter length restrictions when talking to the PAD, so you may have to
- Xset up "2-character aliases" in the PAD configuration.
- X
- XTypical L-devices entry:
- X
- XPAD <tty> ignored <baud> <chat sequence>
- X
- XThe <baud> must be the same as in the L.sys entry. <tty> is the ttyname
- Xthat the PAD is connected to. Eg: "tty44". Chat sequence (alternatively
- Xprotocol specification in some versions of SV UUCP) is probably not
- Xof any use unless you have the rest of 4.3BSD UUCP. Duplicate this line
- Xwith "DIR" instead of "PAD" so that you can "cu" to the line.
- X
- XOther setup: on dialer out-going line: disable getty, and connect the line
- Xto the PAD. Initialize the PAD line parameters so that it is a "outgoing"
- Xport, and that you can get at X.28 command mode. Eg: you should be able
- Xto "cu" to the line and dial out using X.28 commands. Do not worry about
- Xany other parameters because the dialer will initialize all of the parameters
- Xon the line every time it starts up, and when the link is broken, the parameters
- Xrevert. Thus, the best thing to do is initialize the line for outgoing
- Xcu.
- /
- echo 'x - pad.c'
- sed 's/^X//' > pad.c << '/'
- X
- X#ifndef lint
- Xstatic char *RcsId = "$Header: pad.c,v 1.1 85/01/08 19:58:45 rick Exp $";
- X#endif !lint
- X
- X#include "../condevs.h"
- X#ifdef PAD
- X
- X/*
- X * padopn: establish connection through a PAD.
- X * Returns descriptor open to tty for reading and writing.
- X * Negative values (-1...-7) denote errors in connmsg.
- X * Be sure to disconnect tty when done, via HUPCL or stty 0.
- X */
- X
- Xchar *padparms[] = {
- X "set1:0,2:0,3:2,4:1,5:1,6:5,7:4,9:0,10:0,13:0",
- X "set14:0,15:0,16:0,17:0,18:0,19:1,20:255",
- X "set102:0,103:17,104:19,105:0,106:0,107:0,108:0",
- X "set109:0,110:0,111:0,112:0,113:0,114:0,115:0,116:0",
- X NULL
- X};
- X
- Xextern char *AbortOn;
- Xint padcls();
- Xpadopn(flds)
- Xregister char *flds[];
- X{
- X char phone[MAXPH+1];
- X register char **parmptr;
- X extern errno;
- X char *rindex(), *fdig(), dcname[20];
- X int dh, ok = 0, speed;
- X register struct condev *cd;
- X register FILE *dfp;
- X struct Devices dev;
- X
- X dfp = fopen(DEVFILE, "r");
- X ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
- X
- X signal(SIGALRM, alarmtr);
- X dh = -1;
- X for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) {
- X if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) {
- X fseek(dfp, (off_t)0, 0);
- X while(rddev(dfp, &dev) != FAIL) {
- X if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
- X continue;
- X if (snccmp(flds[F_LINE], dev.D_type) != SAME)
- X continue;
- X DEBUG(4, "Trying line %s\n", dev.D_line);
- X if (mlock(dev.D_line) == FAIL)
- X continue;
- X
- X sprintf(dcname, "/dev/%s", dev.D_line);
- X getnextfd();
- X alarm(10);
- X if (setjmp(Sjbuf)) {
- X delock(dev.D_line);
- X logent(dev.D_line,"pad open TIMEOUT");
- X dh = -1;
- X break;
- X }
- X dh = open(dcname, 2);
- X alarm(0);
- X next_fd = -1;
- X if (dh > 0) {
- X break;
- X }
- X DEBUG(4, "Can't open line %s\n", dev.D_line);
- X devSel[0] = '\0';
- X delock(dev.D_line);
- X }
- X }
- X }
- X fclose(dfp);
- X if (dh < 0)
- X return CF_NODEV;
- X DEBUG(4, "Using line %s\n", dev.D_line);
- X
- X speed = atoi(fdig(flds[F_CLASS]));
- X fixline(dh, speed);
- X /* Do we need this? I don't know */
- X sleep(1);
- X
- X /* Synchronize with PAD prompt */
- X write(dh, "\r", 1);
- X DEBUG(10, "Pad Sync: wanted %s\n", ">");
- X ok = expect(">", dh);
- X DEBUG(10, "got %s\n", ok ? "?" : "that");
- X
- X if (ok) {
- X logent(dev.D_line, "PAD SYNC FAILED");
- X close(dh);
- X return CF_DIAL;
- X }
- X
- X /* Initialization of PAD */
- X AbortOn = "err";
- X for (parmptr = padparms; ok == 0 && *parmptr; parmptr++) {
- X DEBUG(10, "PAD setup: %s\n", *parmptr);
- X write(dh, *parmptr, strlen(*parmptr));
- X write(dh, "\r", 1);
- X ok = expect(">", dh);
- X DEBUG(4, "setup %s\n", ok? "failed": "worked");
- X }
- X if (Debug > 10) {
- X DEBUG(10, "PAD %s:\n", "configuration");
- X write(dh, "par?\r", 6);
- X ok = expect(">", dh);
- X }
- X AbortOn = NULL; /* dochat(login) does this anyways */
- X if (ok) {
- X logent(dev.D_line, "PAD SETUP/CONFIG DEBUG FAILED");
- X close(dh);
- X return CF_DIAL;
- X }
- X
- X /* Do chat from L-devices */
- X if (dochat(&dev, flds, dh)) {
- X logent(dev.D_line, "CHAT FAILED");
- X close(dh);
- X return CF_DIAL;
- X }
- X
- X if (ok == 0) {
- X exphone(flds[F_PHONE], phone);
- X DEBUG(4, "PAD: calling %s\n", phone);
- X write(dh, "c ", 2);
- X write(dh, phone, strlen(phone));
- X write(dh, "\r", 1);
- X DEBUG(4, "wanted %s ", "com");
- X AbortOn = "clr";
- X ok = expect("com", dh);
- X DEBUG(4, "got %s\n", ok ? "?" : "that");
- X AbortOn = NULL;
- X }
- X
- X if (ok != 0) {
- X if (dh > 2)
- X close(dh);
- X DEBUG(4, "pad failed\n", "");
- X delock(dev.D_line);
- X return(CF_DIAL);
- X }
- X else
- X DEBUG(4, "pad ok\n", "");
- X
- X CU_end = padcls;
- X strcat(devSel, dev.D_line); /* for later unlock */
- X return dh;
- X}
- X
- Xpadcls(fd)
- Xregister int fd;
- X{
- X
- X if (fd > 0) {
- X DEBUG(4, "Closing %s\n", "PAD");
- X close(fd);
- X delock(devSel);
- X }
- X}
- X#endif MICOM
- /
- echo 'x - fio.c'
- sed 's/^X//' > fio.c << '/'
- X/* $Header: fio.c,v 1.20 85/04/30 12:57:32 rick Exp $ */
- X/* %M% %I% %E% (Mathematisch Centrum) */
- X
- X/*
- X * flow control protocol.
- X *
- X * This protocol relies on flow control of the data stream.
- X * It is meant for working over links that can (almost) be
- X * guaranteed to be errorfree, specifically X.25/PAD links.
- X * A sumcheck is carried out over a whole file only. If a
- X * transport fails the receiver can request retransmission(s).
- X * This protocol uses a 7-bit datapath only, so it can be
- X * used on links that are not 8-bit transparent.
- X *
- X * When using this protocol with an X.25 PAD:
- X * Although this protocol uses no control chars except CR,
- X * control chars NULL and ^P are used before this protocol
- X * is started; since ^P is the default char for accessing
- X * PAD X.28 command mode, be sure to disable that access
- X * (PAD par 1). Also make sure both flow control pars
- X * (5 and 12) are set. The CR used in this proto is meant
- X * to trigger packet transmission, hence par 3 should be
- X * set to 2; a good value for the Idle Timer (par 4) is 10.
- X * All other pars should be set to 0.
- X * Normally a calling site will take care of setting the
- X * local PAD pars via an X.28 command and those of the remote
- X * PAD via an X.29 command, unless the remote site has a
- X * special channel assigned for this protocol with the proper
- X * par settings.
- X *
- X * Author: Piet Beertema, CWI, Amsterdam, Sep 1984
- X */
- X
- X#include "uucp.h"
- X#include <signal.h>
- X#ifdef USG
- X#include <termio.h>
- X#else !USG
- X#include <sgtty.h>
- X#endif !USG
- X#include <setjmp.h>
- X
- X#define FBUFSIZ 256
- X
- X#ifndef MAXMSGLEN
- X#define MAXMSGLEN BUFSIZ
- X#endif MAXMSGLEN
- X
- Xstatic int chksum;
- Xstatic jmp_buf Ffailbuf;
- X
- Xstatic
- Xfalarm()
- X{
- X signal(SIGALRM, falarm);
- X longjmp(Ffailbuf, 1);
- X}
- X
- Xstatic int (*fsig)();
- X
- X#ifndef USG
- X#define TCGETA TIOCGETP
- X#define TCSETAF TIOCSETP
- X#define termio sgttyb
- X#else
- X#endif USG
- X
- Xfturnon()
- X{
- X int ret;
- X struct termio ttbuf;
- X
- X ioctl(Ifn, TCGETA, &ttbuf);
- X#ifdef USG
- X ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
- X ttbuf.c_cc[VMIN] = FBUFSIZ > 64 ? 64 : FBUFSIZ;
- X ttbuf.c_cc[VTIME] = 5;
- X#else
- X ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
- X#endif USG
- X ret = ioctl(Ifn, TCSETAF, &ttbuf);
- X ASSERT(ret >= 0, "STTY FAILED", "", ret);
- X#ifndef USG
- X {
- X int localmodeword;
- X ioctl(Ifn, TIOCLGET, &localmodeword);
- X DEBUG(8, "local mode word: %o\n", localmodeword);
- X localmodeword &= ~LNOHANG;
- X ioctl(Ifn, TIOCLSET, &localmodeword);
- X }
- X#endif
- X fsig = signal(SIGALRM, falarm);
- X /* give the other side time to perform its ioctl;
- X * otherwise it may flush out the first data this
- X * side is about to send.
- X */
- X sleep(2);
- X return SUCCESS;
- X}
- X
- Xfturnoff()
- X{
- X (void) signal(SIGALRM, fsig);
- X return SUCCESS;
- X}
- X
- Xfwrmsg(type, str, fn)
- Xregister char *str;
- Xint fn;
- Xchar type;
- X{
- X register char *s;
- X char bufr[MAXMSGLEN];
- X
- X s = bufr;
- X *s++ = type;
- X while (*str)
- X *s++ = *str++;
- X if (*(s-1) == '\n')
- X s--;
- X *s++ = '\r';
- X (void) write(fn, bufr, s - bufr);
- X return SUCCESS;
- X}
- X
- Xfrdmsg(str, fn)
- Xregister char *str;
- Xregister int fn;
- X{
- X register char *smax;
- X
- X if (setjmp(Ffailbuf))
- X return FAIL;
- X smax = str + MAXMSGLEN - 1;
- X (void) alarm(2*MAXMSGTIME);
- X for (;;) {
- X if (read(fn, str, 1) <= 0)
- X goto msgerr;
- X if (*str == '\r')
- X break;
- X if (*str < ' ')
- X continue;
- X if (str++ >= smax)
- X goto msgerr;
- X }
- X *str = '\0';
- X (void) alarm(0);
- X return SUCCESS;
- Xmsgerr:
- X (void) alarm(0);
- X return FAIL;
- X}
- X
- Xfwrdata(fp1, fn)
- XFILE *fp1;
- Xint fn;
- X{
- X register int flen, alen, ret;
- X register char *obp;
- X char ibuf[FBUFSIZ];
- X char ack;
- X long abytes, fbytes;
- X struct timeb t1, t2;
- X int mil, retries = 0;
- X
- X ret = FAIL;
- Xretry:
- X chksum = 0xffff;
- X abytes = fbytes = 0L;
- X ack = '\0';
- X#ifdef USG
- X time(&t1.time);
- X t1.millitm = 0;
- X#else !USG
- X ftime(&t1);
- X#endif !USG
- X while ((flen = fread(ibuf, sizeof (char), FBUFSIZ, fp1)) > 0) {
- X alen = fwrblk(fn, ibuf, flen);
- X abytes += alen >= 0 ? alen : -alen;
- X if (alen <= 0)
- X goto acct;
- X fbytes += flen;
- X }
- X sprintf(ibuf, "\176\176%04x\r", chksum);
- X abytes += alen = strlen(ibuf);
- X if (write(fn, ibuf, alen) == alen) {
- X DEBUG(8, "wrdata: checksum length: %d\n", alen);
- X DEBUG(8, "checksum: %04x\n", chksum);
- X if (frdmsg(ibuf, fn) != FAIL) {
- X if ((ack = ibuf[0]) == 'G')
- X ret = 0;
- X DEBUG(4, "ack - '%c'\n", ack);
- X }
- X }
- Xacct:
- X if (ack == 'R') {
- X DEBUG(4, "RETRY:\n", 0);
- X fseek(fp1, 0L, 0);
- X retries++;
- X goto retry;
- X }
- X#ifdef USG
- X time(&t2.time);
- X t2.millitm = 0;
- X#else !USG
- X ftime(&t2);
- X#endif !USG
- X Now = t2;
- X t2.time -= t1.time;
- X mil = t2.millitm - t1.millitm;
- X if (mil < 0) {
- X --t2.time;
- X mil += 1000;
- X }
- X sprintf(ibuf, "sent data %ld bytes %ld.%02d secs",
- X fbytes, (long)t2.time, mil/10);
- X sysacct(abytes, t2.time - t1.time);
- X if (retries > 0)
- X sprintf((char *)ibuf+strlen(ibuf)," %d retries", retries);
- X DEBUG(1, "%s\n", ibuf);
- X syslog(ibuf);
- X#ifdef SYSACCT
- X if (ret)
- X sysaccf(NULL); /* force accounting */
- X#endif SYSACCT
- X return ret;
- X}
- X
- X/* max. attempts to retransmit a file: */
- X#define MAXRETRIES (fbytes < 10000L ? 2 : 1)
- X
- Xfrddata(fn, fp2)
- Xregister int fn;
- Xregister FILE *fp2;
- X{
- X register int flen;
- X register char eof;
- X char ibuf[FBUFSIZ];
- X int ret, retries = 0;
- X long alen, abytes, fbytes;
- X struct timeb t1, t2;
- X int mil;
- X
- X ret = FAIL;
- Xretry:
- X chksum = 0xffff;
- X abytes = fbytes = 0L;
- X#ifdef USG
- X time(&t1.time);
- X t1.millitm = 0;
- X#else !USG
- X ftime(&t1);
- X#endif !USG
- X do {
- X flen = frdblk(ibuf, fn, &alen);
- X abytes += alen;
- X if (flen < 0)
- X goto acct;
- X if (eof = flen > FBUFSIZ)
- X flen -= FBUFSIZ + 1;
- X fbytes += flen;
- X if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
- X goto acct;
- X } while (!eof);
- X ret = 0;
- Xacct:
- X if (ret) {
- X if (retries++ < MAXRETRIES) {
- X DEBUG(8, "send ack: 'R'\n", 0);
- X fwrmsg('R', "", fn);
- X fseek(fp2, 0L, 0);
- X DEBUG(4, "RETRY:\n", 0);
- X goto retry;
- X }
- X DEBUG(8, "send ack: 'Q'\n", 0);
- X fwrmsg('Q', "", fn);
- X#ifdef SYSACCT
- X sysaccf(NULL); /* force accounting */
- X#endif SYSACCT
- X } else {
- X DEBUG(8, "send ack: 'G'\n", 0);
- X fwrmsg('G', "", fn);
- X }
- X#ifdef USG
- X time(&t2.time);
- X t2.millitm = 0;
- X#else !USG
- X ftime(&t2);
- X#endif !USG
- X Now = t2;
- X t2.time -= t1.time;
- X mil = t2.millitm - t1.millitm;
- X if (mil < 0) {
- X --t2.time;
- X mil += 1000;
- X }
- X sprintf(ibuf, "received data %ld bytes %ld.%02d secs",
- X fbytes, (long)t2.time, mil/10);
- X sysacct(abytes, t2.time - t1.time);
- X if (retries > 0)
- X sprintf((char *)ibuf+strlen(ibuf)," %d retries", retries);
- X DEBUG(1, "%s\n", ibuf);
- X syslog(ibuf);
- X return ret;
- X}
- X
- Xstatic
- Xfrdbuf(blk, len, fn)
- Xregister char *blk;
- Xregister int len;
- Xregister int fn;
- X{
- X static int ret = FBUFSIZ / 2;
- X#ifndef Not080
- X extern int linebaudrate;
- X#endif Not080
- X
- X if (setjmp(Ffailbuf))
- X return FAIL;
- X#ifndef Not080
- X if (len == FBUFSIZ && ret < FBUFSIZ / 2 &&
- X linebaudrate > 0 && linebaudrate < 4800)
- X sleep(1);
- X#endif Not080
- X (void) alarm(MAXMSGTIME);
- X ret = read(fn, blk, len);
- X alarm(0);
- X return ret <= 0 ? FAIL : ret;
- X}
- X
- X/* call ultouch every TC calls to either frdblk or fwrblk */
- X
- X#define TC 20
- Xstatic int tc = TC;
- X
- X/* Byte conversion:
- X *
- X * from pre to
- X * 000-037 172 100-137
- X * 040-171 040-171
- X * 172-177 173 072-077
- X * 200-237 174 100-137
- X * 240-371 175 040-171
- X * 372-377 176 072-077
- X */
- X
- Xstatic
- Xfwrblk(fn, ip, len)
- Xint fn;
- Xregister char *ip;
- Xregister int len;
- X{
- X register char *op;
- X register int sum, nl;
- X int ret;
- X char obuf[FBUFSIZ * 2];
- X
- X /* call ultouch occasionally */
- X if (--tc < 0) {
- X tc = TC;
- X ultouch();
- X }
- X DEBUG(8, "fwrblk: %d/", len);
- X op = obuf;
- X nl = 0;
- X sum = chksum;
- X do {
- X if (sum & 0x8000) {
- X sum <<= 1;
- X sum++;
- X } else
- X sum <<= 1;
- X sum += *ip & 0377;
- X sum &= 0xffff;
- X if (*ip & 0200) {
- X *ip &= 0177;
- X if (*ip < 040) {
- X *op++ = '\174';
- X *op++ = *ip++ + 0100;
- X } else
- X if (*ip <= 0171) {
- X *op++ = '\175';
- X *op++ = *ip++;
- X }
- X else {
- X *op++ = '\176';
- X *op++ = *ip++ - 0100;
- X }
- X nl += 2;
- X } else {
- X if (*ip < 040) {
- X *op++ = '\172';
- X *op++ = *ip++ + 0100;
- X nl += 2;
- X } else
- X if (*ip <= 0171) {
- X *op++ = *ip++;
- X nl++;
- X } else {
- X *op++ = '\173';
- X *op++ = *ip++ - 0100;
- X nl += 2;
- X }
- X }
- X } while (--len);
- X chksum = sum;
- X DEBUG(8, "%d\n", nl);
- X ret = write(fn, obuf, nl);
- X return ret == nl ? nl : ret < 0 ? 0 : -ret;
- X}
- X
- Xstatic
- Xfrdblk(ip, fn, rlen)
- Xregister char *ip;
- Xint fn;
- Xlong *rlen;
- X{
- X register char *op, c;
- X register int sum, len, nl;
- X char buf[5], *erbp = ip;
- X int i;
- X static char special = 0;
- X
- X /* call ultouch occasionally */
- X if (--tc < 0) {
- X tc = TC;
- X ultouch();
- X }
- X
- X if ((len = frdbuf(ip, FBUFSIZ, fn)) == FAIL) {
- X *rlen = 0;
- X goto dcorr;
- X }
- X *rlen = len;
- X DEBUG(8, "%d/", len);
- X op = ip;
- X nl = 0;
- X sum = chksum;
- X do {
- X if ((*ip &= 0177) >= '\172') {
- X if (special) {
- X DEBUG(8, "%d", nl);
- X special = 0;
- X op = buf;
- X if (*ip++ != '\176' || (i = --len) > 5)
- X goto dcorr;
- X while (i--)
- X *op++ = *ip++;
- X while (len < 5) {
- X i = frdbuf(&buf[len], 5 - len, fn);
- X if (i == FAIL) {
- X len = FAIL;
- X goto dcorr;
- X }
- X DEBUG(8, ",%d", i);
- X len += i;
- X *rlen += i;
- X }
- X if (buf[4] != '\r')
- X goto dcorr;
- X sscanf(buf, "%4x", &chksum);
- X DEBUG(8, "\nchecksum: %04x\n", sum);
- X if (chksum == sum)
- X return FBUFSIZ + 1 + nl;
- X else {
- X DEBUG(8, "\n", 0);
- X DEBUG(4, "Bad checksum\n", 0);
- X return FAIL;
- X }
- X }
- X special = *ip++;
- X } else {
- X if (*ip < '\040') {
- X /* error: shouldn't get control chars */
- X goto dcorr;
- X }
- X switch (special) {
- X case 0:
- X c = *ip++;
- X break;
- X case '\172':
- X c = *ip++ - 0100;
- X break;
- X case '\173':
- X c = *ip++ + 0100;
- X break;
- X case '\174':
- X c = *ip++ + 0100;
- X break;
- X case '\175':
- X c = *ip++ + 0200;
- X break;
- X case '\176':
- X c = *ip++ + 0300;
- X break;
- X }
- X *op++ = c;
- X if (sum & 0x8000) {
- X sum <<= 1;
- X sum++;
- X } else
- X sum <<= 1;
- X sum += c & 0377;
- X sum &= 0xffff;
- X special = 0;
- X nl++;
- X }
- X } while (--len);
- X chksum = sum;
- X DEBUG(8, "%d,", nl);
- X return nl;
- Xdcorr:
- X DEBUG(8, "\n", 0);
- X DEBUG(4, "Data corrupted\n", 0);
- X while (len != FAIL) {
- X if ((len = frdbuf(erbp, FBUFSIZ, fn)) != FAIL)
- X *rlen += len;
- X }
- X return FAIL;
- X}
- /
- echo 'Part 01 of pack.out complete.'
- exit
-
-
-