No empty .Rs/.Re
[netbsd-mini2440.git] / usr.bin / telnet / tn3270.c
blob3e05374a3d5e77ed01ecbf883cf55f0b2342bc91
1 /* $NetBSD: tn3270.c,v 1.21 2003/08/07 11:16:12 agc Exp $ */
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 5/30/95";
36 #else
37 __RCSID("$NetBSD: tn3270.c,v 1.21 2003/08/07 11:16:12 agc Exp $");
38 #endif
39 #endif /* not lint */
41 #include <sys/types.h>
42 #include <sys/time.h>
43 #include <arpa/telnet.h>
44 #include <unistd.h>
45 #include <poll.h>
47 #include "general.h"
48 #include "defines.h"
49 #include "ring.h"
50 #include "externs.h"
52 #ifdef TN3270
54 #include "../ctlr/screen.h"
55 #include "../ctlr/declare.h"
57 #include "../ascii/state.h"
59 #include "../general/globals.h"
61 #include "../sys_curses/telextrn.h"
63 int
64 HaveInput, /* There is input available to scan */
65 cursesdata, /* Do we dump curses data? */
66 sigiocount; /* Number of times we got a SIGIO */
68 char tline[200];
69 char *transcom = 0; /* transparent mode command (default: none) */
71 char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
73 static char sb_terminal[] = { IAC, SB,
74 TELOPT_TTYPE, TELQUAL_IS,
75 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
76 IAC, SE };
77 #define SBTERMMODEL 13
79 static int
80 Sent3270TerminalType; /* Have we said we are a 3270? */
82 #endif /* defined(TN3270) */
85 #ifdef TN3270
86 void
87 init_3270(void)
89 HaveInput = 0;
90 sigiocount = 0;
91 Sent3270TerminalType = 0;
92 Ifrontp = Ibackp = Ibuf;
93 init_ctlr(); /* Initialize some things */
94 init_keyboard();
95 init_screen();
96 init_system();
98 #endif /* defined(TN3270) */
101 #ifdef TN3270
104 * DataToNetwork - queue up some data to go to network. If "done" is set,
105 * then when last byte is queued, we add on an IAC EOR sequence (so,
106 * don't call us with "done" until you want that done...)
108 * We actually do send all the data to the network buffer, since our
109 * only client needs for us to do that.
113 DataToNetwork(char *buffer, /* where the data is */
114 int count, /* how much to send */
115 int done) /* is this the last of a logical block */
117 int loop, c;
118 int origCount;
120 origCount = count;
122 while (count) {
123 /* If not enough room for EORs, IACs, etc., wait */
124 if (NETROOM() < 6) {
125 struct pollfd set[1];
127 set[0].fd = net;
128 set[0].events = POLLOUT;
129 netflush();
130 while (NETROOM() < 6) {
131 (void) poll(set, 1, INFTIM);
132 netflush();
135 c = ring_empty_count(&netoring);
136 if (c > count) {
137 c = count;
139 loop = c;
140 while (loop) {
141 if (((unsigned char)*buffer) == IAC) {
142 break;
144 buffer++;
145 loop--;
147 if ((c = c-loop)) {
148 ring_supply_data(&netoring, buffer-c, c);
149 count -= c;
151 if (loop) {
152 NET2ADD(IAC, IAC);
153 count--;
154 buffer++;
158 if (done) {
159 NET2ADD(IAC, EOR);
160 netflush(); /* try to move along as quickly as ... */
162 return(origCount - count);
166 void
167 inputAvailable(int signo)
169 HaveInput = 1;
170 sigiocount++;
173 void
174 outputPurge(void)
176 (void) ttyflush(1);
181 * The following routines are places where the various tn3270
182 * routines make calls into telnet.c.
186 * DataToTerminal - queue up some data to go to terminal.
188 * Note: there are people who call us and depend on our processing
189 * *all* the data at one time (thus the poll).
193 DataToTerminal(
194 char *buffer, /* where the data is */
195 int count) /* how much to send */
197 int c;
198 int origCount;
200 origCount = count;
202 while (count) {
203 if (TTYROOM() == 0) {
204 struct pollfd set[1];
206 set[0].fd = tout;
207 set[0].events = POLLOUT;
208 (void) ttyflush(0);
209 while (TTYROOM() == 0) {
210 (void) poll(set, 1, INFTIM);
211 (void) ttyflush(0);
214 c = TTYROOM();
215 if (c > count) {
216 c = count;
218 ring_supply_data(&ttyoring, buffer, c);
219 count -= c;
220 buffer += c;
222 return(origCount);
227 * Push3270 - Try to send data along the 3270 output (to screen) direction.
231 Push3270(void)
233 int save = ring_full_count(&netiring);
235 if (save) {
236 if (Ifrontp+save > Ibuf+sizeof Ibuf) {
237 if (Ibackp != Ibuf) {
238 memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
239 Ifrontp -= (Ibackp-Ibuf);
240 Ibackp = Ibuf;
243 if (Ifrontp+save < Ibuf+sizeof Ibuf) {
244 (void)telrcv();
247 return save != ring_full_count(&netiring);
252 * Finish3270 - get the last dregs of 3270 data out to the terminal
253 * before quitting.
256 void
257 Finish3270(void)
259 while (Push3270() || !DoTerminalOutput()) {
260 HaveInput = 0;
266 /* StringToTerminal - output a null terminated string to the terminal */
268 void
269 StringToTerminal(char *s)
271 int count;
273 count = strlen(s);
274 if (count) {
275 (void) DataToTerminal(s, count); /* we know it always goes... */
280 /* _putchar - output a single character to the terminal. This name is so that
281 * curses(3x) can call us to send out data.
285 _putchar(int cc)
287 char c = (char)cc;
288 if (cursesdata) {
289 Dump('>', &c, 1);
291 if (!TTYROOM()) {
292 (void) DataToTerminal(&c, 1);
293 } else {
294 TTYADD(c);
297 return (0);
300 void
301 SetIn3270(void)
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);
312 } else {
313 if (In3270) {
314 StopScreen(1);
315 In3270 = 0;
316 Stop3270(); /* Tell 3270 we aren't here anymore */
317 setconnmode(0);
323 * tn3270_ttype()
325 * Send a response to a terminal type negotiation.
327 * Return '0' if no more responses to send; '1' if a response sent.
331 tn3270_ttype(void)
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.
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';
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",
364 /*NOTREACHED*/
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;
375 settranscom(int argc, char *argv[])
377 int i;
379 if (argc == 1 && transcom) {
380 transcom = 0;
382 if (argc == 1) {
383 return 1;
385 transcom = tline;
386 (void) strlcpy(tline, argv[1], sizeof(tline));
387 for (i = 2; i < argc; ++i) {
388 (void) strlcat(tline, " ", sizeof(tline));
389 (void) strlcat(tline, argv[i], sizeof(tline));
391 return 1;
394 #endif /* defined(TN3270) */