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: }

Defined functions

cgalarm defined in line 350; used 1 times
pkcget defined in line 355; used 3 times
pkdata defined in line 219; used 1 times
pkgetpack defined in line 127; used 4 times
pkmove defined in line 322; used 2 times
pkopen defined in line 46; used 2 times
pkxstart defined in line 263; used 2 times

Defined variables

Connodata defined in line 31; used 4 times
Getjbuf defined in line 349; used 2 times
Ntimeout defined in line 32; used 5 times
iomask defined in line 17; used 1 times
pksizes defined in line 118; used 3 times
pktimeout defined in line 33; used 7 times
pktimeskew defined in line 34; used 3 times
sccsid defined in line 2; never used

Defined macros

CONNODATA defined in line 22; used 1 times
GETRIES defined in line 122; used 2 times
MAXPKTIME defined in line 21; used 2 times
MAXTIMEOUT defined in line 23; used 1 times
PKMAXBUF defined in line 255; used 1 times
PKMAXSTMSG defined in line 20; used 2 times
Last modified: 1986-05-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1549
Valid CSS Valid XHTML 1.0 Strict