1/* Copyright (c) 1993-2002 2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) 3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) 4 * Copyright (c) 1987 Oliver Laumann 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program (see the file COPYING); if not, write to the 18 * Free Software Foundation, Inc., 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 * 21 **************************************************************** 22 */ 23 24/* 25 * NOTICE: tty.c is automatically generated from tty.sh 26 * Do not change anything here. If you then change tty.sh. 27 */ 28 29#include <sys/types.h> 30#include <signal.h> 31#include <fcntl.h> 32#ifndef sgi 33# include <sys/file.h> 34#endif 35#if !defined(sun) || defined(SUNOS3) 36# include <sys/ioctl.h> /* collosions with termios.h */ 37#else 38# ifndef TIOCEXCL 39# include <sys/ttold.h> /* needed for TIOCEXCL */ 40# endif 41#endif 42#ifdef __hpux 43# include <sys/modem.h> 44#endif 45 46#ifdef ISC 47# include <sys/tty.h> 48# include <sys/sioctl.h> 49# include <sys/pty.h> 50#endif 51 52#include "config.h" 53#ifdef SVR4 54#include <sys/stropts.h> /* for I_POP */ 55#endif 56 57#include "screen.h" 58#include "extern.h" 59 60#if !defined(TIOCCONS) && defined(sun) && defined(SVR4) 61# include <sys/strredir.h> 62#endif 63 64extern struct display *display, *displays; 65extern int iflag; 66#if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) 67extern struct win *console_window; 68static void consredir_readev_fn __P((struct event *, char *)); 69#endif 70 71int separate_sids = 1; 72 73static void DoSendBreak __P((int, int, int)); 74static sigret_t SigAlrmDummy __P(SIGPROTOARG); 75 76 77/* Frank Schulz (fschulz@pyramid.com): 78 * I have no idea why VSTART is not defined and my fix is probably not 79 * the cleanest, but it works. 80 */ 81#if !defined(VSTART) && defined(_VSTART) 82#define VSTART _VSTART 83#endif 84#if !defined(VSTOP) && defined(_VSTOP) 85#define VSTOP _VSTOP 86#endif 87 88#ifndef O_NOCTTY 89# define O_NOCTTY 0 90#endif 91 92#ifndef TTYVMIN 93# define TTYVMIN 1 94#endif 95#ifndef TTYVTIME 96#define TTYVTIME 0 97#endif 98 99 100static sigret_t 101SigAlrmDummy SIGDEFARG 102{ 103 debug("SigAlrmDummy()\n"); 104 SIGRETURN; 105} 106 107/* 108 * Carefully open a charcter device. Not used to open display ttys. 109 * The second parameter is parsed for a few stty style options. 110 */ 111 112int 113OpenTTY(line, opt) 114char *line, *opt; 115{ 116 int f; 117 struct mode Mode; 118 sigret_t (*sigalrm)__P(SIGPROTOARG); 119 120 sigalrm = signal(SIGALRM, SigAlrmDummy); 121 alarm(2); 122 123 /* this open only succeeds, if real uid is allowed */ 124 if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) 125 { 126 if (errno == EINTR) 127 Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line); 128 else 129 Msg(errno, "Cannot open line '%s' for R/W", line); 130 alarm(0); 131 signal(SIGALRM, sigalrm); 132 return -1; 133 } 134 if (!isatty(f)) 135 { 136 Msg(0, "'%s' is not a tty", line); 137 alarm(0); 138 signal(SIGALRM, sigalrm); 139 close(f); 140 return -1; 141 } 142#if defined(I_POP) && defined(POP_TTYMODULES) 143 debug("OpenTTY I_POP\n"); 144 while (ioctl(f, I_POP, (char *)0) >= 0) 145 ; 146#endif 147 /* 148 * We come here exclusively. This is to stop all kermit and cu type things 149 * accessing the same tty line. 150 * Perhaps we should better create a lock in some /usr/spool/locks directory? 151 */ 152#ifdef TIOCEXCL 153 errno = 0; 154 if (ioctl(f, TIOCEXCL, (char *) 0) < 0) 155 Msg(errno, "%s: ioctl TIOCEXCL failed", line); 156 debug3("%d %d %d\n", getuid(), geteuid(), getpid()); 157 debug2("%s TIOCEXCL errno %d\n", line, errno); 158#endif /* TIOCEXCL */ 159 /* 160 * We create a sane tty mode. We do not copy things from the display tty 161 */ 162#if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE 163 if (display) 164 { 165 debug1("OpenTTY: using mode of display for %s\n", line); 166 Mode = D_NewMode; 167 } 168 else 169#endif 170 InitTTY(&Mode, W_TYPE_PLAIN); 171 172 SttyMode(&Mode, opt); 173#ifdef DEBUG 174 DebugTTY(&Mode); 175#endif 176 SetTTY(f, &Mode); 177 178#if defined(linux) && defined(TIOCMSET) 179 { 180 int mcs = 0; 181 ioctl(f, TIOCMGET, &mcs); 182 mcs |= TIOCM_RTS; 183 ioctl(f, TIOCMSET, &mcs); 184 } 185#endif 186 187 brktty(f); 188 alarm(0); 189 signal(SIGALRM, sigalrm); 190 debug2("'%s' CONNECT fd=%d.\n", line, f); 191 return f; 192} 193 194 195/* 196 * Tty mode handling 197 */ 198 199void 200InitTTY(m, ttyflag) 201struct mode *m; 202int ttyflag; 203{ 204 bzero((char *)m, sizeof(*m)); 205#ifdef POSIX 206 /* struct termios tio 207 * defaults, as seen on SunOS 4.1.3 208 */ 209 debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); 210#if defined(BRKINT) 211 m->tio.c_iflag |= BRKINT; 212#endif /* BRKINT */ 213#if defined(IGNPAR) 214 m->tio.c_iflag |= IGNPAR; 215#endif /* IGNPAR */ 216/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ 217#if defined(IXON) 218 m->tio.c_iflag |= IXON; 219#endif /* IXON */ 220/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ 221 222 if (!ttyflag) /* may not even be good for ptys.. */ 223 { 224#if defined(ICRNL) 225 m->tio.c_iflag |= ICRNL; 226#endif /* ICRNL */ 227#if defined(ONLCR) 228 m->tio.c_oflag |= ONLCR; 229#endif /* ONLCR */ 230#if defined(TAB3) 231 m->tio.c_oflag |= TAB3; 232#endif /* TAB3 */ 233#if defined(OXTABS) 234 m->tio.c_oflag |= OXTABS; 235#endif /* OXTABS */ 236/* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ 237#if defined(OPOST) 238 m->tio.c_oflag |= OPOST; 239#endif /* OPOST */ 240 } 241 242 243/* 244 * Or-ing the speed into c_cflags is dangerous. 245 * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs. 246 * 247 * IF{B9600} m->tio.c_cflag |= B9600; 248 * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; 249 * 250 * We hope that we have the posix calls to do it right: 251 * If these are not available you might try the above. 252 */ 253#if defined(B9600) 254 cfsetospeed(&m->tio, B9600); 255#endif /* B9600 */ 256#if defined(B9600) 257 cfsetispeed(&m->tio, B9600); 258#endif /* B9600 */ 259 260#if defined(CS8) 261 m->tio.c_cflag |= CS8; 262#endif /* CS8 */ 263#if defined(CREAD) 264 m->tio.c_cflag |= CREAD; 265#endif /* CREAD */ 266#if defined(CLOCAL) 267 m->tio.c_cflag |= CLOCAL; 268#endif /* CLOCAL */ 269 270#if defined(ECHOCTL) 271 m->tio.c_lflag |= ECHOCTL; 272#endif /* ECHOCTL */ 273#if defined(ECHOKE) 274 m->tio.c_lflag |= ECHOKE; 275#endif /* ECHOKE */ 276 277 if (!ttyflag) 278 { 279#if defined(ISIG) 280 m->tio.c_lflag |= ISIG; 281#endif /* ISIG */ 282#if defined(ICANON) 283 m->tio.c_lflag |= ICANON; 284#endif /* ICANON */ 285#if defined(ECHO) 286 m->tio.c_lflag |= ECHO; 287#endif /* ECHO */ 288 } 289#if defined(ECHOE) 290 m->tio.c_lflag |= ECHOE; 291#endif /* ECHOE */ 292#if defined(ECHOK) 293 m->tio.c_lflag |= ECHOK; 294#endif /* ECHOK */ 295#if defined(IEXTEN) 296 m->tio.c_lflag |= IEXTEN; 297#endif /* IEXTEN */ 298 299#if defined(VINTR) 300#if (VINTR < MAXCC) 301 m->tio.c_cc[VINTR] = Ctrl('C'); 302#endif 303#endif /* VINTR */ 304#if defined(VQUIT) 305#if (VQUIT < MAXCC) 306 m->tio.c_cc[VQUIT] = Ctrl('\\'); 307#endif 308#endif /* VQUIT */ 309#if defined(VERASE) 310#if (VERASE < MAXCC) 311 m->tio.c_cc[VERASE] = 0x7f; /* DEL */ 312#endif 313#endif /* VERASE */ 314#if defined(VKILL) 315#if (VKILL < MAXCC) 316 m->tio.c_cc[VKILL] = Ctrl('H'); 317#endif 318#endif /* VKILL */ 319#if defined(VEOF) 320#if (VEOF < MAXCC) 321 m->tio.c_cc[VEOF] = Ctrl('D'); 322#endif 323#endif /* VEOF */ 324#if defined(VEOL) 325#if (VEOL < MAXCC) 326 m->tio.c_cc[VEOL] = 0000; 327#endif 328#endif /* VEOL */ 329#if defined(VEOL2) 330#if (VEOL2 < MAXCC) 331 m->tio.c_cc[VEOL2] = 0000; 332#endif 333#endif /* VEOL2 */ 334#if defined(VSWTCH) 335#if (VSWTCH < MAXCC) 336 m->tio.c_cc[VSWTCH] = 0000; 337#endif 338#endif /* VSWTCH */ 339#if defined(VSTART) 340#if (VSTART < MAXCC) 341 m->tio.c_cc[VSTART] = Ctrl('Q'); 342#endif 343#endif /* VSTART */ 344#if defined(VSTOP) 345#if (VSTOP < MAXCC) 346 m->tio.c_cc[VSTOP] = Ctrl('S'); 347#endif 348#endif /* VSTOP */ 349#if defined(VSUSP) 350#if (VSUSP < MAXCC) 351 m->tio.c_cc[VSUSP] = Ctrl('Z'); 352#endif 353#endif /* VSUSP */ 354#if defined(VDSUSP) 355#if (VDSUSP < MAXCC) 356 m->tio.c_cc[VDSUSP] = Ctrl('Y'); 357#endif 358#endif /* VDSUSP */ 359#if defined(VREPRINT) 360#if (VREPRINT < MAXCC) 361 m->tio.c_cc[VREPRINT] = Ctrl('R'); 362#endif 363#endif /* VREPRINT */ 364#if defined(VDISCARD) 365#if (VDISCARD < MAXCC) 366 m->tio.c_cc[VDISCARD] = Ctrl('O'); 367#endif 368#endif /* VDISCARD */ 369#if defined(VWERASE) 370#if (VWERASE < MAXCC) 371 m->tio.c_cc[VWERASE] = Ctrl('W'); 372#endif 373#endif /* VWERASE */ 374#if defined(VLNEXT) 375#if (VLNEXT < MAXCC) 376 m->tio.c_cc[VLNEXT] = Ctrl('V'); 377#endif 378#endif /* VLNEXT */ 379#if defined(VSTATUS) 380#if (VSTATUS < MAXCC) 381 m->tio.c_cc[VSTATUS] = Ctrl('T'); 382#endif 383#endif /* VSTATUS */ 384 385 if (ttyflag) 386 { 387 m->tio.c_cc[VMIN] = TTYVMIN; 388 m->tio.c_cc[VTIME] = TTYVTIME; 389 } 390 391# ifdef HPUX_LTCHARS_HACK 392 m->m_ltchars.t_suspc = Ctrl('Z'); 393 m->m_ltchars.t_dsuspc = Ctrl('Y'); 394 m->m_ltchars.t_rprntc = Ctrl('R'); 395 m->m_ltchars.t_flushc = Ctrl('O'); 396 m->m_ltchars.t_werasc = Ctrl('W'); 397 m->m_ltchars.t_lnextc = Ctrl('V'); 398# endif /* HPUX_LTCHARS_HACK */ 399 400#else /* POSIX */ 401 402# ifdef TERMIO 403 debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); 404 /* struct termio tio 405 * defaults, as seen on Mototola SYSV68: 406 * input: 7bit, CR->NL, ^S/^Q flow control 407 * output: POSTprocessing: NL->NL-CR, Tabs to spaces 408 * control: 9600baud, 8bit CSIZE, enable input 409 * local: enable signals, erase/kill processing, echo on. 410 */ 411#if defined(ISTRIP) 412 m->tio.c_iflag |= ISTRIP; 413#endif /* ISTRIP */ 414#if defined(IXON) 415 m->tio.c_iflag |= IXON; 416#endif /* IXON */ 417 418 if (!ttyflag) /* may not even be good for ptys.. */ 419 { 420#if defined(OPOST) 421 m->tio.c_oflag |= OPOST; 422#endif /* OPOST */ 423#if defined(ICRNL) 424 m->tio.c_iflag |= ICRNL; 425#endif /* ICRNL */ 426#if defined(ONLCR) 427 m->tio.c_oflag |= ONLCR; 428#endif /* ONLCR */ 429#if defined(TAB3) 430 m->tio.c_oflag |= TAB3; 431#endif /* TAB3 */ 432 } 433 434#ifdef __bsdi__ 435 )-: cannot handle BSDI without POSIX 436#else 437#if defined(B9600) 438 m->tio.c_cflag = B9600; 439#endif /* B9600 */ 440#endif 441#if defined(CS8) 442 m->tio.c_cflag |= CS8; 443#endif /* CS8 */ 444#if defined(CREAD) 445 m->tio.c_cflag |= CREAD; 446#endif /* CREAD */ 447 448 if (!ttyflag) 449 { 450#if defined(ISIG) 451 m->tio.c_lflag |= ISIG; 452#endif /* ISIG */ 453#if defined(ICANON) 454 m->tio.c_lflag |= ICANON; 455#endif /* ICANON */ 456#if defined(ECHO) 457 m->tio.c_lflag |= ECHO; 458#endif /* ECHO */ 459 } 460#if defined(ECHOE) 461 m->tio.c_lflag |= ECHOE; 462#endif /* ECHOE */ 463#if defined(ECHOK) 464 m->tio.c_lflag |= ECHOK; 465#endif /* ECHOK */ 466 467#if defined(VINTR) 468#if (VINTR < MAXCC) 469 m->tio.c_cc[VINTR] = Ctrl('C'); 470#endif 471#endif /* VINTR */ 472#if defined(VQUIT) 473#if (VQUIT < MAXCC) 474 m->tio.c_cc[VQUIT] = Ctrl('\\'); 475#endif 476#endif /* VQUIT */ 477#if defined(VERASE) 478#if (VERASE < MAXCC) 479 m->tio.c_cc[VERASE] = 0177; /* DEL */ 480#endif 481#endif /* VERASE */ 482#if defined(VKILL) 483#if (VKILL < MAXCC) 484 m->tio.c_cc[VKILL] = Ctrl('H'); 485#endif 486#endif /* VKILL */ 487#if defined(VEOF) 488#if (VEOF < MAXCC) 489 m->tio.c_cc[VEOF] = Ctrl('D'); 490#endif 491#endif /* VEOF */ 492#if defined(VEOL) 493#if (VEOL < MAXCC) 494 m->tio.c_cc[VEOL] = 0377; 495#endif 496#endif /* VEOL */ 497#if defined(VEOL2) 498#if (VEOL2 < MAXCC) 499 m->tio.c_cc[VEOL2] = 0377; 500#endif 501#endif /* VEOL2 */ 502#if defined(VSWTCH) 503#if (VSWTCH < MAXCC) 504 m->tio.c_cc[VSWTCH] = 0000; 505#endif 506#endif /* VSWTCH */ 507 508 if (ttyflag) 509 { 510 m->tio.c_cc[VMIN] = TTYVMIN; 511 m->tio.c_cc[VTIME] = TTYVTIME; 512 } 513 514# else /* TERMIO */ 515 debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); 516 m->m_ttyb.sg_ispeed = B9600; 517 m->m_ttyb.sg_ospeed = B9600; 518 m->m_ttyb.sg_erase = 0177; /*DEL */ 519 m->m_ttyb.sg_kill = Ctrl('H'); 520 if (!ttyflag) 521 m->m_ttyb.sg_flags = CRMOD | ECHO 522#if defined(ANYP) 523 | ANYP 524#endif /* ANYP */ 525 ; 526 else 527 m->m_ttyb.sg_flags = CBREAK 528#if defined(ANYP) 529 | ANYP 530#endif /* ANYP */ 531 ; 532 533 m->m_tchars.t_intrc = Ctrl('C'); 534 m->m_tchars.t_quitc = Ctrl('\\'); 535 m->m_tchars.t_startc = Ctrl('Q'); 536 m->m_tchars.t_stopc = Ctrl('S'); 537 m->m_tchars.t_eofc = Ctrl('D'); 538 m->m_tchars.t_brkc = -1; 539 540 m->m_ltchars.t_suspc = Ctrl('Z'); 541 m->m_ltchars.t_dsuspc = Ctrl('Y'); 542 m->m_ltchars.t_rprntc = Ctrl('R'); 543 m->m_ltchars.t_flushc = Ctrl('O'); 544 m->m_ltchars.t_werasc = Ctrl('W'); 545 m->m_ltchars.t_lnextc = Ctrl('V'); 546 547#if defined(NTTYDISC) 548 m->m_ldisc = NTTYDISC; 549#endif /* NTTYDISC */ 550 551 m->m_lmode = 0 552#if defined(LDECCTQ) 553 | LDECCTQ 554#endif /* LDECCTQ */ 555#if defined(LCTLECH) 556 | LCTLECH 557#endif /* LCTLECH */ 558#if defined(LPASS8) 559 | LPASS8 560#endif /* LPASS8 */ 561#if defined(LCRTKIL) 562 | LCRTKIL 563#endif /* LCRTKIL */ 564#if defined(LCRTERA) 565 | LCRTERA 566#endif /* LCRTERA */ 567#if defined(LCRTBS) 568 | LCRTBS 569#endif /* LCRTBS */ 570 ; 571# endif /* TERMIO */ 572#endif /* POSIX */ 573 574#if defined(ENCODINGS) && defined(TIOCKSET) 575 m->m_jtchars.t_ascii = 'J'; 576 m->m_jtchars.t_kanji = 'B'; 577 m->m_knjmode = KM_ASCII | KM_SYSSJIS; 578#endif 579} 580 581void 582SetTTY(fd, mp) 583int fd; 584struct mode *mp; 585{ 586 errno = 0; 587#ifdef POSIX 588 tcsetattr(fd, TCSADRAIN, &mp->tio); 589# ifdef HPUX_LTCHARS_HACK 590 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); 591# endif 592#else 593# ifdef TERMIO 594 ioctl(fd, TCSETAW, (char *)&mp->tio); 595# ifdef CYTERMIO 596 if (mp->tio.c_line == 3) 597 { 598 ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey); 599 ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen); 600 ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace); 601 } 602# endif 603# else 604 /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ 605 ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); 606 ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); 607 ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); 608 ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); 609 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ 610# endif 611#endif 612#if defined(ENCODINGS) && defined(TIOCKSET) 613 ioctl(fd, TIOCKSETC, &mp->m_jtchars); 614 ioctl(fd, TIOCKSET, &mp->m_knjmode); 615#endif 616 if (errno) 617 Msg(errno, "SetTTY (fd %d): ioctl failed", fd); 618} 619 620void 621GetTTY(fd, mp) 622int fd; 623struct mode *mp; 624{ 625 errno = 0; 626#ifdef POSIX 627 tcgetattr(fd, &mp->tio); 628# ifdef HPUX_LTCHARS_HACK 629 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); 630# endif 631#else 632# ifdef TERMIO 633 ioctl(fd, TCGETA, (char *)&mp->tio); 634# ifdef CYTERMIO 635 if (mp->tio.c_line == 3) 636 { 637 ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey); 638 ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen); 639 ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace); 640 } 641 else 642 { 643 mp->m_mapkey = NOMAPKEY; 644 mp->m_mapscreen = NOMAPSCREEN; 645 mp->m_backspace = '\b'; 646 } 647# endif 648# else 649 ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); 650 ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); 651 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); 652 ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); 653 ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); 654# endif 655#endif 656#if defined(ENCODINGS) && defined(TIOCKSET) 657 ioctl(fd, TIOCKGETC, &mp->m_jtchars); 658 ioctl(fd, TIOCKGET, &mp->m_knjmode); 659#endif 660 if (errno) 661 Msg(errno, "GetTTY (fd %d): ioctl failed", fd); 662} 663 664/* 665 * needs interrupt = iflag and flow = d->d_flow 666 */ 667void 668SetMode(op, np, flow, interrupt) 669struct mode *op, *np; 670int flow, interrupt; 671{ 672 *np = *op; 673 674 ASSERT(display); 675#if defined(TERMIO) || defined(POSIX) 676# ifdef CYTERMIO 677 np->m_mapkey = NOMAPKEY; 678 np->m_mapscreen = NOMAPSCREEN; 679 np->tio.c_line = 0; 680# endif 681#if defined(ICRNL) 682 np->tio.c_iflag &= ~ICRNL; 683#endif /* ICRNL */ 684#if defined(ISTRIP) 685 np->tio.c_iflag &= ~ISTRIP; 686#endif /* ISTRIP */ 687#if defined(ONLCR) 688 np->tio.c_oflag &= ~ONLCR; 689#endif /* ONLCR */ 690 np->tio.c_lflag &= ~(ICANON | ECHO); 691 /* 692 * From Andrew Myers (andru@tonic.lcs.mit.edu) 693 * to avoid ^V^V-Problem on OSF1 694 */ 695#if defined(IEXTEN) 696 np->tio.c_lflag &= ~IEXTEN; 697#endif /* IEXTEN */ 698 699 /* 700 * Unfortunately, the master process never will get SIGINT if the real 701 * terminal is different from the one on which it was originaly started 702 * (process group membership has not been restored or the new tty could not 703 * be made controlling again). In my solution, it is the attacher who 704 * receives SIGINT (because it is always correctly associated with the real 705 * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. 706 * Marc Boucher (marc@CAM.ORG) 707 */ 708 if (interrupt) 709 np->tio.c_lflag |= ISIG; 710 else 711 np->tio.c_lflag &= ~ISIG; 712 /* 713 * careful, careful catche monkey.. 714 * never set VMIN and VTIME to zero, if you want blocking io. 715 * 716 * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to 717 * reduce interrupt frequency. But then we would not know how to 718 * handle read returning 0. jw. 719 */ 720 np->tio.c_cc[VMIN] = 1; 721 np->tio.c_cc[VTIME] = 0; 722 if (!interrupt || !flow) 723 np->tio.c_cc[VINTR] = VDISABLE; 724 np->tio.c_cc[VQUIT] = VDISABLE; 725 if (flow == 0) 726 { 727#if defined(VSTART) 728#if (VSTART < MAXCC) 729 np->tio.c_cc[VSTART] = VDISABLE; 730#endif 731#endif /* VSTART */ 732#if defined(VSTOP) 733#if (VSTOP < MAXCC) 734 np->tio.c_cc[VSTOP] = VDISABLE; 735#endif 736#endif /* VSTOP */ 737 np->tio.c_iflag &= ~IXON; 738 } 739#if defined(VDISCARD) 740#if (VDISCARD < MAXCC) 741 np->tio.c_cc[VDISCARD] = VDISABLE; 742#endif 743#endif /* VDISCARD */ 744#if defined(VLNEXT) 745#if (VLNEXT < MAXCC) 746 np->tio.c_cc[VLNEXT] = VDISABLE; 747#endif 748#endif /* VLNEXT */ 749#if defined(VSTATUS) 750#if (VSTATUS < MAXCC) 751 np->tio.c_cc[VSTATUS] = VDISABLE; 752#endif 753#endif /* VSTATUS */ 754#if defined(VSUSP) 755#if (VSUSP < MAXCC) 756 np->tio.c_cc[VSUSP] = VDISABLE; 757#endif 758#endif /* VSUSP */ 759#if defined(VERASE) 760#if (VERASE < MAXCC) 761 np->tio.c_cc[VERASE] = VDISABLE; 762#endif 763#endif /* VERASE */ 764#if defined(VKILL) 765#if (VKILL < MAXCC) 766 np->tio.c_cc[VKILL] = VDISABLE; 767#endif 768#endif /* VKILL */ 769# ifdef HPUX_LTCHARS_HACK 770 np->m_ltchars.t_suspc = VDISABLE; 771 np->m_ltchars.t_dsuspc = VDISABLE; 772 np->m_ltchars.t_rprntc = VDISABLE; 773 np->m_ltchars.t_flushc = VDISABLE; 774 np->m_ltchars.t_werasc = VDISABLE; 775 np->m_ltchars.t_lnextc = VDISABLE; 776# else /* HPUX_LTCHARS_HACK */ 777#if defined(VDSUSP) 778#if (VDSUSP < MAXCC) 779 np->tio.c_cc[VDSUSP] = VDISABLE; 780#endif 781#endif /* VDSUSP */ 782#if defined(VREPRINT) 783#if (VREPRINT < MAXCC) 784 np->tio.c_cc[VREPRINT] = VDISABLE; 785#endif 786#endif /* VREPRINT */ 787#if defined(VWERASE) 788#if (VWERASE < MAXCC) 789 np->tio.c_cc[VWERASE] = VDISABLE; 790#endif 791#endif /* VWERASE */ 792# endif /* HPUX_LTCHARS_HACK */ 793#else /* TERMIO || POSIX */ 794 if (!interrupt || !flow) 795 np->m_tchars.t_intrc = -1; 796 np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); 797 np->m_ttyb.sg_flags |= CBREAK; 798# if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS) 799 np->m_ttyb.sg_flags &= ~CSTYLE; 800 np->m_ttyb.sg_flags |= CS_8BITS; 801# endif 802 np->m_tchars.t_quitc = -1; 803 if (flow == 0) 804 { 805 np->m_tchars.t_startc = -1; 806 np->m_tchars.t_stopc = -1; 807 } 808 np->m_ltchars.t_suspc = -1; 809 np->m_ltchars.t_dsuspc = -1; 810 np->m_ltchars.t_flushc = -1; 811 np->m_ltchars.t_lnextc = -1; 812#endif /* defined(TERMIO) || defined(POSIX) */ 813} 814 815/* operates on display */ 816void 817SetFlow(on) 818int on; 819{ 820 ASSERT(display); 821 if (D_flow == on) 822 return; 823#if defined(TERMIO) || defined(POSIX) 824 if (on) 825 { 826 D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE; 827#if defined(VSTART) 828#if (VSTART < MAXCC) 829 D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART]; 830#endif 831#endif /* VSTART */ 832#if defined(VSTOP) 833#if (VSTOP < MAXCC) 834 D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP]; 835#endif 836#endif /* VSTOP */ 837 D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON; 838 } 839 else 840 { 841 D_NewMode.tio.c_cc[VINTR] = VDISABLE; 842#if defined(VSTART) 843#if (VSTART < MAXCC) 844 D_NewMode.tio.c_cc[VSTART] = VDISABLE; 845#endif 846#endif /* VSTART */ 847#if defined(VSTOP) 848#if (VSTOP < MAXCC) 849 D_NewMode.tio.c_cc[VSTOP] = VDISABLE; 850#endif 851#endif /* VSTOP */ 852 D_NewMode.tio.c_iflag &= ~IXON; 853 } 854# ifdef POSIX 855 if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio)) 856# else 857 if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0) 858# endif 859 debug1("SetFlow: ioctl errno %d\n", errno); 860#else /* POSIX || TERMIO */ 861 if (on) 862 { 863 D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1; 864 D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc; 865 D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc; 866 } 867 else 868 { 869 D_NewMode.m_tchars.t_intrc = -1; 870 D_NewMode.m_tchars.t_startc = -1; 871 D_NewMode.m_tchars.t_stopc = -1; 872 } 873 if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0) 874 debug1("SetFlow: ioctl errno %d\n", errno); 875#endif /* POSIX || TERMIO */ 876 D_flow = on; 877} 878 879/* parse commands from opt and modify m */ 880int 881SttyMode(m, opt) 882struct mode *m; 883char *opt; 884{ 885 static const char sep[] = " \t:;,"; 886 887 if (!opt) 888 return 0; 889 890 while (*opt) 891 { 892 while (index(sep, *opt)) opt++; 893 if (*opt >= '0' && *opt <= '9') 894 { 895 if (SetBaud(m, atoi(opt), atoi(opt))) 896 return -1; 897 } 898 else if (!strncmp("cs7", opt, 3)) 899 { 900#if defined(POSIX) || defined(TERMIO) 901 m->tio.c_cflag &= ~CSIZE; 902 m->tio.c_cflag |= CS7; 903#else 904 m->m_lmode &= ~LPASS8; 905#endif 906 } 907 else if (!strncmp("cs8", opt, 3)) 908 { 909#if defined(POSIX) || defined(TERMIO) 910 m->tio.c_cflag &= ~CSIZE; 911 m->tio.c_cflag |= CS8; 912#else 913 m->m_lmode |= LPASS8; 914#endif 915 } 916 else if (!strncmp("istrip", opt, 6)) 917 { 918#if defined(POSIX) || defined(TERMIO) 919 m->tio.c_iflag |= ISTRIP; 920#else 921 m->m_lmode &= ~LPASS8; 922#endif 923 } 924 else if (!strncmp("-istrip", opt, 7)) 925 { 926#if defined(POSIX) || defined(TERMIO) 927 m->tio.c_iflag &= ~ISTRIP; 928#else 929 m->m_lmode |= LPASS8; 930#endif 931 } 932 else if (!strncmp("ixon", opt, 4)) 933 { 934#if defined(POSIX) || defined(TERMIO) 935 m->tio.c_iflag |= IXON; 936#else 937 debug("SttyMode: no ixon in old bsd land.\n"); 938#endif 939 } 940 else if (!strncmp("-ixon", opt, 5)) 941 { 942#if defined(POSIX) || defined(TERMIO) 943 m->tio.c_iflag &= ~IXON; 944#else 945 debug("SttyMode: no -ixon in old bsd land.\n"); 946#endif 947 } 948 else if (!strncmp("ixoff", opt, 5)) 949 { 950#if defined(POSIX) || defined(TERMIO) 951 m->tio.c_iflag |= IXOFF; 952#else 953 m->m_ttyb.sg_flags |= TANDEM; 954#endif 955 } 956 else if (!strncmp("-ixoff", opt, 6)) 957 { 958#if defined(POSIX) || defined(TERMIO) 959 m->tio.c_iflag &= ~IXOFF; 960#else 961 m->m_ttyb.sg_flags &= ~TANDEM; 962#endif 963 } 964 else if (!strncmp("crtscts", opt, 7)) 965 { 966#if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) 967 m->tio.c_cflag |= CRTSCTS; 968#endif 969 } 970 else if (!strncmp("-crtscts", opt, 8)) 971 { 972#if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) 973 m->tio.c_cflag &= ~CRTSCTS; 974#endif 975 } 976 else 977 return -1; 978 while (*opt && !index(sep, *opt)) opt++; 979 } 980 return 0; 981} 982 983/* 984 * Job control handling 985 * 986 * Somehow the ultrix session handling is broken, so use 987 * the bsdish variant. 988 */ 989 990/*ARGSUSED*/ 991void 992brktty(fd) 993int fd; 994{ 995#if defined(POSIX) && !defined(ultrix) 996 if (separate_sids) 997 setsid(); /* will break terminal affiliation */ 998 /* GNU added for Hurd systems 2001-10-10 */ 999# if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__) 1000 ioctl(fd, TIOCSCTTY, (char *)0); 1001# endif /* BSD && TIOCSCTTY */ 1002#else /* POSIX */ 1003# ifdef SYSV 1004 if (separate_sids) 1005 setpgrp(); /* will break terminal affiliation */ 1006# else /* SYSV */ 1007# ifdef BSDJOBS 1008 int devtty; 1009 1010 if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0) 1011 { 1012 if (ioctl(devtty, TIOCNOTTY, (char *)0)) 1013 debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); 1014 close(devtty); 1015 } 1016# endif /* BSDJOBS */ 1017# endif /* SYSV */ 1018#endif /* POSIX */ 1019} 1020 1021int 1022fgtty(fd) 1023int fd; 1024{ 1025#ifdef BSDJOBS 1026 int mypid; 1027 1028 mypid = getpid(); 1029 1030 /* The next lines should be obsolete. Can anybody check if they 1031 * are really needed on the BSD platforms? 1032 * 1033 * this is to avoid the message: 1034 * fgtty: Not a typewriter (25) 1035 */ 1036# if defined(__osf__) || (BSD >= 199103) || defined(ISC) 1037 if (separate_sids) 1038 setsid(); /* should be already done */ 1039# ifdef TIOCSCTTY 1040 ioctl(fd, TIOCSCTTY, (char *)0); 1041# endif 1042# endif 1043 1044# ifdef POSIX 1045 if (separate_sids) 1046 if (tcsetpgrp(fd, mypid)) 1047 { 1048 debug1("fgtty: tcsetpgrp: %d\n", errno); 1049 return -1; 1050 } 1051# else /* POSIX */ 1052 if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) 1053 debug1("fgtty: TIOSETPGRP: %d\n", errno); 1054# ifndef SYSV /* Already done in brktty():setpgrp() */ 1055 if (separate_sids) 1056 if (setpgrp(fd, mypid)) 1057 debug1("fgtty: setpgrp: %d\n", errno); 1058# endif 1059# endif /* POSIX */ 1060#endif /* BSDJOBS */ 1061 return 0; 1062} 1063 1064/* 1065 * The alm boards on our sparc center 1000 have a lousy driver. 1066 * We cannot generate long breaks unless we use the most ugly form 1067 * of ioctls. jw. 1068 */ 1069#ifdef POSIX 1070int breaktype = 2; 1071#else /* POSIX */ 1072# ifdef TCSBRK 1073int breaktype = 1; 1074# else 1075int breaktype = 0; 1076# endif 1077#endif /* POSIX */ 1078 1079#if defined(sun) && !defined(SVR4) 1080# define HAVE_SUPER_TCSENDBREAK 1081#endif 1082 1083/* 1084 * type: 1085 * 0: TIOCSBRK / TIOCCBRK 1086 * 1: TCSBRK 1087 * 2: tcsendbreak() 1088 * n: approximate duration in 1/4 seconds. 1089 */ 1090static void 1091DoSendBreak(fd, n, type) 1092int fd, n, type; 1093{ 1094 switch (type) 1095 { 1096 case 2: /* tcsendbreak() =============================== */ 1097#ifdef POSIX 1098# ifdef HAVE_SUPER_TCSENDBREAK 1099 /* There is one rare case that I have tested, where tcsendbreak works 1100 * really great: this was an alm driver that came with SunOS 4.1.3 1101 * If you have this one, define the above symbol. 1102 * here we can use the second parameter to specify the duration. 1103 */ 1104 debug2("tcsendbreak(fd=%d, %d)\n", fd, n); 1105 if (tcsendbreak(fd, n) < 0) 1106 Msg(errno, "cannot send BREAK (tcsendbreak)"); 1107# else 1108 /* 1109 * here we hope, that multiple calls to tcsendbreak() can 1110 * be concatenated to form a long break, as we do not know 1111 * what exact interpretation the second parameter has: 1112 * 1113 * - sunos 4: duration in quarter seconds 1114 * - sunos 5: 0 a short break, nonzero a tcdrain() 1115 * - hpux, irix: ignored 1116 * - mot88: duration in milliseconds 1117 * - aix: duration in milliseconds, but 0 is 25 milliseconds. 1118 */ 1119 debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd); 1120 { 1121 int i; 1122 1123 if (!n) 1124 n++; 1125 for (i = 0; i < n; i++) 1126 if (tcsendbreak(fd, 0) < 0) 1127 { 1128 Msg(errno, "cannot send BREAK (tcsendbreak SVR4)"); 1129 return; 1130 } 1131 } 1132# endif 1133#else /* POSIX */ 1134 Msg(0, "tcsendbreak() not available, change breaktype"); 1135#endif /* POSIX */ 1136 break; 1137 1138 case 1: /* TCSBRK ======================================= */ 1139#ifdef TCSBRK 1140 if (!n) 1141 n++; 1142 /* 1143 * Here too, we assume that short breaks can be concatenated to 1144 * perform long breaks. But for SOLARIS, this is not true, of course. 1145 */ 1146 debug2("%d * TCSBRK fd=%d\n", n, fd); 1147 { 1148 int i; 1149 1150 for (i = 0; i < n; i++) 1151 if (ioctl(fd, TCSBRK, (char *)0) < 0) 1152 { 1153 Msg(errno, "Cannot send BREAK (TCSBRK)"); 1154 return; 1155 } 1156 } 1157#else /* TCSBRK */ 1158 Msg(0, "TCSBRK not available, change breaktype"); 1159#endif /* TCSBRK */ 1160 break; 1161 1162 case 0: /* TIOCSBRK / TIOCCBRK ========================== */ 1163#if defined(TIOCSBRK) && defined(TIOCCBRK) 1164 /* 1165 * This is very rude. Screen actively celebrates the break. 1166 * But it may be the only save way to issue long breaks. 1167 */ 1168 debug("TIOCSBRK TIOCCBRK\n"); 1169 if (ioctl(fd, TIOCSBRK, (char *)0) < 0) 1170 { 1171 Msg(errno, "Can't send BREAK (TIOCSBRK)"); 1172 return; 1173 } 1174 sleep1000(n ? n * 250 : 250); 1175 if (ioctl(fd, TIOCCBRK, (char *)0) < 0) 1176 { 1177 Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)"); 1178 return; 1179 } 1180#else /* TIOCSBRK && TIOCCBRK */ 1181 Msg(0, "TIOCSBRK/CBRK not available, change breaktype"); 1182#endif /* TIOCSBRK && TIOCCBRK */ 1183 break; 1184 1185 default: /* unknown ========================== */ 1186 Msg(0, "Internal SendBreak error: method %d unknown", type); 1187 } 1188} 1189 1190/* 1191 * Send a break for n * 0.25 seconds. Tty must be PLAIN. 1192 * The longest possible break allowed here is 15 seconds. 1193 */ 1194 1195void 1196SendBreak(wp, n, closeopen) 1197struct win *wp; 1198int n, closeopen; 1199{ 1200 sigret_t (*sigalrm)__P(SIGPROTOARG); 1201 1202#ifdef BUILTIN_TELNET 1203 if (wp->w_type == W_TYPE_TELNET) 1204 { 1205 TelBreak(wp); 1206 return; 1207 } 1208#endif 1209 if (wp->w_type != W_TYPE_PLAIN) 1210 return; 1211 1212 debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); 1213 1214#ifdef POSIX 1215 (void) tcflush(wp->w_ptyfd, TCIOFLUSH); 1216#else 1217# ifdef TIOCFLUSH 1218 (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); 1219# endif /* TIOCFLUSH */ 1220#endif /* POSIX */ 1221 1222 if (closeopen) 1223 { 1224 close(wp->w_ptyfd); 1225 sleep1000(n ? n * 250 : 250); 1226 if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1) 1227 { 1228 Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); 1229 return; 1230 } 1231 (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK); 1232 } 1233 else 1234 { 1235 sigalrm = signal(SIGALRM, SigAlrmDummy); 1236 alarm(15); 1237 1238 DoSendBreak(wp->w_ptyfd, n, breaktype); 1239 1240 alarm(0); 1241 signal(SIGALRM, sigalrm); 1242 } 1243 debug(" broken.\n"); 1244} 1245 1246/* 1247 * Console grabbing 1248 */ 1249 1250#if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) 1251 1252static struct event consredir_ev; 1253static int consredirfd[2] = {-1, -1}; 1254 1255static void 1256consredir_readev_fn(ev, data) 1257struct event *ev; 1258char *data; 1259{ 1260 char *p, *n, buf[256]; 1261 int l; 1262 1263 if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0) 1264 { 1265 close(consredirfd[0]); 1266 close(consredirfd[1]); 1267 consredirfd[0] = consredirfd[1] = -1; 1268 evdeq(ev); 1269 return; 1270 } 1271 for (p = n = buf; l > 0; n++, l--) 1272 if (*n == '\n') 1273 { 1274 if (n > p) 1275 WriteString(console_window, p, n - p); 1276 WriteString(console_window, "\r\n", 2); 1277 p = n + 1; 1278 } 1279 if (n > p) 1280 WriteString(console_window, p, n - p); 1281} 1282 1283#endif 1284 1285/*ARGSUSED*/ 1286int 1287TtyGrabConsole(fd, on, rc_name) 1288int fd, on; 1289char *rc_name; 1290{ 1291#if defined(TIOCCONS) && !defined(linux) 1292 struct display *d; 1293 int ret = 0; 1294 int sfd = -1; 1295 1296 if (on < 0) 1297 return 0; /* pty close will ungrab */ 1298 if (on) 1299 { 1300 if (displays == 0) 1301 { 1302 Msg(0, "I need a display"); 1303 return -1; 1304 } 1305 for (d = displays; d; d = d->d_next) 1306 if (strcmp(d->d_usertty, "/dev/console") == 0) 1307 break; 1308 if (d) 1309 { 1310 Msg(0, "too dangerous - screen is running on /dev/console"); 1311 return -1; 1312 } 1313 } 1314 1315 if (!on) 1316 { 1317 char *slave; 1318 if ((fd = OpenPTY(&slave)) < 0) 1319 { 1320 Msg(errno, "%s: could not open detach pty master", rc_name); 1321 return -1; 1322 } 1323 if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0) 1324 { 1325 Msg(errno, "%s: could not open detach pty slave", rc_name); 1326 close(fd); 1327 return -1; 1328 } 1329 } 1330 if (UserContext() == 1) 1331 UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); 1332 ret = UserStatus(); 1333 if (ret) 1334 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); 1335 if (!on) 1336 { 1337 close(sfd); 1338 close(fd); 1339 } 1340 return ret; 1341 1342#else 1343# if defined(SRIOCSREDIR) || defined(linux) 1344 struct display *d; 1345# ifdef SRIOCSREDIR 1346 int cfd; 1347# else 1348 struct mode new1, new2; 1349 char *slave; 1350# endif 1351 1352 if (on > 0) 1353 { 1354 if (displays == 0) 1355 { 1356 Msg(0, "I need a display"); 1357 return -1; 1358 } 1359 for (d = displays; d; d = d->d_next) 1360 if (strcmp(d->d_usertty, "/dev/console") == 0) 1361 break; 1362 if (d) 1363 { 1364 Msg(0, "too dangerous - screen is running on /dev/console"); 1365 return -1; 1366 } 1367 } 1368 if (consredirfd[0] >= 0) 1369 { 1370 evdeq(&consredir_ev); 1371 close(consredirfd[0]); 1372 close(consredirfd[1]); 1373 consredirfd[0] = consredirfd[1] = -1; 1374 } 1375 if (on <= 0) 1376 return 0; 1377# ifdef SRIOCSREDIR 1378 if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1) 1379 { 1380 Msg(errno, "/dev/console"); 1381 return -1; 1382 } 1383 if (pipe(consredirfd)) 1384 { 1385 Msg(errno, "pipe"); 1386 close(cfd); 1387 consredirfd[0] = consredirfd[1] = -1; 1388 return -1; 1389 } 1390 if (ioctl(cfd, SRIOCSREDIR, consredirfd[1])) 1391 { 1392 Msg(errno, "SRIOCSREDIR ioctl"); 1393 close(cfd); 1394 close(consredirfd[0]); 1395 close(consredirfd[1]); 1396 consredirfd[0] = consredirfd[1] = -1; 1397 return -1; 1398 } 1399 close(cfd); 1400# else 1401 /* special linux workaround for a too restrictive kernel */ 1402 if ((consredirfd[0] = OpenPTY(&slave)) < 0) 1403 { 1404 Msg(errno, "%s: could not open detach pty master", rc_name); 1405 return -1; 1406 } 1407 if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0) 1408 { 1409 Msg(errno, "%s: could not open detach pty slave", rc_name); 1410 close(consredirfd[0]); 1411 return -1; 1412 } 1413 InitTTY(&new1, 0); 1414 SetMode(&new1, &new2, 0, 0); 1415 SetTTY(consredirfd[1], &new2); 1416 if (UserContext() == 1) 1417 UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on)); 1418 if (UserStatus()) 1419 { 1420 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); 1421 close(consredirfd[0]); 1422 close(consredirfd[1]); 1423 return -1; 1424 } 1425# endif 1426 consredir_ev.fd = consredirfd[0]; 1427 consredir_ev.type = EV_READ; 1428 consredir_ev.handler = consredir_readev_fn; 1429 evenq(&consredir_ev); 1430 return 0; 1431# else 1432 if (on > 0) 1433 Msg(0, "%s: don't know how to grab the console", rc_name); 1434 return -1; 1435# endif 1436#endif 1437} 1438 1439/* 1440 * Read modem control lines of a physical tty and write them to buf 1441 * in a readable format. 1442 * Will not write more than 256 characters to buf. 1443 * Returns buf; 1444 */ 1445char * 1446TtyGetModemStatus(fd, buf) 1447int fd; 1448char *buf; 1449{ 1450 char *p = buf; 1451#ifdef TIOCGSOFTCAR 1452 unsigned int softcar; 1453#endif 1454#if defined(TIOCMGET) || defined(TIOCMODG) 1455 unsigned int mflags; 1456#else 1457# ifdef MCGETA 1458 /* this is yet another interface, found on hpux. grrr */ 1459 mflag mflags; 1460#if defined(MDTR) 1461# define TIOCM_DTR MDTR 1462#endif /* MDTR */ 1463#if defined(MRTS) 1464# define TIOCM_RTS MRTS 1465#endif /* MRTS */ 1466#if defined(MDSR) 1467# define TIOCM_DSR MDSR 1468#endif /* MDSR */ 1469#if defined(MDCD) 1470# define TIOCM_CAR MDCD 1471#endif /* MDCD */ 1472#if defined(MRI) 1473# define TIOCM_RNG MRI 1474#endif /* MRI */ 1475#if defined(MCTS) 1476# define TIOCM_CTS MCTS 1477#endif /* MCTS */ 1478# endif 1479#endif 1480#if defined(CLOCAL) || defined(CRTSCTS) 1481 struct mode mtio; /* screen.h */ 1482#endif 1483#if defined(CRTSCTS) || defined(TIOCM_CTS) 1484 int rtscts; 1485#endif 1486 int clocal; 1487 1488#if defined(CLOCAL) || defined(CRTSCTS) 1489 GetTTY(fd, &mtio); 1490#endif 1491 clocal = 0; 1492#ifdef CLOCAL 1493 if (mtio.tio.c_cflag & CLOCAL) 1494 { 1495 clocal = 1; 1496 *p++ = '{'; 1497 } 1498#endif 1499 1500#ifdef TIOCM_CTS 1501# ifdef CRTSCTS 1502 if (!(mtio.tio.c_cflag & CRTSCTS)) 1503 rtscts = 0; 1504 else 1505# endif /* CRTSCTS */ 1506 rtscts = 1; 1507#endif /* TIOCM_CTS */ 1508 1509#ifdef TIOCGSOFTCAR 1510 if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0) 1511 softcar = 0; 1512#endif 1513 1514#if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA) 1515# ifdef TIOCMGET 1516 if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0) 1517# else 1518# ifdef TIOCMODG 1519 if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0) 1520# else 1521 if (ioctl(fd, MCGETA, &mflags) < 0) 1522# endif 1523# endif 1524 { 1525#ifdef TIOCGSOFTCAR 1526 sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD"); 1527#else 1528 sprintf(p, "NO-TTY?"); 1529#endif 1530 p += strlen(p); 1531 } 1532 else 1533 { 1534 char *s; 1535# ifdef FANCY_MODEM 1536# ifdef TIOCM_LE 1537 if (!(mflags & TIOCM_LE)) 1538 for (s = "!LE "; *s; *p++ = *s++); 1539# endif 1540# endif /* FANCY_MODEM */ 1541 1542# ifdef TIOCM_RTS 1543 s = "!RTS "; if (mflags & TIOCM_RTS) s++; 1544 while (*s) *p++ = *s++; 1545# endif 1546# ifdef TIOCM_CTS 1547 s = "!CTS "; 1548 if (!rtscts) 1549 { 1550 *p++ = '('; 1551 s = "!CTS) "; 1552 } 1553 if (mflags & TIOCM_CTS) s++; 1554 while (*s) *p++ = *s++; 1555# endif 1556 1557# ifdef TIOCM_DTR 1558 s = "!DTR "; if (mflags & TIOCM_DTR) s++; 1559 while (*s) *p++ = *s++; 1560# endif 1561# ifdef TIOCM_DSR 1562 s = "!DSR "; if (mflags & TIOCM_DSR) s++; 1563 while (*s) *p++ = *s++; 1564# endif 1565# if defined(TIOCM_CD) || defined(TIOCM_CAR) 1566 s = "!CD "; 1567# ifdef TIOCGSOFTCAR 1568 if (softcar) 1569 { 1570 *p++ = '('; 1571 s = "!CD) "; 1572 } 1573# endif 1574# ifdef TIOCM_CD 1575 if (mflags & TIOCM_CD) s++; 1576# else 1577 if (mflags & TIOCM_CAR) s++; 1578# endif 1579 while (*s) *p++ = *s++; 1580# endif 1581# if defined(TIOCM_RI) || defined(TIOCM_RNG) 1582# ifdef TIOCM_RI 1583 if (mflags & TIOCM_RI) 1584# else 1585 if (mflags & TIOCM_RNG) 1586# endif 1587 for (s = "RI "; *s; *p++ = *s++); 1588# endif 1589# ifdef FANCY_MODEM 1590# ifdef TIOCM_ST 1591 s = "!ST "; if (mflags & TIOCM_ST) s++; 1592 while (*s) *p++ = *s++; 1593# endif 1594# ifdef TIOCM_SR 1595 s = "!SR "; if (mflags & TIOCM_SR) s++; 1596 while (*s) *p++ = *s++; 1597# endif 1598# endif /* FANCY_MODEM */ 1599 if (p > buf && p[-1] == ' ') 1600 p--; 1601 *p = '\0'; 1602 } 1603#else 1604# ifdef TIOCGSOFTCAR 1605 sprintf(p, " %s", softcar ? "(CD)", "CD"); 1606 p += strlen(p); 1607# endif 1608#endif 1609 if (clocal) 1610 *p++ = '}'; 1611 *p = '\0'; 1612 return buf; 1613} 1614 1615/* 1616 * Old bsd-ish machines may not have any of the baudrate B... symbols. 1617 * We hope to detect them here, so that the btable[] below always has 1618 * many entries. 1619 */ 1620#ifndef POSIX 1621# ifndef TERMIO 1622# if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300) 1623#if !defined(B0) 1624#define B0 0 1625#endif /* B0 */ 1626#if !defined(B50) 1627#define B50 1 1628#endif /* B50 */ 1629#if !defined(B75) 1630#define B75 2 1631#endif /* B75 */ 1632#if !defined(B110) 1633#define B110 3 1634#endif /* B110 */ 1635#if !defined(B134) 1636#define B134 4 1637#endif /* B134 */ 1638#if !defined(B150) 1639#define B150 5 1640#endif /* B150 */ 1641#if !defined(B200) 1642#define B200 6 1643#endif /* B200 */ 1644#if !defined(B300) 1645#define B300 7 1646#endif /* B300 */ 1647#if !defined(B600) 1648#define B600 8 1649#endif /* B600 */ 1650#if !defined(B1200) 1651#define B1200 9 1652#endif /* B1200 */ 1653#if !defined(B1800) 1654#define B1800 10 1655#endif /* B1800 */ 1656#if !defined(B2400) 1657#define B2400 11 1658#endif /* B2400 */ 1659#if !defined(B4800) 1660#define B4800 12 1661#endif /* B4800 */ 1662#if !defined(B9600) 1663#define B9600 13 1664#endif /* B9600 */ 1665#if !defined(EXTA) 1666#define EXTA 14 1667#endif /* EXTA */ 1668#if !defined(EXTB) 1669#define EXTB 15 1670#endif /* EXTB */ 1671# endif 1672# endif 1673#endif 1674 1675/* 1676 * On hpux, idx and sym will be different. 1677 * Rumor has it that, we need idx in D_dospeed to make tputs 1678 * padding correct. 1679 * Frequently used entries come first. 1680 */ 1681static struct baud_values btable[] = 1682{ 1683#if defined(B9600) 1684 { 13, 9600, B9600 }, 1685#endif /* B9600 */ 1686#if defined(B19200) 1687 { 14, 19200, B19200 }, 1688#endif /* B19200 */ 1689#if defined(EXTA) 1690 { 14, 19200, EXTA }, 1691#endif /* EXTA */ 1692#if defined(B38400) 1693 { 15, 38400, B38400 }, 1694#endif /* B38400 */ 1695#if defined(EXTB) 1696 { 15, 38400, EXTB }, 1697#endif /* EXTB */ 1698#if defined(B57600) 1699 { 16, 57600, B57600 }, 1700#endif /* B57600 */ 1701#if defined(B115200) 1702 { 17, 115200, B115200 }, 1703#endif /* B115200 */ 1704#if defined(B230400) 1705 { 18, 230400, B230400 }, 1706#endif /* B230400 */ 1707#if defined(B460800) 1708 { 19, 460800, B460800 }, 1709#endif /* B460800 */ 1710#if defined(B7200) 1711 { 13, 7200, B7200 }, 1712#endif /* B7200 */ 1713#if defined(B4800) 1714 { 12, 4800, B4800 }, 1715#endif /* B4800 */ 1716#if defined(B3600) 1717 { 12, 3600, B3600 }, 1718#endif /* B3600 */ 1719#if defined(B2400) 1720 { 11, 2400, B2400 }, 1721#endif /* B2400 */ 1722#if defined(B1800) 1723 { 10, 1800, B1800 }, 1724#endif /* B1800 */ 1725#if defined(B1200) 1726 { 9, 1200, B1200 }, 1727#endif /* B1200 */ 1728#if defined(B900) 1729 { 9, 900, B900 }, 1730#endif /* B900 */ 1731#if defined(B600) 1732 { 8, 600, B600 }, 1733#endif /* B600 */ 1734#if defined(B300) 1735 { 7, 300, B300 }, 1736#endif /* B300 */ 1737#if defined(B200) 1738 { 6, 200, B200 }, 1739#endif /* B200 */ 1740#if defined(B150) 1741 { 5, 150, B150 }, 1742#endif /* B150 */ 1743#if defined(B134) 1744 { 4, 134, B134 }, 1745#endif /* B134 */ 1746#if defined(B110) 1747 { 3, 110, B110 }, 1748#endif /* B110 */ 1749#if defined(B75) 1750 { 2, 75, B75 }, 1751#endif /* B75 */ 1752#if defined(B50) 1753 { 1, 50, B50 }, 1754#endif /* B50 */ 1755#if defined(B0) 1756 { 0, 0, B0 }, 1757#endif /* B0 */ 1758 { -1, -1, -1 } 1759}; 1760 1761/* 1762 * baud may either be a bits-per-second value or a symbolic 1763 * value as returned by cfget?speed() 1764 */ 1765struct baud_values * 1766lookup_baud(baud) 1767int baud; 1768{ 1769 struct baud_values *p; 1770 1771 for (p = btable; p->idx >= 0; p++) 1772 if (baud == p->bps || baud == p->sym) 1773 return p; 1774 return NULL; 1775} 1776 1777/* 1778 * change the baud rate in a mode structure. 1779 * ibaud and obaud are given in bit/second, or at your option as 1780 * termio B... symbols as defined in e.g. suns sys/ttydev.h 1781 * -1 means don't change. 1782 */ 1783int 1784SetBaud(m, ibaud, obaud) 1785struct mode *m; 1786int ibaud, obaud; 1787{ 1788 struct baud_values *ip, *op; 1789 1790 if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) || 1791 (!(op = lookup_baud(obaud)) && obaud != -1)) 1792 return -1; 1793 1794#ifdef POSIX 1795 if (ip) cfsetispeed(&m->tio, ip->sym); 1796 if (op) cfsetospeed(&m->tio, op->sym); 1797#else /* POSIX */ 1798# ifdef TERMIO 1799 if (ip) 1800 { 1801# ifdef IBSHIFT 1802 m->tio.c_cflag &= ~(CBAUD << IBSHIFT); 1803 m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT; 1804# else /* IBSHIFT */ 1805 if (ibaud != obaud) 1806 return -1; 1807# endif /* IBSHIFT */ 1808 } 1809 if (op) 1810 { 1811 m->tio.c_cflag &= ~CBAUD; 1812 m->tio.c_cflag |= op->sym & CBAUD; 1813 } 1814# else /* TERMIO */ 1815 if (ip) m->m_ttyb.sg_ispeed = ip->idx; 1816 if (op) m->m_ttyb.sg_ospeed = op->idx; 1817# endif /* TERMIO */ 1818#endif /* POSIX */ 1819 return 0; 1820} 1821 1822/* 1823 * Write out the mode struct in a readable form 1824 */ 1825 1826#ifdef DEBUG 1827void 1828DebugTTY(m) 1829struct mode *m; 1830{ 1831 int i; 1832 1833#ifdef POSIX 1834 debug("struct termios tio:\n"); 1835 debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag); 1836 debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag); 1837 debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag); 1838 debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag); 1839 debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio)); 1840 debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio)); 1841 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) 1842 { 1843 debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); 1844 } 1845# ifdef HPUX_LTCHARS_HACK 1846 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); 1847 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); 1848 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); 1849 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); 1850 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); 1851 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); 1852# endif /* HPUX_LTCHARS_HACK */ 1853#else /* POSIX */ 1854# ifdef TERMIO 1855 debug("struct termio tio:\n"); 1856 debug1("c_iflag = %04o\n", m->tio.c_iflag); 1857 debug1("c_oflag = %04o\n", m->tio.c_oflag); 1858 debug1("c_cflag = %04o\n", m->tio.c_cflag); 1859 debug1("c_lflag = %04o\n", m->tio.c_lflag); 1860 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) 1861 { 1862 debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); 1863 } 1864# else /* TERMIO */ 1865 debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); 1866 debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); 1867 debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); 1868 debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); 1869 debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); 1870 debug1("intrc = %#02x\n", m->m_tchars.t_intrc); 1871 debug1("quitc = %#02x\n", m->m_tchars.t_quitc); 1872 debug1("startc = %#02x\n", m->m_tchars.t_startc); 1873 debug1("stopc = %#02x\n", m->m_tchars.t_stopc); 1874 debug1("eofc = %#02x\n", m->m_tchars.t_eofc); 1875 debug1("brkc = %#02x\n", m->m_tchars.t_brkc); 1876 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); 1877 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); 1878 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); 1879 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); 1880 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); 1881 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); 1882 debug1("ldisc = %d\n", m->m_ldisc); 1883 debug1("lmode = %#x\n", m->m_lmode); 1884# endif /* TERMIO */ 1885#endif /* POSIX */ 1886} 1887#endif /* DEBUG */ 1888