|
|
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 provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)tn3270.c 1.21 (Berkeley) 6/28/90";
22: #endif /* not lint */
23:
24: #include <sys/types.h>
25: #include <arpa/telnet.h>
26:
27: #include "general.h"
28:
29: #include "defines.h"
30: #include "ring.h"
31: #include "externs.h"
32: #include "fdset.h"
33:
34: #if defined(TN3270)
35:
36: #include "../ctlr/screen.h"
37: #include "../general/globals.h"
38:
39: #include "../telextrn.h"
40: #include "../ctlr/externs.h"
41:
42: #if defined(unix)
43: int
44: HaveInput, /* There is input available to scan */
45: cursesdata, /* Do we dump curses data? */
46: sigiocount; /* Number of times we got a SIGIO */
47:
48: char tline[200];
49: char *transcom = 0; /* transparent mode command (default: none) */
50: #endif /* defined(unix) */
51:
52: char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
53:
54: static char sb_terminal[] = { IAC, SB,
55: TELOPT_TTYPE, TELQUAL_IS,
56: 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
57: IAC, SE };
58: #define SBTERMMODEL 13
59:
60: static int
61: Sent3270TerminalType; /* Have we said we are a 3270? */
62:
63: #endif /* defined(TN3270) */
64:
65:
66: void
67: init_3270()
68: {
69: #if defined(TN3270)
70: #if defined(unix)
71: HaveInput = 0;
72: sigiocount = 0;
73: #endif /* defined(unix) */
74: Sent3270TerminalType = 0;
75: Ifrontp = Ibackp = Ibuf;
76: init_ctlr(); /* Initialize some things */
77: init_keyboard();
78: init_screen();
79: init_system();
80: #endif /* defined(TN3270) */
81: }
82:
83:
84: #if defined(TN3270)
85:
86: /*
87: * DataToNetwork - queue up some data to go to network. If "done" is set,
88: * then when last byte is queued, we add on an IAC EOR sequence (so,
89: * don't call us with "done" until you want that done...)
90: *
91: * We actually do send all the data to the network buffer, since our
92: * only client needs for us to do that.
93: */
94:
95: int
96: DataToNetwork(buffer, count, done)
97: register char *buffer; /* where the data is */
98: register int count; /* how much to send */
99: int done; /* is this the last of a logical block */
100: {
101: register int loop, c;
102: int origCount;
103:
104: origCount = count;
105:
106: while (count) {
107: /* If not enough room for EORs, IACs, etc., wait */
108: if (NETROOM() < 6) {
109: fd_set o;
110:
111: FD_ZERO(&o);
112: netflush();
113: while (NETROOM() < 6) {
114: FD_SET(net, &o);
115: (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
116: (struct timeval *) 0);
117: netflush();
118: }
119: }
120: c = ring_empty_count(&netoring);
121: if (c > count) {
122: c = count;
123: }
124: loop = c;
125: while (loop) {
126: if (((unsigned char)*buffer) == IAC) {
127: break;
128: }
129: buffer++;
130: loop--;
131: }
132: if ((c = c-loop)) {
133: ring_supply_data(&netoring, buffer-c, c);
134: count -= c;
135: }
136: if (loop) {
137: NET2ADD(IAC, IAC);
138: count--;
139: buffer++;
140: }
141: }
142:
143: if (done) {
144: NET2ADD(IAC, EOR);
145: netflush(); /* try to move along as quickly as ... */
146: }
147: return(origCount - count);
148: }
149:
150:
151: #if defined(unix)
152: void
153: inputAvailable()
154: {
155: HaveInput = 1;
156: sigiocount++;
157: }
158: #endif /* defined(unix) */
159:
160: void
161: outputPurge()
162: {
163: (void) ttyflush(1);
164: }
165:
166:
167: /*
168: * The following routines are places where the various tn3270
169: * routines make calls into telnet.c.
170: */
171:
172: /*
173: * DataToTerminal - queue up some data to go to terminal.
174: *
175: * Note: there are people who call us and depend on our processing
176: * *all* the data at one time (thus the select).
177: */
178:
179: int
180: DataToTerminal(buffer, count)
181: register char *buffer; /* where the data is */
182: register int count; /* how much to send */
183: {
184: register int c;
185: int origCount;
186:
187: origCount = count;
188:
189: while (count) {
190: if (TTYROOM() == 0) {
191: #if defined(unix)
192: fd_set o;
193:
194: FD_ZERO(&o);
195: #endif /* defined(unix) */
196: (void) ttyflush(0);
197: while (TTYROOM() == 0) {
198: #if defined(unix)
199: FD_SET(tout, &o);
200: (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
201: (struct timeval *) 0);
202: #endif /* defined(unix) */
203: (void) ttyflush(0);
204: }
205: }
206: c = TTYROOM();
207: if (c > count) {
208: c = count;
209: }
210: ring_supply_data(&ttyoring, buffer, c);
211: count -= c;
212: buffer += c;
213: }
214: return(origCount);
215: }
216:
217:
218: /*
219: * Push3270 - Try to send data along the 3270 output (to screen) direction.
220: */
221:
222: int
223: Push3270()
224: {
225: int save = ring_full_count(&netiring);
226:
227: if (save) {
228: if (Ifrontp+save > Ibuf+sizeof Ibuf) {
229: if (Ibackp != Ibuf) {
230: memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
231: Ifrontp -= (Ibackp-Ibuf);
232: Ibackp = Ibuf;
233: }
234: }
235: if (Ifrontp+save < Ibuf+sizeof Ibuf) {
236: (void)telrcv();
237: }
238: }
239: return save != ring_full_count(&netiring);
240: }
241:
242:
243: /*
244: * Finish3270 - get the last dregs of 3270 data out to the terminal
245: * before quitting.
246: */
247:
248: void
249: Finish3270()
250: {
251: while (Push3270() || !DoTerminalOutput()) {
252: #if defined(unix)
253: HaveInput = 0;
254: #endif /* defined(unix) */
255: ;
256: }
257: }
258:
259:
260: /* StringToTerminal - output a null terminated string to the terminal */
261:
262: void
263: StringToTerminal(s)
264: char *s;
265: {
266: int count;
267:
268: count = strlen(s);
269: if (count) {
270: (void) DataToTerminal(s, count); /* we know it always goes... */
271: }
272: }
273:
274:
275: #if ((!defined(NOT43)) || defined(PUTCHAR))
276: /* _putchar - output a single character to the terminal. This name is so that
277: * curses(3x) can call us to send out data.
278: */
279:
280: void
281: _putchar(c)
282: char c;
283: {
284: #if defined(sun) /* SunOS 4.0 bug */
285: c &= 0x7f;
286: #endif /* defined(sun) */
287: if (cursesdata) {
288: Dump('>', &c, 1);
289: }
290: if (!TTYROOM()) {
291: (void) DataToTerminal(&c, 1);
292: } else {
293: TTYADD(c);
294: }
295: }
296: #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
297:
298: void
299: SetIn3270()
300: {
301: if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
302: && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
303: if (!In3270) {
304: In3270 = 1;
305: Init3270(); /* Initialize 3270 functions */
306: /* initialize terminal key mapping */
307: InitTerminal(); /* Start terminal going */
308: setconnmode(0);
309: }
310: } else {
311: if (In3270) {
312: StopScreen(1);
313: In3270 = 0;
314: Stop3270(); /* Tell 3270 we aren't here anymore */
315: setconnmode(0);
316: }
317: }
318: }
319:
320: /*
321: * tn3270_ttype()
322: *
323: * Send a response to a terminal type negotiation.
324: *
325: * Return '0' if no more responses to send; '1' if a response sent.
326: */
327:
328: int
329: tn3270_ttype()
330: {
331: /*
332: * Try to send a 3270 type terminal name. Decide which one based
333: * on the format of our screen, and (in the future) color
334: * capaiblities.
335: */
336: InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */
337: if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
338: Sent3270TerminalType = 1;
339: if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
340: MaxNumberLines = 27;
341: MaxNumberColumns = 132;
342: sb_terminal[SBTERMMODEL] = '5';
343: } else if (MaxNumberLines >= 43) {
344: MaxNumberLines = 43;
345: MaxNumberColumns = 80;
346: sb_terminal[SBTERMMODEL] = '4';
347: } else if (MaxNumberLines >= 32) {
348: MaxNumberLines = 32;
349: MaxNumberColumns = 80;
350: sb_terminal[SBTERMMODEL] = '3';
351: } else {
352: MaxNumberLines = 24;
353: MaxNumberColumns = 80;
354: sb_terminal[SBTERMMODEL] = '2';
355: }
356: NumberLines = 24; /* before we start out... */
357: NumberColumns = 80;
358: ScreenSize = NumberLines*NumberColumns;
359: if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
360: ExitString("Programming error: MAXSCREENSIZE too small.\n",
361: 1);
362: /*NOTREACHED*/
363: }
364: printsub('>', sb_terminal+2, sizeof sb_terminal-2);
365: ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
366: return 1;
367: } else {
368: return 0;
369: }
370: }
371:
372: #if defined(unix)
373: settranscom(argc, argv)
374: int argc;
375: char *argv[];
376: {
377: int i;
378:
379: if (argc == 1 && transcom) {
380: transcom = 0;
381: }
382: if (argc == 1) {
383: return;
384: }
385: transcom = tline;
386: (void) strcpy(transcom, argv[1]);
387: for (i = 2; i < argc; ++i) {
388: (void) strcat(transcom, " ");
389: (void) strcat(transcom, argv[i]);
390: }
391: }
392: #endif /* defined(unix) */
393:
394: #endif /* defined(TN3270) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.