|
|
1.1 root 1: /* /sccs/src/cmd/uucp/s.pk1.c
2: pk1.c 1.2 8/30/84 17:37:38
3: */
4: #include "uucp.h"
5: VERSION(@(#)pk1.c 1.2);
6:
7: #define USER 1
8:
9: #include "pk.h"
10: #include <sys/buf.h>
11:
12:
13: /*
14: ** Code added to allow translation of states from numbers to
15: ** letters, to be done in such a way as to be meaningful to
16: ** John Q. Public
17: */
18: struct {
19: int state;
20: char *msg;
21: } st_trans[] = {
22: DEAD, "Dead!",
23: INITa, "INIT code a",
24: INITb, "INIT code b",
25: LIVE, "O.K.",
26: RXMIT, "Rcv/Xmit",
27: RREJ, "RREJ?",
28: PDEBUG, "PDEBUG?",
29: DRAINO, "Draino...",
30: WAITO, "Waiting",
31: DOWN, "Link down",
32: RCLOSE, "RCLOSE?",
33: BADFRAME, "Bad frame",
34: -1, "End of the line",
35: };
36:
37:
38:
39: #define PKMAXSTMSG 40
40: extern int Errorrate;
41: int Connodata = 0; /* Continuous Non Valid Data Count */
42: int Ntimeout = 0;
43: #define CONNODATA 20 /* Max Continuous Non Valid Data Count */
44: #define NTIMEOUT 50 /* This is not currently used, but maybe future */
45:
46: /*
47: * packet driver support routines
48: *
49: */
50: extern struct pack *pklines[];
51:
52: /*
53: * start initial synchronization.
54: */
55: struct pack *
56: pkopen(ifn, ofn)
57: int ifn, ofn;
58: {
59: register struct pack *pk;
60: register char **bp;
61: register int i;
62: char *malloc();
63:
64: if (++pkactive >= NPLINES)
65: return(NULL);
66: if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL)
67: return(NULL);
68: pkzero((caddr_t) pk, sizeof (struct pack));
69: pk->p_ifn = ifn;
70: pk->p_ofn = ofn;
71: pk->p_xsize = pk->p_rsize = PACKSIZE;
72: pk->p_rwindow = pk->p_swindow = WINDOWS;
73:
74: /*
75: * allocate input window
76: */
77: for (i = 0; i < pk->p_rwindow; i++) {
78: if ((bp = (char **) malloc((unsigned) pk->p_xsize)) == NULL)
79: break;
80: *bp = (char *) pk->p_ipool;
81: pk->p_ipool = bp;
82: }
83: if (i == 0)
84: return(NULL);
85: pk->p_rwindow = i;
86:
87: /*
88: * start synchronization
89: */
90: pk->p_msg = pk->p_rmsg = M_INITA;
91: for (i = 0; i < NPLINES; i++) {
92: if (pklines[i] == NULL) {
93: pklines[i] = pk;
94: break;
95: }
96: }
97: if (i >= NPLINES)
98: return(NULL);
99: pkoutput(pk);
100:
101: for (i = 0; i < PKMAXSTMSG; i++) {
102: pkgetpack(pk);
103: if ((pk->p_state & LIVE) != 0)
104: break;
105: }
106: if (i >= PKMAXSTMSG)
107: return(NULL);
108:
109: pkreset(pk);
110: return(pk);
111: }
112:
113: /*
114: * input framing and block checking.
115: * frame layout for most devices is:
116: *
117: * S|K|X|Y|C|Z| ... data ... |
118: *
119: * where S == initial synch byte
120: * K == encoded frame size (indexes pksizes[])
121: * X, Y == block check bytes
122: * C == control byte
123: * Z == XOR of header (K^X^Y^C)
124: * data == 0 or more data bytes
125: *
126: */
127: #define GETRIES 10
128: #define GESYN 4100 /* overkill */
129:
130: /*
131: * Pseudo-dma byte collection.
132: */
133: pkgetpack(ipk)
134: register struct pack *ipk;
135: {
136: register char *p;
137: register struct pack *pk;
138: register struct header *h;
139: unsigned short sum;
140: int i, ret, k, tries, ifn, notsyn;
141: char **bp, hdchk, msgline[80], delimc;
142:
143: pk = ipk;
144: if ((pk->p_state & DOWN) ||
145: Connodata > CONNODATA /* || Ntimeout > NTIMEOUT */ )
146: pkfail();
147: ifn = pk->p_ifn;
148:
149: /*=
150: * find HEADER
151: */
152: for (tries = 0, notsyn = 0; tries < GETRIES && notsyn < GESYN; ) {
153: p = (caddr_t) &pk->p_ihbuf;
154: if ((ret = pkcget(ifn, p, 1)) < 0) {
155:
156: /*
157: * set up retransmit or REJ
158: */
159: tries++;
160: pk->p_msg |= pk->p_rmsg;
161: if (pk->p_msg == 0)
162: pk->p_msg |= M_RR;
163: if ((pk->p_state & LIVE) == LIVE)
164: pk->p_state |= RXMIT;
165: pkoutput(pk);
166: continue;
167: }
168: if (*p != SYN) {
169: notsyn++;
170: continue;
171: }
172: p++;
173: ret = pkcget(ifn, p, HDRSIZ - 1);
174: if (ret == -1)
175: continue;
176: break;
177: }
178: if (tries >= GETRIES) {
179: DEBUG(4, "tries = %d\n", tries);
180: pkfail();
181: }
182: if (notsyn >= GESYN) {
183: DEBUG(4, "notsyn = %d\n", notsyn);
184: pkfail();
185: }
186:
187: Connodata++;
188: DEBUG(9, "pkgetpack: Connodata=%d\n", Connodata);
189: h = (struct header * ) &pk->p_ihbuf;
190: p = (caddr_t) h;
191: hdchk = p[1] ^ p[2] ^ p[3] ^ p[4];
192: p += 2;
193: sum = (unsigned) *p++ & 0377;
194: sum |= (unsigned) *p << 8;
195: h->sum = sum;
196: DEBUG(9, "rec h->cntl %o\n", (unsigned) h->cntl);
197: k = h->ksize;
198: if (hdchk != h->ccntl) {
199:
200: /*
201: * bad header
202: */
203: DEBUG(7, "bad header %o,", hdchk);
204: DEBUG(7, "h->ccntl %o\n", h->ccntl);
205: return;
206: }
207: if (k == 9) {
208: if (h->sum + h->cntl == CHECK) {
209: pkcntl(h->cntl, pk);
210: /*
211: ** New code added to make the state diagnostics
212: ** meaningful to human beings that can't figure
213: ** out bizarre, silly, cryptic numbers.
214: **
215: ** Exhibit A: DEBUG(7, "state - %o\n", pk->p_state);
216: */
217: if(Debug >= 7) {
218: sprintf(msgline,"state -");
219: delimc = ' ';
220: for(i=0;st_trans[i].state!= -1;i++) {
221: if(pk->p_state&st_trans[i].state){
222: sprintf(msgline,"%s%c[%s]",msgline,delimc,
223: st_trans[i].msg);
224: delimc = '&';
225: }
226: }
227: sprintf(msgline,"%s (%o)\n",msgline,pk->p_state);
228: DEBUG(7,"%s",msgline);
229: }
230:
231: } else {
232:
233: /*
234: * bad header
235: */
236: DEBUG(7, "bad header %o\n", h->cntl);
237: pk->p_state |= BADFRAME;
238: }
239: return;
240: }
241: if (k && pksizes[k] == pk->p_rsize) {
242: pk->p_rpr = h->cntl & MOD8;
243: pksack(pk);
244: bp = pk->p_ipool;
245: if ((bp = pk->p_ipool) == NULL) {
246: DEBUG(7, "bp NULL %s\n", "");
247: return;
248: }
249: pk->p_ipool = (char **) *bp;
250: ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize);
251: if (ret == 0)
252: pkdata(h->cntl, h->sum, pk, bp);
253: }
254: }
255:
256:
257: pkdata(c, sum, pk, bp)
258: register struct pack *pk;
259: unsigned short sum;
260: char c;
261: char **bp;
262: {
263: register x;
264: int t;
265: char m;
266:
267: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) {
268: pk->p_msg |= pk->p_rmsg;
269: pkoutput(pk);
270: goto drop;
271: }
272: t = next[pk->p_pr];
273: for(x=pk->p_pr; x!=t; x = (x-1)&7) {
274: if (pk->p_is[x] == 0)
275: goto slot;
276: }
277: drop:
278: *bp = (char *)pk->p_ipool;
279: pk->p_ipool = bp;
280: return;
281:
282: slot:
283: m = mask[x];
284: pk->p_imap |= m;
285: pk->p_is[x] = c;
286: pk->p_isum[x] = sum;
287: pk->p_ib[x] = (char *)bp;
288: return;
289: }
290:
291: #define PKMAXBUF 128
292:
293: /*
294: * Start transmission on output device
295: * device associated with pk.
296: * For asynch devices (t_line==1) framing is
297: * imposed. For devices with framing and crc
298: * in the driver (t_line==2) the transfer is
299: * passed on to the driver.
300: */
301: pkxstart(pk, cntl, x)
302: register struct pack *pk;
303: int x;
304: char cntl;
305: {
306: register char *p;
307: register short checkword;
308: register char hdchk;
309: int ret;
310:
311: p = (caddr_t) &pk->p_ohbuf;
312: *p++ = SYN;
313: if (x < 0) {
314: *p++ = hdchk = 9;
315: checkword = cntl;
316: } else {
317: *p++ = hdchk = pk->p_lpsize;
318: checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377);
319: }
320: checkword = CHECK - checkword;
321: *p = checkword;
322: hdchk ^= *p++;
323: *p = checkword>>8;
324: hdchk ^= *p++;
325: *p = cntl;
326: hdchk ^= *p++;
327: *p = hdchk;
328:
329: /*
330: * writes
331: */
332: DEBUG(9, "send %o\n", (unsigned) cntl);
333: p = (caddr_t) & pk->p_ohbuf;
334: if (x < 0) {
335: ret = write(pk->p_ofn, p, HDRSIZ);
336: PKASSERT(ret == HDRSIZ, "PKXSTART ret", "", ret);
337: } else {
338: register char *b, *q;
339: register int i;
340: char buf[PKMAXBUF + HDRSIZ];
341:
342:
343: /*
344: for (i = 0, b = buf; i < HDRSIZ; i++)
345: *b++ = *p++;
346: for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++)
347: *b++ = *p++;
348: */
349: i = HDRSIZ;
350: b = buf;
351: q = p;
352: do
353: *b++ = *q++;
354: while(--i);
355: if(i = pk->p_xsize){
356: q = pk->p_ob[x];
357: do
358: *b++ = *q++;
359: while(--i);
360: }
361: ret = write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ);
362: PKASSERT(ret == pk->p_xsize + HDRSIZ,
363: "PKXSTART ret", "", ret);
364: }
365: if (pk->p_msg)
366: pkoutput(pk);
367: return;
368: }
369:
370:
371:
372:
373: /*
374: * get n characters from input
375: * b -> buffer for characters
376: * fn -> file descriptor
377: * n -> requested number of characters
378: * return:
379: * n -> number of characters returned
380: * 0 -> end of file
381: */
382: jmp_buf Getjbuf;
383: cgalarm() { longjmp(Getjbuf, 1); }
384: int npkccall, npkctry, npkcnap, npkcchar;
385:
386: pkcget(fn, b, n)
387: register int n;
388: register char *b;
389: register int fn;
390: {
391: register int ret;
392: register int donap;
393:
394: if (n == 0)
395: return(0);
396: npkccall++;
397: donap = (linebaudrate > 0 && linebaudrate < 4800);
398: if (setjmp(Getjbuf)) {
399: Ntimeout++;
400: DEBUG(4, "alarm %d\n", Ntimeout);
401: return(-1);
402: }
403: (void) signal(SIGALRM, cgalarm);
404:
405: (void) alarm((unsigned) (n < HDRSIZ ? 10 : 20));
406: while (1) {
407: if ((ret = read(fn, b, n)) == 0) {
408: (void) alarm(0);
409: return(-1);
410: }
411: npkctry++;
412: npkcchar += ret;
413: PKASSERT(ret > 0, "PKCGET READ", "", ret);
414: if ((n -= ret) <= 0)
415: break;
416: #ifdef PKSPEEDUP
417: if (donap) {
418: sleep(1);
419: npkcnap++;
420: #ifdef BSD4_2
421: } else {
422: nap(HZ/6);
423: #endif BSD4_2
424: }
425: #endif PKSPEEDUP
426: b += ret;
427: }
428: (void) alarm(0);
429: return(0);
430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.