1 1.40 maya /* $NetBSD: sys_bsd.c,v 1.40 2018/12/14 06:28:49 maya Exp $ */ 2 1.11 thorpej 3 1.1 cgd /* 4 1.5 cgd * Copyright (c) 1988, 1990, 1993 5 1.5 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.29 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.12 christos #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.11 thorpej #if 0 35 1.11 thorpej from: static char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; 36 1.11 thorpej #else 37 1.40 maya __RCSID("$NetBSD: sys_bsd.c,v 1.40 2018/12/14 06:28:49 maya Exp $"); 38 1.11 thorpej #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.1 cgd /* 42 1.1 cgd * The following routines try to encapsulate what is system dependent 43 1.1 cgd * (at least between 4.x and dos) which is used in telnet.c. 44 1.1 cgd */ 45 1.1 cgd 46 1.1 cgd 47 1.1 cgd #include <fcntl.h> 48 1.1 cgd #include <sys/types.h> 49 1.1 cgd #include <sys/time.h> 50 1.1 cgd #include <sys/socket.h> 51 1.1 cgd #include <signal.h> 52 1.12 christos #include <stdlib.h> 53 1.12 christos #include <unistd.h> 54 1.1 cgd #include <errno.h> 55 1.21 itojun #include <poll.h> 56 1.1 cgd #include <arpa/telnet.h> 57 1.1 cgd 58 1.1 cgd #include "ring.h" 59 1.1 cgd #include "defines.h" 60 1.1 cgd #include "externs.h" 61 1.1 cgd #include "types.h" 62 1.1 cgd 63 1.37 maya void susp(int); 64 1.37 maya void ayt(int); 65 1.1 cgd 66 1.37 maya void intr(int); 67 1.37 maya void intr2(int); 68 1.37 maya void sendwin(int); 69 1.12 christos 70 1.12 christos 71 1.1 cgd int 72 1.1 cgd tout, /* Output file descriptor */ 73 1.1 cgd tin, /* Input file descriptor */ 74 1.1 cgd net; 75 1.1 cgd 76 1.33 christos struct termios old_tc = { .c_iflag = 0 }; 77 1.25 itojun extern struct termios new_tc; 78 1.1 cgd 79 1.24 christos void 80 1.24 christos init_sys(void) 81 1.1 cgd { 82 1.1 cgd tout = fileno(stdout); 83 1.1 cgd tin = fileno(stdin); 84 1.1 cgd 85 1.1 cgd errno = 0; 86 1.1 cgd } 87 1.1 cgd 88 1.1 cgd 89 1.24 christos int 90 1.24 christos TerminalWrite(char *buf, int n) 91 1.1 cgd { 92 1.1 cgd return write(tout, buf, n); 93 1.1 cgd } 94 1.1 cgd 95 1.24 christos int 96 1.24 christos TerminalRead(unsigned char *buf, int n) 97 1.1 cgd { 98 1.1 cgd return read(tin, buf, n); 99 1.1 cgd } 100 1.1 cgd 101 1.1 cgd /* 102 1.1 cgd * 103 1.1 cgd */ 104 1.1 cgd 105 1.24 christos int 106 1.24 christos TerminalAutoFlush(void) 107 1.1 cgd { 108 1.1 cgd return 1; 109 1.1 cgd } 110 1.1 cgd 111 1.1 cgd #ifdef KLUDGELINEMODE 112 1.1 cgd extern int kludgelinemode; 113 1.1 cgd #endif 114 1.1 cgd /* 115 1.1 cgd * TerminalSpecialChars() 116 1.1 cgd * 117 1.1 cgd * Look at an input character to see if it is a special character 118 1.1 cgd * and decide what to do. 119 1.1 cgd * 120 1.1 cgd * Output: 121 1.1 cgd * 122 1.1 cgd * 0 Don't add this character. 123 1.1 cgd * 1 Do add this character 124 1.1 cgd */ 125 1.1 cgd 126 1.24 christos int 127 1.24 christos TerminalSpecialChars(int c) 128 1.1 cgd { 129 1.1 cgd if (c == termIntChar) { 130 1.1 cgd intp(); 131 1.1 cgd return 0; 132 1.1 cgd } else if (c == termQuitChar) { 133 1.1 cgd #ifdef KLUDGELINEMODE 134 1.1 cgd if (kludgelinemode) 135 1.1 cgd sendbrk(); 136 1.1 cgd else 137 1.1 cgd #endif 138 1.1 cgd sendabort(); 139 1.1 cgd return 0; 140 1.1 cgd } else if (c == termEofChar) { 141 1.1 cgd if (my_want_state_is_will(TELOPT_LINEMODE)) { 142 1.1 cgd sendeof(); 143 1.1 cgd return 0; 144 1.1 cgd } 145 1.1 cgd return 1; 146 1.1 cgd } else if (c == termSuspChar) { 147 1.1 cgd sendsusp(); 148 1.1 cgd return(0); 149 1.1 cgd } else if (c == termFlushChar) { 150 1.1 cgd xmitAO(); /* Transmit Abort Output */ 151 1.1 cgd return 0; 152 1.1 cgd } else if (!MODE_LOCAL_CHARS(globalmode)) { 153 1.1 cgd if (c == termKillChar) { 154 1.1 cgd xmitEL(); 155 1.1 cgd return 0; 156 1.1 cgd } else if (c == termEraseChar) { 157 1.1 cgd xmitEC(); /* Transmit Erase Character */ 158 1.1 cgd return 0; 159 1.1 cgd } 160 1.1 cgd } 161 1.1 cgd return 1; 162 1.1 cgd } 163 1.1 cgd 164 1.1 cgd 165 1.1 cgd /* 166 1.1 cgd * Flush output to the terminal 167 1.1 cgd */ 168 1.8 jtk 169 1.24 christos void 170 1.24 christos TerminalFlushOutput(void) 171 1.1 cgd { 172 1.28 jdolecek int com = 0; 173 1.28 jdolecek (void) ioctl(fileno(stdout), TIOCFLUSH, &com); 174 1.1 cgd } 175 1.1 cgd 176 1.24 christos void 177 1.24 christos TerminalSaveState(void) 178 1.1 cgd { 179 1.1 cgd tcgetattr(0, &old_tc); 180 1.1 cgd 181 1.1 cgd new_tc = old_tc; 182 1.1 cgd } 183 1.1 cgd 184 1.24 christos cc_t * 185 1.24 christos tcval(int func) 186 1.1 cgd { 187 1.1 cgd switch(func) { 188 1.1 cgd case SLC_IP: return(&termIntChar); 189 1.1 cgd case SLC_ABORT: return(&termQuitChar); 190 1.1 cgd case SLC_EOF: return(&termEofChar); 191 1.1 cgd case SLC_EC: return(&termEraseChar); 192 1.1 cgd case SLC_EL: return(&termKillChar); 193 1.1 cgd case SLC_XON: return(&termStartChar); 194 1.1 cgd case SLC_XOFF: return(&termStopChar); 195 1.1 cgd case SLC_FORW1: return(&termForw1Char); 196 1.1 cgd case SLC_FORW2: return(&termForw2Char); 197 1.1 cgd case SLC_AO: return(&termFlushChar); 198 1.1 cgd case SLC_SUSP: return(&termSuspChar); 199 1.1 cgd case SLC_EW: return(&termWerasChar); 200 1.1 cgd case SLC_RP: return(&termRprntChar); 201 1.1 cgd case SLC_LNEXT: return(&termLiteralNextChar); 202 1.1 cgd case SLC_AYT: return(&termAytChar); 203 1.1 cgd 204 1.1 cgd case SLC_SYNCH: 205 1.1 cgd case SLC_BRK: 206 1.1 cgd case SLC_EOR: 207 1.1 cgd default: 208 1.1 cgd return((cc_t *)0); 209 1.1 cgd } 210 1.1 cgd } 211 1.1 cgd 212 1.24 christos void 213 1.24 christos TerminalDefaultChars(void) 214 1.1 cgd { 215 1.8 jtk memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); 216 1.1 cgd } 217 1.1 cgd 218 1.1 cgd /* 219 1.1 cgd * TerminalNewMode - set up terminal to a specific mode. 220 1.1 cgd * MODE_ECHO: do local terminal echo 221 1.1 cgd * MODE_FLOW: do local flow control 222 1.1 cgd * MODE_TRAPSIG: do local mapping to TELNET IAC sequences 223 1.1 cgd * MODE_EDIT: do local line editing 224 1.1 cgd * 225 1.1 cgd * Command mode: 226 1.1 cgd * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG 227 1.1 cgd * local echo 228 1.1 cgd * local editing 229 1.1 cgd * local xon/xoff 230 1.1 cgd * local signal mapping 231 1.1 cgd * 232 1.1 cgd * Linemode: 233 1.1 cgd * local/no editing 234 1.1 cgd * Both Linemode and Single Character mode: 235 1.1 cgd * local/remote echo 236 1.1 cgd * local/no xon/xoff 237 1.1 cgd * local/no signal mapping 238 1.1 cgd */ 239 1.1 cgd 240 1.1 cgd 241 1.24 christos void 242 1.24 christos TerminalNewMode(int f) 243 1.1 cgd { 244 1.1 cgd static int prevmode = 0; 245 1.25 itojun struct termios tmp_tc; 246 1.1 cgd int onoff; 247 1.1 cgd int old; 248 1.1 cgd cc_t esc; 249 1.1 cgd 250 1.1 cgd globalmode = f&~MODE_FORCE; 251 1.1 cgd if (prevmode == f) 252 1.1 cgd return; 253 1.1 cgd 254 1.1 cgd /* 255 1.1 cgd * Write any outstanding data before switching modes 256 1.1 cgd * ttyflush() returns 0 only when there is no more data 257 1.1 cgd * left to write out, it returns -1 if it couldn't do 258 1.1 cgd * anything at all, otherwise it returns 1 + the number 259 1.1 cgd * of characters left to write. 260 1.1 cgd #ifndef USE_TERMIO 261 1.23 christos * We would really like to ask the kernel to wait for the output 262 1.1 cgd * to drain, like we can do with the TCSADRAIN, but we don't have 263 1.1 cgd * that option. The only ioctl that waits for the output to 264 1.1 cgd * drain, TIOCSETP, also flushes the input queue, which is NOT 265 1.1 cgd * what we want (TIOCSETP is like TCSADFLUSH). 266 1.1 cgd #endif 267 1.1 cgd */ 268 1.1 cgd old = ttyflush(SYNCHing|flushout); 269 1.1 cgd if (old < 0 || old > 1) { 270 1.1 cgd tcgetattr(tin, &tmp_tc); 271 1.1 cgd do { 272 1.1 cgd /* 273 1.1 cgd * Wait for data to drain, then flush again. 274 1.1 cgd */ 275 1.1 cgd tcsetattr(tin, TCSADRAIN, &tmp_tc); 276 1.1 cgd old = ttyflush(SYNCHing|flushout); 277 1.1 cgd } while (old < 0 || old > 1); 278 1.1 cgd } 279 1.1 cgd 280 1.1 cgd old = prevmode; 281 1.1 cgd prevmode = f&~MODE_FORCE; 282 1.1 cgd tmp_tc = new_tc; 283 1.1 cgd 284 1.1 cgd if (f&MODE_ECHO) { 285 1.1 cgd tmp_tc.c_lflag |= ECHO; 286 1.1 cgd tmp_tc.c_oflag |= ONLCR; 287 1.1 cgd if (crlf) 288 1.1 cgd tmp_tc.c_iflag |= ICRNL; 289 1.1 cgd } else { 290 1.1 cgd tmp_tc.c_lflag &= ~ECHO; 291 1.1 cgd tmp_tc.c_oflag &= ~ONLCR; 292 1.1 cgd # ifdef notdef 293 1.1 cgd if (crlf) 294 1.1 cgd tmp_tc.c_iflag &= ~ICRNL; 295 1.1 cgd # endif 296 1.1 cgd } 297 1.1 cgd 298 1.1 cgd if ((f&MODE_FLOW) == 0) { 299 1.5 cgd tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ 300 1.1 cgd } else { 301 1.5 cgd if (restartany < 0) { 302 1.5 cgd tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ 303 1.5 cgd } else if (restartany > 0) { 304 1.5 cgd tmp_tc.c_iflag |= IXOFF|IXON|IXANY; 305 1.5 cgd } else { 306 1.5 cgd tmp_tc.c_iflag |= IXOFF|IXON; 307 1.5 cgd tmp_tc.c_iflag &= ~IXANY; 308 1.5 cgd } 309 1.1 cgd } 310 1.1 cgd 311 1.1 cgd if ((f&MODE_TRAPSIG) == 0) { 312 1.1 cgd tmp_tc.c_lflag &= ~ISIG; 313 1.1 cgd localchars = 0; 314 1.1 cgd } else { 315 1.1 cgd tmp_tc.c_lflag |= ISIG; 316 1.1 cgd localchars = 1; 317 1.1 cgd } 318 1.1 cgd 319 1.1 cgd if (f&MODE_EDIT) { 320 1.1 cgd tmp_tc.c_lflag |= ICANON; 321 1.1 cgd } else { 322 1.1 cgd tmp_tc.c_lflag &= ~ICANON; 323 1.1 cgd tmp_tc.c_iflag &= ~ICRNL; 324 1.1 cgd tmp_tc.c_cc[VMIN] = 1; 325 1.1 cgd tmp_tc.c_cc[VTIME] = 0; 326 1.1 cgd } 327 1.1 cgd 328 1.1 cgd if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { 329 1.7 tls tmp_tc.c_lflag &= ~IEXTEN; 330 1.1 cgd } 331 1.1 cgd 332 1.1 cgd if (f&MODE_SOFT_TAB) { 333 1.1 cgd # ifdef OXTABS 334 1.1 cgd tmp_tc.c_oflag |= OXTABS; 335 1.1 cgd # endif 336 1.1 cgd # ifdef TABDLY 337 1.1 cgd tmp_tc.c_oflag &= ~TABDLY; 338 1.1 cgd tmp_tc.c_oflag |= TAB3; 339 1.1 cgd # endif 340 1.1 cgd } else { 341 1.1 cgd # ifdef OXTABS 342 1.1 cgd tmp_tc.c_oflag &= ~OXTABS; 343 1.1 cgd # endif 344 1.1 cgd # ifdef TABDLY 345 1.1 cgd tmp_tc.c_oflag &= ~TABDLY; 346 1.1 cgd # endif 347 1.1 cgd } 348 1.1 cgd 349 1.1 cgd if (f&MODE_LIT_ECHO) { 350 1.1 cgd # ifdef ECHOCTL 351 1.1 cgd tmp_tc.c_lflag &= ~ECHOCTL; 352 1.1 cgd # endif 353 1.1 cgd } else { 354 1.1 cgd # ifdef ECHOCTL 355 1.1 cgd tmp_tc.c_lflag |= ECHOCTL; 356 1.1 cgd # endif 357 1.1 cgd } 358 1.1 cgd 359 1.1 cgd if (f == -1) { 360 1.1 cgd onoff = 0; 361 1.1 cgd } else { 362 1.1 cgd if (f & MODE_INBIN) 363 1.1 cgd tmp_tc.c_iflag &= ~ISTRIP; 364 1.1 cgd else 365 1.1 cgd tmp_tc.c_iflag |= ISTRIP; 366 1.1 cgd if (f & MODE_OUTBIN) { 367 1.1 cgd tmp_tc.c_cflag &= ~(CSIZE|PARENB); 368 1.1 cgd tmp_tc.c_cflag |= CS8; 369 1.1 cgd tmp_tc.c_oflag &= ~OPOST; 370 1.1 cgd } else { 371 1.1 cgd tmp_tc.c_cflag &= ~(CSIZE|PARENB); 372 1.1 cgd tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); 373 1.1 cgd tmp_tc.c_oflag |= OPOST; 374 1.1 cgd } 375 1.1 cgd onoff = 1; 376 1.1 cgd } 377 1.1 cgd 378 1.1 cgd if (f != -1) { 379 1.1 cgd (void) signal(SIGTSTP, susp); 380 1.1 cgd (void) signal(SIGINFO, ayt); 381 1.1 cgd #if defined(USE_TERMIO) && defined(NOKERNINFO) 382 1.1 cgd tmp_tc.c_lflag |= NOKERNINFO; 383 1.1 cgd #endif 384 1.1 cgd /* 385 1.1 cgd * We don't want to process ^Y here. It's just another 386 1.1 cgd * character that we'll pass on to the back end. It has 387 1.1 cgd * to process it because it will be processed when the 388 1.1 cgd * user attempts to read it, not when we send it. 389 1.1 cgd */ 390 1.1 cgd # ifdef VDSUSP 391 1.1 cgd tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); 392 1.1 cgd # endif 393 1.1 cgd /* 394 1.1 cgd * If the VEOL character is already set, then use VEOL2, 395 1.1 cgd * otherwise use VEOL. 396 1.1 cgd */ 397 1.1 cgd esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; 398 1.1 cgd if ((tmp_tc.c_cc[VEOL] != esc) 399 1.1 cgd # ifdef VEOL2 400 1.1 cgd && (tmp_tc.c_cc[VEOL2] != esc) 401 1.1 cgd # endif 402 1.1 cgd ) { 403 1.1 cgd if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) 404 1.1 cgd tmp_tc.c_cc[VEOL] = esc; 405 1.1 cgd # ifdef VEOL2 406 1.1 cgd else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) 407 1.1 cgd tmp_tc.c_cc[VEOL2] = esc; 408 1.1 cgd # endif 409 1.1 cgd } 410 1.1 cgd } else { 411 1.19 wiz (void) signal(SIGINFO, (void (*)(int)) ayt_status); 412 1.1 cgd (void) signal(SIGTSTP, SIG_DFL); 413 1.1 cgd (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 414 1.1 cgd tmp_tc = old_tc; 415 1.1 cgd } 416 1.1 cgd if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) 417 1.1 cgd tcsetattr(tin, TCSANOW, &tmp_tc); 418 1.1 cgd 419 1.40 maya ioctl(tin, FIONBIO, &onoff); 420 1.40 maya ioctl(tout, FIONBIO, &onoff); 421 1.1 cgd 422 1.1 cgd } 423 1.1 cgd 424 1.24 christos void 425 1.24 christos TerminalSpeeds(long *ispeed, long *ospeed) 426 1.1 cgd { 427 1.19 wiz long in, out; 428 1.1 cgd 429 1.1 cgd out = cfgetospeed(&old_tc); 430 1.1 cgd in = cfgetispeed(&old_tc); 431 1.34 mrg if (in == 0) { 432 1.1 cgd in = out; 433 1.1 cgd 434 1.8 jtk *ispeed = in; 435 1.8 jtk *ospeed = out; 436 1.34 mrg } 437 1.1 cgd } 438 1.1 cgd 439 1.24 christos int 440 1.24 christos TerminalWindowSize(long *rows, long *cols) 441 1.1 cgd { 442 1.1 cgd struct winsize ws; 443 1.1 cgd 444 1.1 cgd if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { 445 1.1 cgd *rows = ws.ws_row; 446 1.1 cgd *cols = ws.ws_col; 447 1.1 cgd return 1; 448 1.1 cgd } 449 1.1 cgd return 0; 450 1.1 cgd } 451 1.1 cgd 452 1.24 christos int 453 1.24 christos NetClose(int fd) 454 1.1 cgd { 455 1.1 cgd return close(fd); 456 1.1 cgd } 457 1.1 cgd 458 1.1 cgd /* 459 1.1 cgd * Various signal handling routines. 460 1.1 cgd */ 461 1.1 cgd 462 1.24 christos /* ARGSUSED */ 463 1.37 maya void 464 1.24 christos intr(int sig) 465 1.1 cgd { 466 1.1 cgd if (localchars) { 467 1.1 cgd intp(); 468 1.1 cgd return; 469 1.1 cgd } 470 1.1 cgd setcommandmode(); 471 1.1 cgd longjmp(toplevel, -1); 472 1.1 cgd } 473 1.1 cgd 474 1.24 christos /* ARGSUSED */ 475 1.37 maya void 476 1.24 christos intr2(int sig) 477 1.1 cgd { 478 1.1 cgd if (localchars) { 479 1.1 cgd #ifdef KLUDGELINEMODE 480 1.1 cgd if (kludgelinemode) 481 1.1 cgd sendbrk(); 482 1.1 cgd else 483 1.1 cgd #endif 484 1.1 cgd sendabort(); 485 1.1 cgd return; 486 1.1 cgd } 487 1.1 cgd } 488 1.1 cgd 489 1.24 christos /* ARGSUSED */ 490 1.37 maya void 491 1.24 christos susp(int sig) 492 1.1 cgd { 493 1.1 cgd if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) 494 1.1 cgd return; 495 1.1 cgd if (localchars) 496 1.1 cgd sendsusp(); 497 1.1 cgd } 498 1.1 cgd 499 1.24 christos /* ARGSUSED */ 500 1.37 maya void 501 1.24 christos sendwin(int sig) 502 1.1 cgd { 503 1.1 cgd if (connected) { 504 1.1 cgd sendnaws(); 505 1.1 cgd } 506 1.1 cgd } 507 1.1 cgd 508 1.24 christos /* ARGSUSED */ 509 1.37 maya void 510 1.24 christos ayt(int sig) 511 1.1 cgd { 512 1.1 cgd if (connected) 513 1.1 cgd sendayt(); 514 1.1 cgd else 515 1.1 cgd ayt_status(); 516 1.1 cgd } 517 1.1 cgd 518 1.1 cgd 519 1.24 christos void 521 1.1 cgd sys_telnet_init(void) 522 1.38 maya { 523 1.38 maya int one = 1; 524 1.1 cgd 525 1.1 cgd (void) signal(SIGINT, intr); 526 1.31 heas (void) signal(SIGQUIT, intr2); 527 1.1 cgd (void) signal(SIGPIPE, SIG_IGN); 528 1.1 cgd (void) signal(SIGWINCH, sendwin); 529 1.1 cgd (void) signal(SIGTSTP, susp); 530 1.1 cgd (void) signal(SIGINFO, ayt); 531 1.1 cgd 532 1.1 cgd setconnmode(0); 533 1.38 maya 534 1.38 maya ioctl(net, FIONBIO, &one); 535 1.38 maya if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) { 536 1.1 cgd perror("setsockopt"); 537 1.1 cgd } 538 1.1 cgd } 539 1.1 cgd 540 1.1 cgd /* 541 1.1 cgd * Process rings - 542 1.1 cgd * 543 1.1 cgd * This routine tries to fill up/empty our various rings. 544 1.1 cgd * 545 1.1 cgd * The parameter specifies whether this is a poll operation, 546 1.1 cgd * or a block-until-something-happens operation. 547 1.23 christos * 548 1.30 wiz * The return value is 1 if something happened, 0 if not, < 0 if an 549 1.1 cgd * error occurred. 550 1.1 cgd */ 551 1.24 christos 552 1.24 christos int 553 1.24 christos process_rings(int netin, int netout, int netex, int ttyin, int ttyout, 554 1.1 cgd int dopoll) /* If 0, then block until something to do */ 555 1.20 mycroft { 556 1.19 wiz struct pollfd set[3]; 557 1.1 cgd int c; 558 1.1 cgd /* One wants to be a bit careful about setting returnValue 559 1.1 cgd * to one, since a one implies we did some useful work, 560 1.1 cgd * and therefore probably won't be called to block next 561 1.1 cgd * time (TN3270 mode only). 562 1.1 cgd */ 563 1.14 mcr int returnValue = 0; 564 1.20 mycroft 565 1.20 mycroft set[0].fd = net; 566 1.20 mycroft set[0].events = (netout ? POLLOUT : 0) | (netin ? POLLIN : 0) | 567 1.20 mycroft (netex ? POLLPRI : 0); 568 1.20 mycroft set[1].fd = tout; 569 1.20 mycroft set[1].events = ttyout ? POLLOUT : 0; 570 1.20 mycroft set[2].fd = tin; 571 1.1 cgd set[2].events = ttyin ? POLLIN : 0; 572 1.20 mycroft 573 1.1 cgd if ((c = poll(set, 3, dopoll ? 0 : INFTIM)) < 0) { 574 1.1 cgd if (c == -1) { 575 1.1 cgd /* 576 1.1 cgd * we can get EINTR if we are in line mode, 577 1.1 cgd * and the user does an escape (TSTP), or 578 1.1 cgd * some other signal generator. 579 1.1 cgd */ 580 1.1 cgd if (errno == EINTR) { 581 1.1 cgd return 0; 582 1.1 cgd } 583 1.23 christos /* I don't like this, does it ever happen? */ 584 1.1 cgd printf("sleep(5) from telnet, after poll\r\n"); 585 1.1 cgd sleep(5); 586 1.1 cgd } 587 1.1 cgd return 0; 588 1.1 cgd } 589 1.1 cgd 590 1.1 cgd /* 591 1.1 cgd * Any urgent data? 592 1.20 mycroft */ 593 1.1 cgd if (set[0].revents & POLLPRI) { 594 1.1 cgd SYNCHing = 1; 595 1.1 cgd (void) ttyflush(1); /* flush already enqueued data */ 596 1.1 cgd } 597 1.1 cgd 598 1.1 cgd /* 599 1.1 cgd * Something to read from the network... 600 1.20 mycroft */ 601 1.1 cgd if (set[0].revents & POLLIN) { 602 1.1 cgd int canread; 603 1.1 cgd 604 1.5 cgd canread = ring_empty_consecutive(&netiring); 605 1.1 cgd c = recv(net, (char *)netiring.supply, canread, 0); 606 1.1 cgd if (c < 0 && errno == EWOULDBLOCK) { 607 1.1 cgd c = 0; 608 1.1 cgd } else if (c <= 0) { 609 1.1 cgd return -1; 610 1.1 cgd } 611 1.1 cgd if (netdata) { 612 1.1 cgd Dump('<', netiring.supply, c); 613 1.1 cgd } 614 1.1 cgd if (c) 615 1.1 cgd ring_supplied(&netiring, c); 616 1.1 cgd returnValue = 1; 617 1.1 cgd } 618 1.1 cgd 619 1.1 cgd /* 620 1.1 cgd * Something to read from the tty... 621 1.20 mycroft */ 622 1.1 cgd if (set[2].revents & POLLIN) { 623 1.8 jtk c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 624 1.8 jtk if (c < 0 && errno == EIO) 625 1.1 cgd c = 0; 626 1.1 cgd if (c < 0 && errno == EWOULDBLOCK) { 627 1.1 cgd c = 0; 628 1.9 jtk } else { 629 1.9 jtk if (c < 0) { 630 1.8 jtk return -1; 631 1.9 jtk } 632 1.9 jtk if (c == 0) { 633 1.9 jtk /* must be an EOF... */ 634 1.9 jtk if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 635 1.9 jtk *ttyiring.supply = termEofChar; 636 1.9 jtk c = 1; 637 1.9 jtk } else { 638 1.9 jtk clienteof = 1; 639 1.9 jtk shutdown(net, 1); 640 1.9 jtk return 0; 641 1.1 cgd } 642 1.1 cgd } 643 1.1 cgd if (termdata) { 644 1.1 cgd Dump('<', ttyiring.supply, c); 645 1.1 cgd } 646 1.1 cgd ring_supplied(&ttyiring, c); 647 1.1 cgd } 648 1.1 cgd returnValue = 1; /* did something useful */ 649 1.1 cgd } 650 1.20 mycroft 651 1.1 cgd if (set[0].revents & POLLOUT) { 652 1.1 cgd returnValue |= netflush(); 653 1.31 heas } 654 1.31 heas 655 1.31 heas if (set[1].revents & (POLLHUP|POLLNVAL)) 656 1.31 heas return(-1); 657 1.20 mycroft 658 1.1 cgd if (set[1].revents & POLLOUT) { 659 1.1 cgd returnValue |= (ttyflush(SYNCHing|flushout) > 0); 660 1.1 cgd } 661 1.1 cgd 662 1.1 cgd return returnValue; 663 } 664