Annotation of src/usr.bin/telnet/tn3270.c, Revision 1.7
1.7 ! millert 1: /* $OpenBSD: tn3270.c,v 1.6 2003/06/03 02:56:18 millert 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) {
1.7 ! millert 110: struct pollfd pfd[1];
1.1 deraadt 111:
112: netflush();
113: while (NETROOM() < 6) {
1.7 ! millert 114: pfd[0].fd = net;
! 115: pfd[0].events = POLLOUT;
! 116: (void) poll(pfd, 1, -1);
1.1 deraadt 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(signo)
154: int signo;
155: {
156: HaveInput = 1;
157: sigiocount++;
158: }
159: #endif /* defined(unix) */
160:
161: void
162: outputPurge()
163: {
164: (void) ttyflush(1);
165: }
166:
167:
168: /*
169: * The following routines are places where the various tn3270
170: * routines make calls into telnet.c.
171: */
172:
173: /*
174: * DataToTerminal - queue up some data to go to terminal.
175: *
176: * Note: there are people who call us and depend on our processing
1.7 ! millert 177: * *all* the data at one time (thus the poll).
1.1 deraadt 178: */
179:
180: int
181: DataToTerminal(buffer, count)
1.4 mpech 182: char *buffer; /* where the data is */
183: int count; /* how much to send */
1.1 deraadt 184: {
1.4 mpech 185: int c;
1.1 deraadt 186: int origCount;
187:
188: origCount = count;
189:
190: while (count) {
191: if (TTYROOM() == 0) {
1.7 ! millert 192: struct pollfd pfd[1];
1.1 deraadt 193:
194: (void) ttyflush(0);
195: while (TTYROOM() == 0) {
1.7 ! millert 196: pfd[0].fd = tout;
! 197: pfd[0].events = POLLOUT;
! 198: (void) poll(pfd, 1, -1);
1.1 deraadt 199: (void) ttyflush(0);
200: }
201: }
202: c = TTYROOM();
203: if (c > count) {
204: c = count;
205: }
206: ring_supply_data(&ttyoring, buffer, c);
207: count -= c;
208: buffer += c;
209: }
210: return(origCount);
211: }
212:
213:
214: /*
215: * Push3270 - Try to send data along the 3270 output (to screen) direction.
216: */
217:
218: int
219: Push3270()
220: {
221: int save = ring_full_count(&netiring);
222:
223: if (save) {
224: if (Ifrontp+save > Ibuf+sizeof Ibuf) {
225: if (Ibackp != Ibuf) {
1.2 niklas 226: memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
1.1 deraadt 227: Ifrontp -= (Ibackp-Ibuf);
228: Ibackp = Ibuf;
229: }
230: }
231: if (Ifrontp+save < Ibuf+sizeof Ibuf) {
232: (void)telrcv();
233: }
234: }
235: return save != ring_full_count(&netiring);
236: }
237:
238:
239: /*
240: * Finish3270 - get the last dregs of 3270 data out to the terminal
241: * before quitting.
242: */
243:
244: void
245: Finish3270()
246: {
247: while (Push3270() || !DoTerminalOutput()) {
248: #if defined(unix)
249: HaveInput = 0;
250: #endif /* defined(unix) */
251: ;
252: }
253: }
254:
255:
256: /* StringToTerminal - output a null terminated string to the terminal */
257:
258: void
259: StringToTerminal(s)
260: char *s;
261: {
262: int count;
263:
264: count = strlen(s);
265: if (count) {
266: (void) DataToTerminal(s, count); /* we know it always goes... */
267: }
268: }
269:
270:
271: #if ((!defined(NOT43)) || defined(PUTCHAR))
272: /* _putchar - output a single character to the terminal. This name is so that
273: * curses(3x) can call us to send out data.
274: */
275:
276: void
277: _putchar(c)
278: char c;
279: {
280: #if defined(sun) /* SunOS 4.0 bug */
281: c &= 0x7f;
282: #endif /* defined(sun) */
283: if (cursesdata) {
284: Dump('>', &c, 1);
285: }
286: if (!TTYROOM()) {
287: (void) DataToTerminal(&c, 1);
288: } else {
289: TTYADD(c);
290: }
291: }
292: #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
293:
294: void
295: SetIn3270()
296: {
297: if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
298: && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
299: if (!In3270) {
300: In3270 = 1;
301: Init3270(); /* Initialize 3270 functions */
302: /* initialize terminal key mapping */
303: InitTerminal(); /* Start terminal going */
304: setconnmode(0);
305: }
306: } else {
307: if (In3270) {
308: StopScreen(1);
309: In3270 = 0;
310: Stop3270(); /* Tell 3270 we aren't here anymore */
311: setconnmode(0);
312: }
313: }
314: }
315:
316: /*
317: * tn3270_ttype()
318: *
319: * Send a response to a terminal type negotiation.
320: *
321: * Return '0' if no more responses to send; '1' if a response sent.
322: */
323:
324: int
325: tn3270_ttype()
326: {
327: /*
328: * Try to send a 3270 type terminal name. Decide which one based
329: * on the format of our screen, and (in the future) color
330: * capaiblities.
331: */
332: InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */
333: if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
334: Sent3270TerminalType = 1;
335: if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
336: MaxNumberLines = 27;
337: MaxNumberColumns = 132;
338: sb_terminal[SBTERMMODEL] = '5';
339: } else if (MaxNumberLines >= 43) {
340: MaxNumberLines = 43;
341: MaxNumberColumns = 80;
342: sb_terminal[SBTERMMODEL] = '4';
343: } else if (MaxNumberLines >= 32) {
344: MaxNumberLines = 32;
345: MaxNumberColumns = 80;
346: sb_terminal[SBTERMMODEL] = '3';
347: } else {
348: MaxNumberLines = 24;
349: MaxNumberColumns = 80;
350: sb_terminal[SBTERMMODEL] = '2';
351: }
352: NumberLines = 24; /* before we start out... */
353: NumberColumns = 80;
354: ScreenSize = NumberLines*NumberColumns;
355: if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
356: ExitString("Programming error: MAXSCREENSIZE too small.\n",
357: 1);
358: /*NOTREACHED*/
359: }
360: printsub('>', sb_terminal+2, sizeof sb_terminal-2);
361: ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
362: return 1;
363: } else {
364: return 0;
365: }
366: }
367:
368: #if defined(unix)
369: int
370: settranscom(argc, argv)
371: int argc;
372: char *argv[];
373: {
374: int i;
375:
376: if (argc == 1 && transcom) {
377: transcom = 0;
378: }
379: if (argc == 1) {
380: return 1;
381: }
1.5 hin 382: strlcpy(tline, argv[1], sizeof(tline));
1.1 deraadt 383: for (i = 2; i < argc; ++i) {
1.5 hin 384: strlcat(tline, " ", sizeof(tline));
385: strlcat(tline, argv[i], sizeof(tline));
1.1 deraadt 386: }
1.5 hin 387: transcom = tline;
1.1 deraadt 388: return 1;
389: }
390: #endif /* defined(unix) */
391:
392: #endif /* defined(TN3270) */