|
|
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: if ((bp = pk->p_ipool) == NULL) {
245: DEBUG(7, "bp NULL %s\n", "");
246: return;
247: }
248: pk->p_ipool = (char **) *bp;
249: ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize);
250: if (ret == 0)
251: pkdata(h->cntl, h->sum, pk, bp);
252: }
253: }
254:
255:
256: pkdata(c, sum, pk, bp)
257: register struct pack *pk;
258: unsigned short sum;
259: char c;
260: char **bp;
261: {
262: register x;
263: int t;
264: char m;
265:
266: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) {
267: pk->p_msg |= pk->p_rmsg;
268: pkoutput(pk);
269: goto drop;
270: }
271: t = next[pk->p_pr];
272: for(x=pk->p_pr; x!=t; x = (x-1)&7) {
273: if (pk->p_is[x] == 0)
274: goto slot;
275: }
276: drop:
277: *bp = (char *)pk->p_ipool;
278: pk->p_ipool = bp;
279: return;
280:
281: slot:
282: m = mask[x];
283: pk->p_imap |= m;
284: pk->p_is[x] = c;
285: pk->p_isum[x] = sum;
286: pk->p_ib[x] = (char *)bp;
287: return;
288: }
289:
290: #define PKMAXBUF 128
291:
292: /*
293: * Start transmission on output device
294: * device associated with pk.
295: * For asynch devices (t_line==1) framing is
296: * imposed. For devices with framing and crc
297: * in the driver (t_line==2) the transfer is
298: * passed on to the driver.
299: */
300: pkxstart(pk, cntl, x)
301: register struct pack *pk;
302: int x;
303: char cntl;
304: {
305: register char *p;
306: register short checkword;
307: register char hdchk;
308: int ret;
309:
310: p = (caddr_t) &pk->p_ohbuf;
311: *p++ = SYN;
312: if (x < 0) {
313: *p++ = hdchk = 9;
314: checkword = cntl;
315: } else {
316: *p++ = hdchk = pk->p_lpsize;
317: checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377);
318: }
319: checkword = CHECK - checkword;
320: *p = checkword;
321: hdchk ^= *p++;
322: *p = checkword>>8;
323: hdchk ^= *p++;
324: *p = cntl;
325: hdchk ^= *p++;
326: *p = hdchk;
327:
328: /*
329: * writes
330: */
331: DEBUG(9, "send %o\n", (unsigned) cntl);
332: p = (caddr_t) & pk->p_ohbuf;
333: if (x < 0) {
334: ret = write(pk->p_ofn, p, HDRSIZ);
335: PKASSERT(ret == HDRSIZ, "PKXSTART ret", "", ret);
336: } else {
337: register char *b, *q;
338: register int i;
339: char buf[PKMAXBUF + HDRSIZ];
340:
341:
342: /*
343: for (i = 0, b = buf; i < HDRSIZ; i++)
344: *b++ = *p++;
345: for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++)
346: *b++ = *p++;
347: */
348: i = HDRSIZ;
349: b = buf;
350: q = p;
351: do
352: *b++ = *q++;
353: while(--i);
354: if(i = pk->p_xsize){
355: q = pk->p_ob[x];
356: do
357: *b++ = *q++;
358: while(--i);
359: }
360: ret = write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ);
361: PKASSERT(ret == pk->p_xsize + HDRSIZ,
362: "PKXSTART ret", "", ret);
363: }
364: if (pk->p_msg)
365: pkoutput(pk);
366: return;
367: }
368:
369:
370:
371:
372: /*
373: * get n characters from input
374: * b -> buffer for characters
375: * fn -> file descriptor
376: * n -> requested number of characters
377: * return:
378: * n -> number of characters returned
379: * 0 -> end of file
380: */
381: jmp_buf Getjbuf;
382: cgalarm() { longjmp(Getjbuf, 1); }
383: int npkccall, npkctry, npkcnap, npkcchar;
384:
385: pkcget(fn, b, n)
386: register int n;
387: register char *b;
388: register int fn;
389: {
390: register int ret;
391: register int donap;
392:
393: if (n == 0)
394: return(0);
395: npkccall++;
396: donap = (linebaudrate > 0 && linebaudrate < 4800);
397: if (setjmp(Getjbuf)) {
398: Ntimeout++;
399: DEBUG(4, "alarm %d\n", Ntimeout);
400: return(-1);
401: }
402: (void) signal(SIGALRM, cgalarm);
403:
404: (void) alarm((unsigned) (n < HDRSIZ ? 10 : 20));
405: while (1) {
406: if ((ret = read(fn, b, n)) == 0) {
407: (void) alarm(0);
408: return(-1);
409: }
410: npkctry++;
411: npkcchar += ret;
412: PKASSERT(ret > 0, "PKCGET READ", "", ret);
413: if ((n -= ret) <= 0)
414: break;
415: #ifdef PKSPEEDUP
416: if (donap) {
417: sleep(1);
418: npkcnap++;
419: }
420: #endif PKSPEEDUP
421: b += ret;
422: }
423: (void) alarm(0);
424: return(0);
425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.