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