132185Sminshall void 232185Sminshall tn3270_init() 332185Sminshall { 432185Sminshall #if defined(TN3270) 532185Sminshall Sent3270TerminalType = 0; 632185Sminshall Ifrontp = Ibackp = Ibuf; 732185Sminshall init_ctlr(); /* Initialize some things */ 832185Sminshall init_keyboard(); 932185Sminshall init_screen(); 1032185Sminshall init_system(); 1132185Sminshall #endif /* defined(TN3270) */ 1232185Sminshall } 1332185Sminshall 1432185Sminshall #if defined(TN3270) 1532185Sminshall 16*32531Sminshall 17*32531Sminshall static char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 18*32531Sminshall 19*32531Sminshall static char sb_terminal[] = { IAC, SB, 20*32531Sminshall TELOPT_TTYPE, TELQUAL_IS, 21*32531Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 22*32531Sminshall IAC, SE }; 23*32531Sminshall #define SBTERMMODEL 13 24*32531Sminshall 25*32531Sminshall static int 26*32531Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 27*32531Sminshall 28*32531Sminshall 2932185Sminshall /* 3032185Sminshall * DataToNetwork - queue up some data to go to network. If "done" is set, 3132185Sminshall * then when last byte is queued, we add on an IAC EOR sequence (so, 3232185Sminshall * don't call us with "done" until you want that done...) 3332185Sminshall * 3432185Sminshall * We actually do send all the data to the network buffer, since our 3532185Sminshall * only client needs for us to do that. 3632185Sminshall */ 3732185Sminshall 3832185Sminshall int 3932185Sminshall DataToNetwork(buffer, count, done) 4032185Sminshall register char *buffer; /* where the data is */ 4132185Sminshall register int count; /* how much to send */ 4232185Sminshall int done; /* is this the last of a logical block */ 4332185Sminshall { 4432185Sminshall register int c; 4532185Sminshall int origCount; 4632185Sminshall fd_set o; 4732185Sminshall 4832185Sminshall origCount = count; 4932185Sminshall FD_ZERO(&o); 5032185Sminshall 5132185Sminshall while (count) { 5232185Sminshall if ((netobuf+sizeof netobuf - nfrontp) < 6) { 5332185Sminshall netflush(); 5432185Sminshall while ((netobuf+sizeof netobuf - nfrontp) < 6) { 5532185Sminshall FD_SET(net, &o); 5632185Sminshall (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 5732185Sminshall (struct timeval *) 0); 5832185Sminshall netflush(); 5932185Sminshall } 6032185Sminshall } 6132185Sminshall c = *buffer++; 6232185Sminshall count--; 6332185Sminshall if (c == IAC) { 6432185Sminshall *nfrontp++ = IAC; 6532185Sminshall *nfrontp++ = IAC; 6632185Sminshall } else { 6732185Sminshall *nfrontp++ = c; 6832185Sminshall } 6932185Sminshall } 7032185Sminshall 7132185Sminshall if (done && !count) { 7232185Sminshall *nfrontp++ = IAC; 7332185Sminshall *nfrontp++ = EOR; 7432185Sminshall netflush(); /* try to move along as quickly as ... */ 7532185Sminshall } 7632185Sminshall return(origCount - count); 7732185Sminshall } 7832185Sminshall 7932185Sminshall 8032185Sminshall #if defined(unix) 8132185Sminshall static void 8232185Sminshall inputAvailable() 8332185Sminshall { 8432185Sminshall HaveInput = 1; 8532185Sminshall } 8632185Sminshall #endif /* defined(unix) */ 8732185Sminshall 8832185Sminshall void 8932185Sminshall outputPurge() 9032185Sminshall { 9132257Sminshall ttyflush(1); 9232185Sminshall } 9332185Sminshall 9432185Sminshall 9532185Sminshall /* 9632185Sminshall * The following routines are places where the various tn3270 9732185Sminshall * routines make calls into telnet.c. 9832185Sminshall */ 9932185Sminshall 10032185Sminshall /* TtyChars() - returns the number of characters in the TTY buffer */ 10132185Sminshall TtyChars() 10232185Sminshall { 10332185Sminshall return(tfrontp-tbackp); 10432185Sminshall } 10532185Sminshall 10632185Sminshall /* DataToTerminal - queue up some data to go to terminal. */ 10732185Sminshall 10832185Sminshall int 10932185Sminshall DataToTerminal(buffer, count) 11032185Sminshall register char *buffer; /* where the data is */ 11132185Sminshall register int count; /* how much to send */ 11232185Sminshall { 11332185Sminshall int origCount; 11432185Sminshall #if defined(unix) 11532185Sminshall fd_set o; 11632185Sminshall 11732185Sminshall FD_ZERO(&o); 11832185Sminshall #endif /* defined(unix) */ 11932185Sminshall origCount = count; 12032185Sminshall 12132185Sminshall while (count) { 12232185Sminshall if (tfrontp >= ttyobuf+sizeof ttyobuf) { 12332257Sminshall ttyflush(0); 12432185Sminshall while (tfrontp >= ttyobuf+sizeof ttyobuf) { 12532185Sminshall #if defined(unix) 12632185Sminshall FD_SET(tout, &o); 12732185Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 12832185Sminshall (struct timeval *) 0); 12932185Sminshall #endif /* defined(unix) */ 13032257Sminshall ttyflush(0); 13132185Sminshall } 13232185Sminshall } 13332185Sminshall *tfrontp++ = *buffer++; 13432185Sminshall count--; 13532185Sminshall } 13632185Sminshall return(origCount - count); 13732185Sminshall } 13832185Sminshall 13932185Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty. 14032185Sminshall * Note that we consider the buffer to run all the 14132185Sminshall * way to the kernel (thus the select). 14232185Sminshall */ 14332185Sminshall 14432185Sminshall void 14532185Sminshall EmptyTerminal() 14632185Sminshall { 14732185Sminshall #if defined(unix) 14832185Sminshall fd_set o; 14932185Sminshall 15032185Sminshall FD_ZERO(&o); 15132185Sminshall #endif /* defined(unix) */ 15232185Sminshall 15332185Sminshall if (tfrontp == tbackp) { 15432185Sminshall #if defined(unix) 15532185Sminshall FD_SET(tout, &o); 15632185Sminshall (void) select(tout+1, (int *) 0, &o, (int *) 0, 15732185Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 15832185Sminshall #endif /* defined(unix) */ 15932185Sminshall } else { 16032185Sminshall while (tfrontp != tbackp) { 16132257Sminshall ttyflush(0); 16232185Sminshall #if defined(unix) 16332185Sminshall FD_SET(tout, &o); 16432185Sminshall (void) select(tout+1, (int *) 0, &o, (int *) 0, 16532185Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 16632185Sminshall #endif /* defined(unix) */ 16732185Sminshall } 16832185Sminshall } 16932185Sminshall } 17032185Sminshall 17132185Sminshall 17232185Sminshall /* 17332185Sminshall * Push3270 - Try to send data along the 3270 output (to screen) direction. 17432185Sminshall */ 17532185Sminshall 17632185Sminshall static int 17732185Sminshall Push3270() 17832185Sminshall { 17932185Sminshall int save = scc; 18032185Sminshall 18132185Sminshall if (scc) { 18232185Sminshall if (Ifrontp+scc > Ibuf+sizeof Ibuf) { 18332185Sminshall if (Ibackp != Ibuf) { 18432185Sminshall memcpy(Ibuf, Ibackp, Ifrontp-Ibackp); 18532185Sminshall Ifrontp -= (Ibackp-Ibuf); 18632185Sminshall Ibackp = Ibuf; 18732185Sminshall } 18832185Sminshall } 18932185Sminshall if (Ifrontp+scc < Ibuf+sizeof Ibuf) { 19032185Sminshall telrcv(); 19132185Sminshall } 19232185Sminshall } 19332185Sminshall return save != scc; 19432185Sminshall } 19532185Sminshall 19632185Sminshall 19732185Sminshall /* 19832185Sminshall * Finish3270 - get the last dregs of 3270 data out to the terminal 19932185Sminshall * before quitting. 20032185Sminshall */ 20132185Sminshall 20232185Sminshall static void 20332185Sminshall Finish3270() 20432185Sminshall { 20532185Sminshall while (Push3270() || !DoTerminalOutput()) { 20632185Sminshall #if defined(unix) 20732185Sminshall HaveInput = 0; 20832185Sminshall #endif /* defined(unix) */ 20932185Sminshall ; 21032185Sminshall } 21132185Sminshall } 21232185Sminshall 21332185Sminshall 21432185Sminshall /* StringToTerminal - output a null terminated string to the terminal */ 21532185Sminshall 21632185Sminshall void 21732185Sminshall StringToTerminal(s) 21832185Sminshall char *s; 21932185Sminshall { 22032185Sminshall int count; 22132185Sminshall 22232185Sminshall count = strlen(s); 22332185Sminshall if (count) { 22432185Sminshall (void) DataToTerminal(s, count); /* we know it always goes... */ 22532185Sminshall } 22632185Sminshall } 22732185Sminshall 22832185Sminshall 22932185Sminshall #if ((!defined(NOT43)) || defined(PUTCHAR)) 23032185Sminshall /* _putchar - output a single character to the terminal. This name is so that 23132185Sminshall * curses(3x) can call us to send out data. 23232185Sminshall */ 23332185Sminshall 23432185Sminshall void 23532185Sminshall _putchar(c) 23632185Sminshall char c; 23732185Sminshall { 23832185Sminshall if (tfrontp >= ttyobuf+sizeof ttyobuf) { 23932185Sminshall (void) DataToTerminal(&c, 1); 24032185Sminshall } else { 24132185Sminshall *tfrontp++ = c; /* optimize if possible. */ 24232185Sminshall } 24332185Sminshall } 24432185Sminshall #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 24532185Sminshall 246*32531Sminshall void 247*32531Sminshall SetForExit() 248*32531Sminshall { 249*32531Sminshall setconnmode(); 250*32531Sminshall if (In3270) { 251*32531Sminshall Finish3270(); 252*32531Sminshall } 253*32531Sminshall setcommandmode(); 254*32531Sminshall fflush(stdout); 255*32531Sminshall fflush(stderr); 256*32531Sminshall if (In3270) { 257*32531Sminshall StopScreen(1); 258*32531Sminshall } 259*32531Sminshall setconnmode(); 260*32531Sminshall setcommandmode(); 261*32531Sminshall } 262*32531Sminshall 263*32531Sminshall void 264*32531Sminshall Exit(returnCode) 265*32531Sminshall int returnCode; 266*32531Sminshall { 267*32531Sminshall SetForExit(); 268*32531Sminshall exit(returnCode); 269*32531Sminshall } 270*32531Sminshall 271*32531Sminshall void 272*32531Sminshall ExitString(string, returnCode) 273*32531Sminshall char *string; 274*32531Sminshall int returnCode; 275*32531Sminshall { 276*32531Sminshall SetForExit(); 277*32531Sminshall fwrite(string, 1, strlen(string), stderr); 278*32531Sminshall exit(returnCode); 279*32531Sminshall } 280*32531Sminshall 281*32531Sminshall void 282*32531Sminshall ExitPerror(string, returnCode) 283*32531Sminshall char *string; 284*32531Sminshall int returnCode; 285*32531Sminshall { 286*32531Sminshall SetForExit(); 287*32531Sminshall perror(string); 288*32531Sminshall exit(returnCode); 289*32531Sminshall } 290*32531Sminshall 291*32531Sminshall void 292*32531Sminshall SetIn3270() 293*32531Sminshall { 294*32531Sminshall if (Sent3270TerminalType && myopts[TELOPT_BINARY] 295*32531Sminshall && hisopts[TELOPT_BINARY] && !donebinarytoggle) { 296*32531Sminshall if (!In3270) { 297*32531Sminshall In3270 = 1; 298*32531Sminshall Init3270(); /* Initialize 3270 functions */ 299*32531Sminshall /* initialize terminal key mapping */ 300*32531Sminshall InitTerminal(); /* Start terminal going */ 301*32531Sminshall setconnmode(); 302*32531Sminshall } 303*32531Sminshall } else { 304*32531Sminshall if (In3270) { 305*32531Sminshall StopScreen(1); 306*32531Sminshall In3270 = 0; 307*32531Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 308*32531Sminshall setconnmode(); 309*32531Sminshall } 310*32531Sminshall } 311*32531Sminshall } 312*32531Sminshall 313*32531Sminshall /* 314*32531Sminshall * tn3270_ttype() 315*32531Sminshall * 316*32531Sminshall * Send a response to a terminal type negotiation. 317*32531Sminshall * 318*32531Sminshall * Return '0' if no more responses to send; '1' if a response sent. 319*32531Sminshall */ 320*32531Sminshall 321*32531Sminshall int 322*32531Sminshall tn3270_ttype() 323*32531Sminshall { 324*32531Sminshall /* 325*32531Sminshall * Try to send a 3270 type terminal name. Decide which one based 326*32531Sminshall * on the format of our screen, and (in the future) color 327*32531Sminshall * capaiblities. 328*32531Sminshall */ 329*32531Sminshall InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 330*32531Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 331*32531Sminshall Sent3270TerminalType = 1; 332*32531Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 333*32531Sminshall MaxNumberLines = 27; 334*32531Sminshall MaxNumberColumns = 132; 335*32531Sminshall sb_terminal[SBTERMMODEL] = '5'; 336*32531Sminshall } else if (MaxNumberLines >= 43) { 337*32531Sminshall MaxNumberLines = 43; 338*32531Sminshall MaxNumberColumns = 80; 339*32531Sminshall sb_terminal[SBTERMMODEL] = '4'; 340*32531Sminshall } else if (MaxNumberLines >= 32) { 341*32531Sminshall MaxNumberLines = 32; 342*32531Sminshall MaxNumberColumns = 80; 343*32531Sminshall sb_terminal[SBTERMMODEL] = '3'; 344*32531Sminshall } else { 345*32531Sminshall MaxNumberLines = 24; 346*32531Sminshall MaxNumberColumns = 80; 347*32531Sminshall sb_terminal[SBTERMMODEL] = '2'; 348*32531Sminshall } 349*32531Sminshall NumberLines = 24; /* before we start out... */ 350*32531Sminshall NumberColumns = 80; 351*32531Sminshall ScreenSize = NumberLines*NumberColumns; 352*32531Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 353*32531Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 354*32531Sminshall 1); 355*32531Sminshall /*NOTREACHED*/ 356*32531Sminshall } 357*32531Sminshall printsub(">", sb_terminal+2, sizeof sb_terminal-2); 358*32531Sminshall ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 359*32531Sminshall return 1; 360*32531Sminshall } else { 361*32531Sminshall return 0; 362*32531Sminshall } 363*32531Sminshall } 36432185Sminshall #endif /* defined(TN3270) */ 365