|
|
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.