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