1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 05/30/95"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <arpa/telnet.h> 14 15 #include "general.h" 16 17 #include "defines.h" 18 #include "ring.h" 19 #include "externs.h" 20 #include "fdset.h" 21 22 #if defined(TN3270) 23 24 #include "../ctlr/screen.h" 25 #include "../general/globals.h" 26 27 #include "../sys_curses/telextrn.h" 28 #include "../ctlr/externs.h" 29 30 #if defined(unix) 31 int 32 HaveInput, /* There is input available to scan */ 33 cursesdata, /* Do we dump curses data? */ 34 sigiocount; /* Number of times we got a SIGIO */ 35 36 char tline[200]; 37 char *transcom = 0; /* transparent mode command (default: none) */ 38 #endif /* defined(unix) */ 39 40 char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; 41 42 static char sb_terminal[] = { IAC, SB, 43 TELOPT_TTYPE, TELQUAL_IS, 44 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', 45 IAC, SE }; 46 #define SBTERMMODEL 13 47 48 static int 49 Sent3270TerminalType; /* Have we said we are a 3270? */ 50 51 #endif /* defined(TN3270) */ 52 53 54 void 55 init_3270() 56 { 57 #if defined(TN3270) 58 #if defined(unix) 59 HaveInput = 0; 60 sigiocount = 0; 61 #endif /* defined(unix) */ 62 Sent3270TerminalType = 0; 63 Ifrontp = Ibackp = Ibuf; 64 init_ctlr(); /* Initialize some things */ 65 init_keyboard(); 66 init_screen(); 67 init_system(); 68 #endif /* defined(TN3270) */ 69 } 70 71 72 #if defined(TN3270) 73 74 /* 75 * DataToNetwork - queue up some data to go to network. If "done" is set, 76 * then when last byte is queued, we add on an IAC EOR sequence (so, 77 * don't call us with "done" until you want that done...) 78 * 79 * We actually do send all the data to the network buffer, since our 80 * only client needs for us to do that. 81 */ 82 83 int 84 DataToNetwork(buffer, count, done) 85 register char *buffer; /* where the data is */ 86 register int count; /* how much to send */ 87 int done; /* is this the last of a logical block */ 88 { 89 register int loop, c; 90 int origCount; 91 92 origCount = count; 93 94 while (count) { 95 /* If not enough room for EORs, IACs, etc., wait */ 96 if (NETROOM() < 6) { 97 fd_set o; 98 99 FD_ZERO(&o); 100 netflush(); 101 while (NETROOM() < 6) { 102 FD_SET(net, &o); 103 (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, 104 (struct timeval *) 0); 105 netflush(); 106 } 107 } 108 c = ring_empty_count(&netoring); 109 if (c > count) { 110 c = count; 111 } 112 loop = c; 113 while (loop) { 114 if (((unsigned char)*buffer) == IAC) { 115 break; 116 } 117 buffer++; 118 loop--; 119 } 120 if ((c = c-loop)) { 121 ring_supply_data(&netoring, buffer-c, c); 122 count -= c; 123 } 124 if (loop) { 125 NET2ADD(IAC, IAC); 126 count--; 127 buffer++; 128 } 129 } 130 131 if (done) { 132 NET2ADD(IAC, EOR); 133 netflush(); /* try to move along as quickly as ... */ 134 } 135 return(origCount - count); 136 } 137 138 139 #if defined(unix) 140 void 141 inputAvailable(signo) 142 int signo; 143 { 144 HaveInput = 1; 145 sigiocount++; 146 } 147 #endif /* defined(unix) */ 148 149 void 150 outputPurge() 151 { 152 (void) ttyflush(1); 153 } 154 155 156 /* 157 * The following routines are places where the various tn3270 158 * routines make calls into telnet.c. 159 */ 160 161 /* 162 * DataToTerminal - queue up some data to go to terminal. 163 * 164 * Note: there are people who call us and depend on our processing 165 * *all* the data at one time (thus the select). 166 */ 167 168 int 169 DataToTerminal(buffer, count) 170 register char *buffer; /* where the data is */ 171 register int count; /* how much to send */ 172 { 173 register int c; 174 int origCount; 175 176 origCount = count; 177 178 while (count) { 179 if (TTYROOM() == 0) { 180 #if defined(unix) 181 fd_set o; 182 183 FD_ZERO(&o); 184 #endif /* defined(unix) */ 185 (void) ttyflush(0); 186 while (TTYROOM() == 0) { 187 #if defined(unix) 188 FD_SET(tout, &o); 189 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 190 (struct timeval *) 0); 191 #endif /* defined(unix) */ 192 (void) ttyflush(0); 193 } 194 } 195 c = TTYROOM(); 196 if (c > count) { 197 c = count; 198 } 199 ring_supply_data(&ttyoring, buffer, c); 200 count -= c; 201 buffer += c; 202 } 203 return(origCount); 204 } 205 206 207 /* 208 * Push3270 - Try to send data along the 3270 output (to screen) direction. 209 */ 210 211 int 212 Push3270() 213 { 214 int save = ring_full_count(&netiring); 215 216 if (save) { 217 if (Ifrontp+save > Ibuf+sizeof Ibuf) { 218 if (Ibackp != Ibuf) { 219 memmove(Ibuf, Ibackp, Ifrontp-Ibackp); 220 Ifrontp -= (Ibackp-Ibuf); 221 Ibackp = Ibuf; 222 } 223 } 224 if (Ifrontp+save < Ibuf+sizeof Ibuf) { 225 (void)telrcv(); 226 } 227 } 228 return save != ring_full_count(&netiring); 229 } 230 231 232 /* 233 * Finish3270 - get the last dregs of 3270 data out to the terminal 234 * before quitting. 235 */ 236 237 void 238 Finish3270() 239 { 240 while (Push3270() || !DoTerminalOutput()) { 241 #if defined(unix) 242 HaveInput = 0; 243 #endif /* defined(unix) */ 244 ; 245 } 246 } 247 248 249 /* StringToTerminal - output a null terminated string to the terminal */ 250 251 void 252 StringToTerminal(s) 253 char *s; 254 { 255 int count; 256 257 count = strlen(s); 258 if (count) { 259 (void) DataToTerminal(s, count); /* we know it always goes... */ 260 } 261 } 262 263 264 #if ((!defined(NOT43)) || defined(PUTCHAR)) 265 /* _putchar - output a single character to the terminal. This name is so that 266 * curses(3x) can call us to send out data. 267 */ 268 269 void 270 _putchar(c) 271 char c; 272 { 273 #if defined(sun) /* SunOS 4.0 bug */ 274 c &= 0x7f; 275 #endif /* defined(sun) */ 276 if (cursesdata) { 277 Dump('>', &c, 1); 278 } 279 if (!TTYROOM()) { 280 (void) DataToTerminal(&c, 1); 281 } else { 282 TTYADD(c); 283 } 284 } 285 #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ 286 287 void 288 SetIn3270() 289 { 290 if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) 291 && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { 292 if (!In3270) { 293 In3270 = 1; 294 Init3270(); /* Initialize 3270 functions */ 295 /* initialize terminal key mapping */ 296 InitTerminal(); /* Start terminal going */ 297 setconnmode(0); 298 } 299 } else { 300 if (In3270) { 301 StopScreen(1); 302 In3270 = 0; 303 Stop3270(); /* Tell 3270 we aren't here anymore */ 304 setconnmode(0); 305 } 306 } 307 } 308 309 /* 310 * tn3270_ttype() 311 * 312 * Send a response to a terminal type negotiation. 313 * 314 * Return '0' if no more responses to send; '1' if a response sent. 315 */ 316 317 int 318 tn3270_ttype() 319 { 320 /* 321 * Try to send a 3270 type terminal name. Decide which one based 322 * on the format of our screen, and (in the future) color 323 * capaiblities. 324 */ 325 InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ 326 if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { 327 Sent3270TerminalType = 1; 328 if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { 329 MaxNumberLines = 27; 330 MaxNumberColumns = 132; 331 sb_terminal[SBTERMMODEL] = '5'; 332 } else if (MaxNumberLines >= 43) { 333 MaxNumberLines = 43; 334 MaxNumberColumns = 80; 335 sb_terminal[SBTERMMODEL] = '4'; 336 } else if (MaxNumberLines >= 32) { 337 MaxNumberLines = 32; 338 MaxNumberColumns = 80; 339 sb_terminal[SBTERMMODEL] = '3'; 340 } else { 341 MaxNumberLines = 24; 342 MaxNumberColumns = 80; 343 sb_terminal[SBTERMMODEL] = '2'; 344 } 345 NumberLines = 24; /* before we start out... */ 346 NumberColumns = 80; 347 ScreenSize = NumberLines*NumberColumns; 348 if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { 349 ExitString("Programming error: MAXSCREENSIZE too small.\n", 350 1); 351 /*NOTREACHED*/ 352 } 353 printsub('>', sb_terminal+2, sizeof sb_terminal-2); 354 ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); 355 return 1; 356 } else { 357 return 0; 358 } 359 } 360 361 #if defined(unix) 362 int 363 settranscom(argc, argv) 364 int argc; 365 char *argv[]; 366 { 367 int i; 368 369 if (argc == 1 && transcom) { 370 transcom = 0; 371 } 372 if (argc == 1) { 373 return 1; 374 } 375 transcom = tline; 376 (void) strcpy(transcom, argv[1]); 377 for (i = 2; i < argc; ++i) { 378 (void) strcat(transcom, " "); 379 (void) strcat(transcom, argv[i]); 380 } 381 return 1; 382 } 383 #endif /* defined(unix) */ 384 385 #endif /* defined(TN3270) */ 386