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