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