133686Sbostic /* 233686Sbostic * Copyright (c) 1988 Regents of the University of California. 333686Sbostic * All rights reserved. 433686Sbostic * 533686Sbostic * Redistribution and use in source and binary forms are permitted 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633686Sbostic */ 1733686Sbostic 1833686Sbostic #ifndef lint 19*37226Sminshall static char sccsid[] = "@(#)tn3270.c 1.17 (Berkeley) 03/21/89"; 2033686Sbostic #endif /* not lint */ 2133686Sbostic 2233801Sminshall #include <sys/types.h> 2333801Sminshall #include <arpa/telnet.h> 2433801Sminshall 2534305Sminshall #include "general.h" 2634305Sminshall 2733801Sminshall #include "defines.h" 2833801Sminshall #include "ring.h" 2933801Sminshall #include "externs.h" 3032657Sminshall #include "fdset.h" 3132657Sminshall 3232185Sminshall #if defined(TN3270) 3332185Sminshall 3433801Sminshall #include "../ctlr/screen.h" 3533801Sminshall #include "../general/globals.h" 3632185Sminshall 3735417Sminshall #include "../telextrn.h" 3835417Sminshall #include "../ctlr/externs.h" 3935417Sminshall 4033801Sminshall #if defined(unix) 4136240Sminshall int 4236240Sminshall HaveInput, /* There is input available to scan */ 4336240Sminshall sigiocount; /* Number of times we got a SIGIO */ 4436240Sminshall 4533801Sminshall char tline[200]; 4633801Sminshall char *transcom = 0; /* transparent mode command (default: none) */ 4733801Sminshall #endif /* defined(unix) */ 4832531Sminshall 4933801Sminshall char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 5032531Sminshall 5132531Sminshall static char sb_terminal[] = { IAC, SB, 5232531Sminshall TELOPT_TTYPE, TELQUAL_IS, 5332531Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 5432531Sminshall IAC, SE }; 5532531Sminshall #define SBTERMMODEL 13 5632531Sminshall 5732531Sminshall static int 5832531Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 5932531Sminshall 6033801Sminshall #endif /* defined(TN3270) */ 6132531Sminshall 6233801Sminshall 6333801Sminshall void 6434303Sminshall init_3270() 6532551Sminshall { 6633801Sminshall #if defined(TN3270) 6736240Sminshall #if defined(unix) 6836240Sminshall HaveInput = 0; 6936240Sminshall sigiocount = 0; 7036240Sminshall #endif /* defined(unix) */ 7133801Sminshall Sent3270TerminalType = 0; 7233801Sminshall Ifrontp = Ibackp = Ibuf; 7333801Sminshall init_ctlr(); /* Initialize some things */ 7433801Sminshall init_keyboard(); 7533801Sminshall init_screen(); 7633801Sminshall init_system(); 7733801Sminshall #endif /* defined(TN3270) */ 7832551Sminshall } 7932551Sminshall 8033801Sminshall 8133801Sminshall #if defined(TN3270) 8233801Sminshall 8332185Sminshall /* 8432185Sminshall * DataToNetwork - queue up some data to go to network. If "done" is set, 8532185Sminshall * then when last byte is queued, we add on an IAC EOR sequence (so, 8632185Sminshall * don't call us with "done" until you want that done...) 8732185Sminshall * 8832185Sminshall * We actually do send all the data to the network buffer, since our 8932185Sminshall * only client needs for us to do that. 9032185Sminshall */ 9132185Sminshall 9232185Sminshall int 9332185Sminshall DataToNetwork(buffer, count, done) 9432185Sminshall register char *buffer; /* where the data is */ 9532185Sminshall register int count; /* how much to send */ 9632185Sminshall int done; /* is this the last of a logical block */ 9732185Sminshall { 9833801Sminshall register int loop, c; 9932185Sminshall int origCount; 10032185Sminshall 10132185Sminshall origCount = count; 10232185Sminshall 10332185Sminshall while (count) { 10434303Sminshall /* If not enough room for EORs, IACs, etc., wait */ 10533801Sminshall if (NETROOM() < 6) { 10633801Sminshall fd_set o; 10733801Sminshall 10833801Sminshall FD_ZERO(&o); 10932185Sminshall netflush(); 11033801Sminshall while (NETROOM() < 6) { 11132185Sminshall FD_SET(net, &o); 11232185Sminshall (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 11332185Sminshall (struct timeval *) 0); 11432185Sminshall netflush(); 11532185Sminshall } 11632185Sminshall } 11734303Sminshall c = ring_empty_count(&netoring); 11834303Sminshall if (c > count) { 11934303Sminshall c = count; 12034303Sminshall } 12134303Sminshall loop = c; 12233801Sminshall while (loop) { 12334311Sminshall if (((unsigned char)*buffer) == IAC) { 12433801Sminshall break; 12533801Sminshall } 12633801Sminshall buffer++; 12733801Sminshall loop--; 12832185Sminshall } 12933801Sminshall if ((c = c-loop)) { 13033801Sminshall ring_supply_data(&netoring, buffer-c, c); 13133801Sminshall count -= c; 13233801Sminshall } 13333801Sminshall if (loop) { 13433801Sminshall NET2ADD(IAC, IAC); 13533801Sminshall count--; 13634303Sminshall buffer++; 13733801Sminshall } 13832185Sminshall } 13932185Sminshall 14033801Sminshall if (done) { 14134303Sminshall NET2ADD(IAC, EOR); 14232185Sminshall netflush(); /* try to move along as quickly as ... */ 14332185Sminshall } 14432185Sminshall return(origCount - count); 14532185Sminshall } 14632185Sminshall 14732185Sminshall 14832185Sminshall #if defined(unix) 14933801Sminshall void 15032185Sminshall inputAvailable() 15132185Sminshall { 15232185Sminshall HaveInput = 1; 15336240Sminshall sigiocount++; 15432185Sminshall } 15532185Sminshall #endif /* defined(unix) */ 15632185Sminshall 15732185Sminshall void 15832185Sminshall outputPurge() 15932185Sminshall { 16032257Sminshall ttyflush(1); 16132185Sminshall } 16232185Sminshall 16332185Sminshall 16432185Sminshall /* 16532185Sminshall * The following routines are places where the various tn3270 16632185Sminshall * routines make calls into telnet.c. 16732185Sminshall */ 16832185Sminshall 16934303Sminshall /* 17034303Sminshall * DataToTerminal - queue up some data to go to terminal. 17134303Sminshall * 17234303Sminshall * Note: there are people who call us and depend on our processing 17334303Sminshall * *all* the data at one time (thus the select). 17434303Sminshall */ 17532185Sminshall 17632185Sminshall int 17732185Sminshall DataToTerminal(buffer, count) 17832185Sminshall register char *buffer; /* where the data is */ 17932185Sminshall register int count; /* how much to send */ 18032185Sminshall { 18135417Sminshall register int c; 18232185Sminshall int origCount; 18332185Sminshall 18432185Sminshall origCount = count; 18532185Sminshall 18632185Sminshall while (count) { 18733801Sminshall if (TTYROOM() == 0) { 18832185Sminshall #if defined(unix) 18933801Sminshall fd_set o; 19033801Sminshall 19133801Sminshall FD_ZERO(&o); 19233801Sminshall #endif /* defined(unix) */ 19335417Sminshall ttyflush(0); 19433801Sminshall while (TTYROOM() == 0) { 19533801Sminshall #if defined(unix) 19632185Sminshall FD_SET(tout, &o); 19732185Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 19832185Sminshall (struct timeval *) 0); 19932185Sminshall #endif /* defined(unix) */ 20035417Sminshall ttyflush(0); 20132185Sminshall } 20232185Sminshall } 20334303Sminshall c = TTYROOM(); 20434303Sminshall if (c > count) { 20534303Sminshall c = count; 20633801Sminshall } 20734303Sminshall ring_supply_data(&ttyoring, buffer, c); 20834303Sminshall count -= c; 20934303Sminshall buffer += c; 21032185Sminshall } 21134303Sminshall return(origCount); 21232185Sminshall } 21332185Sminshall 21432185Sminshall 21532185Sminshall /* 21632185Sminshall * Push3270 - Try to send data along the 3270 output (to screen) direction. 21732185Sminshall */ 21832185Sminshall 21933801Sminshall int 22032185Sminshall Push3270() 22132185Sminshall { 22233801Sminshall int save = ring_full_count(&netiring); 22332185Sminshall 22433801Sminshall if (save) { 22533801Sminshall if (Ifrontp+save > Ibuf+sizeof Ibuf) { 22632185Sminshall if (Ibackp != Ibuf) { 22732185Sminshall memcpy(Ibuf, Ibackp, Ifrontp-Ibackp); 22832185Sminshall Ifrontp -= (Ibackp-Ibuf); 22932185Sminshall Ibackp = Ibuf; 23032185Sminshall } 23132185Sminshall } 23233801Sminshall if (Ifrontp+save < Ibuf+sizeof Ibuf) { 23332185Sminshall telrcv(); 23432185Sminshall } 23532185Sminshall } 23633801Sminshall return save != ring_full_count(&netiring); 23732185Sminshall } 23832185Sminshall 23932185Sminshall 24032185Sminshall /* 24132185Sminshall * Finish3270 - get the last dregs of 3270 data out to the terminal 24232185Sminshall * before quitting. 24332185Sminshall */ 24432185Sminshall 24533801Sminshall void 24632185Sminshall Finish3270() 24732185Sminshall { 24832185Sminshall while (Push3270() || !DoTerminalOutput()) { 24932185Sminshall #if defined(unix) 25032185Sminshall HaveInput = 0; 25132185Sminshall #endif /* defined(unix) */ 25232185Sminshall ; 25332185Sminshall } 25432185Sminshall } 25532185Sminshall 25632185Sminshall 25732185Sminshall /* StringToTerminal - output a null terminated string to the terminal */ 25832185Sminshall 25932185Sminshall void 26032185Sminshall StringToTerminal(s) 26132185Sminshall char *s; 26232185Sminshall { 26332185Sminshall int count; 26432185Sminshall 26532185Sminshall count = strlen(s); 26632185Sminshall if (count) { 26732185Sminshall (void) DataToTerminal(s, count); /* we know it always goes... */ 26832185Sminshall } 26932185Sminshall } 27032185Sminshall 27132185Sminshall 27232185Sminshall #if ((!defined(NOT43)) || defined(PUTCHAR)) 27332185Sminshall /* _putchar - output a single character to the terminal. This name is so that 27432185Sminshall * curses(3x) can call us to send out data. 27532185Sminshall */ 27632185Sminshall 27732185Sminshall void 27832185Sminshall _putchar(c) 27932185Sminshall char c; 28032185Sminshall { 28136201Sminshall #if defined(sun) /* SunOS 4.0 bug */ 28236201Sminshall c &= 0x7f; 28336201Sminshall #endif /* defined(sun) */ 28436240Sminshall if (!TTYROOM()) { 28532185Sminshall (void) DataToTerminal(&c, 1); 28632185Sminshall } else { 28733801Sminshall TTYADD(c); 28832185Sminshall } 28932185Sminshall } 29032185Sminshall #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 29132185Sminshall 29232531Sminshall void 29332531Sminshall SetIn3270() 29432531Sminshall { 295*37226Sminshall if (Sent3270TerminalType && should_I(TELOPT_BINARY) 296*37226Sminshall && should_he(TELOPT_BINARY) && !donebinarytoggle) { 29732531Sminshall if (!In3270) { 29832531Sminshall In3270 = 1; 29932531Sminshall Init3270(); /* Initialize 3270 functions */ 30032531Sminshall /* initialize terminal key mapping */ 30132531Sminshall InitTerminal(); /* Start terminal going */ 30232531Sminshall setconnmode(); 30332531Sminshall } 30432531Sminshall } else { 30532531Sminshall if (In3270) { 30632531Sminshall StopScreen(1); 30732531Sminshall In3270 = 0; 30832531Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 30932531Sminshall setconnmode(); 31032531Sminshall } 31132531Sminshall } 31232531Sminshall } 31332531Sminshall 31432531Sminshall /* 31532531Sminshall * tn3270_ttype() 31632531Sminshall * 31732531Sminshall * Send a response to a terminal type negotiation. 31832531Sminshall * 31932531Sminshall * Return '0' if no more responses to send; '1' if a response sent. 32032531Sminshall */ 32132531Sminshall 32232531Sminshall int 32332531Sminshall tn3270_ttype() 32432531Sminshall { 32532531Sminshall /* 32632531Sminshall * Try to send a 3270 type terminal name. Decide which one based 32732531Sminshall * on the format of our screen, and (in the future) color 32832531Sminshall * capaiblities. 32932531Sminshall */ 33032531Sminshall InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 33132531Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 33232531Sminshall Sent3270TerminalType = 1; 33332531Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 33432531Sminshall MaxNumberLines = 27; 33532531Sminshall MaxNumberColumns = 132; 33632531Sminshall sb_terminal[SBTERMMODEL] = '5'; 33732531Sminshall } else if (MaxNumberLines >= 43) { 33832531Sminshall MaxNumberLines = 43; 33932531Sminshall MaxNumberColumns = 80; 34032531Sminshall sb_terminal[SBTERMMODEL] = '4'; 34132531Sminshall } else if (MaxNumberLines >= 32) { 34232531Sminshall MaxNumberLines = 32; 34332531Sminshall MaxNumberColumns = 80; 34432531Sminshall sb_terminal[SBTERMMODEL] = '3'; 34532531Sminshall } else { 34632531Sminshall MaxNumberLines = 24; 34732531Sminshall MaxNumberColumns = 80; 34832531Sminshall sb_terminal[SBTERMMODEL] = '2'; 34932531Sminshall } 35032531Sminshall NumberLines = 24; /* before we start out... */ 35132531Sminshall NumberColumns = 80; 35232531Sminshall ScreenSize = NumberLines*NumberColumns; 35332531Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 35432531Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 35532531Sminshall 1); 35632531Sminshall /*NOTREACHED*/ 35732531Sminshall } 35832531Sminshall printsub(">", sb_terminal+2, sizeof sb_terminal-2); 35932531Sminshall ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 36032531Sminshall return 1; 36132531Sminshall } else { 36232531Sminshall return 0; 36332531Sminshall } 36432531Sminshall } 36533801Sminshall 36633801Sminshall #if defined(unix) 36733801Sminshall settranscom(argc, argv) 36833801Sminshall int argc; 36933801Sminshall char *argv[]; 37033801Sminshall { 37135417Sminshall int i; 37233801Sminshall 37333801Sminshall if (argc == 1 && transcom) { 37433801Sminshall transcom = 0; 37533801Sminshall } 37633801Sminshall if (argc == 1) { 37733801Sminshall return; 37833801Sminshall } 37933801Sminshall transcom = tline; 38033801Sminshall (void) strcpy(transcom, argv[1]); 38133801Sminshall for (i = 2; i < argc; ++i) { 38233801Sminshall (void) strcat(transcom, " "); 38333801Sminshall (void) strcat(transcom, argv[i]); 38433801Sminshall } 38533801Sminshall } 38633801Sminshall #endif /* defined(unix) */ 38733801Sminshall 38832185Sminshall #endif /* defined(TN3270) */ 389