home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume8 / uucp.x25pad < prev    next >
Text File  |  1987-02-08  |  20KB  |  816 lines

  1. Subject:  v08i050:  UUCP X.25 'f' protocol and PAD dialer
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!mnetor!spectrix!clewis
  6. Mod.sources: Volume 8, Issue 50
  7. Archive-name: uucp.x25pad
  8.  
  9. [  A Makefile and manpage wouldn't be sensible for this posting.
  10.    I haven't tested this code; heck, it usually takes strong medicine
  11.    to get me to even _look_ at UUCP code.  Still and all, this may
  12.    be useful, given the recent increase in net interest in writing
  13.    a public-domain UUCP.  --r$  ]
  14.  
  15. I mentioned on the net that I had written a PAD dialer for UUCP, and
  16. I've had a fair number of requests for it.  I spoke to Rick Adams about
  17. it, and he said that I can post it along with the "f" protocol source
  18. itself.
  19.     -Chris Lewis
  20.  
  21. #!/bin/sh
  22. echo 'Start of pack.out, part 01 of 01:'
  23. echo 'x - READMEfio'
  24. sed 's/^X//' > READMEfio << '/'
  25. X            F protocol (X.25 PAD)
  26. X            Installation hints
  27. X
  28. X"F" protocol is a UUCP protocol used to communicate over X.25 networks.
  29. XThe PAD dialer is a "real" dialer that can be used to set up connections
  30. Xto remote X.25 destinations using MICOM or Motorola PADS - and will probably
  31. Xwork with most other PADS.  fio.c was originally distributed with various 
  32. X"alpha-test" versions of the UUCP in BSD4.3 and has been posted several
  33. Xtimes.  I wrote the PAD dialer.  This readme gives some pointers on how 
  34. Xto install this into your UUCP.
  35. X
  36. XApplicability: if you already have "f" protocol (eg: you already have BSD4.3 
  37. XUUCP), fio.c is likely to be a little older than the one you have, so don't 
  38. Xbother using it.  However, Rick Adams has told me that the PAD dialer 
  39. Xdidn't make it into real BSD4.3, so the dialer should be really useful to you
  40. Xwithout any changes.  If you have an older UUCP (eg: BSD4.2 or previous, 
  41. XSystem V, XENIX) you may be able to install both of these files.
  42. X
  43. XNote: I have never tried to install either of these into non-4.3 UUCP,
  44. Xso your mileage may vary - greatly.  The pad dialer in particular makes use
  45. Xof "generic" facilities (ABORT sequences, chat scripts etc.) that are not
  46. Xlikely to be accessible in older UUCPs.  So you may have to do some carving
  47. Xjust to get your new UUCP to compile and link.  I'm afraid you're on your
  48. Xown in that case.
  49. X
  50. XInstallation:
  51. X    1) Make copies of cntrl.c and condevs.c
  52. X    2) Insert into cntrl.c, near the beginning:
  53. X        #ifdef PAD
  54. X        extern int fturnon(), fturnoff();
  55. X        extern int frdmsg(), frddata();
  56. X        extern int fwrmsg(), fwrdata();
  57. X        #endif PAD
  58. X    3) in cntrl.c, inside the "struct Proto Ptbl[] =" initialization,
  59. X       insert the following just before the "g" proto definition:
  60. X        #ifdef PAD
  61. X        'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff,
  62. X        #endif PAD
  63. X    4) In cntrl.c, inside the fptcl(str) function,
  64. X       you will see something like:
  65. X        for (p = Ptbl; p->P_id != '\0'; p++) {
  66. X        ...
  67. X        if (index(str, p->P_id) != NULL) {
  68. X            return p->P_id;
  69. X        }
  70. X        }
  71. X       Insert the following code just before the "index" line:
  72. X        #ifdef PAD
  73. X        /* only use 'f' protocol on PAD */
  74. X        if (p->P_id == 'f' && strcmp("PAD", Flds[F_LINE]))
  75. X            continue;
  76. X        #endif PAD
  77. X    
  78. X    5) in condevs.c, insert the following into the 
  79. X       "struct condev condevs[]=" initialization:
  80. X        #ifdef PAD
  81. X        { "PAD", "PAD", padopn, nulldev, padcls },
  82. X        #endif
  83. X    6) insert "#define PAD 1" into your uucp.h
  84. X    7) copy pad.c into the directory containing the rest of the dialers
  85. X       and modify the makefile to compile it.
  86. X    8) copy fio.c into the main UUCP directory and modify the makefile
  87. X       to compile it.
  88. X    9) run your UUCP make.
  89. X
  90. XYou may encounter a number of undefined things.  If "dochat" is undefined,
  91. Xremove it from pad.c.  Ditto the stuff about ABORT sequences.
  92. X
  93. XTypical L.sys entry:
  94. X
  95. X<system> Any PAD <speed> <seq> 
  96. X
  97. XWhere <speed> is the baud rate between your computer and your pad.  <seq>
  98. Xis the "dial number" to dial the destination.  Eg: if you have to type
  99. X"c 12345555" to reach that destination, place "12345555" here.  You may
  100. Xencounter length restrictions when talking to the PAD, so you may have to
  101. Xset up "2-character aliases" in the PAD configuration.
  102. X
  103. XTypical L-devices entry:
  104. X
  105. XPAD <tty> ignored <baud> <chat sequence>
  106. X
  107. XThe <baud> must be the same as in the L.sys entry.  <tty> is the ttyname
  108. Xthat the PAD is connected to.  Eg: "tty44".  Chat sequence (alternatively
  109. Xprotocol specification in some versions of SV UUCP) is probably not
  110. Xof any use unless you have the rest of 4.3BSD UUCP.  Duplicate this line
  111. Xwith "DIR" instead of "PAD" so that you can "cu" to the line.
  112. X
  113. XOther setup: on dialer out-going line: disable getty, and connect the line
  114. Xto the PAD.  Initialize the PAD line parameters so that it is a "outgoing"
  115. Xport, and that you can get at X.28 command mode.  Eg: you should be able
  116. Xto "cu" to the line and dial out using X.28 commands.  Do not worry about
  117. Xany other parameters because the dialer will initialize all of the parameters
  118. Xon the line every time it starts up, and when the link is broken, the parameters
  119. Xrevert.  Thus, the best thing to do is initialize the line for outgoing
  120. Xcu.
  121. /
  122. echo 'x - pad.c'
  123. sed 's/^X//' > pad.c << '/'
  124. X
  125. X#ifndef lint
  126. Xstatic char    *RcsId = "$Header: pad.c,v 1.1 85/01/08 19:58:45 rick Exp $";
  127. X#endif !lint
  128. X
  129. X#include "../condevs.h"
  130. X#ifdef PAD
  131. X
  132. X/*
  133. X *    padopn: establish connection through a PAD.
  134. X *    Returns descriptor open to tty for reading and writing.
  135. X *    Negative values (-1...-7) denote errors in connmsg.
  136. X *    Be sure to disconnect tty when done, via HUPCL or stty 0.
  137. X */
  138. X
  139. Xchar *padparms[] = {
  140. X    "set1:0,2:0,3:2,4:1,5:1,6:5,7:4,9:0,10:0,13:0",
  141. X    "set14:0,15:0,16:0,17:0,18:0,19:1,20:255",
  142. X    "set102:0,103:17,104:19,105:0,106:0,107:0,108:0",
  143. X    "set109:0,110:0,111:0,112:0,113:0,114:0,115:0,116:0",
  144. X    NULL
  145. X};
  146. X
  147. Xextern    char    *AbortOn;
  148. Xint    padcls();
  149. Xpadopn(flds)
  150. Xregister char *flds[];
  151. X{
  152. X    char phone[MAXPH+1];
  153. X    register char **parmptr;
  154. X    extern errno;
  155. X    char *rindex(), *fdig(), dcname[20];
  156. X    int dh, ok = 0, speed;
  157. X    register struct condev *cd;
  158. X    register FILE *dfp;
  159. X    struct Devices dev;
  160. X
  161. X    dfp = fopen(DEVFILE, "r");
  162. X    ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
  163. X
  164. X    signal(SIGALRM, alarmtr);
  165. X    dh = -1;
  166. X    for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) {
  167. X        if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) {
  168. X            fseek(dfp, (off_t)0, 0);
  169. X            while(rddev(dfp, &dev) != FAIL) {
  170. X                if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
  171. X                    continue;
  172. X                if (snccmp(flds[F_LINE], dev.D_type) != SAME)
  173. X                    continue;
  174. X                DEBUG(4, "Trying line %s\n", dev.D_line);
  175. X                if (mlock(dev.D_line) == FAIL)
  176. X                    continue;
  177. X
  178. X                sprintf(dcname, "/dev/%s", dev.D_line);
  179. X                getnextfd();
  180. X                alarm(10);
  181. X                if (setjmp(Sjbuf)) {
  182. X                    delock(dev.D_line);
  183. X                    logent(dev.D_line,"pad open TIMEOUT");
  184. X                    dh = -1;
  185. X                    break;
  186. X                }
  187. X                dh = open(dcname, 2);
  188. X                alarm(0);
  189. X                next_fd = -1;
  190. X                if (dh > 0) {
  191. X                    break;
  192. X                }
  193. X                DEBUG(4, "Can't open line %s\n", dev.D_line);
  194. X                devSel[0] = '\0';
  195. X                delock(dev.D_line);
  196. X            }
  197. X        }
  198. X    }
  199. X    fclose(dfp);
  200. X    if (dh < 0)
  201. X        return CF_NODEV;
  202. X    DEBUG(4, "Using line %s\n", dev.D_line);
  203. X
  204. X    speed = atoi(fdig(flds[F_CLASS]));
  205. X    fixline(dh, speed);
  206. X    /*    Do we need this?  I don't know    */
  207. X    sleep(1);
  208. X
  209. X    /* Synchronize with PAD prompt */
  210. X    write(dh, "\r", 1);
  211. X    DEBUG(10, "Pad Sync: wanted %s\n", ">");
  212. X    ok = expect(">", dh);
  213. X    DEBUG(10, "got %s\n", ok ? "?" : "that");
  214. X
  215. X    if (ok) {
  216. X        logent(dev.D_line, "PAD SYNC FAILED");
  217. X        close(dh);
  218. X        return CF_DIAL;
  219. X    }
  220. X
  221. X    /*    Initialization of PAD    */
  222. X    AbortOn = "err";
  223. X    for (parmptr = padparms; ok == 0 && *parmptr; parmptr++) {
  224. X        DEBUG(10, "PAD setup: %s\n", *parmptr);
  225. X        write(dh, *parmptr, strlen(*parmptr));
  226. X        write(dh, "\r", 1);
  227. X        ok = expect(">", dh);
  228. X        DEBUG(4, "setup %s\n", ok? "failed": "worked");
  229. X    }
  230. X    if (Debug > 10) {
  231. X        DEBUG(10, "PAD %s:\n", "configuration");
  232. X        write(dh, "par?\r", 6);
  233. X        ok = expect(">", dh);
  234. X    }
  235. X    AbortOn = NULL;        /* dochat(login) does this anyways */
  236. X    if (ok) {
  237. X        logent(dev.D_line, "PAD SETUP/CONFIG DEBUG FAILED");
  238. X        close(dh);
  239. X        return CF_DIAL;
  240. X    }
  241. X
  242. X    /*    Do chat from L-devices */
  243. X    if (dochat(&dev, flds, dh)) {
  244. X        logent(dev.D_line, "CHAT FAILED");
  245. X        close(dh);
  246. X        return CF_DIAL;
  247. X    }
  248. X
  249. X    if (ok == 0) {
  250. X        exphone(flds[F_PHONE], phone);
  251. X        DEBUG(4, "PAD: calling %s\n", phone);
  252. X        write(dh, "c ", 2);
  253. X        write(dh, phone, strlen(phone));
  254. X        write(dh, "\r", 1);
  255. X        DEBUG(4, "wanted %s ", "com");
  256. X        AbortOn = "clr";
  257. X        ok = expect("com", dh);
  258. X        DEBUG(4, "got %s\n", ok ? "?" : "that");
  259. X        AbortOn = NULL;
  260. X    }
  261. X
  262. X    if (ok != 0) {
  263. X        if (dh > 2)
  264. X            close(dh);
  265. X        DEBUG(4, "pad failed\n", "");
  266. X        delock(dev.D_line);
  267. X        return(CF_DIAL);
  268. X    } 
  269. X    else
  270. X        DEBUG(4, "pad ok\n", "");
  271. X
  272. X    CU_end = padcls;
  273. X    strcat(devSel, dev.D_line);    /* for later unlock */
  274. X    return dh;
  275. X}
  276. X
  277. Xpadcls(fd)
  278. Xregister int fd;
  279. X{
  280. X
  281. X    if (fd > 0) {
  282. X        DEBUG(4, "Closing %s\n", "PAD");
  283. X        close(fd);
  284. X        delock(devSel);
  285. X    }
  286. X}
  287. X#endif MICOM
  288. /
  289. echo 'x - fio.c'
  290. sed 's/^X//' > fio.c << '/'
  291. X/* $Header: fio.c,v 1.20 85/04/30 12:57:32 rick Exp $ */
  292. X/*    %M%    %I%    %E%    (Mathematisch Centrum)    */
  293. X
  294. X/*
  295. X * flow control protocol.
  296. X *
  297. X * This protocol relies on flow control of the data stream.
  298. X * It is meant for working over links that can (almost) be
  299. X * guaranteed to be errorfree, specifically X.25/PAD links.
  300. X * A sumcheck is carried out over a whole file only. If a
  301. X * transport fails the receiver can request retransmission(s).
  302. X * This protocol uses a 7-bit datapath only, so it can be
  303. X * used on links that are not 8-bit transparent.
  304. X *
  305. X * When using this protocol with an X.25 PAD:
  306. X * Although this protocol uses no control chars except CR,
  307. X * control chars NULL and ^P are used before this protocol
  308. X * is started; since ^P is the default char for accessing
  309. X * PAD X.28 command mode, be sure to disable that access
  310. X * (PAD par 1). Also make sure both flow control pars
  311. X * (5 and 12) are set. The CR used in this proto is meant
  312. X * to trigger packet transmission, hence par 3 should be 
  313. X * set to 2; a good value for the Idle Timer (par 4) is 10.
  314. X * All other pars should be set to 0.
  315. X * Normally a calling site will take care of setting the
  316. X * local PAD pars via an X.28 command and those of the remote
  317. X * PAD via an X.29 command, unless the remote site has a
  318. X * special channel assigned for this protocol with the proper
  319. X * par settings.
  320. X *
  321. X * Author: Piet Beertema, CWI, Amsterdam, Sep 1984
  322. X */
  323. X
  324. X#include "uucp.h"
  325. X#include <signal.h>
  326. X#ifdef USG
  327. X#include <termio.h>
  328. X#else !USG
  329. X#include <sgtty.h>
  330. X#endif !USG
  331. X#include <setjmp.h>
  332. X
  333. X#define FBUFSIZ        256
  334. X
  335. X#ifndef MAXMSGLEN
  336. X#define MAXMSGLEN    BUFSIZ
  337. X#endif MAXMSGLEN
  338. X
  339. Xstatic int chksum;
  340. Xstatic jmp_buf Ffailbuf;
  341. X
  342. Xstatic
  343. Xfalarm()
  344. X{
  345. X    signal(SIGALRM, falarm);
  346. X    longjmp(Ffailbuf, 1);
  347. X}
  348. X
  349. Xstatic int (*fsig)();
  350. X
  351. X#ifndef USG
  352. X#define TCGETA    TIOCGETP
  353. X#define TCSETAF    TIOCSETP
  354. X#define termio    sgttyb
  355. X#else
  356. X#endif USG
  357. X
  358. Xfturnon()
  359. X{
  360. X    int ret;
  361. X    struct termio ttbuf;
  362. X
  363. X    ioctl(Ifn, TCGETA, &ttbuf);
  364. X#ifdef USG
  365. X    ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
  366. X    ttbuf.c_cc[VMIN] = FBUFSIZ > 64 ? 64 : FBUFSIZ;
  367. X    ttbuf.c_cc[VTIME] = 5;
  368. X#else
  369. X    ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
  370. X#endif USG
  371. X    ret = ioctl(Ifn, TCSETAF, &ttbuf);
  372. X    ASSERT(ret >= 0, "STTY FAILED", "", ret);
  373. X#ifndef    USG
  374. X    {
  375. X        int    localmodeword;
  376. X        ioctl(Ifn, TIOCLGET, &localmodeword);
  377. X        DEBUG(8, "local mode word: %o\n", localmodeword);
  378. X        localmodeword &= ~LNOHANG;
  379. X        ioctl(Ifn, TIOCLSET, &localmodeword);
  380. X    }
  381. X#endif
  382. X    fsig = signal(SIGALRM, falarm);
  383. X    /* give the other side time to perform its ioctl;
  384. X     * otherwise it may flush out the first data this
  385. X     * side is about to send.
  386. X     */
  387. X    sleep(2);
  388. X    return SUCCESS;
  389. X}
  390. X
  391. Xfturnoff()
  392. X{
  393. X    (void) signal(SIGALRM, fsig);
  394. X    return SUCCESS;
  395. X}
  396. X
  397. Xfwrmsg(type, str, fn)
  398. Xregister char *str;
  399. Xint fn;
  400. Xchar type;
  401. X{
  402. X    register char *s;
  403. X    char bufr[MAXMSGLEN];
  404. X
  405. X    s = bufr;
  406. X    *s++ = type;
  407. X    while (*str)
  408. X        *s++ = *str++;
  409. X    if (*(s-1) == '\n')
  410. X        s--;
  411. X    *s++ = '\r';
  412. X    (void) write(fn, bufr, s - bufr);
  413. X    return SUCCESS;
  414. X}
  415. X
  416. Xfrdmsg(str, fn)
  417. Xregister char *str;
  418. Xregister int fn;
  419. X{
  420. X    register char *smax;
  421. X
  422. X    if (setjmp(Ffailbuf))
  423. X        return FAIL;
  424. X    smax = str + MAXMSGLEN - 1;
  425. X    (void) alarm(2*MAXMSGTIME);
  426. X    for (;;) {
  427. X        if (read(fn, str, 1) <= 0)
  428. X            goto msgerr;
  429. X        if (*str == '\r')
  430. X            break;
  431. X        if (*str < ' ')
  432. X            continue;
  433. X        if (str++ >= smax)
  434. X            goto msgerr;
  435. X    }
  436. X    *str = '\0';
  437. X    (void) alarm(0);
  438. X    return SUCCESS;
  439. Xmsgerr:
  440. X    (void) alarm(0);
  441. X    return FAIL;
  442. X}
  443. X
  444. Xfwrdata(fp1, fn)
  445. XFILE *fp1;
  446. Xint fn;
  447. X{
  448. X    register int flen, alen, ret;
  449. X    register char *obp;
  450. X    char ibuf[FBUFSIZ];
  451. X    char ack;
  452. X    long abytes, fbytes;
  453. X    struct timeb t1, t2;
  454. X    int mil, retries = 0;
  455. X
  456. X    ret = FAIL;
  457. Xretry:
  458. X    chksum = 0xffff;
  459. X    abytes = fbytes = 0L;
  460. X    ack = '\0';
  461. X#ifdef USG
  462. X    time(&t1.time);
  463. X    t1.millitm = 0;
  464. X#else !USG
  465. X    ftime(&t1);
  466. X#endif !USG
  467. X    while ((flen = fread(ibuf, sizeof (char), FBUFSIZ, fp1)) > 0) {
  468. X        alen = fwrblk(fn, ibuf, flen);
  469. X        abytes += alen >= 0 ? alen : -alen;
  470. X        if (alen <= 0)
  471. X            goto acct;
  472. X        fbytes += flen;
  473. X    }
  474. X    sprintf(ibuf, "\176\176%04x\r", chksum);
  475. X    abytes += alen = strlen(ibuf);
  476. X    if (write(fn, ibuf, alen) == alen) {
  477. X        DEBUG(8, "wrdata: checksum length: %d\n", alen);
  478. X        DEBUG(8, "checksum: %04x\n", chksum);
  479. X        if (frdmsg(ibuf, fn) != FAIL) {
  480. X            if ((ack = ibuf[0]) == 'G')
  481. X                ret = 0;
  482. X            DEBUG(4, "ack - '%c'\n", ack);
  483. X        }
  484. X    }
  485. Xacct:
  486. X    if (ack == 'R') {
  487. X        DEBUG(4, "RETRY:\n", 0);
  488. X        fseek(fp1, 0L, 0);
  489. X        retries++;
  490. X        goto retry;
  491. X    }
  492. X#ifdef USG
  493. X    time(&t2.time);
  494. X    t2.millitm = 0;
  495. X#else !USG
  496. X    ftime(&t2);
  497. X#endif !USG
  498. X    Now = t2;
  499. X    t2.time -= t1.time;
  500. X    mil = t2.millitm - t1.millitm;
  501. X    if (mil < 0) {
  502. X        --t2.time;
  503. X        mil += 1000;
  504. X    }
  505. X    sprintf(ibuf, "sent data %ld bytes %ld.%02d secs",
  506. X                fbytes, (long)t2.time, mil/10);
  507. X    sysacct(abytes, t2.time - t1.time);
  508. X    if (retries > 0) 
  509. X        sprintf((char *)ibuf+strlen(ibuf)," %d retries", retries);
  510. X    DEBUG(1, "%s\n", ibuf);
  511. X    syslog(ibuf);
  512. X#ifdef SYSACCT
  513. X    if (ret)
  514. X        sysaccf(NULL);        /* force accounting */
  515. X#endif SYSACCT
  516. X    return ret;
  517. X}
  518. X
  519. X/* max. attempts to retransmit a file: */
  520. X#define MAXRETRIES    (fbytes < 10000L ? 2 : 1)
  521. X
  522. Xfrddata(fn, fp2)
  523. Xregister int fn;
  524. Xregister FILE *fp2;
  525. X{
  526. X    register int flen;
  527. X    register char eof;
  528. X    char ibuf[FBUFSIZ];
  529. X    int ret, retries = 0;
  530. X    long alen, abytes, fbytes;
  531. X    struct timeb t1, t2;
  532. X    int mil;
  533. X
  534. X    ret = FAIL;
  535. Xretry:
  536. X    chksum = 0xffff;
  537. X    abytes = fbytes = 0L;
  538. X#ifdef USG
  539. X    time(&t1.time);
  540. X    t1.millitm = 0;
  541. X#else !USG
  542. X    ftime(&t1);
  543. X#endif !USG
  544. X    do {
  545. X        flen = frdblk(ibuf, fn, &alen);
  546. X        abytes += alen;
  547. X        if (flen < 0)
  548. X            goto acct;
  549. X        if (eof = flen > FBUFSIZ)
  550. X            flen -= FBUFSIZ + 1;
  551. X        fbytes += flen;
  552. X        if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
  553. X            goto acct;
  554. X    } while (!eof);
  555. X    ret = 0;
  556. Xacct:
  557. X    if (ret) {
  558. X        if (retries++ < MAXRETRIES) {
  559. X            DEBUG(8, "send ack: 'R'\n", 0);
  560. X            fwrmsg('R', "", fn);
  561. X            fseek(fp2, 0L, 0);
  562. X            DEBUG(4, "RETRY:\n", 0);
  563. X            goto retry;
  564. X        }
  565. X        DEBUG(8, "send ack: 'Q'\n", 0);
  566. X        fwrmsg('Q', "", fn);
  567. X#ifdef SYSACCT
  568. X        sysaccf(NULL);        /* force accounting */
  569. X#endif SYSACCT
  570. X    } else {
  571. X        DEBUG(8, "send ack: 'G'\n", 0);
  572. X        fwrmsg('G', "", fn);
  573. X    }
  574. X#ifdef USG
  575. X    time(&t2.time);
  576. X    t2.millitm = 0;
  577. X#else !USG
  578. X    ftime(&t2);
  579. X#endif !USG
  580. X    Now = t2;
  581. X    t2.time -= t1.time;
  582. X    mil = t2.millitm - t1.millitm;
  583. X    if (mil < 0) {
  584. X        --t2.time;
  585. X        mil += 1000;
  586. X    }
  587. X    sprintf(ibuf, "received data %ld bytes %ld.%02d secs",
  588. X                fbytes, (long)t2.time, mil/10);
  589. X    sysacct(abytes, t2.time - t1.time);
  590. X    if (retries > 0) 
  591. X        sprintf((char *)ibuf+strlen(ibuf)," %d retries", retries);
  592. X    DEBUG(1, "%s\n", ibuf);
  593. X    syslog(ibuf);
  594. X    return ret;
  595. X}
  596. X
  597. Xstatic
  598. Xfrdbuf(blk, len, fn)
  599. Xregister char *blk;
  600. Xregister int len;
  601. Xregister int fn;
  602. X{
  603. X    static int ret = FBUFSIZ / 2;
  604. X#ifndef Not080
  605. X    extern int linebaudrate;
  606. X#endif Not080
  607. X
  608. X    if (setjmp(Ffailbuf))
  609. X        return FAIL;
  610. X#ifndef Not080
  611. X    if (len == FBUFSIZ && ret < FBUFSIZ / 2 &&
  612. X        linebaudrate > 0 && linebaudrate < 4800)
  613. X        sleep(1);
  614. X#endif Not080
  615. X    (void) alarm(MAXMSGTIME);
  616. X    ret = read(fn, blk, len);
  617. X    alarm(0);
  618. X    return ret <= 0 ? FAIL : ret;
  619. X}
  620. X
  621. X/* call ultouch every TC calls to either frdblk or fwrblk  */
  622. X
  623. X#define    TC    20
  624. Xstatic    int tc = TC;
  625. X
  626. X/* Byte conversion:
  627. X *
  628. X *   from        pre       to
  629. X * 000-037       172     100-137
  630. X * 040-171               040-171
  631. X * 172-177       173     072-077
  632. X * 200-237       174     100-137
  633. X * 240-371       175     040-171
  634. X * 372-377       176     072-077
  635. X */
  636. X
  637. Xstatic
  638. Xfwrblk(fn, ip, len)
  639. Xint fn;
  640. Xregister char *ip;
  641. Xregister int len;
  642. X{
  643. X    register char *op;
  644. X    register int sum, nl;
  645. X    int ret;
  646. X    char obuf[FBUFSIZ * 2];
  647. X
  648. X    /* call ultouch occasionally */
  649. X    if (--tc < 0) {
  650. X        tc = TC;
  651. X        ultouch();
  652. X    }
  653. X    DEBUG(8, "fwrblk: %d/", len);
  654. X    op = obuf;
  655. X    nl = 0;
  656. X    sum = chksum;
  657. X    do {
  658. X        if (sum & 0x8000) {
  659. X            sum <<= 1;
  660. X            sum++;
  661. X        } else
  662. X            sum <<= 1;
  663. X        sum += *ip & 0377;
  664. X        sum &= 0xffff;
  665. X        if (*ip & 0200) {
  666. X            *ip &= 0177;
  667. X            if (*ip < 040) {
  668. X                *op++ = '\174';
  669. X                *op++ = *ip++ + 0100;
  670. X            } else
  671. X            if (*ip <= 0171) {
  672. X                *op++ = '\175';
  673. X                *op++ = *ip++;
  674. X            }
  675. X            else {
  676. X                *op++ = '\176';
  677. X                *op++ = *ip++ - 0100;
  678. X            }
  679. X            nl += 2;
  680. X        } else {
  681. X            if (*ip < 040) {
  682. X                *op++ = '\172';
  683. X                *op++ = *ip++ + 0100;
  684. X                nl += 2;
  685. X            } else
  686. X            if (*ip <= 0171) {
  687. X                *op++ = *ip++;
  688. X                nl++;
  689. X            } else {
  690. X                *op++ = '\173';
  691. X                *op++ = *ip++ - 0100;
  692. X                nl += 2;
  693. X            }
  694. X        }
  695. X    } while (--len);
  696. X    chksum = sum;
  697. X    DEBUG(8, "%d\n", nl);
  698. X    ret = write(fn, obuf, nl);
  699. X    return ret == nl ? nl : ret < 0 ? 0 : -ret;
  700. X}
  701. X
  702. Xstatic
  703. Xfrdblk(ip, fn, rlen)
  704. Xregister char *ip;
  705. Xint fn;
  706. Xlong *rlen;
  707. X{
  708. X    register char *op, c;
  709. X    register int sum, len, nl;
  710. X    char buf[5], *erbp = ip;
  711. X    int i;
  712. X    static char special = 0;
  713. X
  714. X    /* call ultouch occasionally */
  715. X    if (--tc < 0) {
  716. X        tc = TC;
  717. X        ultouch();
  718. X    }
  719. X
  720. X    if ((len = frdbuf(ip, FBUFSIZ, fn)) == FAIL) {
  721. X        *rlen = 0;
  722. X        goto dcorr;
  723. X    }
  724. X    *rlen = len;
  725. X    DEBUG(8, "%d/", len);
  726. X    op = ip;
  727. X    nl = 0;
  728. X    sum = chksum;
  729. X    do {
  730. X        if ((*ip &= 0177) >= '\172') {
  731. X            if (special) {
  732. X                DEBUG(8, "%d", nl);
  733. X                special = 0;
  734. X                op = buf;
  735. X                if (*ip++ != '\176' || (i = --len) > 5)
  736. X                    goto dcorr;
  737. X                while (i--)
  738. X                    *op++ = *ip++;
  739. X                while (len < 5) {
  740. X                    i = frdbuf(&buf[len], 5 - len, fn);
  741. X                    if (i == FAIL) {
  742. X                        len = FAIL;
  743. X                        goto dcorr;
  744. X                    }
  745. X                    DEBUG(8, ",%d", i);
  746. X                    len += i;
  747. X                    *rlen += i;
  748. X                }
  749. X                if (buf[4] != '\r')
  750. X                    goto dcorr;
  751. X                sscanf(buf, "%4x", &chksum);
  752. X                DEBUG(8, "\nchecksum: %04x\n", sum);
  753. X                if (chksum == sum)
  754. X                    return FBUFSIZ + 1 + nl;
  755. X                else {
  756. X                    DEBUG(8, "\n", 0);
  757. X                    DEBUG(4, "Bad checksum\n", 0);
  758. X                    return FAIL;
  759. X                }
  760. X            }
  761. X            special = *ip++;
  762. X        } else {
  763. X            if (*ip < '\040') {
  764. X                /* error: shouldn't get control chars */
  765. X                goto dcorr;
  766. X            }
  767. X            switch (special) {
  768. X            case 0:
  769. X                c = *ip++;
  770. X                break;
  771. X            case '\172':
  772. X                c = *ip++ - 0100;
  773. X                break;
  774. X            case '\173':
  775. X                c = *ip++ + 0100;
  776. X                break;
  777. X            case '\174':
  778. X                c = *ip++ + 0100;
  779. X                break;
  780. X            case '\175':
  781. X                c = *ip++ + 0200;
  782. X                break;
  783. X            case '\176':
  784. X                c = *ip++ + 0300;
  785. X                break;
  786. X            }
  787. X            *op++ = c;
  788. X            if (sum & 0x8000) {
  789. X                sum <<= 1;
  790. X                sum++;
  791. X            } else
  792. X                sum <<= 1;
  793. X            sum += c & 0377;
  794. X            sum &= 0xffff;
  795. X            special = 0;
  796. X            nl++;
  797. X        }
  798. X    } while (--len);
  799. X    chksum = sum;
  800. X    DEBUG(8, "%d,", nl);
  801. X    return nl;
  802. Xdcorr:
  803. X    DEBUG(8, "\n", 0);
  804. X    DEBUG(4, "Data corrupted\n", 0);
  805. X    while (len != FAIL) {
  806. X        if ((len = frdbuf(erbp, FBUFSIZ, fn)) != FAIL)
  807. X            *rlen += len;
  808. X    }
  809. X    return FAIL;
  810. X}
  811. /
  812. echo 'Part 01 of pack.out complete.'
  813. exit
  814.  
  815.  
  816.