1: #ifndef lint
   2: static char sccsid[] = "@(#)fio.c	5.3 (Berkeley) 10/9/85";
   3: #endif
   4: 
   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: #include <signal.h>
  48: #ifdef USG
  49: #include <termio.h>
  50: #else !USG
  51: #include <sgtty.h>
  52: #endif !USG
  53: #include <setjmp.h>
  54: 
  55: #define FIBUFSIZ    256 /* for X.25 interfaces: set equal to packet size,
  56: 				 * but see comment above
  57: 				 */
  58: 
  59: #define FOBUFSIZ    256 /* for X.25 interfaces: set equal to packet size;
  60: 				 * otherwise make as large as feasible to reduce
  61: 				 * number of write system calls
  62: 				 */
  63: 
  64: #ifndef MAXMSGLEN
  65: #define MAXMSGLEN   BUFSIZ
  66: #endif MAXMSGLEN
  67: 
  68: static int fchksum;
  69: static jmp_buf Ffailbuf;
  70: 
  71: static
  72: falarm()
  73: {
  74:     signal(SIGALRM, falarm);
  75:     longjmp(Ffailbuf, 1);
  76: }
  77: 
  78: static int (*fsig)();
  79: 
  80: #ifndef USG
  81: #define TCGETA  TIOCGETP
  82: #define TCSETA  TIOCSETP
  83: #define termio  sgttyb
  84: #endif USG
  85: 
  86: fturnon()
  87: {
  88:     int ret;
  89:     struct termio ttbuf;
  90: 
  91:     if (!IsTcpIp) {
  92:         ioctl(Ifn, TCGETA, &ttbuf);
  93: #ifdef USG
  94:         ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
  95:         ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
  96:         ttbuf.c_cc[VTIME] = 5;
  97: #else !USG
  98:         ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
  99: #endif USG
 100:         ret = ioctl(Ifn, TCSETA, &ttbuf);
 101:         ASSERT(ret >= 0, "STTY FAILED", "", ret);
 102:     }
 103:     fsig = signal(SIGALRM, falarm);
 104:     /* give the other side time to perform its ioctl;
 105: 	 * otherwise it may flush out the first data this
 106: 	 * side is about to send.
 107: 	 */
 108:     sleep(2);
 109:     return SUCCESS;
 110: }
 111: 
 112: fturnoff()
 113: {
 114:     (void) signal(SIGALRM, fsig);
 115:     return SUCCESS;
 116: }
 117: 
 118: fwrmsg(type, str, fn)
 119: register char *str;
 120: int fn;
 121: char type;
 122: {
 123:     register char *s;
 124:     char bufr[MAXMSGLEN];
 125: 
 126:     s = bufr;
 127:     *s++ = type;
 128:     while (*str)
 129:         *s++ = *str++;
 130:     if (*(s-1) == '\n')
 131:         s--;
 132:     *s++ = '\r';
 133:     *s = 0;
 134:     (void) write(fn, bufr, s - bufr);
 135:     return SUCCESS;
 136: }
 137: 
 138: frdmsg(str, fn)
 139: register char *str;
 140: register int fn;
 141: {
 142:     register char *smax;
 143: 
 144:     if (setjmp(Ffailbuf))
 145:         return FAIL;
 146:     smax = str + MAXMSGLEN - 1;
 147:     (void) alarm(2*MAXMSGTIME);
 148:     for (;;) {
 149:         if (read(fn, str, 1) <= 0)
 150:             goto msgerr;
 151:         *str &= 0177;
 152:         if (*str == '\r')
 153:             break;
 154:         if (*str < ' ') {
 155:             continue;
 156:         }
 157:         if (str++ >= smax)
 158:             goto msgerr;
 159:     }
 160:     *str = '\0';
 161:     (void) alarm(0);
 162:     return SUCCESS;
 163: msgerr:
 164:     (void) alarm(0);
 165:     return FAIL;
 166: }
 167: 
 168: fwrdata(fp1, fn)
 169: FILE *fp1;
 170: int fn;
 171: {
 172:     register int alen, ret;
 173:     register char *obp;
 174:     char ack, ibuf[MAXMSGLEN];
 175:     int flen, mil, retries = 0;
 176:     long abytes, fbytes;
 177:     struct timeb t1, t2;
 178: 
 179:     ret = FAIL;
 180: retry:
 181:     fchksum = 0xffff;
 182:     abytes = fbytes = 0L;
 183:     ack = '\0';
 184: #ifdef USG
 185:     time(&t1.time);
 186:     t1.millitm = 0;
 187: #else !USG
 188:     ftime(&t1);
 189: #endif !USG
 190:     do {
 191:         alen = fwrblk(fn, fp1, &flen);
 192:         fbytes += flen;
 193:         if (alen <= 0) {
 194:             abytes -= alen;
 195:             goto acct;
 196:         }
 197:         abytes += alen;
 198:     } while (!feof(fp1) && !ferror(fp1));
 199:     DEBUG(8, "\nchecksum: %04x\n", fchksum);
 200:     if (frdmsg(ibuf, fn) != FAIL) {
 201:         if ((ack = ibuf[0]) == 'G')
 202:             ret = SUCCESS;
 203:         DEBUG(4, "ack - '%c'\n", ack);
 204:     }
 205: acct:
 206: #ifdef USG
 207:     time(&t2.time);
 208:     t2.millitm = 0;
 209: #else !USG
 210:     ftime(&t2);
 211: #endif !USG
 212:     Now = t2;
 213:     t2.time -= t1.time;
 214:     mil = t2.millitm - t1.millitm;
 215:     if (mil < 0) {
 216:         --t2.time;
 217:         mil += 1000;
 218:     }
 219:     sprintf(ibuf, "sent data %ld bytes %ld.%02d secs",
 220:         fbytes, (long)t2.time, mil / 10);
 221:     sysacct(abytes, t2.time);
 222:     if (retries > 0)
 223:         sprintf(&ibuf[strlen(ibuf)], ", %d retries", retries);
 224:     DEBUG(1, "%s\n", ibuf);
 225:     syslog(ibuf);
 226:     if (ack == 'R') {
 227:         DEBUG(4, "RETRY:\n", 0);
 228:         fseek(fp1, 0L, 0);
 229:         retries++;
 230:         goto retry;
 231:     }
 232: #ifdef SYSACCT
 233:     if (ret == FAIL)
 234:         sysaccf(NULL);      /* force accounting */
 235: #endif SYSACCT
 236:     return ret;
 237: }
 238: 
 239: /* max. attempts to retransmit a file: */
 240: #define MAXRETRIES  (fbytes < 10000L ? 2 : 1)
 241: 
 242: frddata(fn, fp2)
 243: register int fn;
 244: register FILE *fp2;
 245: {
 246:     register int flen;
 247:     register char eof;
 248:     char ibuf[FIBUFSIZ];
 249:     int ret, mil, retries = 0;
 250:     long alen, abytes, fbytes;
 251:     struct timeb t1, t2;
 252: 
 253:     ret = FAIL;
 254: retry:
 255:     fchksum = 0xffff;
 256:     abytes = fbytes = 0L;
 257: #ifdef USG
 258:     time(&t1.time);
 259:     t1.millitm = 0;
 260: #else !USG
 261:     ftime(&t1);
 262: #endif !USG
 263:     do {
 264:         flen = frdblk(ibuf, fn, &alen);
 265:         abytes += alen;
 266:         if (flen < 0)
 267:             goto acct;
 268:         if (eof = flen > FIBUFSIZ)
 269:             flen -= FIBUFSIZ + 1;
 270:         fbytes += flen;
 271:         if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
 272:             goto acct;
 273:     } while (!eof);
 274:     ret = SUCCESS;
 275: acct:
 276: #ifdef USG
 277:     time(&t2.time);
 278:     t2.millitm = 0;
 279: #else !USG
 280:     ftime(&t2);
 281: #endif !USG
 282:     Now = t2;
 283:     t2.time -= t1.time;
 284:     mil = t2.millitm - t1.millitm;
 285:     if (mil < 0) {
 286:         --t2.time;
 287:         mil += 1000;
 288:     }
 289:     sprintf(ibuf, "received data %ld bytes %ld.%02d secs",
 290:         fbytes, (long)t2.time, mil/10);
 291:     if (retries > 0)
 292:         sprintf(&ibuf[strlen(ibuf)]," %d retries", retries);
 293:     sysacct(abytes, t2.time);
 294:     DEBUG(1, "%s\n", ibuf);
 295:     syslog(ibuf);
 296:     if (ret == FAIL) {
 297:         if (retries++ < MAXRETRIES) {
 298:             DEBUG(8, "send ack: 'R'\n", 0);
 299:             fwrmsg('R', "", fn);
 300:             fseek(fp2, 0L, 0);
 301:             DEBUG(4, "RETRY:\n", 0);
 302:             goto retry;
 303:         }
 304:         DEBUG(8, "send ack: 'Q'\n", 0);
 305:         fwrmsg('Q', "", fn);
 306: #ifdef SYSACCT
 307:         sysaccf(NULL);      /* force accounting */
 308: #endif SYSACCT
 309:     }
 310:     else {
 311:         DEBUG(8, "send ack: 'G'\n", 0);
 312:         fwrmsg('G', "", fn);
 313:     }
 314:     return ret;
 315: }
 316: 
 317: static
 318: frdbuf(blk, len, fn)
 319: register char *blk;
 320: register int len;
 321: register int fn;
 322: {
 323:     static int ret = FIBUFSIZ / 2;
 324: 
 325:     if (setjmp(Ffailbuf))
 326:         return FAIL;
 327:     (void) alarm(MAXMSGTIME);
 328:     ret = read(fn, blk, len);
 329:     alarm(0);
 330:     return ret <= 0 ? FAIL : ret;
 331: }
 332: 
 333: #if !defined(BSD4_2) && !defined(USG)
 334: /* call ultouch every TC calls to either frdblk or fwrblk  */
 335: #define TC  20
 336: static int tc = TC;
 337: #endif !defined(BSD4_2) && !defined(USG)
 338: 
 339: /* Byte conversion:
 340:  *
 341:  *   from	 pre	   to
 342:  * 000-037	 172	 100-137
 343:  * 040-171		 040-171
 344:  * 172-177	 173	 072-077
 345:  * 200-237	 174	 100-137
 346:  * 240-371	 175	 040-171
 347:  * 372-377	 176	 072-077
 348:  */
 349: 
 350: static
 351: fwrblk(fn, fp, lenp)
 352: int fn;
 353: register FILE *fp;
 354: int *lenp;
 355: {
 356:     register char *op;
 357:     register int c, sum, nl, len;
 358:     char obuf[FOBUFSIZ + 8];
 359:     int ret;
 360: 
 361: #if !defined(BSD4_2) && !defined(USG)
 362:     /* call ultouch occasionally */
 363:     if (--tc < 0) {
 364:         tc = TC;
 365:         ultouch();
 366:     }
 367: #endif !defined(BSD4_2) && !defined(USG)
 368:     op = obuf;
 369:     nl = 0;
 370:     len = 0;
 371:     sum = fchksum;
 372:     while ((c = getc(fp)) != EOF) {
 373:         len++;
 374:         if (sum & 0x8000) {
 375:             sum <<= 1;
 376:             sum++;
 377:         } else
 378:             sum <<= 1;
 379:         sum += c;
 380:         sum &= 0xffff;
 381:         if (c & 0200) {
 382:             c &= 0177;
 383:             if (c < 040) {
 384:                 *op++ = '\174';
 385:                 *op++ = c + 0100;
 386:             } else
 387:             if (c <= 0171) {
 388:                 *op++ = '\175';
 389:                 *op++ = c;
 390:             }
 391:             else {
 392:                 *op++ = '\176';
 393:                 *op++ = c - 0100;
 394:             }
 395:             nl += 2;
 396:         } else {
 397:             if (c < 040) {
 398:                 *op++ = '\172';
 399:                 *op++ = c + 0100;
 400:                 nl += 2;
 401:             } else
 402:             if (c <= 0171) {
 403:                 *op++ = c;
 404:                 nl++;
 405:             } else {
 406:                 *op++ = '\173';
 407:                 *op++ = c - 0100;
 408:                 nl += 2;
 409:             }
 410:         }
 411:         if (nl >= FOBUFSIZ - 1) {
 412:             /*
 413: 			 * peek at next char, see if it will fit
 414: 			 */
 415:             c = getc(fp);
 416:             if (c == EOF)
 417:                 break;
 418:             (void) ungetc(c, fp);
 419:             if (nl >= FOBUFSIZ || c < 040 || c > 0171)
 420:                 goto writeit;
 421:         }
 422:     }
 423:     /*
 424: 	 * At EOF - append checksum, there is space for it...
 425: 	 */
 426:     sprintf(op, "\176\176%04x\r", sum);
 427:     nl += strlen(op);
 428: writeit:
 429:     *lenp = len;
 430:     fchksum = sum;
 431:     DEBUG(8, "%d/", len);
 432:     DEBUG(8, "%d,", nl);
 433:     ret = write(fn, obuf, nl);
 434:     return ret == nl ? nl : ret < 0 ? 0 : -ret;
 435: }
 436: 
 437: static
 438: frdblk(ip, fn, rlen)
 439: register char *ip;
 440: int fn;
 441: long *rlen;
 442: {
 443:     register char *op, c;
 444:     register int sum, len, nl;
 445:     char buf[5], *erbp = ip;
 446:     int i;
 447:     static char special = 0;
 448: 
 449: #if !defined(BSD4_2) && !defined(USG)
 450:     /* call ultouch occasionally */
 451:     if (--tc < 0) {
 452:         tc = TC;
 453:         ultouch();
 454:     }
 455: #endif !defined(BSD4_2) && !defined(USG)
 456:     if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
 457:         *rlen = 0;
 458:         goto dcorr;
 459:     }
 460:     *rlen = len;
 461:     DEBUG(8, "%d/", len);
 462:     op = ip;
 463:     nl = 0;
 464:     sum = fchksum;
 465:     do {
 466:         if ((*ip &= 0177) >= '\172') {
 467:             if (special) {
 468:                 DEBUG(8, "%d", nl);
 469:                 special = 0;
 470:                 op = buf;
 471:                 if (*ip++ != '\176' || (i = --len) > 5)
 472:                     goto dcorr;
 473:                 while (i--)
 474:                     *op++ = *ip++ & 0177;
 475:                 while (len < 5) {
 476:                     i = frdbuf(&buf[len], 5 - len, fn);
 477:                     if (i == FAIL) {
 478:                         len = FAIL;
 479:                         goto dcorr;
 480:                     }
 481:                     DEBUG(8, ",%d", i);
 482:                     len += i;
 483:                     *rlen += i;
 484:                     while (i--)
 485:                         *op++ &= 0177;
 486:                 }
 487:                 if (buf[4] != '\r')
 488:                     goto dcorr;
 489:                 sscanf(buf, "%4x", &fchksum);
 490:                 DEBUG(8, "\nchecksum: %04x\n", sum);
 491:                 if (fchksum == sum)
 492:                     return FIBUFSIZ + 1 + nl;
 493:                 else {
 494:                     DEBUG(8, "\n", 0);
 495:                     DEBUG(4, "Bad checksum\n", 0);
 496:                     return FAIL;
 497:                 }
 498:             }
 499:             special = *ip++;
 500:         } else {
 501:             if (*ip < '\040') {
 502:                 /* error: shouldn't get control chars */
 503:                 goto dcorr;
 504:             }
 505:             switch (special) {
 506:             case 0:
 507:                 c = *ip++;
 508:                 break;
 509:             case '\172':
 510:                 c = *ip++ - 0100;
 511:                 break;
 512:             case '\173':
 513:                 c = *ip++ + 0100;
 514:                 break;
 515:             case '\174':
 516:                 c = *ip++ + 0100;
 517:                 break;
 518:             case '\175':
 519:                 c = *ip++ + 0200;
 520:                 break;
 521:             case '\176':
 522:                 c = *ip++ + 0300;
 523:                 break;
 524:             }
 525:             *op++ = c;
 526:             if (sum & 0x8000) {
 527:                 sum <<= 1;
 528:                 sum++;
 529:             } else
 530:                 sum <<= 1;
 531:             sum += c & 0377;
 532:             sum &= 0xffff;
 533:             special = 0;
 534:             nl++;
 535:         }
 536:     } while (--len);
 537:     fchksum = sum;
 538:     DEBUG(8, "%d,", nl);
 539:     return nl;
 540: dcorr:
 541:     DEBUG(8, "\n", 0);
 542:     DEBUG(4, "Data corrupted\n", 0);
 543:     while (len != FAIL) {
 544:         if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
 545:             *rlen += len;
 546:     }
 547:     return FAIL;
 548: }

Defined functions

falarm defined in line 71; used 2 times
frdblk defined in line 437; used 1 times
frdbuf defined in line 317; used 3 times
frddata defined in line 242; used 2 times
frdmsg defined in line 138; used 3 times
fturnoff defined in line 112; used 2 times
fturnon defined in line 86; used 2 times
fwrblk defined in line 350; used 1 times
fwrdata defined in line 168; used 2 times
fwrmsg defined in line 118; used 5 times

Defined variables

Ffailbuf defined in line 69; used 3 times
fchksum defined in line 68; used 9 times
sccsid defined in line 2; never used
tc defined in line 336; used 4 times

Defined macros

FIBUFSIZ defined in line 55; used 9 times
FOBUFSIZ defined in line 59; used 3 times
MAXMSGLEN defined in line 65; used 4 times
MAXRETRIES defined in line 240; used 1 times
TC defined in line 335; used 3 times
TCGETA defined in line 81; used 1 times
  • in line 92
TCSETA defined in line 82; used 1 times
termio defined in line 83; never used
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3274
Valid CSS Valid XHTML 1.0 Strict