1*32657Sminshall #include "fdset.h" 2*32657Sminshall 332185Sminshall void 432185Sminshall tn3270_init() 532185Sminshall { 632185Sminshall #if defined(TN3270) 732185Sminshall Sent3270TerminalType = 0; 832185Sminshall Ifrontp = Ibackp = Ibuf; 932185Sminshall init_ctlr(); /* Initialize some things */ 1032185Sminshall init_keyboard(); 1132185Sminshall init_screen(); 1232185Sminshall init_system(); 1332185Sminshall #endif /* defined(TN3270) */ 1432185Sminshall } 1532185Sminshall 1632185Sminshall #if defined(TN3270) 1732185Sminshall 1832531Sminshall 1932531Sminshall static char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 2032531Sminshall 2132531Sminshall static char sb_terminal[] = { IAC, SB, 2232531Sminshall TELOPT_TTYPE, TELQUAL_IS, 2332531Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 2432531Sminshall IAC, SE }; 2532531Sminshall #define SBTERMMODEL 13 2632531Sminshall 2732531Sminshall static int 2832531Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 2932531Sminshall 3032531Sminshall 3132551Sminshall #if defined(unix) 3232551Sminshall static 3332551Sminshall settranscom(argc, argv) 3432551Sminshall int argc; 3532551Sminshall char *argv[]; 3632551Sminshall { 3732551Sminshall int i, len = 0; 3832551Sminshall char *strcpy(), *strcat(); 3932551Sminshall 4032551Sminshall if (argc == 1 && transcom) { 4132551Sminshall transcom = 0; 4232551Sminshall } 4332551Sminshall if (argc == 1) { 4432551Sminshall return; 4532551Sminshall } 4632551Sminshall for (i = 1; i < argc; ++i) { 4732551Sminshall len += 1 + strlen(argv[1]); 4832551Sminshall } 4932551Sminshall transcom = tline; 5032551Sminshall (void) strcpy(transcom, argv[1]); 5132551Sminshall for (i = 2; i < argc; ++i) { 5232551Sminshall (void) strcat(transcom, " "); 5332551Sminshall (void) strcat(transcom, argv[i]); 5432551Sminshall } 5532551Sminshall } 5632551Sminshall #endif /* defined(unix) */ 5732551Sminshall 5832185Sminshall /* 5932185Sminshall * DataToNetwork - queue up some data to go to network. If "done" is set, 6032185Sminshall * then when last byte is queued, we add on an IAC EOR sequence (so, 6132185Sminshall * don't call us with "done" until you want that done...) 6232185Sminshall * 6332185Sminshall * We actually do send all the data to the network buffer, since our 6432185Sminshall * only client needs for us to do that. 6532185Sminshall */ 6632185Sminshall 6732185Sminshall int 6832185Sminshall DataToNetwork(buffer, count, done) 6932185Sminshall register char *buffer; /* where the data is */ 7032185Sminshall register int count; /* how much to send */ 7132185Sminshall int done; /* is this the last of a logical block */ 7232185Sminshall { 7332185Sminshall register int c; 7432185Sminshall int origCount; 7532185Sminshall fd_set o; 7632185Sminshall 7732185Sminshall origCount = count; 7832185Sminshall FD_ZERO(&o); 7932185Sminshall 8032185Sminshall while (count) { 8132185Sminshall if ((netobuf+sizeof netobuf - nfrontp) < 6) { 8232185Sminshall netflush(); 8332185Sminshall while ((netobuf+sizeof netobuf - nfrontp) < 6) { 8432185Sminshall FD_SET(net, &o); 8532185Sminshall (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 8632185Sminshall (struct timeval *) 0); 8732185Sminshall netflush(); 8832185Sminshall } 8932185Sminshall } 9032185Sminshall c = *buffer++; 9132185Sminshall count--; 9232185Sminshall if (c == IAC) { 9332185Sminshall *nfrontp++ = IAC; 9432185Sminshall *nfrontp++ = IAC; 9532185Sminshall } else { 9632185Sminshall *nfrontp++ = c; 9732185Sminshall } 9832185Sminshall } 9932185Sminshall 10032185Sminshall if (done && !count) { 10132185Sminshall *nfrontp++ = IAC; 10232185Sminshall *nfrontp++ = EOR; 10332185Sminshall netflush(); /* try to move along as quickly as ... */ 10432185Sminshall } 10532185Sminshall return(origCount - count); 10632185Sminshall } 10732185Sminshall 10832185Sminshall 10932185Sminshall #if defined(unix) 11032185Sminshall static void 11132185Sminshall inputAvailable() 11232185Sminshall { 11332185Sminshall HaveInput = 1; 11432185Sminshall } 11532185Sminshall #endif /* defined(unix) */ 11632185Sminshall 11732185Sminshall void 11832185Sminshall outputPurge() 11932185Sminshall { 12032257Sminshall ttyflush(1); 12132185Sminshall } 12232185Sminshall 12332185Sminshall 12432185Sminshall /* 12532185Sminshall * The following routines are places where the various tn3270 12632185Sminshall * routines make calls into telnet.c. 12732185Sminshall */ 12832185Sminshall 12932185Sminshall /* TtyChars() - returns the number of characters in the TTY buffer */ 13032185Sminshall TtyChars() 13132185Sminshall { 13232185Sminshall return(tfrontp-tbackp); 13332185Sminshall } 13432185Sminshall 13532185Sminshall /* DataToTerminal - queue up some data to go to terminal. */ 13632185Sminshall 13732185Sminshall int 13832185Sminshall DataToTerminal(buffer, count) 13932185Sminshall register char *buffer; /* where the data is */ 14032185Sminshall register int count; /* how much to send */ 14132185Sminshall { 14232185Sminshall int origCount; 14332185Sminshall #if defined(unix) 14432185Sminshall fd_set o; 14532185Sminshall 14632185Sminshall FD_ZERO(&o); 14732185Sminshall #endif /* defined(unix) */ 14832185Sminshall origCount = count; 14932185Sminshall 15032185Sminshall while (count) { 15132185Sminshall if (tfrontp >= ttyobuf+sizeof ttyobuf) { 15232257Sminshall ttyflush(0); 15332185Sminshall while (tfrontp >= ttyobuf+sizeof ttyobuf) { 15432185Sminshall #if defined(unix) 15532185Sminshall FD_SET(tout, &o); 15632185Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 15732185Sminshall (struct timeval *) 0); 15832185Sminshall #endif /* defined(unix) */ 15932257Sminshall ttyflush(0); 16032185Sminshall } 16132185Sminshall } 16232185Sminshall *tfrontp++ = *buffer++; 16332185Sminshall count--; 16432185Sminshall } 16532185Sminshall return(origCount - count); 16632185Sminshall } 16732185Sminshall 16832185Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty. 16932185Sminshall * Note that we consider the buffer to run all the 17032185Sminshall * way to the kernel (thus the select). 17132185Sminshall */ 17232185Sminshall 17332185Sminshall void 17432185Sminshall EmptyTerminal() 17532185Sminshall { 17632185Sminshall #if defined(unix) 17732185Sminshall fd_set o; 17832185Sminshall 17932185Sminshall FD_ZERO(&o); 18032185Sminshall #endif /* defined(unix) */ 18132185Sminshall 18232185Sminshall if (tfrontp == tbackp) { 18332185Sminshall #if defined(unix) 18432185Sminshall FD_SET(tout, &o); 18532185Sminshall (void) select(tout+1, (int *) 0, &o, (int *) 0, 18632185Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 18732185Sminshall #endif /* defined(unix) */ 18832185Sminshall } else { 18932185Sminshall while (tfrontp != tbackp) { 19032257Sminshall ttyflush(0); 19132185Sminshall #if defined(unix) 19232185Sminshall FD_SET(tout, &o); 19332185Sminshall (void) select(tout+1, (int *) 0, &o, (int *) 0, 19432185Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 19532185Sminshall #endif /* defined(unix) */ 19632185Sminshall } 19732185Sminshall } 19832185Sminshall } 19932185Sminshall 20032185Sminshall 20132185Sminshall /* 20232185Sminshall * Push3270 - Try to send data along the 3270 output (to screen) direction. 20332185Sminshall */ 20432185Sminshall 20532185Sminshall static int 20632185Sminshall Push3270() 20732185Sminshall { 20832185Sminshall int save = scc; 20932185Sminshall 21032185Sminshall if (scc) { 21132185Sminshall if (Ifrontp+scc > Ibuf+sizeof Ibuf) { 21232185Sminshall if (Ibackp != Ibuf) { 21332185Sminshall memcpy(Ibuf, Ibackp, Ifrontp-Ibackp); 21432185Sminshall Ifrontp -= (Ibackp-Ibuf); 21532185Sminshall Ibackp = Ibuf; 21632185Sminshall } 21732185Sminshall } 21832185Sminshall if (Ifrontp+scc < Ibuf+sizeof Ibuf) { 21932185Sminshall telrcv(); 22032185Sminshall } 22132185Sminshall } 22232185Sminshall return save != scc; 22332185Sminshall } 22432185Sminshall 22532185Sminshall 22632185Sminshall /* 22732185Sminshall * Finish3270 - get the last dregs of 3270 data out to the terminal 22832185Sminshall * before quitting. 22932185Sminshall */ 23032185Sminshall 23132185Sminshall static void 23232185Sminshall Finish3270() 23332185Sminshall { 23432185Sminshall while (Push3270() || !DoTerminalOutput()) { 23532185Sminshall #if defined(unix) 23632185Sminshall HaveInput = 0; 23732185Sminshall #endif /* defined(unix) */ 23832185Sminshall ; 23932185Sminshall } 24032185Sminshall } 24132185Sminshall 24232185Sminshall 24332185Sminshall /* StringToTerminal - output a null terminated string to the terminal */ 24432185Sminshall 24532185Sminshall void 24632185Sminshall StringToTerminal(s) 24732185Sminshall char *s; 24832185Sminshall { 24932185Sminshall int count; 25032185Sminshall 25132185Sminshall count = strlen(s); 25232185Sminshall if (count) { 25332185Sminshall (void) DataToTerminal(s, count); /* we know it always goes... */ 25432185Sminshall } 25532185Sminshall } 25632185Sminshall 25732185Sminshall 25832185Sminshall #if ((!defined(NOT43)) || defined(PUTCHAR)) 25932185Sminshall /* _putchar - output a single character to the terminal. This name is so that 26032185Sminshall * curses(3x) can call us to send out data. 26132185Sminshall */ 26232185Sminshall 26332185Sminshall void 26432185Sminshall _putchar(c) 26532185Sminshall char c; 26632185Sminshall { 26732185Sminshall if (tfrontp >= ttyobuf+sizeof ttyobuf) { 26832185Sminshall (void) DataToTerminal(&c, 1); 26932185Sminshall } else { 27032185Sminshall *tfrontp++ = c; /* optimize if possible. */ 27132185Sminshall } 27232185Sminshall } 27332185Sminshall #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 27432185Sminshall 27532531Sminshall void 27632531Sminshall SetForExit() 27732531Sminshall { 27832531Sminshall setconnmode(); 27932531Sminshall if (In3270) { 28032531Sminshall Finish3270(); 28132531Sminshall } 28232531Sminshall setcommandmode(); 28332531Sminshall fflush(stdout); 28432531Sminshall fflush(stderr); 28532531Sminshall if (In3270) { 28632531Sminshall StopScreen(1); 28732531Sminshall } 28832531Sminshall setconnmode(); 28932531Sminshall setcommandmode(); 29032531Sminshall } 29132531Sminshall 29232531Sminshall void 29332531Sminshall Exit(returnCode) 29432531Sminshall int returnCode; 29532531Sminshall { 29632531Sminshall SetForExit(); 29732531Sminshall exit(returnCode); 29832531Sminshall } 29932531Sminshall 30032531Sminshall void 30132531Sminshall ExitString(string, returnCode) 30232531Sminshall char *string; 30332531Sminshall int returnCode; 30432531Sminshall { 30532531Sminshall SetForExit(); 30632531Sminshall fwrite(string, 1, strlen(string), stderr); 30732531Sminshall exit(returnCode); 30832531Sminshall } 30932531Sminshall 31032531Sminshall void 31132531Sminshall ExitPerror(string, returnCode) 31232531Sminshall char *string; 31332531Sminshall int returnCode; 31432531Sminshall { 31532531Sminshall SetForExit(); 31632531Sminshall perror(string); 31732531Sminshall exit(returnCode); 31832531Sminshall } 31932531Sminshall 32032531Sminshall void 32132531Sminshall SetIn3270() 32232531Sminshall { 32332531Sminshall if (Sent3270TerminalType && myopts[TELOPT_BINARY] 32432531Sminshall && hisopts[TELOPT_BINARY] && !donebinarytoggle) { 32532531Sminshall if (!In3270) { 32632531Sminshall In3270 = 1; 32732531Sminshall Init3270(); /* Initialize 3270 functions */ 32832531Sminshall /* initialize terminal key mapping */ 32932531Sminshall InitTerminal(); /* Start terminal going */ 33032531Sminshall setconnmode(); 33132531Sminshall } 33232531Sminshall } else { 33332531Sminshall if (In3270) { 33432531Sminshall StopScreen(1); 33532531Sminshall In3270 = 0; 33632531Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 33732531Sminshall setconnmode(); 33832531Sminshall } 33932531Sminshall } 34032531Sminshall } 34132531Sminshall 34232531Sminshall /* 34332531Sminshall * tn3270_ttype() 34432531Sminshall * 34532531Sminshall * Send a response to a terminal type negotiation. 34632531Sminshall * 34732531Sminshall * Return '0' if no more responses to send; '1' if a response sent. 34832531Sminshall */ 34932531Sminshall 35032531Sminshall int 35132531Sminshall tn3270_ttype() 35232531Sminshall { 35332531Sminshall /* 35432531Sminshall * Try to send a 3270 type terminal name. Decide which one based 35532531Sminshall * on the format of our screen, and (in the future) color 35632531Sminshall * capaiblities. 35732531Sminshall */ 35832531Sminshall InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 35932531Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 36032531Sminshall Sent3270TerminalType = 1; 36132531Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 36232531Sminshall MaxNumberLines = 27; 36332531Sminshall MaxNumberColumns = 132; 36432531Sminshall sb_terminal[SBTERMMODEL] = '5'; 36532531Sminshall } else if (MaxNumberLines >= 43) { 36632531Sminshall MaxNumberLines = 43; 36732531Sminshall MaxNumberColumns = 80; 36832531Sminshall sb_terminal[SBTERMMODEL] = '4'; 36932531Sminshall } else if (MaxNumberLines >= 32) { 37032531Sminshall MaxNumberLines = 32; 37132531Sminshall MaxNumberColumns = 80; 37232531Sminshall sb_terminal[SBTERMMODEL] = '3'; 37332531Sminshall } else { 37432531Sminshall MaxNumberLines = 24; 37532531Sminshall MaxNumberColumns = 80; 37632531Sminshall sb_terminal[SBTERMMODEL] = '2'; 37732531Sminshall } 37832531Sminshall NumberLines = 24; /* before we start out... */ 37932531Sminshall NumberColumns = 80; 38032531Sminshall ScreenSize = NumberLines*NumberColumns; 38132531Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 38232531Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 38332531Sminshall 1); 38432531Sminshall /*NOTREACHED*/ 38532531Sminshall } 38632531Sminshall printsub(">", sb_terminal+2, sizeof sb_terminal-2); 38732531Sminshall ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 38832531Sminshall return 1; 38932531Sminshall } else { 39032531Sminshall return 0; 39132531Sminshall } 39232531Sminshall } 39332185Sminshall #endif /* defined(TN3270) */ 394