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