|
|
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.