don't open target for writing if we're just verifying the tapes
[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
b36fc510 19static char sccsid[] = "@(#)tn3270.c 1.12 (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
476b1e3a
GM
37#if defined(unix)
38char tline[200];
39char *transcom = 0; /* transparent mode command (default: none) */
40#endif /* defined(unix) */
b307f09e 41
476b1e3a 42char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
b307f09e
GM
43
44static char sb_terminal[] = { IAC, SB,
45 TELOPT_TTYPE, TELQUAL_IS,
46 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
47 IAC, SE };
48#define SBTERMMODEL 13
49
50static int
51 Sent3270TerminalType; /* Have we said we are a 3270? */
52
476b1e3a 53#endif /* defined(TN3270) */
b307f09e 54
e571aa72 55
476b1e3a 56void
66c4b72a 57init_3270()
476b1e3a
GM
58{
59#if defined(TN3270)
60 Sent3270TerminalType = 0;
61 Ifrontp = Ibackp = Ibuf;
62 init_ctlr(); /* Initialize some things */
63 init_keyboard();
64 init_screen();
65 init_system();
66#endif /* defined(TN3270) */
e571aa72 67}
476b1e3a
GM
68
69\f
70#if defined(TN3270)
e571aa72 71
b6a8714b
GM
72/*
73 * DataToNetwork - queue up some data to go to network. If "done" is set,
74 * then when last byte is queued, we add on an IAC EOR sequence (so,
75 * don't call us with "done" until you want that done...)
76 *
77 * We actually do send all the data to the network buffer, since our
78 * only client needs for us to do that.
79 */
80
81int
82DataToNetwork(buffer, count, done)
83register char *buffer; /* where the data is */
84register int count; /* how much to send */
85int done; /* is this the last of a logical block */
86{
476b1e3a 87 register int loop, c;
b6a8714b 88 int origCount;
b6a8714b
GM
89
90 origCount = count;
b6a8714b
GM
91
92 while (count) {
66c4b72a 93 /* If not enough room for EORs, IACs, etc., wait */
476b1e3a
GM
94 if (NETROOM() < 6) {
95 fd_set o;
96
97 FD_ZERO(&o);
b6a8714b 98 netflush();
476b1e3a 99 while (NETROOM() < 6) {
b6a8714b
GM
100 FD_SET(net, &o);
101 (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
102 (struct timeval *) 0);
103 netflush();
104 }
105 }
66c4b72a
GM
106 c = ring_empty_count(&netoring);
107 if (c > count) {
108 c = count;
109 }
110 loop = c;
476b1e3a 111 while (loop) {
5dc973da 112 if (((unsigned char)*buffer) == IAC) {
476b1e3a
GM
113 break;
114 }
115 buffer++;
116 loop--;
117 }
118 if ((c = c-loop)) {
119 ring_supply_data(&netoring, buffer-c, c);
120 count -= c;
121 }
122 if (loop) {
123 NET2ADD(IAC, IAC);
124 count--;
66c4b72a 125 buffer++;
b6a8714b
GM
126 }
127 }
128
476b1e3a 129 if (done) {
66c4b72a 130 NET2ADD(IAC, EOR);
b6a8714b
GM
131 netflush(); /* try to move along as quickly as ... */
132 }
133 return(origCount - count);
134}
135
136
137#if defined(unix)
476b1e3a 138void
b6a8714b
GM
139inputAvailable()
140{
141 HaveInput = 1;
142}
143#endif /* defined(unix) */
144
145void
146outputPurge()
147{
d732be39 148 ttyflush(1);
b6a8714b
GM
149}
150
151
152/*
153 * The following routines are places where the various tn3270
154 * routines make calls into telnet.c.
155 */
156
66c4b72a
GM
157/*
158 * DataToTerminal - queue up some data to go to terminal.
159 *
160 * Note: there are people who call us and depend on our processing
161 * *all* the data at one time (thus the select).
162 */
b6a8714b
GM
163
164int
165DataToTerminal(buffer, count)
166register char *buffer; /* where the data is */
167register int count; /* how much to send */
168{
476b1e3a 169 register int loop, c;
b6a8714b 170 int origCount;
b6a8714b 171
b6a8714b
GM
172 origCount = count;
173
174 while (count) {
476b1e3a
GM
175 if (TTYROOM() == 0) {
176#if defined(unix)
177 fd_set o;
178
179 FD_ZERO(&o);
180#endif /* defined(unix) */
181 ttyflush();
182 while (TTYROOM() == 0) {
b6a8714b
GM
183#if defined(unix)
184 FD_SET(tout, &o);
185 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
186 (struct timeval *) 0);
187#endif /* defined(unix) */
476b1e3a 188 ttyflush();
b6a8714b
GM
189 }
190 }
66c4b72a
GM
191 c = TTYROOM();
192 if (c > count) {
193 c = count;
476b1e3a 194 }
66c4b72a
GM
195 ring_supply_data(&ttyoring, buffer, c);
196 count -= c;
197 buffer += c;
b6a8714b 198 }
66c4b72a 199 return(origCount);
b6a8714b
GM
200}
201
202/* EmptyTerminal - called to make sure that the terminal buffer is empty.
203 * Note that we consider the buffer to run all the
204 * way to the kernel (thus the select).
205 */
206
207void
208EmptyTerminal()
209{
210#if defined(unix)
211 fd_set o;
212
213 FD_ZERO(&o);
214#endif /* defined(unix) */
215
66c4b72a 216 if (TTYBYTES() == 0) {
b6a8714b
GM
217#if defined(unix)
218 FD_SET(tout, &o);
219 (void) select(tout+1, (int *) 0, &o, (int *) 0,
220 (struct timeval *) 0); /* wait for TTLOWAT */
221#endif /* defined(unix) */
222 } else {
476b1e3a 223 while (TTYBYTES()) {
d732be39 224 ttyflush(0);
b6a8714b
GM
225#if defined(unix)
226 FD_SET(tout, &o);
227 (void) select(tout+1, (int *) 0, &o, (int *) 0,
228 (struct timeval *) 0); /* wait for TTLOWAT */
229#endif /* defined(unix) */
230 }
231 }
232}
233\f
234
235/*
236 * Push3270 - Try to send data along the 3270 output (to screen) direction.
237 */
238
476b1e3a 239int
b6a8714b
GM
240Push3270()
241{
476b1e3a 242 int save = ring_full_count(&netiring);
b6a8714b 243
476b1e3a
GM
244 if (save) {
245 if (Ifrontp+save > Ibuf+sizeof Ibuf) {
b6a8714b
GM
246 if (Ibackp != Ibuf) {
247 memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
248 Ifrontp -= (Ibackp-Ibuf);
249 Ibackp = Ibuf;
250 }
251 }
476b1e3a 252 if (Ifrontp+save < Ibuf+sizeof Ibuf) {
b6a8714b
GM
253 telrcv();
254 }
255 }
476b1e3a 256 return save != ring_full_count(&netiring);
b6a8714b
GM
257}
258
259
260/*
261 * Finish3270 - get the last dregs of 3270 data out to the terminal
262 * before quitting.
263 */
264
476b1e3a 265void
b6a8714b
GM
266Finish3270()
267{
268 while (Push3270() || !DoTerminalOutput()) {
269#if defined(unix)
270 HaveInput = 0;
271#endif /* defined(unix) */
272 ;
273 }
274}
275
276
277/* StringToTerminal - output a null terminated string to the terminal */
278
279void
280StringToTerminal(s)
281char *s;
282{
283 int count;
284
285 count = strlen(s);
286 if (count) {
287 (void) DataToTerminal(s, count); /* we know it always goes... */
288 }
289}
290
291
292#if ((!defined(NOT43)) || defined(PUTCHAR))
293/* _putchar - output a single character to the terminal. This name is so that
294 * curses(3x) can call us to send out data.
295 */
296
297void
298_putchar(c)
299char c;
300{
476b1e3a 301 if (TTYBYTES()) {
b6a8714b
GM
302 (void) DataToTerminal(&c, 1);
303 } else {
476b1e3a 304 TTYADD(c);
b6a8714b
GM
305 }
306}
307#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
308
b307f09e
GM
309void
310SetForExit()
311{
312 setconnmode();
313 if (In3270) {
314 Finish3270();
315 }
316 setcommandmode();
317 fflush(stdout);
318 fflush(stderr);
319 if (In3270) {
320 StopScreen(1);
321 }
322 setconnmode();
323 setcommandmode();
324}
325
326void
327Exit(returnCode)
328int returnCode;
329{
330 SetForExit();
331 exit(returnCode);
332}
333
334void
335ExitString(string, returnCode)
336char *string;
337int returnCode;
338{
339 SetForExit();
340 fwrite(string, 1, strlen(string), stderr);
341 exit(returnCode);
342}
343
344void
345ExitPerror(string, returnCode)
346char *string;
347int returnCode;
348{
349 SetForExit();
350 perror(string);
351 exit(returnCode);
352}
353
354void
355SetIn3270()
356{
357 if (Sent3270TerminalType && myopts[TELOPT_BINARY]
358 && hisopts[TELOPT_BINARY] && !donebinarytoggle) {
359 if (!In3270) {
360 In3270 = 1;
361 Init3270(); /* Initialize 3270 functions */
362 /* initialize terminal key mapping */
363 InitTerminal(); /* Start terminal going */
364 setconnmode();
365 }
366 } else {
367 if (In3270) {
368 StopScreen(1);
369 In3270 = 0;
370 Stop3270(); /* Tell 3270 we aren't here anymore */
371 setconnmode();
372 }
373 }
374}
375
376/*
377 * tn3270_ttype()
378 *
379 * Send a response to a terminal type negotiation.
380 *
381 * Return '0' if no more responses to send; '1' if a response sent.
382 */
383
384int
385tn3270_ttype()
386{
387 /*
388 * Try to send a 3270 type terminal name. Decide which one based
389 * on the format of our screen, and (in the future) color
390 * capaiblities.
391 */
392 InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */
393 if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
394 Sent3270TerminalType = 1;
395 if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
396 MaxNumberLines = 27;
397 MaxNumberColumns = 132;
398 sb_terminal[SBTERMMODEL] = '5';
399 } else if (MaxNumberLines >= 43) {
400 MaxNumberLines = 43;
401 MaxNumberColumns = 80;
402 sb_terminal[SBTERMMODEL] = '4';
403 } else if (MaxNumberLines >= 32) {
404 MaxNumberLines = 32;
405 MaxNumberColumns = 80;
406 sb_terminal[SBTERMMODEL] = '3';
407 } else {
408 MaxNumberLines = 24;
409 MaxNumberColumns = 80;
410 sb_terminal[SBTERMMODEL] = '2';
411 }
412 NumberLines = 24; /* before we start out... */
413 NumberColumns = 80;
414 ScreenSize = NumberLines*NumberColumns;
415 if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
416 ExitString("Programming error: MAXSCREENSIZE too small.\n",
417 1);
418 /*NOTREACHED*/
419 }
420 printsub(">", sb_terminal+2, sizeof sb_terminal-2);
421 ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
422 return 1;
423 } else {
424 return 0;
425 }
426}
476b1e3a
GM
427
428#if defined(unix)
429settranscom(argc, argv)
430 int argc;
431 char *argv[];
432{
433 int i, len = 0;
434
435 if (argc == 1 && transcom) {
436 transcom = 0;
437 }
438 if (argc == 1) {
439 return;
440 }
441 for (i = 1; i < argc; ++i) {
442 len += 1 + strlen(argv[1]);
443 }
444 transcom = tline;
445 (void) strcpy(transcom, argv[1]);
446 for (i = 2; i < argc; ++i) {
447 (void) strcat(transcom, " ");
448 (void) strcat(transcom, argv[i]);
449 }
450}
451#endif /* defined(unix) */
452
b6a8714b 453#endif /* defined(TN3270) */