|
|
1.1 ! root 1: /* /sccs/src/cmd/uucp/s.pk0.c ! 2: pk0.c 1.2 8/30/84 17:37:36 ! 3: */ ! 4: #include "uucp.h" ! 5: VERSION(@(#)pk0.c 1.2); ! 6: #define USER 1 ! 7: ! 8: #include "pk.h" ! 9: #include <sys/buf.h> ! 10: ! 11: extern int Connodata; /* Continuous No Valid Data Count */ ! 12: ! 13: /* ! 14: * packet driver ! 15: */ ! 16: extern struct pack *pklines[]; ! 17: ! 18: /* ! 19: * receive control messages ! 20: * c -> message type fields ! 21: * pk -> line control unit ! 22: */ ! 23: pkcntl(c, pk) ! 24: register struct pack *pk; ! 25: { ! 26: register cntl, val; ! 27: static int reack = 0; ! 28: ! 29: val = c & MOD8; ! 30: cntl = (c>>3) & MOD8; ! 31: ! 32: if ( ! ISCNTL(c) ) { ! 33: fprintf(stderr, "not cntl\n"); ! 34: return; ! 35: } ! 36: ! 37: if (pk->p_mode & 02) ! 38: fprintf(stderr, "%o ",c); ! 39: switch(cntl) { ! 40: ! 41: case INITB: ! 42: val++; ! 43: pk->p_xsize = pksizes[val]; ! 44: pk->p_lpsize = val; ! 45: pk->p_bits = 1; ! 46: if (pk->p_state & LIVE) { ! 47: pk->p_msg |= M_INITC; ! 48: break; ! 49: } ! 50: pk->p_state |= INITb; ! 51: if ((pk->p_state & INITa)==0) { ! 52: break; ! 53: } ! 54: pk->p_rmsg &= ~M_INITA; ! 55: pk->p_msg |= M_INITC; ! 56: break; ! 57: ! 58: case INITC: ! 59: if ((pk->p_state&INITab)==INITab) { ! 60: pk->p_state = LIVE; ! 61: pk->p_rmsg &= ~M_INITB; ! 62: } else ! 63: pk->p_msg |= M_INITB; ! 64: if (val) ! 65: pk->p_swindow = val; ! 66: break; ! 67: case INITA: ! 68: if (val==0 && pk->p_state&LIVE) { ! 69: fprintf(stderr, "alloc change not implemented\n"); ! 70: break; ! 71: } ! 72: if (val) { ! 73: pk->p_state |= INITa; ! 74: pk->p_msg |= M_INITB; ! 75: pk->p_rmsg |= M_INITB; ! 76: pk->p_swindow = val; ! 77: } ! 78: break; ! 79: case RJ: ! 80: pk->p_state |= RXMIT; ! 81: pk->p_msg |= M_RR; ! 82: pk->p_rpr = val; ! 83: (void) pksack(pk); ! 84: DEBUG(9, "pkcntl: RJ: Connodata=%d\n", Connodata); ! 85: break; ! 86: case RR: ! 87: pk->p_rpr = val; ! 88: if (pk->p_rpr != pk->p_ps) { ! 89: reack = 0; ! 90: (void) pksack(pk); ! 91: } else { ! 92: DEBUG(9, "pkcntl: reack %d\n", reack); ! 93: if (++reack >= 4) { ! 94: DEBUG(6, "reack ovfl %d\n", val); ! 95: pk->p_state |= RXMIT; ! 96: pk->p_msg |= M_RR; ! 97: reack = 0; ! 98: } ! 99: } ! 100: break; ! 101: case SRJ: ! 102: fprintf(stderr, "srj not implemented\n"); ! 103: break; ! 104: case CLOSE: ! 105: pk->p_state = DOWN+RCLOSE; ! 106: return; ! 107: } ! 108: if (pk->p_msg) ! 109: pkoutput(pk); ! 110: } ! 111: ! 112: pkaccept(pk) ! 113: register struct pack *pk; ! 114: { ! 115: register x,seq; ! 116: char m, cntl, *p, imask, **bp; ! 117: int bad,accept,skip,t,cc; ! 118: unsigned short sum; ! 119: ! 120: ! 121: bad = accept = skip = 0; ! 122: ! 123: /* ! 124: * wait for input ! 125: */ ! 126: x = next[pk->p_pr]; ! 127: while ((imask=pk->p_imap) == 0 && pk->p_rcount==0) { ! 128: pkgetpack(pk); ! 129: } ! 130: pk->p_imap = 0; ! 131: ! 132: ! 133: /* ! 134: * determine input window in m. ! 135: */ ! 136: t = (~(-1<<pk->p_rwindow)) <<x; ! 137: m = t; ! 138: m |= t>>8; ! 139: ! 140: ! 141: /* ! 142: * mark newly accepted input buffers ! 143: */ ! 144: for(x=0; x<8; x++) { ! 145: ! 146: if ((imask & mask[x]) == 0) ! 147: continue; ! 148: ! 149: if (((cntl=pk->p_is[x])&0200)==0) { ! 150: bad++; ! 151: free: ! 152: bp = (char **)pk->p_ib[x]; ! 153: *bp = (char *)pk->p_ipool; ! 154: pk->p_ipool = bp; ! 155: pk->p_is[x] = 0; ! 156: continue; ! 157: } ! 158: ! 159: pk->p_is[x] = ~(B_COPY+B_MARK); ! 160: sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); ! 161: sum += pk->p_isum[x]; ! 162: if (sum == CHECK) { ! 163: seq = (cntl>>3) & MOD8; ! 164: if (m & mask[seq]) { ! 165: if (pk->p_is[seq] & (B_COPY | B_MARK)) { ! 166: dup: ! 167: pk->p_msg |= M_RR; ! 168: skip++; ! 169: goto free; ! 170: } ! 171: if (x != seq) { ! 172: p = pk->p_ib[x]; ! 173: pk->p_ib[x] = pk->p_ib[seq]; ! 174: pk->p_is[x] = pk->p_is[seq]; ! 175: pk->p_ib[seq] = p; ! 176: } ! 177: pk->p_is[seq] = B_MARK; ! 178: accept++; ! 179: cc = 0; ! 180: if (cntl&B_SHORT) { ! 181: pk->p_is[seq] = B_MARK+B_SHORT; ! 182: p = pk->p_ib[seq]; ! 183: cc = (unsigned)*p++ & 0377; ! 184: if (cc & 0200) { ! 185: cc &= 0177; ! 186: cc |= *p << 7; ! 187: } ! 188: } ! 189: pk->p_isum[seq] = pk->p_rsize - cc; ! 190: } else { ! 191: goto dup; ! 192: } ! 193: } else { ! 194: bad++; ! 195: goto free; ! 196: } ! 197: } ! 198: ! 199: /* ! 200: * scan window again turning marked buffers into ! 201: * COPY buffers and looking for missing sequence ! 202: * numbers. ! 203: */ ! 204: accept = 0; ! 205: for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) { ! 206: if (pk->p_is[x] & B_MARK) ! 207: pk->p_is[x] |= B_COPY; ! 208: ! 209: if (pk->p_is[x] & B_COPY) { ! 210: if (t >= 0) { ! 211: bp = (char **)pk->p_ib[x]; ! 212: *bp = (char *)pk->p_ipool; ! 213: pk->p_ipool = bp; ! 214: pk->p_is[x] = 0; ! 215: skip++; ! 216: } else ! 217: accept++; ! 218: } else { ! 219: if (t<0) ! 220: t = x; ! 221: } ! 222: } ! 223: ! 224: if (bad) { ! 225: pk->p_msg |= M_RJ; ! 226: } ! 227: ! 228: if (skip) { ! 229: pk->p_msg |= M_RR; ! 230: } ! 231: ! 232: pk->p_rcount = accept; ! 233: return(accept); ! 234: } ! 235: ! 236: ! 237: pkread(ipk, ibuf, icount) ! 238: int icount; char *ibuf; struct pack *ipk; ! 239: { ! 240: register struct pack *pk; ! 241: register x; ! 242: int is,cc,xfr,count; ! 243: char *cp, **bp; ! 244: ! 245: pk = ipk; ! 246: xfr = 0; ! 247: count = 0; ! 248: while (pkaccept(pk)==0) ! 249: ; ! 250: Connodata = 0; /* accecpted a packet -- good data */ ! 251: ! 252: ! 253: while (icount) { ! 254: ! 255: x = next[pk->p_pr]; ! 256: is = pk->p_is[x]; ! 257: ! 258: if (is & B_COPY) { ! 259: cc = MIN(pk->p_isum[x], icount); ! 260: if (cc==0 && xfr) { ! 261: break; ! 262: } ! 263: if (is & B_RESID) ! 264: cp = pk->p_rptr; ! 265: else { ! 266: cp = pk->p_ib[x]; ! 267: if (is & B_SHORT) { ! 268: if (*cp++ & 0200) ! 269: cp++; ! 270: } ! 271: } ! 272: { ! 273: register char *p, *q; ! 274: register int c; ! 275: ! 276: if(c=cc){ ! 277: p = ibuf; ! 278: q = cp; ! 279: do ! 280: *p++ = *q++; ! 281: while(--c); ! 282: ibuf += cc; ! 283: icount -= cc; ! 284: } ! 285: } ! 286: count += cc; ! 287: xfr++; ! 288: pk->p_isum[x] -= cc; ! 289: if (pk->p_isum[x] == 0) { ! 290: pk->p_pr = x; ! 291: bp = (char **)pk->p_ib[x]; ! 292: *bp = (char *)pk->p_ipool; ! 293: pk->p_ipool = bp; ! 294: pk->p_is[x] = 0; ! 295: pk->p_rcount--; ! 296: pk->p_msg |= M_RR; ! 297: } else { ! 298: pk->p_rptr = cp+cc; ! 299: pk->p_is[x] |= B_RESID; ! 300: } ! 301: if (cc==0) ! 302: break; ! 303: } else ! 304: break; ! 305: } ! 306: pkoutput(pk); ! 307: return(count); ! 308: } ! 309: ! 310: ! 311: ! 312: ! 313: pkwrite(ipk, ibuf, icount) ! 314: int icount; char *ibuf; struct pack *ipk; ! 315: { ! 316: register struct pack *pk; ! 317: register x; ! 318: caddr_t cp; ! 319: int partial; ! 320: int cc, fc, count; ! 321: char *malloc(); ! 322: ! 323: pk = ipk; ! 324: if (pk->p_state&DOWN || !pk->p_state&LIVE) { ! 325: return(-1); ! 326: } ! 327: ! 328: count = icount; ! 329: do { ! 330: while (pk->p_xcount>=pk->p_swindow) { ! 331: pkoutput(pk); ! 332: pkgetpack(pk); ! 333: } ! 334: x = next[pk->p_pscopy]; ! 335: while (pk->p_os[x]!=B_NULL) { ! 336: pkgetpack(pk); ! 337: } ! 338: pk->p_os[x] = B_MARK; ! 339: pk->p_pscopy = x; ! 340: pk->p_xcount++; ! 341: ! 342: cp = pk->p_ob[x] = (caddr_t) malloc((unsigned) pk->p_xsize); ! 343: partial = 0; ! 344: if ((int)icount < pk->p_xsize) { ! 345: cc = icount; ! 346: fc = pk->p_xsize - cc; ! 347: *cp = fc&0177; ! 348: if (fc > 127) { ! 349: *cp++ |= 0200; ! 350: *cp++ = fc>>7; ! 351: } else ! 352: cp++; ! 353: partial = B_SHORT; ! 354: } else ! 355: cc = pk->p_xsize; ! 356: { ! 357: register char *p, *q; ! 358: register int c; ! 359: ! 360: if(c=cc){ ! 361: q = ibuf; ! 362: p = cp; ! 363: do ! 364: *p++ = *q++; ! 365: while(--c); ! 366: ibuf += cc; ! 367: icount -= cc; ! 368: } ! 369: } ! 370: pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); ! 371: pk->p_os[x] = B_READY+partial; ! 372: pkoutput(pk); ! 373: } while (icount); ! 374: ! 375: return(count); ! 376: } ! 377: ! 378: pksack(pk) ! 379: register struct pack *pk; ! 380: { ! 381: register x, i; ! 382: ! 383: i = 0; ! 384: for(x=pk->p_ps; x!=pk->p_rpr; ) { ! 385: x = next[x]; ! 386: if (pk->p_os[x]&B_SENT) { ! 387: i++; ! 388: Connodata = 0; ! 389: pk->p_os[x] = B_NULL; ! 390: pk->p_state &= ~WAITO; ! 391: pk->p_xcount--; ! 392: free((char *) pk->p_ob[x]); ! 393: pk->p_ps = x; ! 394: } ! 395: } ! 396: return(i); ! 397: } ! 398: ! 399: ! 400: ! 401: pkoutput(pk) ! 402: register struct pack *pk; ! 403: { ! 404: register x; ! 405: char bstate; ! 406: int i; ! 407: ! 408: if (pk->p_obusy++) { ! 409: pk->p_obusy--; ! 410: return; ! 411: } ! 412: ! 413: ! 414: /* ! 415: * find seq number and buffer state ! 416: * of next output packet ! 417: */ ! 418: if (pk->p_state&RXMIT) ! 419: pk->p_nxtps = next[pk->p_rpr]; ! 420: x = pk->p_nxtps; ! 421: bstate = pk->p_os[x]; ! 422: ! 423: ! 424: /* ! 425: * Send control packet if indicated ! 426: */ ! 427: if (pk->p_msg) { ! 428: if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { ! 429: x = pk->p_msg; ! 430: for(i=0; i<8; i++) ! 431: if (x&1) ! 432: break; ! 433: else ! 434: x >>= 1; ! 435: x = i; ! 436: x <<= 3; ! 437: switch(i) { ! 438: case CLOSE: ! 439: break; ! 440: case RJ: ! 441: case RR: ! 442: x += pk->p_pr; ! 443: break; ! 444: case SRJ: ! 445: break; ! 446: case INITB: ! 447: x += pksize(pk->p_rsize); ! 448: break; ! 449: case INITC: ! 450: x += pk->p_rwindow; ! 451: break; ! 452: case INITA: ! 453: x += pk->p_rwindow; ! 454: break; ! 455: } ! 456: ! 457: pk->p_msg &= ~mask[i]; ! 458: pkxstart(pk, x, -1); ! 459: goto out; ! 460: } ! 461: } ! 462: ! 463: ! 464: /* ! 465: * Don't send data packets if line is marked dead. ! 466: */ ! 467: if (pk->p_state&DOWN) { ! 468: goto out; ! 469: } ! 470: ! 471: /* ! 472: * Start transmission (or retransmission) of data packets. ! 473: */ ! 474: if (bstate & (B_READY|B_SENT)) { ! 475: char seq; ! 476: ! 477: bstate |= B_SENT; ! 478: seq = x; ! 479: pk->p_nxtps = next[x]; ! 480: ! 481: x = 0200+pk->p_pr+(seq<<3); ! 482: if (bstate & B_SHORT) ! 483: x |= 0100; ! 484: pkxstart(pk, x, seq); ! 485: pk->p_os[seq] = bstate; ! 486: pk->p_state &= ~RXMIT; ! 487: pk->p_nout++; ! 488: goto out; ! 489: } ! 490: ! 491: /* ! 492: * enable timeout if there's nothing to send ! 493: * and transmission buffers are languishing ! 494: */ ! 495: if (pk->p_xcount) { ! 496: pk->p_timer = 2; ! 497: pk->p_state |= WAITO; ! 498: } else ! 499: pk->p_state &= ~WAITO; ! 500: out: ! 501: pk->p_obusy = 0; ! 502: } ! 503: ! 504: /* ! 505: * shut down line by ignoring new input ! 506: * letting output drain ! 507: * releasing space and turning off line discipline ! 508: */ ! 509: pkclose(ipk) ! 510: struct pack *ipk; ! 511: { ! 512: register struct pack *pk; ! 513: register i; ! 514: int rcheck; ! 515: char **bp; ! 516: ! 517: pk = ipk; ! 518: pk->p_state |= DRAINO; ! 519: ! 520: /* ! 521: * try to flush output ! 522: */ ! 523: i = 0; ! 524: pk->p_timer = 2; ! 525: while (pk->p_xcount && pk->p_state&LIVE) { ! 526: if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) ! 527: break; ! 528: pkoutput(pk); ! 529: } ! 530: pk->p_timer = 0; ! 531: pk->p_state |= DOWN; ! 532: ! 533: /* ! 534: * try to exchange CLOSE messages ! 535: */ ! 536: i = 0; ! 537: while ((pk->p_state&RCLOSE)==0 && i<2) { ! 538: pk->p_msg = M_CLOSE; ! 539: pk->p_timer = 2; ! 540: pkoutput(pk); ! 541: i++; ! 542: } ! 543: ! 544: ! 545: for(i=0;i<NPLINES;i++) ! 546: if (pklines[i]==pk) { ! 547: pklines[i] = NULL; ! 548: } ! 549: ! 550: /* ! 551: * free space ! 552: */ ! 553: rcheck = 0; ! 554: for (i=0;i<8;i++) { ! 555: if (pk->p_os[i]!=B_NULL) { ! 556: free((char *) pk->p_ob[i]); ! 557: pk->p_xcount--; ! 558: } ! 559: if (pk->p_is[i]!=B_NULL) { ! 560: free((char *) pk->p_ib[i]); ! 561: rcheck++; ! 562: } ! 563: } ! 564: while (pk->p_ipool != NULL) { ! 565: bp = pk->p_ipool; ! 566: pk->p_ipool = (char **)*bp; ! 567: rcheck++; ! 568: free((char *) bp); ! 569: } ! 570: if (rcheck != pk->p_rwindow) { ! 571: fprintf(stderr, "r short %d want %d\n",rcheck,pk->p_rwindow); ! 572: fprintf(stderr, "rcount = %d\n",pk->p_rcount); ! 573: fprintf(stderr, "xcount = %d\n",pk->p_xcount); ! 574: } ! 575: free((char *) pk); ! 576: } ! 577: ! 578: ! 579: ! 580: pkreset(pk) ! 581: register struct pack *pk; ! 582: { ! 583: ! 584: pk->p_ps = pk->p_pr = pk->p_rpr = 0; ! 585: pk->p_nxtps = 1; ! 586: } ! 587: ! 588: chksum(s,n) ! 589: register char *s; ! 590: register n; ! 591: { ! 592: register short sum; ! 593: register unsigned short t; ! 594: register short x; ! 595: ! 596: sum = -1; ! 597: x = 0; ! 598: ! 599: do { ! 600: if (sum<0) { ! 601: sum <<= 1; ! 602: sum++; ! 603: } else ! 604: sum <<= 1; ! 605: t = sum; ! 606: sum += (unsigned)*s++ & 0377; ! 607: x += sum^n; ! 608: if ((unsigned short)sum <= t) { ! 609: sum ^= x; ! 610: } ! 611: } while (--n > 0); ! 612: ! 613: return(sum); ! 614: } ! 615: ! 616: pkzero(s,n) ! 617: register char *s; ! 618: register n; ! 619: { ! 620: while (n--) ! 621: *s++ = 0; ! 622: } ! 623: ! 624: pksize(n) ! 625: register n; ! 626: { ! 627: register k; ! 628: ! 629: n >>= 5; ! 630: for(k=0; n >>= 1; k++); ! 631: return(k); ! 632: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.