home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / uucico / fio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-21  |  10.7 KB  |  551 lines

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