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