|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)outbound.c 3.3 (Berkeley) 3/28/88";
15: #endif /* not lint */
16:
17: #include <stdio.h>
18:
19: #include "../general/general.h"
20:
21: #include "hostctlr.h"
22: #include "oia.h"
23: #include "screen.h"
24: #include "../api/ebc_disp.h"
25:
26: #include "../general/globals.h"
27: #include "options.ext"
28: #include "../telnet.ext"
29: #include "inbound.ext"
30: #include "outbound.ext"
31: #include "../general/bsubs.ext"
32:
33: #define SetHighestLowest(position) { \
34: if (position < Lowest) { \
35: Lowest = position; \
36: } \
37: if (position > Highest) { \
38: Highest = position; \
39: } \
40: }
41:
42:
43: static int LastWasTerminated = 1; /* was "control" = 1 last time? */
44:
45: /* some globals */
46:
47: #if !defined(PURE3274)
48: int OutputClock; /* what time it is */
49: int TransparentClock; /* time we were last in transparent */
50: #endif /* !defined(PURE3274) */
51:
52: char CIABuffer[64] = {
53: 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
54: 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
55: 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
56: 0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
57: 0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
58: 0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
59: 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
60: 0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
61: };
62:
63: static struct orders_def orders_def[] = ORDERS_DEF;
64:
65: /*
66: * init_ctlr()
67: *
68: * Initialize all data from the 'data' portion to their startup values.
69: */
70:
71: void
72: init_ctlr()
73: {
74: LastWasTerminated = 1;
75: init_inbound();
76: init_oia();
77: }
78:
79:
80: FieldInc(position)
81: register int position; /* Position in previous field */
82: {
83: register ScreenImage *ptr;
84:
85: ptr = (ScreenImage *)memNSchr((char *)Host+position+1, ATTR_MASK,
86: HighestScreen()-position, ATTR_MASK, sizeof Host[0]);
87: if (ptr == 0) {
88: ptr = (ScreenImage *)memNSchr((char *)Host+LowestScreen(), ATTR_MASK,
89: position-LowestScreen(), ATTR_MASK, sizeof Host[0]);
90: if (ptr == 0) {
91: return LowestScreen();
92: }
93: }
94: return ptr-Host;
95: }
96:
97: FieldDec(position)
98: int position;
99: {
100: register ScreenImage *ptr;
101:
102: ptr = (ScreenImage *)memNSchr((char *)(Host+position)-1, ATTR_MASK,
103: position-LowestScreen(), ATTR_MASK, -sizeof Host[0]);
104: if (ptr == 0) {
105: ptr = (ScreenImage *)memNSchr((char *)Host+HighestScreen(), ATTR_MASK,
106: HighestScreen()-position, ATTR_MASK, -sizeof Host[0]);
107: if (ptr == 0) {
108: return LowestScreen();
109: }
110: }
111: return ptr-Host;
112: }
113:
114: /* Clear3270 - called to clear the screen */
115:
116: void
117: Clear3270()
118: {
119: ClearArray(Host);
120: DeleteAllFields(); /* get rid of all fields */
121: BufferAddress = SetBufferAddress(0,0);
122: CursorAddress = SetBufferAddress(0,0);
123: Lowest = LowestScreen();
124: Highest = HighestScreen();
125: }
126:
127: /* AddHost - called to add a character to the buffer.
128: * We use a macro in this module, since we call it so
129: * often from loops.
130: *
131: * NOTE: It is a macro, so don't go around using AddHost(p, *c++), or
132: * anything similar. (I don't define any temporary variables, again
133: * just for the speed.)
134: */
135: void
136: AddHost(position, character)
137: int position;
138: char character;
139: {
140: # define AddHostA(p,c) \
141: { \
142: if (IsStartField(p)) { \
143: DeleteField(p); \
144: Highest = HighestScreen(); \
145: Lowest = LowestScreen(); \
146: SetHighestLowest(p); \
147: } \
148: SetHost(p, c); \
149: }
150: # define AddHost(p,c) \
151: { \
152: if (c != GetHost(p)) { \
153: SetHighestLowest(p); \
154: } \
155: AddHostA(p,c); \
156: } /* end of macro of AddHost */
157:
158: AddHost(position, character);
159: }
160:
161: /* returns the number of characters consumed */
162: int
163: DataFromNetwork(buffer, count, control)
164: register unsigned char *buffer; /* what the data is */
165: register int count; /* and how much there is */
166: int control; /* this buffer ended block? */
167: {
168: int origCount;
169: register int c;
170: register int i;
171: static int Command;
172: static int Wcc;
173:
174: origCount = count;
175:
176: /*
177: * If this is the start of a new data stream, then look
178: * for an op-code and (possibly) a WCC.
179: */
180: if (LastWasTerminated) {
181:
182: if (count < 2) {
183: if (count == 0) {
184: ExitString(stderr, "Short count received from host!\n", 1);
185: return(count);
186: }
187: Command = buffer[0];
188: switch (Command) { /* This had better be a read command */
189: case CMD_READ_MODIFIED:
190: case CMD_SNA_READ_MODIFIED:
191: case CMD_SNA_READ_MODIFIED_ALL:
192: SetOiaOnlineA(&OperatorInformationArea);
193: SetOiaModified();
194: DoReadModified(Command);
195: break;
196: case CMD_READ_BUFFER:
197: case CMD_SNA_READ_BUFFER:
198: SetOiaOnlineA(&OperatorInformationArea);
199: SetOiaModified();
200: DoReadBuffer();
201: break;
202: default:
203: {
204: char buffer[100];
205:
206: sprintf(buffer,
207: "Unexpected read command code 0x%x received.\n",
208: Command);
209: ExitString(stderr, buffer, 1);
210: break;
211: }
212: }
213: return(1); /* We consumed everything */
214: }
215: Command = buffer[0];
216: Wcc = buffer[1];
217: if (Wcc & WCC_RESET_MDT) {
218: i = c = WhereAttrByte(LowestScreen());
219: do {
220: if (HasMdt(i)) {
221: TurnOffMdt(i);
222: }
223: i = FieldInc(i);
224: } while (i != c);
225: }
226:
227: switch (Command) {
228: case CMD_ERASE_WRITE:
229: case CMD_ERASE_WRITE_ALTERNATE:
230: case CMD_SNA_ERASE_WRITE:
231: case CMD_SNA_ERASE_WRITE_ALTERNATE:
232: {
233: int newlines, newcolumns;
234:
235: SetOiaOnlineA(&OperatorInformationArea);
236: ResetOiaTWait(&OperatorInformationArea);
237: SetOiaModified();
238: if ((Command == CMD_ERASE_WRITE)
239: || (Command == CMD_SNA_ERASE_WRITE)) {
240: newlines = 24;
241: newcolumns = 80;
242: } else {
243: newlines = MaxNumberLines;
244: newcolumns = MaxNumberColumns;
245: }
246: if ((newlines != NumberLines)
247: || (newcolumns != NumberColumns)) {
248: /*
249: * The LocalClearScreen() is really for when we
250: * are going from a larger screen to a smaller
251: * screen, and we need to clear off the stuff
252: * at the end of the lines, or the lines at
253: * the end of the screen.
254: */
255: LocalClearScreen();
256: NumberLines = newlines;
257: NumberColumns = newcolumns;
258: ScreenSize = NumberLines * NumberColumns;
259: }
260: Clear3270();
261: #if !defined(PURE3274)
262: if (TransparentClock == OutputClock) {
263: TransStop();
264: }
265: #endif /* !defined(PURE3274) */
266: break;
267: }
268:
269: case CMD_ERASE_ALL_UNPROTECTED:
270: case CMD_SNA_ERASE_ALL_UNPROTECTED:
271: SetOiaOnlineA(&OperatorInformationArea);
272: ResetOiaTWait(&OperatorInformationArea);
273: SetOiaModified();
274: CursorAddress = HighestScreen()+1;
275: for (i = LowestScreen(); i <= HighestScreen(); i = ScreenInc(i)) {
276: if (IsUnProtected(i)) {
277: if (CursorAddress > i) {
278: CursorAddress = i;
279: }
280: AddHost(i, '\0');
281: }
282: if (HasMdt(i)) {
283: TurnOffMdt(i);
284: }
285: }
286: if (CursorAddress == HighestScreen()+1) {
287: CursorAddress = SetBufferAddress(0,0);
288: }
289: UnLocked = 1;
290: AidByte = 0;
291: ResetOiaSystemLocked(&OperatorInformationArea);
292: SetOiaModified();
293: TerminalIn();
294: break;
295: case CMD_WRITE:
296: case CMD_SNA_WRITE:
297: SetOiaOnlineA(&OperatorInformationArea);
298: ResetOiaTWait(&OperatorInformationArea);
299: SetOiaModified();
300: break;
301: default:
302: {
303: char buffer[100];
304:
305: sprintf(buffer,
306: "Unexpected write command code 0x%x received.\n",
307: Command);
308: ExitString(stderr, buffer, 1);
309: break;
310: }
311: }
312:
313: count -= 2; /* strip off command and wcc */
314: buffer += 2;
315:
316: } else {
317: #if !defined(PURE3274)
318: if (TransparentClock == OutputClock) {
319: TransOut(buffer, count, -1, control);
320: count = 0;
321: }
322: #endif /* !defined(PURE3274) */
323: }
324: LastWasTerminated = 0; /* then, reset at end... */
325:
326: while (count) {
327: count--;
328: c = *buffer++;
329: if (IsOrder(c)) {
330: /* handle an order */
331: switch (c) {
332: # define Ensure(x) if (count < x) { \
333: if (!control) { \
334: return(origCount-(count+1)); \
335: } else { \
336: /* XXX - should not occur */ \
337: count = 0; \
338: break; \
339: } \
340: }
341: case ORDER_SF:
342: Ensure(1);
343: c = *buffer++;
344: count--;
345: if ( ! (IsStartField(BufferAddress) &&
346: FieldAttributes(BufferAddress) == c)) {
347: SetHighestLowest(BufferAddress);
348: NewField(BufferAddress,c);
349: }
350: BufferAddress = ScreenInc(BufferAddress);
351: break;
352: case ORDER_SBA:
353: Ensure(2);
354: i = buffer[0];
355: c = buffer[1];
356: #if !defined(PURE3274)
357: /* Check for transparent write */
358: if ((i == 0) && ((c == 0) || (c == 1) || (c == 5))) {
359: TransparentClock = OutputClock+1;
360: TransOut(buffer+2, count-2, c, control);
361: buffer += count;
362: count -= count;
363: break;
364: }
365: #endif /* !defined(PURE3274) */
366: BufferAddress = Addr3270(i, c);
367: buffer += 2;
368: count -= 2;
369: break;
370: case ORDER_IC:
371: CursorAddress = BufferAddress;
372: break;
373: /*
374: * XXX - PT is supposed to null fill the screen buffer
375: * under certain draconian conditions.
376: */
377: case ORDER_PT:
378: i = BufferAddress;
379: do {
380: if (IsStartField(i)) {
381: if (!IsProtected(ScreenInc(i))) {
382: break;
383: }
384: }
385: i = ScreenInc(i);
386: } while (i != HighestScreen());
387: BufferAddress = ScreenInc(i);
388: break;
389: case ORDER_RA:
390: Ensure(3);
391: i = Addr3270(buffer[0], buffer[1]);
392: c = buffer[2];
393: if (c == ORDER_GE) {
394: Ensure(4);
395: c = buffer[3];
396: buffer += 4;
397: count -= 4;
398: } else {
399: buffer += 3;
400: count -= 3;
401: }
402: do {
403: AddHost(BufferAddress, ebc_disp[c]);
404: BufferAddress = ScreenInc(BufferAddress);
405: } while (BufferAddress != i);
406: break;
407: case ORDER_EUA: /* (from [here,there), ie: half open interval] */
408: Ensure(2);
409: /*
410: * Compiler error - msc version 4.0:
411: * "expression too complicated".
412: */
413: i = WhereAttrByte(BufferAddress);
414: c = FieldAttributes(i);
415: i = Addr3270(buffer[0], buffer[1]);
416: do {
417: if (IsStartField(BufferAddress)) {
418: c = FieldAttributes(BufferAddress);
419: } else if (!IsProtectedAttr(BufferAddress, c)) {
420: AddHost(BufferAddress, 0);
421: }
422: BufferAddress = ScreenInc(BufferAddress);
423: } while (i != BufferAddress);
424: buffer += 2;
425: count -= 2;
426: break;
427: case ORDER_GE:
428: Ensure(2);
429: /* XXX Should do SOMETHING! */
430: buffer += 0;
431: count -= 0; /* For now, just use this character */
432: break;
433: case ORDER_YALE: /* special YALE defined order */
434: Ensure(2); /* need at least two characters */
435: if (*buffer == 0x5b) {
436: i = OptOrder(buffer+1, count-1, control);
437: if (i == 0) {
438: return(origCount-(count+1)); /* come here again */
439: } else {
440: buffer += 1 + i;
441: count -= (1 + i);
442: }
443: }
444: break;
445: default:
446: {
447: char buffer[100];
448: static struct orders_def unk_order
449: = { 0, "??", "(unknown)" };
450: struct orders_def *porder = &unk_order;
451: int i;
452:
453: for (i = 0; i <= highestof(orders_def); i++) {
454: if (orders_def[i].code == c) {
455: porder = &orders_def[i];
456: break;
457: }
458: }
459: sprintf(buffer,
460: "Unsupported order '%s' (%s, 0x%x) received.\n",
461: porder->long_name, porder->short_name, c);
462: ExitString(stderr, buffer, 1);
463: /*NOTREACHED*/
464: }
465: }
466: if (count < 0) {
467: count = 0;
468: }
469: } else {
470: /* Data comes in large clumps - take it all */
471: i = BufferAddress;
472: AddHostA(i, ebc_disp[c]);
473: SetHighestLowest(i);
474: i = ScreenInc(i);
475: c = *buffer;
476: while (count && !IsOrder(c)) {
477: AddHostA(i, ebc_disp[c]);
478: i = ScreenInc(i);
479: if (i == LowestScreen()) {
480: SetHighestLowest(HighestScreen());
481: }
482: count--;
483: buffer++;
484: c = *buffer;
485: }
486: SetHighestLowest(i);
487: BufferAddress = i;
488: }
489: }
490: if (count == 0) {
491: if (control) {
492: #if !defined(PURE3274)
493: OutputClock++; /* time rolls on */
494: #endif /* !defined(PURE3274) */
495: if (Wcc & WCC_RESTORE) {
496: #if !defined(PURE3274)
497: if (TransparentClock != OutputClock) {
498: AidByte = 0;
499: }
500: #else /* !defined(PURE3274) */
501: AidByte = 0;
502: #endif /* !defined(PURE3274) */
503: UnLocked = 1;
504: ResetOiaSystemLocked(&OperatorInformationArea);
505: SetOiaModified();
506: SetPsModified();
507: TerminalIn();
508: }
509: if (Wcc & WCC_ALARM) {
510: RingBell(0);
511: }
512: }
513: LastWasTerminated = control; /* state for next time */
514: return(origCount);
515: } else {
516: return(origCount-count);
517: }
518: }
519:
520: /*
521: * Init3270()
522: *
523: * Initialize any 3270 (controller) variables to an initial state
524: * in preparation for accepting a connection.
525: */
526:
527: void
528: Init3270()
529: {
530: int i;
531:
532: OptInit(); /* initialize mappings */
533:
534: ClearArray(Host);
535:
536: ClearArray(Orders);
537: for (i = 0; i <= highestof(orders_def); i++) {
538: Orders[orders_def[i].code] = 1;
539: }
540:
541: DeleteAllFields(); /* Clear screen */
542: Lowest = HighestScreen()+1;
543: Highest = LowestScreen()-1;
544: CursorAddress = BufferAddress = SetBufferAddress(0,0);
545: UnLocked = 1;
546: #if !defined(PURE3274)
547: OutputClock = 1;
548: TransparentClock = -1;
549: #endif /* !defined(PURE3274) */
550: SetOiaReady3274(&OperatorInformationArea);
551: }
552:
553:
554: void
555: Stop3270()
556: {
557: ResetOiaReady3274(&OperatorInformationArea);
558: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.