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