|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)pk1.c 5.11 (Berkeley) 4/5/88"; ! 3: #endif ! 4: ! 5: #include <signal.h> ! 6: #include "uucp.h" ! 7: #include "pk.h" ! 8: #include <setjmp.h> ! 9: #ifdef BSD4_2 ! 10: #include <sys/time.h> ! 11: #include <sys/uio.h> ! 12: #else /* !BSD4_2 */ ! 13: struct iovec { ! 14: caddr_t iov_base; ! 15: int iov_len; ! 16: } ! 17: #endif /* !BSD4_2 */ ! 18: ! 19: #ifdef VMS ! 20: #include <eunice/eunice.h> ! 21: #include <vms/iodef.h> ! 22: #include <vms/ssdef.h> ! 23: int iomask[2]; ! 24: #endif VMS ! 25: ! 26: #define PKMAXSTMSG 40 ! 27: #define MAXPKTIME 32 /* was 16 */ ! 28: #define CONNODATA 10 ! 29: #define MAXTIMEOUT 32 ! 30: ! 31: extern int errno; ! 32: extern int Retries; ! 33: extern char *sys_errlist[]; ! 34: extern jmp_buf Sjbuf; ! 35: extern char *malloc(); ! 36: ! 37: int Connodata = 0; ! 38: int Ntimeout = 0; ! 39: int pktimeout = 4; ! 40: int pktimeskew = 2; ! 41: /* ! 42: * packet driver support routines ! 43: * ! 44: */ ! 45: ! 46: extern struct pack *pklines[]; ! 47: ! 48: /* ! 49: * start initial synchronization. ! 50: */ ! 51: ! 52: struct pack * ! 53: pkopen(ifn, ofn) ! 54: int ifn, ofn; ! 55: { ! 56: register struct pack *pk; ! 57: register char **bp; ! 58: register int i; ! 59: ! 60: if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL) ! 61: return NULL; ! 62: bzero((caddr_t) pk, sizeof (struct pack)); ! 63: pk->p_ifn = ifn; ! 64: pk->p_ofn = ofn; ! 65: pk->p_xsize = pk->p_rsize = PACKSIZE; ! 66: pk->p_rwindow = pk->p_swindow = WINDOWS; ! 67: /* allocate input windows */ ! 68: for (i = 0; i < pk->p_rwindow; i++) { ! 69: if ((bp = (char **) malloc((unsigned)pk->p_xsize)) == NULL) ! 70: break; ! 71: *bp = (char *) pk->p_ipool; ! 72: pk->p_ipool = bp; ! 73: } ! 74: if (i == 0) { ! 75: DEBUG(1, "pkopen: can't malloc i = 0\n", CNULL); ! 76: return NULL; ! 77: } ! 78: pk->p_rwindow = i; ! 79: ! 80: /* start synchronization */ ! 81: pk->p_msg = pk->p_rmsg = M_INITA; ! 82: for (i = 0; i < NPLINES; i++) { ! 83: if (pklines[i] == NULL) { ! 84: pklines[i] = pk; ! 85: break; ! 86: } ! 87: } ! 88: if (i >= NPLINES) { ! 89: DEBUG(1,"pkopen: i>=NPLINES\n", CNULL); ! 90: return NULL; ! 91: } ! 92: pkoutput(pk); ! 93: ! 94: for (i = 0; i < PKMAXSTMSG; i++) { ! 95: pkgetpack(pk); ! 96: if ((pk->p_state & LIVE) != 0) ! 97: break; ! 98: } ! 99: if (i >= PKMAXSTMSG) { ! 100: DEBUG(1, "pkopen: i>= PKMAXSTMSG\n", CNULL); ! 101: return NULL; ! 102: } ! 103: ! 104: pkreset(pk); ! 105: return pk; ! 106: } ! 107: ! 108: ! 109: /* ! 110: * input framing and block checking. ! 111: * frame layout for most devices is: ! 112: * ! 113: * S|K|X|Y|C|Z| ... data ... | ! 114: * ! 115: * where S == initial synch byte ! 116: * K == encoded frame size (indexes pksizes[]) ! 117: * X, Y == block check bytes ! 118: * C == control byte ! 119: * Z == XOR of header (K^X^Y^C) ! 120: * data == 0 or more data bytes ! 121: * ! 122: */ ! 123: ! 124: int pksizes[] = { ! 125: 1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1 ! 126: }; ! 127: ! 128: #define GETRIES 10 ! 129: /* ! 130: * Pseudo-dma byte collection. ! 131: */ ! 132: ! 133: pkgetpack(pk) ! 134: register struct pack *pk; ! 135: { ! 136: int k, tries, noise; ! 137: register char *p; ! 138: register struct header *h; ! 139: unsigned short sum; ! 140: int ifn; ! 141: char **bp; ! 142: char hdchk; ! 143: ! 144: if ((pk->p_state & DOWN) || Connodata > CONNODATA || Ntimeout > MAXTIMEOUT) ! 145: pkfail(); ! 146: ifn = pk->p_ifn; ! 147: ! 148: /* find HEADER */ ! 149: for (tries = 0, noise = 0; tries < GETRIES; ) { ! 150: p = (caddr_t) &pk->p_ihbuf; ! 151: if (pkcget(ifn, p, 1) == SUCCESS) { ! 152: if (*p++ == SYN) { ! 153: if (pkcget(ifn, p, HDRSIZ-1) == SUCCESS) ! 154: break; ! 155: } else { ! 156: if (noise++ < 10 || noise < (3*pk->p_rsize)) ! 157: continue; ! 158: } ! 159: DEBUG(4, "Noisy line - set up RXMIT\n", CNULL); ! 160: noise = 0; ! 161: } ! 162: /* set up retransmit or REJ */ ! 163: tries++; ! 164: Retries++; ! 165: pk->p_msg |= pk->p_rmsg; ! 166: if (pk->p_msg == 0) ! 167: pk->p_msg |= M_RR; ! 168: if ((pk->p_state & LIVE) == LIVE) ! 169: pk->p_state |= RXMIT; ! 170: pkoutput(pk); ! 171: } ! 172: if (tries >= GETRIES) { ! 173: DEBUG(4, "tries = %d\n", tries); ! 174: pkfail(); ! 175: } ! 176: ! 177: Connodata++; ! 178: h = (struct header *) &pk->p_ihbuf; ! 179: p = (caddr_t) h; ! 180: hdchk = p[1] ^ p[2] ^ p[3] ^ p[4]; ! 181: p += 2; ! 182: sum = (unsigned) *p++ & 0377; ! 183: sum |= (unsigned) *p << 8; ! 184: h->sum = sum; ! 185: DEBUG(7, "rec h->cntl 0%o\n", h->cntl&0xff); ! 186: k = h->ksize; ! 187: if (hdchk != h->ccntl) { ! 188: /* bad header */ ! 189: DEBUG(7, "bad header 0%o,", hdchk&0xff); ! 190: DEBUG(7, "h->ccntl 0%o\n", h->ccntl&0xff); ! 191: return; ! 192: } ! 193: if (k == 9) { ! 194: if (((h->sum + h->cntl) & 0xffff) == CHECK) { ! 195: pkcntl(h->cntl, pk); ! 196: DEBUG(7, "state - 0%o\n", pk->p_state); ! 197: } else { ! 198: /* bad header */ ! 199: pk->p_state |= BADFRAME; ! 200: DEBUG(7, "bad header (k==9) 0%o\n", h->cntl&0xff); ! 201: } ! 202: return; ! 203: } ! 204: if (k && pksizes[k] == pk->p_rsize) { ! 205: pk->p_rpr = h->cntl & MOD8; ! 206: DEBUG(7, "end pksack 0%o\n", pk->p_rpr); ! 207: pksack(pk); ! 208: bp = pk->p_ipool; ! 209: if (bp == NULL) { ! 210: DEBUG(7, "bp NULL %s\n", ""); ! 211: return; ! 212: } ! 213: pk->p_ipool = (char **) *bp; ! 214: Connodata = 0; ! 215: } else ! 216: return; ! 217: ! 218: if (pkcget(pk->p_ifn, (char *) bp, pk->p_rsize) == SUCCESS) { ! 219: pkdata(h->cntl, h->sum, pk, (char **) bp); ! 220: } else { ! 221: *bp = (char *)pk->p_ipool; ! 222: pk->p_ipool = bp; ! 223: } ! 224: } ! 225: ! 226: pkdata(c, sum, pk, bp) ! 227: char c; ! 228: unsigned short sum; ! 229: register struct pack *pk; ! 230: char **bp; ! 231: { ! 232: register x; ! 233: register int t; ! 234: ! 235: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) { ! 236: pk->p_msg |= pk->p_rmsg; ! 237: pkoutput(pk); ! 238: goto drop; ! 239: } ! 240: t = next[pk->p_pr]; ! 241: for(x = pk->p_pr; x != t; x = (x-1)&7) { ! 242: if (pk->p_is[x] == 0) { ! 243: pk->p_imap |= mask[x]; ! 244: pk->p_is[x] = c; ! 245: pk->p_isum[x] = sum; ! 246: pk->p_ib[x] = (char *)bp; ! 247: return; ! 248: } ! 249: } ! 250: drop: ! 251: *bp = (char *)pk->p_ipool; ! 252: pk->p_ipool = bp; ! 253: } ! 254: ! 255: /* ! 256: * setup input transfers ! 257: * ! 258: * Start transmission on output device associated with pk. ! 259: * For asynch devices (t_line==1) framing is ! 260: * imposed. For devices with framing and crc ! 261: * in the driver (t_line==2) the transfer is ! 262: * passed on to the driver. ! 263: */ ! 264: pkxstart(pk, cntl, x) ! 265: register struct pack *pk; ! 266: char cntl; ! 267: register x; ! 268: { ! 269: register char *p; ! 270: short checkword; ! 271: char hdchk; ! 272: ! 273: p = (caddr_t) &pk->p_ohbuf; ! 274: *p++ = SYN; ! 275: if (x < 0) { ! 276: *p++ = hdchk = 9; ! 277: checkword = cntl; ! 278: } else { ! 279: *p++ = hdchk = pk->p_lpsize; ! 280: checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377); ! 281: } ! 282: checkword = CHECK - checkword; ! 283: *p = checkword; ! 284: hdchk ^= *p++; ! 285: *p = checkword>>8; ! 286: hdchk ^= *p++; ! 287: *p = cntl; ! 288: hdchk ^= *p++; ! 289: *p = hdchk; ! 290: /* writes */ ! 291: DEBUG(7, "send 0%o\n", cntl&0xff); ! 292: p = (caddr_t) & pk->p_ohbuf; ! 293: if (x < 0) { ! 294: if(write(pk->p_ofn, p, HDRSIZ) != HDRSIZ) { ! 295: alarm(0); ! 296: logent("PKXSTART write failed", sys_errlist[errno]); ! 297: longjmp(Sjbuf, 4); ! 298: } ! 299: } else { ! 300: struct iovec iov[2]; ! 301: ! 302: iov[0].iov_base = p; ! 303: iov[0].iov_len = HDRSIZ; ! 304: iov[1].iov_base = pk->p_ob[x]; ! 305: iov[1].iov_len = pk->p_xsize; ! 306: ! 307: if (writev(pk->p_ofn, iov, 2) < 0) { ! 308: alarm(0); ! 309: logent("PKXSTART write failed", sys_errlist[errno]); ! 310: longjmp(Sjbuf, 5); ! 311: } ! 312: #ifdef 0 ! 313: char buf[PKMAXBUF + HDRSIZ], *b; ! 314: int i; ! 315: for (i = 0, b = buf; i < HDRSIZ; i++) ! 316: *b++ = *p++; ! 317: for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++) ! 318: *b++ = *p++; ! 319: ! 320: if (write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ) ! 321: != (HDRSIZ + pk->p_xsize)) { ! 322: alarm(0); ! 323: logent("PKXSTART write failed", sys_errlist[errno]); ! 324: longjmp(Sjbuf, 5); ! 325: } ! 326: #endif 0 ! 327: Connodata = 0; ! 328: } ! 329: if (pk->p_msg) ! 330: pkoutput(pk); ! 331: } ! 332: ! 333: /* ! 334: * get n characters from input ! 335: * ! 336: * return codes: ! 337: * n - number of characters returned ! 338: * 0 - end of file ! 339: */ ! 340: ! 341: jmp_buf Getjbuf; ! 342: cgalarm() ! 343: { ! 344: longjmp(Getjbuf, 1); ! 345: } ! 346: ! 347: pkcget(fn, b, n) ! 348: int fn; ! 349: register char *b; ! 350: register int n; ! 351: { ! 352: register int ret; ! 353: extern int linebaudrate; ! 354: #ifdef BSD4_2 ! 355: long r, itime = 100000L; /* guess it's been 1/10th second since we ! 356: last read the line */ ! 357: struct timeval tv; ! 358: #endif BSD4_2 ! 359: #ifdef VMS ! 360: short iosb[4]; ! 361: int SYS$QioW(); /* use this for long reads on vms */ ! 362: #endif VMS ! 363: ! 364: if (setjmp(Getjbuf)) { ! 365: Ntimeout++; ! 366: DEBUG(4, "pkcget: alarm %d\n", pktimeout * 1000 + Ntimeout); ! 367: pktimeout += pktimeskew; ! 368: if (pktimeout > MAXPKTIME) ! 369: pktimeout = MAXPKTIME; ! 370: return FAIL; ! 371: } ! 372: signal(SIGALRM, cgalarm); ! 373: ! 374: alarm(pktimeout); ! 375: while (n > 0) { ! 376: #ifdef BSD4_2 ! 377: if (linebaudrate > 0) { ! 378: r = n * 100000L; ! 379: r = r / linebaudrate; ! 380: r = (r * 100) - itime; ! 381: itime = 0; ! 382: /* we predict that more than 1/50th of a ! 383: second will go by before the read will ! 384: give back all that we want. */ ! 385: if (r > 20000) { ! 386: tv.tv_sec = r / 1000000L; ! 387: tv.tv_usec = r % 1000000L; ! 388: DEBUG(11, "PKCGET stall for %d", tv.tv_sec); ! 389: DEBUG(11, ".%06d sec\n", tv.tv_usec); ! 390: (void) select (0, (int *)0, (int *)0, (int *)0, &tv); ! 391: } ! 392: } ! 393: #endif BSD4_2 ! 394: #ifndef VMS ! 395: ret = read(fn, b, n); ! 396: #else VMS ! 397: _$Cancel_IO_On_Signal = FD_FAB_Pointer[fn]; ! 398: ret = SYS$QioW(_$EFN,(FD_FAB_Pointer[fn]->fab).fab$l_stv, ! 399: IO$_READVBLK|IO$M_NOFILTR|IO$M_NOECHO, ! 400: iosb,0,0,b,n,0, ! 401: iomask,0,0); ! 402: _$Cancel_IO_On_Signal = 0; ! 403: if (ret == SS$_NORMAL) ! 404: ret = iosb[1]+iosb[3]; /* get length of transfer */ ! 405: else ! 406: ret = 0; ! 407: #endif VMS ! 408: if (ret == 0) { ! 409: alarm(0); ! 410: return FAIL; ! 411: } ! 412: if (ret <= 0) { ! 413: alarm(0); ! 414: logent(sys_errlist[errno],"FAILED pkcget Read"); ! 415: longjmp(Sjbuf, 6); ! 416: } ! 417: b += ret; ! 418: n -= ret; ! 419: } ! 420: alarm(0); ! 421: return SUCCESS; ! 422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.