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