|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.