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