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*38690Sborman static char sccsid[] = "@(#)tn3270.c 1.19 (Berkeley) 08/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 */ 4338208Sminshall cursesdata, /* Do we dump curses data? */ 4436240Sminshall sigiocount; /* Number of times we got a SIGIO */ 4536240Sminshall 4633801Sminshall char tline[200]; 4733801Sminshall char *transcom = 0; /* transparent mode command (default: none) */ 4833801Sminshall #endif /* defined(unix) */ 4932531Sminshall 5033801Sminshall char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 5132531Sminshall 5232531Sminshall static char sb_terminal[] = { IAC, SB, 5332531Sminshall TELOPT_TTYPE, TELQUAL_IS, 5432531Sminshall 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 5532531Sminshall IAC, SE }; 5632531Sminshall #define SBTERMMODEL 13 5732531Sminshall 5832531Sminshall static int 5932531Sminshall Sent3270TerminalType; /* Have we said we are a 3270? */ 6032531Sminshall 6133801Sminshall #endif /* defined(TN3270) */ 6232531Sminshall 6333801Sminshall 6433801Sminshall void 6534303Sminshall init_3270() 6632551Sminshall { 6733801Sminshall #if defined(TN3270) 6836240Sminshall #if defined(unix) 6936240Sminshall HaveInput = 0; 7036240Sminshall sigiocount = 0; 7136240Sminshall #endif /* defined(unix) */ 7233801Sminshall Sent3270TerminalType = 0; 7333801Sminshall Ifrontp = Ibackp = Ibuf; 7433801Sminshall init_ctlr(); /* Initialize some things */ 7533801Sminshall init_keyboard(); 7633801Sminshall init_screen(); 7733801Sminshall init_system(); 7833801Sminshall #endif /* defined(TN3270) */ 7932551Sminshall } 8032551Sminshall 8133801Sminshall 8233801Sminshall #if defined(TN3270) 8333801Sminshall 8432185Sminshall /* 8532185Sminshall * DataToNetwork - queue up some data to go to network. If "done" is set, 8632185Sminshall * then when last byte is queued, we add on an IAC EOR sequence (so, 8732185Sminshall * don't call us with "done" until you want that done...) 8832185Sminshall * 8932185Sminshall * We actually do send all the data to the network buffer, since our 9032185Sminshall * only client needs for us to do that. 9132185Sminshall */ 9232185Sminshall 9332185Sminshall int 9432185Sminshall DataToNetwork(buffer, count, done) 9532185Sminshall register char *buffer; /* where the data is */ 9632185Sminshall register int count; /* how much to send */ 9732185Sminshall int done; /* is this the last of a logical block */ 9832185Sminshall { 9933801Sminshall register int loop, c; 10032185Sminshall int origCount; 10132185Sminshall 10232185Sminshall origCount = count; 10332185Sminshall 10432185Sminshall while (count) { 10534303Sminshall /* If not enough room for EORs, IACs, etc., wait */ 10633801Sminshall if (NETROOM() < 6) { 10733801Sminshall fd_set o; 10833801Sminshall 10933801Sminshall FD_ZERO(&o); 11032185Sminshall netflush(); 11133801Sminshall while (NETROOM() < 6) { 11232185Sminshall FD_SET(net, &o); 11332185Sminshall (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 11432185Sminshall (struct timeval *) 0); 11532185Sminshall netflush(); 11632185Sminshall } 11732185Sminshall } 11834303Sminshall c = ring_empty_count(&netoring); 11934303Sminshall if (c > count) { 12034303Sminshall c = count; 12134303Sminshall } 12234303Sminshall loop = c; 12333801Sminshall while (loop) { 12434311Sminshall if (((unsigned char)*buffer) == IAC) { 12533801Sminshall break; 12633801Sminshall } 12733801Sminshall buffer++; 12833801Sminshall loop--; 12932185Sminshall } 13033801Sminshall if ((c = c-loop)) { 13133801Sminshall ring_supply_data(&netoring, buffer-c, c); 13233801Sminshall count -= c; 13333801Sminshall } 13433801Sminshall if (loop) { 13533801Sminshall NET2ADD(IAC, IAC); 13633801Sminshall count--; 13734303Sminshall buffer++; 13833801Sminshall } 13932185Sminshall } 14032185Sminshall 14133801Sminshall if (done) { 14234303Sminshall NET2ADD(IAC, EOR); 14332185Sminshall netflush(); /* try to move along as quickly as ... */ 14432185Sminshall } 14532185Sminshall return(origCount - count); 14632185Sminshall } 14732185Sminshall 14832185Sminshall 14932185Sminshall #if defined(unix) 15033801Sminshall void 15132185Sminshall inputAvailable() 15232185Sminshall { 15332185Sminshall HaveInput = 1; 15436240Sminshall sigiocount++; 15532185Sminshall } 15632185Sminshall #endif /* defined(unix) */ 15732185Sminshall 15832185Sminshall void 15932185Sminshall outputPurge() 16032185Sminshall { 16132257Sminshall ttyflush(1); 16232185Sminshall } 16332185Sminshall 16432185Sminshall 16532185Sminshall /* 16632185Sminshall * The following routines are places where the various tn3270 16732185Sminshall * routines make calls into telnet.c. 16832185Sminshall */ 16932185Sminshall 17034303Sminshall /* 17134303Sminshall * DataToTerminal - queue up some data to go to terminal. 17234303Sminshall * 17334303Sminshall * Note: there are people who call us and depend on our processing 17434303Sminshall * *all* the data at one time (thus the select). 17534303Sminshall */ 17632185Sminshall 17732185Sminshall int 17832185Sminshall DataToTerminal(buffer, count) 17932185Sminshall register char *buffer; /* where the data is */ 18032185Sminshall register int count; /* how much to send */ 18132185Sminshall { 18235417Sminshall register int c; 18332185Sminshall int origCount; 18432185Sminshall 18532185Sminshall origCount = count; 18632185Sminshall 18732185Sminshall while (count) { 18833801Sminshall if (TTYROOM() == 0) { 18932185Sminshall #if defined(unix) 19033801Sminshall fd_set o; 19133801Sminshall 19233801Sminshall FD_ZERO(&o); 19333801Sminshall #endif /* defined(unix) */ 19435417Sminshall ttyflush(0); 19533801Sminshall while (TTYROOM() == 0) { 19633801Sminshall #if defined(unix) 19732185Sminshall FD_SET(tout, &o); 19832185Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 19932185Sminshall (struct timeval *) 0); 20032185Sminshall #endif /* defined(unix) */ 20135417Sminshall ttyflush(0); 20232185Sminshall } 20332185Sminshall } 20434303Sminshall c = TTYROOM(); 20534303Sminshall if (c > count) { 20634303Sminshall c = count; 20733801Sminshall } 20834303Sminshall ring_supply_data(&ttyoring, buffer, c); 20934303Sminshall count -= c; 21034303Sminshall buffer += c; 21132185Sminshall } 21234303Sminshall return(origCount); 21332185Sminshall } 21432185Sminshall 21532185Sminshall 21632185Sminshall /* 21732185Sminshall * Push3270 - Try to send data along the 3270 output (to screen) direction. 21832185Sminshall */ 21932185Sminshall 22033801Sminshall int 22132185Sminshall Push3270() 22232185Sminshall { 22333801Sminshall int save = ring_full_count(&netiring); 22432185Sminshall 22533801Sminshall if (save) { 22633801Sminshall if (Ifrontp+save > Ibuf+sizeof Ibuf) { 22732185Sminshall if (Ibackp != Ibuf) { 22832185Sminshall memcpy(Ibuf, Ibackp, Ifrontp-Ibackp); 22932185Sminshall Ifrontp -= (Ibackp-Ibuf); 23032185Sminshall Ibackp = Ibuf; 23132185Sminshall } 23232185Sminshall } 23333801Sminshall if (Ifrontp+save < Ibuf+sizeof Ibuf) { 23432185Sminshall telrcv(); 23532185Sminshall } 23632185Sminshall } 23733801Sminshall return save != ring_full_count(&netiring); 23832185Sminshall } 23932185Sminshall 24032185Sminshall 24132185Sminshall /* 24232185Sminshall * Finish3270 - get the last dregs of 3270 data out to the terminal 24332185Sminshall * before quitting. 24432185Sminshall */ 24532185Sminshall 24633801Sminshall void 24732185Sminshall Finish3270() 24832185Sminshall { 24932185Sminshall while (Push3270() || !DoTerminalOutput()) { 25032185Sminshall #if defined(unix) 25132185Sminshall HaveInput = 0; 25232185Sminshall #endif /* defined(unix) */ 25332185Sminshall ; 25432185Sminshall } 25532185Sminshall } 25632185Sminshall 25732185Sminshall 25832185Sminshall /* StringToTerminal - output a null terminated string to the terminal */ 25932185Sminshall 26032185Sminshall void 26132185Sminshall StringToTerminal(s) 26232185Sminshall char *s; 26332185Sminshall { 26432185Sminshall int count; 26532185Sminshall 26632185Sminshall count = strlen(s); 26732185Sminshall if (count) { 26832185Sminshall (void) DataToTerminal(s, count); /* we know it always goes... */ 26932185Sminshall } 27032185Sminshall } 27132185Sminshall 27232185Sminshall 27332185Sminshall #if ((!defined(NOT43)) || defined(PUTCHAR)) 27432185Sminshall /* _putchar - output a single character to the terminal. This name is so that 27532185Sminshall * curses(3x) can call us to send out data. 27632185Sminshall */ 27732185Sminshall 27832185Sminshall void 27932185Sminshall _putchar(c) 28032185Sminshall char c; 28132185Sminshall { 28236201Sminshall #if defined(sun) /* SunOS 4.0 bug */ 28336201Sminshall c &= 0x7f; 28436201Sminshall #endif /* defined(sun) */ 28538208Sminshall if (cursesdata) { 28638208Sminshall Dump('>', &c, 1); 28738208Sminshall } 28836240Sminshall if (!TTYROOM()) { 28932185Sminshall (void) DataToTerminal(&c, 1); 29032185Sminshall } else { 29133801Sminshall TTYADD(c); 29232185Sminshall } 29332185Sminshall } 29432185Sminshall #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 29532185Sminshall 29632531Sminshall void 29732531Sminshall SetIn3270() 29832531Sminshall { 299*38690Sborman if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) 300*38690Sborman && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { 30132531Sminshall if (!In3270) { 30232531Sminshall In3270 = 1; 30332531Sminshall Init3270(); /* Initialize 3270 functions */ 30432531Sminshall /* initialize terminal key mapping */ 30532531Sminshall InitTerminal(); /* Start terminal going */ 306*38690Sborman setconnmode(0); 30732531Sminshall } 30832531Sminshall } else { 30932531Sminshall if (In3270) { 31032531Sminshall StopScreen(1); 31132531Sminshall In3270 = 0; 31232531Sminshall Stop3270(); /* Tell 3270 we aren't here anymore */ 313*38690Sborman setconnmode(0); 31432531Sminshall } 31532531Sminshall } 31632531Sminshall } 31732531Sminshall 31832531Sminshall /* 31932531Sminshall * tn3270_ttype() 32032531Sminshall * 32132531Sminshall * Send a response to a terminal type negotiation. 32232531Sminshall * 32332531Sminshall * Return '0' if no more responses to send; '1' if a response sent. 32432531Sminshall */ 32532531Sminshall 32632531Sminshall int 32732531Sminshall tn3270_ttype() 32832531Sminshall { 32932531Sminshall /* 33032531Sminshall * Try to send a 3270 type terminal name. Decide which one based 33132531Sminshall * on the format of our screen, and (in the future) color 33232531Sminshall * capaiblities. 33332531Sminshall */ 33432531Sminshall InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 33532531Sminshall if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 33632531Sminshall Sent3270TerminalType = 1; 33732531Sminshall if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 33832531Sminshall MaxNumberLines = 27; 33932531Sminshall MaxNumberColumns = 132; 34032531Sminshall sb_terminal[SBTERMMODEL] = '5'; 34132531Sminshall } else if (MaxNumberLines >= 43) { 34232531Sminshall MaxNumberLines = 43; 34332531Sminshall MaxNumberColumns = 80; 34432531Sminshall sb_terminal[SBTERMMODEL] = '4'; 34532531Sminshall } else if (MaxNumberLines >= 32) { 34632531Sminshall MaxNumberLines = 32; 34732531Sminshall MaxNumberColumns = 80; 34832531Sminshall sb_terminal[SBTERMMODEL] = '3'; 34932531Sminshall } else { 35032531Sminshall MaxNumberLines = 24; 35132531Sminshall MaxNumberColumns = 80; 35232531Sminshall sb_terminal[SBTERMMODEL] = '2'; 35332531Sminshall } 35432531Sminshall NumberLines = 24; /* before we start out... */ 35532531Sminshall NumberColumns = 80; 35632531Sminshall ScreenSize = NumberLines*NumberColumns; 35732531Sminshall if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 35832531Sminshall ExitString("Programming error: MAXSCREENSIZE too small.\n", 35932531Sminshall 1); 36032531Sminshall /*NOTREACHED*/ 36132531Sminshall } 362*38690Sborman printsub('>', sb_terminal+2, sizeof sb_terminal-2); 36332531Sminshall ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 36432531Sminshall return 1; 36532531Sminshall } else { 36632531Sminshall return 0; 36732531Sminshall } 36832531Sminshall } 36933801Sminshall 37033801Sminshall #if defined(unix) 37133801Sminshall settranscom(argc, argv) 37233801Sminshall int argc; 37333801Sminshall char *argv[]; 37433801Sminshall { 37535417Sminshall int i; 37633801Sminshall 37733801Sminshall if (argc == 1 && transcom) { 37833801Sminshall transcom = 0; 37933801Sminshall } 38033801Sminshall if (argc == 1) { 38133801Sminshall return; 38233801Sminshall } 38333801Sminshall transcom = tline; 38433801Sminshall (void) strcpy(transcom, argv[1]); 38533801Sminshall for (i = 2; i < argc; ++i) { 38633801Sminshall (void) strcat(transcom, " "); 38733801Sminshall (void) strcat(transcom, argv[i]); 38833801Sminshall } 38933801Sminshall } 39033801Sminshall #endif /* defined(unix) */ 39133801Sminshall 39232185Sminshall #endif /* defined(TN3270) */ 393