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