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