133686Sbostic /* 262313Sbostic * Copyright (c) 1988, 1993 362313Sbostic * The Regents of the University of California. All rights reserved. 433686Sbostic * 542770Sbostic * %sccs.include.redist.c% 633686Sbostic */ 733686Sbostic 833686Sbostic #ifndef lint 9*69785Sdab static char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 05/30/95"; 1033686Sbostic #endif /* not lint */ 1133686Sbostic 1233801Sminshall #include <sys/types.h> 1333801Sminshall #include <arpa/telnet.h> 1433801Sminshall 1534305Sminshall #include "general.h" 1634305Sminshall 1733801Sminshall #include "defines.h" 1833801Sminshall #include "ring.h" 1933801Sminshall #include "externs.h" 2032657Sminshall #include "fdset.h" 2132657Sminshall 2232185Sminshall #if defined(TN3270) 2332185Sminshall 2433801Sminshall #include "../ctlr/screen.h" 2533801Sminshall #include "../general/globals.h" 2632185Sminshall 2759892Sbostic #include "../sys_curses/telextrn.h" 2835417Sminshall #include "../ctlr/externs.h" 2935417Sminshall 3033801Sminshall #if defined(unix) 3136240Sminshall int 3236240Sminshall HaveInput, /* There is input available to scan */ 3338208Sminshall cursesdata, /* Do we dump curses data? */ 3436240Sminshall sigiocount; /* Number of times we got a SIGIO */ 3536240Sminshall 3633801Sminshall char tline[200]; 3733801Sminshall char *transcom = 0; /* transparent mode command (default: none) */ 3833801Sminshall #endif /* defined(unix) */ 3932531Sminshall 4033801Sminshall char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 4132531Sminshall 4232531Sminshall static char sb_terminal[] = { IAC, SB, 4332531Sminshall TELOPT_TTYPE, TELQUAL_IS, 4432531Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 4532531Sminshall IAC, SE }; 4632531Sminshall #define SBTERMMODEL 13 4732531Sminshall 4832531Sminshall static int 4932531Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 5032531Sminshall 5133801Sminshall #endif /* defined(TN3270) */ 5232531Sminshall 5333801Sminshall 5446808Sdab void 5534303Sminshall init_3270() 5632551Sminshall { 5733801Sminshall #if defined(TN3270) 5836240Sminshall #if defined(unix) 5936240Sminshall HaveInput = 0; 6036240Sminshall sigiocount = 0; 6136240Sminshall #endif /* defined(unix) */ 6233801Sminshall Sent3270TerminalType = 0; 6333801Sminshall Ifrontp = Ibackp = Ibuf; 6433801Sminshall init_ctlr(); /* Initialize some things */ 6533801Sminshall init_keyboard(); 6633801Sminshall init_screen(); 6733801Sminshall init_system(); 6833801Sminshall #endif /* defined(TN3270) */ 6932551Sminshall } 7032551Sminshall 7133801Sminshall 7233801Sminshall #if defined(TN3270) 7333801Sminshall 7432185Sminshall /* 7532185Sminshall * DataToNetwork - queue up some data to go to network. If "done" is set, 7632185Sminshall * then when last byte is queued, we add on an IAC EOR sequence (so, 7732185Sminshall * don't call us with "done" until you want that done...) 7832185Sminshall * 7932185Sminshall * We actually do send all the data to the network buffer, since our 8032185Sminshall * only client needs for us to do that. 8132185Sminshall */ 8232185Sminshall 8346808Sdab int 8432185Sminshall DataToNetwork(buffer, count, done) 8546808Sdab register char *buffer; /* where the data is */ 8646808Sdab register int count; /* how much to send */ 8746808Sdab int done; /* is this the last of a logical block */ 8832185Sminshall { 8933801Sminshall register int loop, c; 9032185Sminshall int origCount; 9132185Sminshall 9232185Sminshall origCount = count; 9332185Sminshall 9432185Sminshall while (count) { 9534303Sminshall /* If not enough room for EORs, IACs, etc., wait */ 9633801Sminshall if (NETROOM() < 6) { 9733801Sminshall fd_set o; 9833801Sminshall 9933801Sminshall FD_ZERO(&o); 10032185Sminshall netflush(); 10133801Sminshall while (NETROOM() < 6) { 10232185Sminshall FD_SET(net, &o); 10332185Sminshall (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 10432185Sminshall (struct timeval *) 0); 10532185Sminshall netflush(); 10632185Sminshall } 10732185Sminshall } 10834303Sminshall c = ring_empty_count(&netoring); 10934303Sminshall if (c > count) { 11034303Sminshall c = count; 11134303Sminshall } 11234303Sminshall loop = c; 11333801Sminshall while (loop) { 11434311Sminshall if (((unsigned char)*buffer) == IAC) { 11533801Sminshall break; 11633801Sminshall } 11733801Sminshall buffer++; 11833801Sminshall loop--; 11932185Sminshall } 12033801Sminshall if ((c = c-loop)) { 12133801Sminshall ring_supply_data(&netoring, buffer-c, c); 12233801Sminshall count -= c; 12333801Sminshall } 12433801Sminshall if (loop) { 12533801Sminshall NET2ADD(IAC, IAC); 12633801Sminshall count--; 12734303Sminshall buffer++; 12833801Sminshall } 12932185Sminshall } 13032185Sminshall 13133801Sminshall if (done) { 13234303Sminshall NET2ADD(IAC, EOR); 13332185Sminshall netflush(); /* try to move along as quickly as ... */ 13432185Sminshall } 13532185Sminshall return(origCount - count); 13632185Sminshall } 13732185Sminshall 13832185Sminshall 13932185Sminshall #if defined(unix) 14046808Sdab void 14159893Sbostic inputAvailable(signo) 14259893Sbostic int signo; 14332185Sminshall { 14432185Sminshall HaveInput = 1; 14536240Sminshall sigiocount++; 14632185Sminshall } 14732185Sminshall #endif /* defined(unix) */ 14832185Sminshall 14946808Sdab void 15032185Sminshall outputPurge() 15132185Sminshall { 15244360Sborman (void) ttyflush(1); 15332185Sminshall } 15432185Sminshall 15532185Sminshall 15632185Sminshall /* 15732185Sminshall * The following routines are places where the various tn3270 15832185Sminshall * routines make calls into telnet.c. 15932185Sminshall */ 16032185Sminshall 16134303Sminshall /* 16234303Sminshall * DataToTerminal - queue up some data to go to terminal. 16334303Sminshall * 16434303Sminshall * Note: there are people who call us and depend on our processing 16534303Sminshall * *all* the data at one time (thus the select). 16634303Sminshall */ 16732185Sminshall 16846808Sdab int 16932185Sminshall DataToTerminal(buffer, count) 17046808Sdab register char *buffer; /* where the data is */ 17146808Sdab register int count; /* how much to send */ 17232185Sminshall { 17335417Sminshall register int c; 17432185Sminshall int origCount; 17532185Sminshall 17632185Sminshall origCount = count; 17732185Sminshall 17832185Sminshall while (count) { 17933801Sminshall if (TTYROOM() == 0) { 18032185Sminshall #if defined(unix) 18133801Sminshall fd_set o; 18233801Sminshall 18333801Sminshall FD_ZERO(&o); 18433801Sminshall #endif /* defined(unix) */ 18544360Sborman (void) ttyflush(0); 18633801Sminshall while (TTYROOM() == 0) { 18733801Sminshall #if defined(unix) 18832185Sminshall FD_SET(tout, &o); 18932185Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 19032185Sminshall (struct timeval *) 0); 19132185Sminshall #endif /* defined(unix) */ 19244360Sborman (void) ttyflush(0); 19332185Sminshall } 19432185Sminshall } 19534303Sminshall c = TTYROOM(); 19634303Sminshall if (c > count) { 19734303Sminshall c = count; 19833801Sminshall } 19934303Sminshall ring_supply_data(&ttyoring, buffer, c); 20034303Sminshall count -= c; 20134303Sminshall buffer += c; 20232185Sminshall } 20334303Sminshall return(origCount); 20432185Sminshall } 20532185Sminshall 20632185Sminshall 20732185Sminshall /* 20832185Sminshall * Push3270 - Try to send data along the 3270 output (to screen) direction. 20932185Sminshall */ 21032185Sminshall 21146808Sdab int 21232185Sminshall Push3270() 21332185Sminshall { 21433801Sminshall int save = ring_full_count(&netiring); 21532185Sminshall 21633801Sminshall if (save) { 21733801Sminshall if (Ifrontp+save > Ibuf+sizeof Ibuf) { 21832185Sminshall if (Ibackp != Ibuf) { 219*69785Sdab memmove(Ibuf, Ibackp, Ifrontp-Ibackp); 22032185Sminshall Ifrontp -= (Ibackp-Ibuf); 22132185Sminshall Ibackp = Ibuf; 22232185Sminshall } 22332185Sminshall } 22433801Sminshall if (Ifrontp+save < Ibuf+sizeof Ibuf) { 22544360Sborman (void)telrcv(); 22632185Sminshall } 22732185Sminshall } 22833801Sminshall return save != ring_full_count(&netiring); 22932185Sminshall } 23032185Sminshall 23132185Sminshall 23232185Sminshall /* 23332185Sminshall * Finish3270 - get the last dregs of 3270 data out to the terminal 23432185Sminshall * before quitting. 23532185Sminshall */ 23632185Sminshall 23746808Sdab void 23832185Sminshall Finish3270() 23932185Sminshall { 24032185Sminshall while (Push3270() || !DoTerminalOutput()) { 24132185Sminshall #if defined(unix) 24232185Sminshall HaveInput = 0; 24332185Sminshall #endif /* defined(unix) */ 24432185Sminshall ; 24532185Sminshall } 24632185Sminshall } 24732185Sminshall 24832185Sminshall 24932185Sminshall /* StringToTerminal - output a null terminated string to the terminal */ 25032185Sminshall 25146808Sdab void 25232185Sminshall StringToTerminal(s) 25346808Sdab char *s; 25432185Sminshall { 25532185Sminshall int count; 25632185Sminshall 25732185Sminshall count = strlen(s); 25832185Sminshall if (count) { 25932185Sminshall (void) DataToTerminal(s, count); /* we know it always goes... */ 26032185Sminshall } 26132185Sminshall } 26232185Sminshall 26332185Sminshall 26432185Sminshall #if ((!defined(NOT43)) || defined(PUTCHAR)) 26532185Sminshall /* _putchar - output a single character to the terminal. This name is so that 26632185Sminshall * curses(3x) can call us to send out data. 26732185Sminshall */ 26832185Sminshall 26946808Sdab void 27032185Sminshall _putchar(c) 27146808Sdab char c; 27232185Sminshall { 27336201Sminshall #if defined(sun) /* SunOS 4.0 bug */ 27436201Sminshall c &= 0x7f; 27536201Sminshall #endif /* defined(sun) */ 27638208Sminshall if (cursesdata) { 27738208Sminshall Dump('>', &c, 1); 27838208Sminshall } 27936240Sminshall if (!TTYROOM()) { 28032185Sminshall (void) DataToTerminal(&c, 1); 28132185Sminshall } else { 28233801Sminshall TTYADD(c); 28332185Sminshall } 28432185Sminshall } 28532185Sminshall #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 28632185Sminshall 28746808Sdab void 28832531Sminshall SetIn3270() 28932531Sminshall { 29038690Sborman if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) 29138690Sborman && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { 29232531Sminshall if (!In3270) { 29332531Sminshall In3270 = 1; 29432531Sminshall Init3270(); /* Initialize 3270 functions */ 29532531Sminshall /* initialize terminal key mapping */ 29632531Sminshall InitTerminal(); /* Start terminal going */ 29738690Sborman setconnmode(0); 29832531Sminshall } 29932531Sminshall } else { 30032531Sminshall if (In3270) { 30132531Sminshall StopScreen(1); 30232531Sminshall In3270 = 0; 30332531Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 30438690Sborman setconnmode(0); 30532531Sminshall } 30632531Sminshall } 30732531Sminshall } 30832531Sminshall 30932531Sminshall /* 31032531Sminshall * tn3270_ttype() 31132531Sminshall * 31232531Sminshall * Send a response to a terminal type negotiation. 31332531Sminshall * 31432531Sminshall * Return '0' if no more responses to send; '1' if a response sent. 31532531Sminshall */ 31632531Sminshall 31746808Sdab int 31832531Sminshall tn3270_ttype() 31932531Sminshall { 32032531Sminshall /* 32132531Sminshall * Try to send a 3270 type terminal name. Decide which one based 32232531Sminshall * on the format of our screen, and (in the future) color 32332531Sminshall * capaiblities. 32432531Sminshall */ 32532531Sminshall InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 32632531Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 32732531Sminshall Sent3270TerminalType = 1; 32832531Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 32932531Sminshall MaxNumberLines = 27; 33032531Sminshall MaxNumberColumns = 132; 33132531Sminshall sb_terminal[SBTERMMODEL] = '5'; 33232531Sminshall } else if (MaxNumberLines >= 43) { 33332531Sminshall MaxNumberLines = 43; 33432531Sminshall MaxNumberColumns = 80; 33532531Sminshall sb_terminal[SBTERMMODEL] = '4'; 33632531Sminshall } else if (MaxNumberLines >= 32) { 33732531Sminshall MaxNumberLines = 32; 33832531Sminshall MaxNumberColumns = 80; 33932531Sminshall sb_terminal[SBTERMMODEL] = '3'; 34032531Sminshall } else { 34132531Sminshall MaxNumberLines = 24; 34232531Sminshall MaxNumberColumns = 80; 34332531Sminshall sb_terminal[SBTERMMODEL] = '2'; 34432531Sminshall } 34532531Sminshall NumberLines = 24; /* before we start out... */ 34632531Sminshall NumberColumns = 80; 34732531Sminshall ScreenSize = NumberLines*NumberColumns; 34832531Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 34932531Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 35032531Sminshall 1); 35132531Sminshall /*NOTREACHED*/ 35232531Sminshall } 35338690Sborman printsub('>', sb_terminal+2, sizeof sb_terminal-2); 35432531Sminshall ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 35532531Sminshall return 1; 35632531Sminshall } else { 35732531Sminshall return 0; 35832531Sminshall } 35932531Sminshall } 36033801Sminshall 36133801Sminshall #if defined(unix) 36260179Sbostic int 36333801Sminshall settranscom(argc, argv) 36433801Sminshall int argc; 36533801Sminshall char *argv[]; 36633801Sminshall { 36735417Sminshall int i; 36833801Sminshall 36933801Sminshall if (argc == 1 && transcom) { 37033801Sminshall transcom = 0; 37133801Sminshall } 37233801Sminshall if (argc == 1) { 37360179Sbostic return 1; 37433801Sminshall } 37533801Sminshall transcom = tline; 37633801Sminshall (void) strcpy(transcom, argv[1]); 37733801Sminshall for (i = 2; i < argc; ++i) { 37833801Sminshall (void) strcat(transcom, " "); 37933801Sminshall (void) strcat(transcom, argv[i]); 38033801Sminshall } 38160179Sbostic return 1; 38233801Sminshall } 38333801Sminshall #endif /* defined(unix) */ 38433801Sminshall 38532185Sminshall #endif /* defined(TN3270) */ 386