diff options
Diffstat (limited to 'src/tty.c.dist')
-rw-r--r-- | src/tty.c.dist | 1887 |
1 files changed, 1887 insertions, 0 deletions
diff --git a/src/tty.c.dist b/src/tty.c.dist new file mode 100644 index 0000000..688cf62 --- /dev/null +++ b/src/tty.c.dist @@ -0,0 +1,1887 @@ +/* Copyright (c) 1993-2002 + * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) + * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) + * Copyright (c) 1987 Oliver Laumann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING); if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + **************************************************************** + */ + +/* + * NOTICE: tty.c is automatically generated from tty.sh + * Do not change anything here. If you then change tty.sh. + */ + +#include <sys/types.h> +#include <signal.h> +#include <fcntl.h> +#ifndef sgi +# include <sys/file.h> +#endif +#if !defined(sun) || defined(SUNOS3) +# include <sys/ioctl.h> /* collosions with termios.h */ +#else +# ifndef TIOCEXCL +# include <sys/ttold.h> /* needed for TIOCEXCL */ +# endif +#endif +#ifdef __hpux +# include <sys/modem.h> +#endif + +#ifdef ISC +# include <sys/tty.h> +# include <sys/sioctl.h> +# include <sys/pty.h> +#endif + +#include "config.h" +#ifdef SVR4 +#include <sys/stropts.h> /* for I_POP */ +#endif + +#include "screen.h" +#include "extern.h" + +#if !defined(TIOCCONS) && defined(sun) && defined(SVR4) +# include <sys/strredir.h> +#endif + +extern struct display *display, *displays; +extern int iflag; +#if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) +extern struct win *console_window; +static void consredir_readev_fn __P((struct event *, char *)); +#endif + +int separate_sids = 1; + +static void DoSendBreak __P((int, int, int)); +static sigret_t SigAlrmDummy __P(SIGPROTOARG); + + +/* Frank Schulz (fschulz@pyramid.com): + * I have no idea why VSTART is not defined and my fix is probably not + * the cleanest, but it works. + */ +#if !defined(VSTART) && defined(_VSTART) +#define VSTART _VSTART +#endif +#if !defined(VSTOP) && defined(_VSTOP) +#define VSTOP _VSTOP +#endif + +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef TTYVMIN +# define TTYVMIN 1 +#endif +#ifndef TTYVTIME +#define TTYVTIME 0 +#endif + + +static sigret_t +SigAlrmDummy SIGDEFARG +{ + debug("SigAlrmDummy()\n"); + SIGRETURN; +} + +/* + * Carefully open a charcter device. Not used to open display ttys. + * The second parameter is parsed for a few stty style options. + */ + +int +OpenTTY(line, opt) +char *line, *opt; +{ + int f; + struct mode Mode; + sigret_t (*sigalrm)__P(SIGPROTOARG); + + sigalrm = signal(SIGALRM, SigAlrmDummy); + alarm(2); + + /* this open only succeeds, if real uid is allowed */ + if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) + { + if (errno == EINTR) + Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line); + else + Msg(errno, "Cannot open line '%s' for R/W", line); + alarm(0); + signal(SIGALRM, sigalrm); + return -1; + } + if (!isatty(f)) + { + Msg(0, "'%s' is not a tty", line); + alarm(0); + signal(SIGALRM, sigalrm); + close(f); + return -1; + } +#if defined(I_POP) && defined(POP_TTYMODULES) + debug("OpenTTY I_POP\n"); + while (ioctl(f, I_POP, (char *)0) >= 0) + ; +#endif + /* + * We come here exclusively. This is to stop all kermit and cu type things + * accessing the same tty line. + * Perhaps we should better create a lock in some /usr/spool/locks directory? + */ +#ifdef TIOCEXCL + errno = 0; + if (ioctl(f, TIOCEXCL, (char *) 0) < 0) + Msg(errno, "%s: ioctl TIOCEXCL failed", line); + debug3("%d %d %d\n", getuid(), geteuid(), getpid()); + debug2("%s TIOCEXCL errno %d\n", line, errno); +#endif /* TIOCEXCL */ + /* + * We create a sane tty mode. We do not copy things from the display tty + */ +#if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE + if (display) + { + debug1("OpenTTY: using mode of display for %s\n", line); + Mode = D_NewMode; + } + else +#endif + InitTTY(&Mode, W_TYPE_PLAIN); + + SttyMode(&Mode, opt); +#ifdef DEBUG + DebugTTY(&Mode); +#endif + SetTTY(f, &Mode); + +#if defined(linux) && defined(TIOCMSET) + { + int mcs = 0; + ioctl(f, TIOCMGET, &mcs); + mcs |= TIOCM_RTS; + ioctl(f, TIOCMSET, &mcs); + } +#endif + + brktty(f); + alarm(0); + signal(SIGALRM, sigalrm); + debug2("'%s' CONNECT fd=%d.\n", line, f); + return f; +} + + +/* + * Tty mode handling + */ + +void +InitTTY(m, ttyflag) +struct mode *m; +int ttyflag; +{ + bzero((char *)m, sizeof(*m)); +#ifdef POSIX + /* struct termios tio + * defaults, as seen on SunOS 4.1.3 + */ + debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); +#if defined(BRKINT) + m->tio.c_iflag |= BRKINT; +#endif /* BRKINT */ +#if defined(IGNPAR) + m->tio.c_iflag |= IGNPAR; +#endif /* IGNPAR */ +/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ +#if defined(IXON) + m->tio.c_iflag |= IXON; +#endif /* IXON */ +/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ + + if (!ttyflag) /* may not even be good for ptys.. */ + { +#if defined(ICRNL) + m->tio.c_iflag |= ICRNL; +#endif /* ICRNL */ +#if defined(ONLCR) + m->tio.c_oflag |= ONLCR; +#endif /* ONLCR */ +#if defined(TAB3) + m->tio.c_oflag |= TAB3; +#endif /* TAB3 */ +#if defined(OXTABS) + m->tio.c_oflag |= OXTABS; +#endif /* OXTABS */ +/* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ +#if defined(OPOST) + m->tio.c_oflag |= OPOST; +#endif /* OPOST */ + } + + +/* + * Or-ing the speed into c_cflags is dangerous. + * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs. + * + * IF{B9600} m->tio.c_cflag |= B9600; + * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; + * + * We hope that we have the posix calls to do it right: + * If these are not available you might try the above. + */ +#if defined(B9600) + cfsetospeed(&m->tio, B9600); +#endif /* B9600 */ +#if defined(B9600) + cfsetispeed(&m->tio, B9600); +#endif /* B9600 */ + +#if defined(CS8) + m->tio.c_cflag |= CS8; +#endif /* CS8 */ +#if defined(CREAD) + m->tio.c_cflag |= CREAD; +#endif /* CREAD */ +#if defined(CLOCAL) + m->tio.c_cflag |= CLOCAL; +#endif /* CLOCAL */ + +#if defined(ECHOCTL) + m->tio.c_lflag |= ECHOCTL; +#endif /* ECHOCTL */ +#if defined(ECHOKE) + m->tio.c_lflag |= ECHOKE; +#endif /* ECHOKE */ + + if (!ttyflag) + { +#if defined(ISIG) + m->tio.c_lflag |= ISIG; +#endif /* ISIG */ +#if defined(ICANON) + m->tio.c_lflag |= ICANON; +#endif /* ICANON */ +#if defined(ECHO) + m->tio.c_lflag |= ECHO; +#endif /* ECHO */ + } +#if defined(ECHOE) + m->tio.c_lflag |= ECHOE; +#endif /* ECHOE */ +#if defined(ECHOK) + m->tio.c_lflag |= ECHOK; +#endif /* ECHOK */ +#if defined(IEXTEN) + m->tio.c_lflag |= IEXTEN; +#endif /* IEXTEN */ + +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif +#endif /* VINTR */ +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif +#endif /* VQUIT */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0x7f; /* DEL */ +#endif +#endif /* VERASE */ +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif +#endif /* VKILL */ +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif +#endif /* VEOF */ +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0000; +#endif +#endif /* VEOL */ +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0000; +#endif +#endif /* VEOL2 */ +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif +#endif /* VSWTCH */ +#if defined(VSTART) +#if (VSTART < MAXCC) + m->tio.c_cc[VSTART] = Ctrl('Q'); +#endif +#endif /* VSTART */ +#if defined(VSTOP) +#if (VSTOP < MAXCC) + m->tio.c_cc[VSTOP] = Ctrl('S'); +#endif +#endif /* VSTOP */ +#if defined(VSUSP) +#if (VSUSP < MAXCC) + m->tio.c_cc[VSUSP] = Ctrl('Z'); +#endif +#endif /* VSUSP */ +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + m->tio.c_cc[VDSUSP] = Ctrl('Y'); +#endif +#endif /* VDSUSP */ +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + m->tio.c_cc[VREPRINT] = Ctrl('R'); +#endif +#endif /* VREPRINT */ +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + m->tio.c_cc[VDISCARD] = Ctrl('O'); +#endif +#endif /* VDISCARD */ +#if defined(VWERASE) +#if (VWERASE < MAXCC) + m->tio.c_cc[VWERASE] = Ctrl('W'); +#endif +#endif /* VWERASE */ +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + m->tio.c_cc[VLNEXT] = Ctrl('V'); +#endif +#endif /* VLNEXT */ +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + m->tio.c_cc[VSTATUS] = Ctrl('T'); +#endif +#endif /* VSTATUS */ + + if (ttyflag) + { + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; + } + +# ifdef HPUX_LTCHARS_HACK + m->m_ltchars.t_suspc = Ctrl('Z'); + m->m_ltchars.t_dsuspc = Ctrl('Y'); + m->m_ltchars.t_rprntc = Ctrl('R'); + m->m_ltchars.t_flushc = Ctrl('O'); + m->m_ltchars.t_werasc = Ctrl('W'); + m->m_ltchars.t_lnextc = Ctrl('V'); +# endif /* HPUX_LTCHARS_HACK */ + +#else /* POSIX */ + +# ifdef TERMIO + debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); + /* struct termio tio + * defaults, as seen on Mototola SYSV68: + * input: 7bit, CR->NL, ^S/^Q flow control + * output: POSTprocessing: NL->NL-CR, Tabs to spaces + * control: 9600baud, 8bit CSIZE, enable input + * local: enable signals, erase/kill processing, echo on. + */ +#if defined(ISTRIP) + m->tio.c_iflag |= ISTRIP; +#endif /* ISTRIP */ +#if defined(IXON) + m->tio.c_iflag |= IXON; +#endif /* IXON */ + + if (!ttyflag) /* may not even be good for ptys.. */ + { +#if defined(OPOST) + m->tio.c_oflag |= OPOST; +#endif /* OPOST */ +#if defined(ICRNL) + m->tio.c_iflag |= ICRNL; +#endif /* ICRNL */ +#if defined(ONLCR) + m->tio.c_oflag |= ONLCR; +#endif /* ONLCR */ +#if defined(TAB3) + m->tio.c_oflag |= TAB3; +#endif /* TAB3 */ + } + +#ifdef __bsdi__ + )-: cannot handle BSDI without POSIX +#else +#if defined(B9600) + m->tio.c_cflag = B9600; +#endif /* B9600 */ +#endif +#if defined(CS8) + m->tio.c_cflag |= CS8; +#endif /* CS8 */ +#if defined(CREAD) + m->tio.c_cflag |= CREAD; +#endif /* CREAD */ + + if (!ttyflag) + { +#if defined(ISIG) + m->tio.c_lflag |= ISIG; +#endif /* ISIG */ +#if defined(ICANON) + m->tio.c_lflag |= ICANON; +#endif /* ICANON */ +#if defined(ECHO) + m->tio.c_lflag |= ECHO; +#endif /* ECHO */ + } +#if defined(ECHOE) + m->tio.c_lflag |= ECHOE; +#endif /* ECHOE */ +#if defined(ECHOK) + m->tio.c_lflag |= ECHOK; +#endif /* ECHOK */ + +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif +#endif /* VINTR */ +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif +#endif /* VQUIT */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0177; /* DEL */ +#endif +#endif /* VERASE */ +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif +#endif /* VKILL */ +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif +#endif /* VEOF */ +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0377; +#endif +#endif /* VEOL */ +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0377; +#endif +#endif /* VEOL2 */ +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif +#endif /* VSWTCH */ + + if (ttyflag) + { + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; + } + +# else /* TERMIO */ + debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); + m->m_ttyb.sg_ispeed = B9600; + m->m_ttyb.sg_ospeed = B9600; + m->m_ttyb.sg_erase = 0177; /*DEL */ + m->m_ttyb.sg_kill = Ctrl('H'); + if (!ttyflag) + m->m_ttyb.sg_flags = CRMOD | ECHO +#if defined(ANYP) + | ANYP +#endif /* ANYP */ + ; + else + m->m_ttyb.sg_flags = CBREAK +#if defined(ANYP) + | ANYP +#endif /* ANYP */ + ; + + m->m_tchars.t_intrc = Ctrl('C'); + m->m_tchars.t_quitc = Ctrl('\\'); + m->m_tchars.t_startc = Ctrl('Q'); + m->m_tchars.t_stopc = Ctrl('S'); + m->m_tchars.t_eofc = Ctrl('D'); + m->m_tchars.t_brkc = -1; + + m->m_ltchars.t_suspc = Ctrl('Z'); + m->m_ltchars.t_dsuspc = Ctrl('Y'); + m->m_ltchars.t_rprntc = Ctrl('R'); + m->m_ltchars.t_flushc = Ctrl('O'); + m->m_ltchars.t_werasc = Ctrl('W'); + m->m_ltchars.t_lnextc = Ctrl('V'); + +#if defined(NTTYDISC) + m->m_ldisc = NTTYDISC; +#endif /* NTTYDISC */ + + m->m_lmode = 0 +#if defined(LDECCTQ) + | LDECCTQ +#endif /* LDECCTQ */ +#if defined(LCTLECH) + | LCTLECH +#endif /* LCTLECH */ +#if defined(LPASS8) + | LPASS8 +#endif /* LPASS8 */ +#if defined(LCRTKIL) + | LCRTKIL +#endif /* LCRTKIL */ +#if defined(LCRTERA) + | LCRTERA +#endif /* LCRTERA */ +#if defined(LCRTBS) + | LCRTBS +#endif /* LCRTBS */ + ; +# endif /* TERMIO */ +#endif /* POSIX */ + +#if defined(ENCODINGS) && defined(TIOCKSET) + m->m_jtchars.t_ascii = 'J'; + m->m_jtchars.t_kanji = 'B'; + m->m_knjmode = KM_ASCII | KM_SYSSJIS; +#endif +} + +void +SetTTY(fd, mp) +int fd; +struct mode *mp; +{ + errno = 0; +#ifdef POSIX + tcsetattr(fd, TCSADRAIN, &mp->tio); +# ifdef HPUX_LTCHARS_HACK + ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); +# endif +#else +# ifdef TERMIO + ioctl(fd, TCSETAW, (char *)&mp->tio); +# ifdef CYTERMIO + if (mp->tio.c_line == 3) + { + ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey); + ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen); + ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace); + } +# endif +# else + /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ + ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); + ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); + ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); + ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); + ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ +# endif +#endif +#if defined(ENCODINGS) && defined(TIOCKSET) + ioctl(fd, TIOCKSETC, &mp->m_jtchars); + ioctl(fd, TIOCKSET, &mp->m_knjmode); +#endif + if (errno) + Msg(errno, "SetTTY (fd %d): ioctl failed", fd); +} + +void +GetTTY(fd, mp) +int fd; +struct mode *mp; +{ + errno = 0; +#ifdef POSIX + tcgetattr(fd, &mp->tio); +# ifdef HPUX_LTCHARS_HACK + ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); +# endif +#else +# ifdef TERMIO + ioctl(fd, TCGETA, (char *)&mp->tio); +# ifdef CYTERMIO + if (mp->tio.c_line == 3) + { + ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey); + ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen); + ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace); + } + else + { + mp->m_mapkey = NOMAPKEY; + mp->m_mapscreen = NOMAPSCREEN; + mp->m_backspace = '\b'; + } +# endif +# else + ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); + ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); + ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); + ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); + ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); +# endif +#endif +#if defined(ENCODINGS) && defined(TIOCKSET) + ioctl(fd, TIOCKGETC, &mp->m_jtchars); + ioctl(fd, TIOCKGET, &mp->m_knjmode); +#endif + if (errno) + Msg(errno, "GetTTY (fd %d): ioctl failed", fd); +} + +/* + * needs interrupt = iflag and flow = d->d_flow + */ +void +SetMode(op, np, flow, interrupt) +struct mode *op, *np; +int flow, interrupt; +{ + *np = *op; + + ASSERT(display); +#if defined(TERMIO) || defined(POSIX) +# ifdef CYTERMIO + np->m_mapkey = NOMAPKEY; + np->m_mapscreen = NOMAPSCREEN; + np->tio.c_line = 0; +# endif +#if defined(ICRNL) + np->tio.c_iflag &= ~ICRNL; +#endif /* ICRNL */ +#if defined(ISTRIP) + np->tio.c_iflag &= ~ISTRIP; +#endif /* ISTRIP */ +#if defined(ONLCR) + np->tio.c_oflag &= ~ONLCR; +#endif /* ONLCR */ + np->tio.c_lflag &= ~(ICANON | ECHO); + /* + * From Andrew Myers (andru@tonic.lcs.mit.edu) + * to avoid ^V^V-Problem on OSF1 + */ +#if defined(IEXTEN) + np->tio.c_lflag &= ~IEXTEN; +#endif /* IEXTEN */ + + /* + * Unfortunately, the master process never will get SIGINT if the real + * terminal is different from the one on which it was originaly started + * (process group membership has not been restored or the new tty could not + * be made controlling again). In my solution, it is the attacher who + * receives SIGINT (because it is always correctly associated with the real + * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. + * Marc Boucher (marc@CAM.ORG) + */ + if (interrupt) + np->tio.c_lflag |= ISIG; + else + np->tio.c_lflag &= ~ISIG; + /* + * careful, careful catche monkey.. + * never set VMIN and VTIME to zero, if you want blocking io. + * + * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to + * reduce interrupt frequency. But then we would not know how to + * handle read returning 0. jw. + */ + np->tio.c_cc[VMIN] = 1; + np->tio.c_cc[VTIME] = 0; + if (!interrupt || !flow) + np->tio.c_cc[VINTR] = VDISABLE; + np->tio.c_cc[VQUIT] = VDISABLE; + if (flow == 0) + { +#if defined(VSTART) +#if (VSTART < MAXCC) + np->tio.c_cc[VSTART] = VDISABLE; +#endif +#endif /* VSTART */ +#if defined(VSTOP) +#if (VSTOP < MAXCC) + np->tio.c_cc[VSTOP] = VDISABLE; +#endif +#endif /* VSTOP */ + np->tio.c_iflag &= ~IXON; + } +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + np->tio.c_cc[VDISCARD] = VDISABLE; +#endif +#endif /* VDISCARD */ +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + np->tio.c_cc[VLNEXT] = VDISABLE; +#endif +#endif /* VLNEXT */ +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + np->tio.c_cc[VSTATUS] = VDISABLE; +#endif +#endif /* VSTATUS */ +#if defined(VSUSP) +#if (VSUSP < MAXCC) + np->tio.c_cc[VSUSP] = VDISABLE; +#endif +#endif /* VSUSP */ +#if defined(VERASE) +#if (VERASE < MAXCC) + np->tio.c_cc[VERASE] = VDISABLE; +#endif +#endif /* VERASE */ +#if defined(VKILL) +#if (VKILL < MAXCC) + np->tio.c_cc[VKILL] = VDISABLE; +#endif +#endif /* VKILL */ +# ifdef HPUX_LTCHARS_HACK + np->m_ltchars.t_suspc = VDISABLE; + np->m_ltchars.t_dsuspc = VDISABLE; + np->m_ltchars.t_rprntc = VDISABLE; + np->m_ltchars.t_flushc = VDISABLE; + np->m_ltchars.t_werasc = VDISABLE; + np->m_ltchars.t_lnextc = VDISABLE; +# else /* HPUX_LTCHARS_HACK */ +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + np->tio.c_cc[VDSUSP] = VDISABLE; +#endif +#endif /* VDSUSP */ +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + np->tio.c_cc[VREPRINT] = VDISABLE; +#endif +#endif /* VREPRINT */ +#if defined(VWERASE) +#if (VWERASE < MAXCC) + np->tio.c_cc[VWERASE] = VDISABLE; +#endif +#endif /* VWERASE */ +# endif /* HPUX_LTCHARS_HACK */ +#else /* TERMIO || POSIX */ + if (!interrupt || !flow) + np->m_tchars.t_intrc = -1; + np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); + np->m_ttyb.sg_flags |= CBREAK; +# if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS) + np->m_ttyb.sg_flags &= ~CSTYLE; + np->m_ttyb.sg_flags |= CS_8BITS; +# endif + np->m_tchars.t_quitc = -1; + if (flow == 0) + { + np->m_tchars.t_startc = -1; + np->m_tchars.t_stopc = -1; + } + np->m_ltchars.t_suspc = -1; + np->m_ltchars.t_dsuspc = -1; + np->m_ltchars.t_flushc = -1; + np->m_ltchars.t_lnextc = -1; +#endif /* defined(TERMIO) || defined(POSIX) */ +} + +/* operates on display */ +void +SetFlow(on) +int on; +{ + ASSERT(display); + if (D_flow == on) + return; +#if defined(TERMIO) || defined(POSIX) + if (on) + { + D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART]; +#endif +#endif /* VSTART */ +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP]; +#endif +#endif /* VSTOP */ + D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON; + } + else + { + D_NewMode.tio.c_cc[VINTR] = VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = VDISABLE; +#endif +#endif /* VSTART */ +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = VDISABLE; +#endif +#endif /* VSTOP */ + D_NewMode.tio.c_iflag &= ~IXON; + } +# ifdef POSIX + if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio)) +# else + if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0) +# endif + debug1("SetFlow: ioctl errno %d\n", errno); +#else /* POSIX || TERMIO */ + if (on) + { + D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1; + D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc; + D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc; + } + else + { + D_NewMode.m_tchars.t_intrc = -1; + D_NewMode.m_tchars.t_startc = -1; + D_NewMode.m_tchars.t_stopc = -1; + } + if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0) + debug1("SetFlow: ioctl errno %d\n", errno); +#endif /* POSIX || TERMIO */ + D_flow = on; +} + +/* parse commands from opt and modify m */ +int +SttyMode(m, opt) +struct mode *m; +char *opt; +{ + static const char sep[] = " \t:;,"; + + if (!opt) + return 0; + + while (*opt) + { + while (index(sep, *opt)) opt++; + if (*opt >= '0' && *opt <= '9') + { + if (SetBaud(m, atoi(opt), atoi(opt))) + return -1; + } + else if (!strncmp("cs7", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS7; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("cs8", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS8; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("istrip", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= ISTRIP; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("-istrip", opt, 7)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~ISTRIP; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("ixon", opt, 4)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXON; +#else + debug("SttyMode: no ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("-ixon", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXON; +#else + debug("SttyMode: no -ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("ixoff", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXOFF; +#else + m->m_ttyb.sg_flags |= TANDEM; +#endif + } + else if (!strncmp("-ixoff", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXOFF; +#else + m->m_ttyb.sg_flags &= ~TANDEM; +#endif + } + else if (!strncmp("crtscts", opt, 7)) + { +#if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) + m->tio.c_cflag |= CRTSCTS; +#endif + } + else if (!strncmp("-crtscts", opt, 8)) + { +#if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS) + m->tio.c_cflag &= ~CRTSCTS; +#endif + } + else + return -1; + while (*opt && !index(sep, *opt)) opt++; + } + return 0; +} + +/* + * Job control handling + * + * Somehow the ultrix session handling is broken, so use + * the bsdish variant. + */ + +/*ARGSUSED*/ +void +brktty(fd) +int fd; +{ +#if defined(POSIX) && !defined(ultrix) + if (separate_sids) + setsid(); /* will break terminal affiliation */ + /* GNU added for Hurd systems 2001-10-10 */ +# if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__) + ioctl(fd, TIOCSCTTY, (char *)0); +# endif /* BSD && TIOCSCTTY */ +#else /* POSIX */ +# ifdef SYSV + if (separate_sids) + setpgrp(); /* will break terminal affiliation */ +# else /* SYSV */ +# ifdef BSDJOBS + int devtty; + + if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0) + { + if (ioctl(devtty, TIOCNOTTY, (char *)0)) + debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); + close(devtty); + } +# endif /* BSDJOBS */ +# endif /* SYSV */ +#endif /* POSIX */ +} + +int +fgtty(fd) +int fd; +{ +#ifdef BSDJOBS + int mypid; + + mypid = getpid(); + + /* The next lines should be obsolete. Can anybody check if they + * are really needed on the BSD platforms? + * + * this is to avoid the message: + * fgtty: Not a typewriter (25) + */ +# if defined(__osf__) || (BSD >= 199103) || defined(ISC) + if (separate_sids) + setsid(); /* should be already done */ +# ifdef TIOCSCTTY + ioctl(fd, TIOCSCTTY, (char *)0); +# endif +# endif + +# ifdef POSIX + if (separate_sids) + if (tcsetpgrp(fd, mypid)) + { + debug1("fgtty: tcsetpgrp: %d\n", errno); + return -1; + } +# else /* POSIX */ + if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) + debug1("fgtty: TIOSETPGRP: %d\n", errno); +# ifndef SYSV /* Already done in brktty():setpgrp() */ + if (separate_sids) + if (setpgrp(fd, mypid)) + debug1("fgtty: setpgrp: %d\n", errno); +# endif +# endif /* POSIX */ +#endif /* BSDJOBS */ + return 0; +} + +/* + * The alm boards on our sparc center 1000 have a lousy driver. + * We cannot generate long breaks unless we use the most ugly form + * of ioctls. jw. + */ +#ifdef POSIX +int breaktype = 2; +#else /* POSIX */ +# ifdef TCSBRK +int breaktype = 1; +# else +int breaktype = 0; +# endif +#endif /* POSIX */ + +#if defined(sun) && !defined(SVR4) +# define HAVE_SUPER_TCSENDBREAK +#endif + +/* + * type: + * 0: TIOCSBRK / TIOCCBRK + * 1: TCSBRK + * 2: tcsendbreak() + * n: approximate duration in 1/4 seconds. + */ +static void +DoSendBreak(fd, n, type) +int fd, n, type; +{ + switch (type) + { + case 2: /* tcsendbreak() =============================== */ +#ifdef POSIX +# ifdef HAVE_SUPER_TCSENDBREAK + /* There is one rare case that I have tested, where tcsendbreak works + * really great: this was an alm driver that came with SunOS 4.1.3 + * If you have this one, define the above symbol. + * here we can use the second parameter to specify the duration. + */ + debug2("tcsendbreak(fd=%d, %d)\n", fd, n); + if (tcsendbreak(fd, n) < 0) + Msg(errno, "cannot send BREAK (tcsendbreak)"); +# else + /* + * here we hope, that multiple calls to tcsendbreak() can + * be concatenated to form a long break, as we do not know + * what exact interpretation the second parameter has: + * + * - sunos 4: duration in quarter seconds + * - sunos 5: 0 a short break, nonzero a tcdrain() + * - hpux, irix: ignored + * - mot88: duration in milliseconds + * - aix: duration in milliseconds, but 0 is 25 milliseconds. + */ + debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd); + { + int i; + + if (!n) + n++; + for (i = 0; i < n; i++) + if (tcsendbreak(fd, 0) < 0) + { + Msg(errno, "cannot send BREAK (tcsendbreak SVR4)"); + return; + } + } +# endif +#else /* POSIX */ + Msg(0, "tcsendbreak() not available, change breaktype"); +#endif /* POSIX */ + break; + + case 1: /* TCSBRK ======================================= */ +#ifdef TCSBRK + if (!n) + n++; + /* + * Here too, we assume that short breaks can be concatenated to + * perform long breaks. But for SOLARIS, this is not true, of course. + */ + debug2("%d * TCSBRK fd=%d\n", n, fd); + { + int i; + + for (i = 0; i < n; i++) + if (ioctl(fd, TCSBRK, (char *)0) < 0) + { + Msg(errno, "Cannot send BREAK (TCSBRK)"); + return; + } + } +#else /* TCSBRK */ + Msg(0, "TCSBRK not available, change breaktype"); +#endif /* TCSBRK */ + break; + + case 0: /* TIOCSBRK / TIOCCBRK ========================== */ +#if defined(TIOCSBRK) && defined(TIOCCBRK) + /* + * This is very rude. Screen actively celebrates the break. + * But it may be the only save way to issue long breaks. + */ + debug("TIOCSBRK TIOCCBRK\n"); + if (ioctl(fd, TIOCSBRK, (char *)0) < 0) + { + Msg(errno, "Can't send BREAK (TIOCSBRK)"); + return; + } + sleep1000(n ? n * 250 : 250); + if (ioctl(fd, TIOCCBRK, (char *)0) < 0) + { + Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)"); + return; + } +#else /* TIOCSBRK && TIOCCBRK */ + Msg(0, "TIOCSBRK/CBRK not available, change breaktype"); +#endif /* TIOCSBRK && TIOCCBRK */ + break; + + default: /* unknown ========================== */ + Msg(0, "Internal SendBreak error: method %d unknown", type); + } +} + +/* + * Send a break for n * 0.25 seconds. Tty must be PLAIN. + * The longest possible break allowed here is 15 seconds. + */ + +void +SendBreak(wp, n, closeopen) +struct win *wp; +int n, closeopen; +{ + sigret_t (*sigalrm)__P(SIGPROTOARG); + +#ifdef BUILTIN_TELNET + if (wp->w_type == W_TYPE_TELNET) + { + TelBreak(wp); + return; + } +#endif + if (wp->w_type != W_TYPE_PLAIN) + return; + + debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); + +#ifdef POSIX + (void) tcflush(wp->w_ptyfd, TCIOFLUSH); +#else +# ifdef TIOCFLUSH + (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); +# endif /* TIOCFLUSH */ +#endif /* POSIX */ + + if (closeopen) + { + close(wp->w_ptyfd); + sleep1000(n ? n * 250 : 250); + if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1) + { + Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); + return; + } + (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK); + } + else + { + sigalrm = signal(SIGALRM, SigAlrmDummy); + alarm(15); + + DoSendBreak(wp->w_ptyfd, n, breaktype); + + alarm(0); + signal(SIGALRM, sigalrm); + } + debug(" broken.\n"); +} + +/* + * Console grabbing + */ + +#if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux) + +static struct event consredir_ev; +static int consredirfd[2] = {-1, -1}; + +static void +consredir_readev_fn(ev, data) +struct event *ev; +char *data; +{ + char *p, *n, buf[256]; + int l; + + if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0) + { + close(consredirfd[0]); + close(consredirfd[1]); + consredirfd[0] = consredirfd[1] = -1; + evdeq(ev); + return; + } + for (p = n = buf; l > 0; n++, l--) + if (*n == '\n') + { + if (n > p) + WriteString(console_window, p, n - p); + WriteString(console_window, "\r\n", 2); + p = n + 1; + } + if (n > p) + WriteString(console_window, p, n - p); +} + +#endif + +/*ARGSUSED*/ +int +TtyGrabConsole(fd, on, rc_name) +int fd, on; +char *rc_name; +{ +#if defined(TIOCCONS) && !defined(linux) + struct display *d; + int ret = 0; + int sfd = -1; + + if (on < 0) + return 0; /* pty close will ungrab */ + if (on) + { + if (displays == 0) + { + Msg(0, "I need a display"); + return -1; + } + for (d = displays; d; d = d->d_next) + if (strcmp(d->d_usertty, "/dev/console") == 0) + break; + if (d) + { + Msg(0, "too dangerous - screen is running on /dev/console"); + return -1; + } + } + + if (!on) + { + char *slave; + if ((fd = OpenPTY(&slave)) < 0) + { + Msg(errno, "%s: could not open detach pty master", rc_name); + return -1; + } + if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0) + { + Msg(errno, "%s: could not open detach pty slave", rc_name); + close(fd); + return -1; + } + } + if (UserContext() == 1) + UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); + ret = UserStatus(); + if (ret) + Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); + if (!on) + { + close(sfd); + close(fd); + } + return ret; + +#else +# if defined(SRIOCSREDIR) || defined(linux) + struct display *d; +# ifdef SRIOCSREDIR + int cfd; +# else + struct mode new1, new2; + char *slave; +# endif + + if (on > 0) + { + if (displays == 0) + { + Msg(0, "I need a display"); + return -1; + } + for (d = displays; d; d = d->d_next) + if (strcmp(d->d_usertty, "/dev/console") == 0) + break; + if (d) + { + Msg(0, "too dangerous - screen is running on /dev/console"); + return -1; + } + } + if (consredirfd[0] >= 0) + { + evdeq(&consredir_ev); + close(consredirfd[0]); + close(consredirfd[1]); + consredirfd[0] = consredirfd[1] = -1; + } + if (on <= 0) + return 0; +# ifdef SRIOCSREDIR + if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1) + { + Msg(errno, "/dev/console"); + return -1; + } + if (pipe(consredirfd)) + { + Msg(errno, "pipe"); + close(cfd); + consredirfd[0] = consredirfd[1] = -1; + return -1; + } + if (ioctl(cfd, SRIOCSREDIR, consredirfd[1])) + { + Msg(errno, "SRIOCSREDIR ioctl"); + close(cfd); + close(consredirfd[0]); + close(consredirfd[1]); + consredirfd[0] = consredirfd[1] = -1; + return -1; + } + close(cfd); +# else + /* special linux workaround for a too restrictive kernel */ + if ((consredirfd[0] = OpenPTY(&slave)) < 0) + { + Msg(errno, "%s: could not open detach pty master", rc_name); + return -1; + } + if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0) + { + Msg(errno, "%s: could not open detach pty slave", rc_name); + close(consredirfd[0]); + return -1; + } + InitTTY(&new1, 0); + SetMode(&new1, &new2, 0, 0); + SetTTY(consredirfd[1], &new2); + if (UserContext() == 1) + UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on)); + if (UserStatus()) + { + Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); + close(consredirfd[0]); + close(consredirfd[1]); + return -1; + } +# endif + consredir_ev.fd = consredirfd[0]; + consredir_ev.type = EV_READ; + consredir_ev.handler = consredir_readev_fn; + evenq(&consredir_ev); + return 0; +# else + if (on > 0) + Msg(0, "%s: don't know how to grab the console", rc_name); + return -1; +# endif +#endif +} + +/* + * Read modem control lines of a physical tty and write them to buf + * in a readable format. + * Will not write more than 256 characters to buf. + * Returns buf; + */ +char * +TtyGetModemStatus(fd, buf) +int fd; +char *buf; +{ + char *p = buf; +#ifdef TIOCGSOFTCAR + unsigned int softcar; +#endif +#if defined(TIOCMGET) || defined(TIOCMODG) + unsigned int mflags; +#else +# ifdef MCGETA + /* this is yet another interface, found on hpux. grrr */ + mflag mflags; +#if defined(MDTR) +# define TIOCM_DTR MDTR +#endif /* MDTR */ +#if defined(MRTS) +# define TIOCM_RTS MRTS +#endif /* MRTS */ +#if defined(MDSR) +# define TIOCM_DSR MDSR +#endif /* MDSR */ +#if defined(MDCD) +# define TIOCM_CAR MDCD +#endif /* MDCD */ +#if defined(MRI) +# define TIOCM_RNG MRI +#endif /* MRI */ +#if defined(MCTS) +# define TIOCM_CTS MCTS +#endif /* MCTS */ +# endif +#endif +#if defined(CLOCAL) || defined(CRTSCTS) + struct mode mtio; /* screen.h */ +#endif +#if defined(CRTSCTS) || defined(TIOCM_CTS) + int rtscts; +#endif + int clocal; + +#if defined(CLOCAL) || defined(CRTSCTS) + GetTTY(fd, &mtio); +#endif + clocal = 0; +#ifdef CLOCAL + if (mtio.tio.c_cflag & CLOCAL) + { + clocal = 1; + *p++ = '{'; + } +#endif + +#ifdef TIOCM_CTS +# ifdef CRTSCTS + if (!(mtio.tio.c_cflag & CRTSCTS)) + rtscts = 0; + else +# endif /* CRTSCTS */ + rtscts = 1; +#endif /* TIOCM_CTS */ + +#ifdef TIOCGSOFTCAR + if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0) + softcar = 0; +#endif + +#if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA) +# ifdef TIOCMGET + if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0) +# else +# ifdef TIOCMODG + if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0) +# else + if (ioctl(fd, MCGETA, &mflags) < 0) +# endif +# endif + { +#ifdef TIOCGSOFTCAR + sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD"); +#else + sprintf(p, "NO-TTY?"); +#endif + p += strlen(p); + } + else + { + char *s; +# ifdef FANCY_MODEM +# ifdef TIOCM_LE + if (!(mflags & TIOCM_LE)) + for (s = "!LE "; *s; *p++ = *s++); +# endif +# endif /* FANCY_MODEM */ + +# ifdef TIOCM_RTS + s = "!RTS "; if (mflags & TIOCM_RTS) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_CTS + s = "!CTS "; + if (!rtscts) + { + *p++ = '('; + s = "!CTS) "; + } + if (mflags & TIOCM_CTS) s++; + while (*s) *p++ = *s++; +# endif + +# ifdef TIOCM_DTR + s = "!DTR "; if (mflags & TIOCM_DTR) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_DSR + s = "!DSR "; if (mflags & TIOCM_DSR) s++; + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_CD) || defined(TIOCM_CAR) + s = "!CD "; +# ifdef TIOCGSOFTCAR + if (softcar) + { + *p++ = '('; + s = "!CD) "; + } +# endif +# ifdef TIOCM_CD + if (mflags & TIOCM_CD) s++; +# else + if (mflags & TIOCM_CAR) s++; +# endif + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_RI) || defined(TIOCM_RNG) +# ifdef TIOCM_RI + if (mflags & TIOCM_RI) +# else + if (mflags & TIOCM_RNG) +# endif + for (s = "RI "; *s; *p++ = *s++); +# endif +# ifdef FANCY_MODEM +# ifdef TIOCM_ST + s = "!ST "; if (mflags & TIOCM_ST) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_SR + s = "!SR "; if (mflags & TIOCM_SR) s++; + while (*s) *p++ = *s++; +# endif +# endif /* FANCY_MODEM */ + if (p > buf && p[-1] == ' ') + p--; + *p = '\0'; + } +#else +# ifdef TIOCGSOFTCAR + sprintf(p, " %s", softcar ? "(CD)", "CD"); + p += strlen(p); +# endif +#endif + if (clocal) + *p++ = '}'; + *p = '\0'; + return buf; +} + +/* + * Old bsd-ish machines may not have any of the baudrate B... symbols. + * We hope to detect them here, so that the btable[] below always has + * many entries. + */ +#ifndef POSIX +# ifndef TERMIO +# if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300) +#if !defined(B0) +#define B0 0 +#endif /* B0 */ +#if !defined(B50) +#define B50 1 +#endif /* B50 */ +#if !defined(B75) +#define B75 2 +#endif /* B75 */ +#if !defined(B110) +#define B110 3 +#endif /* B110 */ +#if !defined(B134) +#define B134 4 +#endif /* B134 */ +#if !defined(B150) +#define B150 5 +#endif /* B150 */ +#if !defined(B200) +#define B200 6 +#endif /* B200 */ +#if !defined(B300) +#define B300 7 +#endif /* B300 */ +#if !defined(B600) +#define B600 8 +#endif /* B600 */ +#if !defined(B1200) +#define B1200 9 +#endif /* B1200 */ +#if !defined(B1800) +#define B1800 10 +#endif /* B1800 */ +#if !defined(B2400) +#define B2400 11 +#endif /* B2400 */ +#if !defined(B4800) +#define B4800 12 +#endif /* B4800 */ +#if !defined(B9600) +#define B9600 13 +#endif /* B9600 */ +#if !defined(EXTA) +#define EXTA 14 +#endif /* EXTA */ +#if !defined(EXTB) +#define EXTB 15 +#endif /* EXTB */ +# endif +# endif +#endif + +/* + * On hpux, idx and sym will be different. + * Rumor has it that, we need idx in D_dospeed to make tputs + * padding correct. + * Frequently used entries come first. + */ +static struct baud_values btable[] = +{ +#if defined(B9600) + { 13, 9600, B9600 }, +#endif /* B9600 */ +#if defined(B19200) + { 14, 19200, B19200 }, +#endif /* B19200 */ +#if defined(EXTA) + { 14, 19200, EXTA }, +#endif /* EXTA */ +#if defined(B38400) + { 15, 38400, B38400 }, +#endif /* B38400 */ +#if defined(EXTB) + { 15, 38400, EXTB }, +#endif /* EXTB */ +#if defined(B57600) + { 16, 57600, B57600 }, +#endif /* B57600 */ +#if defined(B115200) + { 17, 115200, B115200 }, +#endif /* B115200 */ +#if defined(B230400) + { 18, 230400, B230400 }, +#endif /* B230400 */ +#if defined(B460800) + { 19, 460800, B460800 }, +#endif /* B460800 */ +#if defined(B7200) + { 13, 7200, B7200 }, +#endif /* B7200 */ +#if defined(B4800) + { 12, 4800, B4800 }, +#endif /* B4800 */ +#if defined(B3600) + { 12, 3600, B3600 }, +#endif /* B3600 */ +#if defined(B2400) + { 11, 2400, B2400 }, +#endif /* B2400 */ +#if defined(B1800) + { 10, 1800, B1800 }, +#endif /* B1800 */ +#if defined(B1200) + { 9, 1200, B1200 }, +#endif /* B1200 */ +#if defined(B900) + { 9, 900, B900 }, +#endif /* B900 */ +#if defined(B600) + { 8, 600, B600 }, +#endif /* B600 */ +#if defined(B300) + { 7, 300, B300 }, +#endif /* B300 */ +#if defined(B200) + { 6, 200, B200 }, +#endif /* B200 */ +#if defined(B150) + { 5, 150, B150 }, +#endif /* B150 */ +#if defined(B134) + { 4, 134, B134 }, +#endif /* B134 */ +#if defined(B110) + { 3, 110, B110 }, +#endif /* B110 */ +#if defined(B75) + { 2, 75, B75 }, +#endif /* B75 */ +#if defined(B50) + { 1, 50, B50 }, +#endif /* B50 */ +#if defined(B0) + { 0, 0, B0 }, +#endif /* B0 */ + { -1, -1, -1 } +}; + +/* + * baud may either be a bits-per-second value or a symbolic + * value as returned by cfget?speed() + */ +struct baud_values * +lookup_baud(baud) +int baud; +{ + struct baud_values *p; + + for (p = btable; p->idx >= 0; p++) + if (baud == p->bps || baud == p->sym) + return p; + return NULL; +} + +/* + * change the baud rate in a mode structure. + * ibaud and obaud are given in bit/second, or at your option as + * termio B... symbols as defined in e.g. suns sys/ttydev.h + * -1 means don't change. + */ +int +SetBaud(m, ibaud, obaud) +struct mode *m; +int ibaud, obaud; +{ + struct baud_values *ip, *op; + + if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) || + (!(op = lookup_baud(obaud)) && obaud != -1)) + return -1; + +#ifdef POSIX + if (ip) cfsetispeed(&m->tio, ip->sym); + if (op) cfsetospeed(&m->tio, op->sym); +#else /* POSIX */ +# ifdef TERMIO + if (ip) + { +# ifdef IBSHIFT + m->tio.c_cflag &= ~(CBAUD << IBSHIFT); + m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT; +# else /* IBSHIFT */ + if (ibaud != obaud) + return -1; +# endif /* IBSHIFT */ + } + if (op) + { + m->tio.c_cflag &= ~CBAUD; + m->tio.c_cflag |= op->sym & CBAUD; + } +# else /* TERMIO */ + if (ip) m->m_ttyb.sg_ispeed = ip->idx; + if (op) m->m_ttyb.sg_ospeed = op->idx; +# endif /* TERMIO */ +#endif /* POSIX */ + return 0; +} + +/* + * Write out the mode struct in a readable form + */ + +#ifdef DEBUG +void +DebugTTY(m) +struct mode *m; +{ + int i; + +#ifdef POSIX + debug("struct termios tio:\n"); + debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag); + debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag); + debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag); + debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag); + debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio)); + debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio)); + for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) + { + debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); + } +# ifdef HPUX_LTCHARS_HACK + debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); + debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); + debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); + debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); + debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); + debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); +# endif /* HPUX_LTCHARS_HACK */ +#else /* POSIX */ +# ifdef TERMIO + debug("struct termio tio:\n"); + debug1("c_iflag = %04o\n", m->tio.c_iflag); + debug1("c_oflag = %04o\n", m->tio.c_oflag); + debug1("c_cflag = %04o\n", m->tio.c_cflag); + debug1("c_lflag = %04o\n", m->tio.c_lflag); + for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) + { + debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); + } +# else /* TERMIO */ + debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); + debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); + debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); + debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); + debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); + debug1("intrc = %#02x\n", m->m_tchars.t_intrc); + debug1("quitc = %#02x\n", m->m_tchars.t_quitc); + debug1("startc = %#02x\n", m->m_tchars.t_startc); + debug1("stopc = %#02x\n", m->m_tchars.t_stopc); + debug1("eofc = %#02x\n", m->m_tchars.t_eofc); + debug1("brkc = %#02x\n", m->m_tchars.t_brkc); + debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); + debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); + debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); + debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); + debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); + debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); + debug1("ldisc = %d\n", m->m_ldisc); + debug1("lmode = %#x\n", m->m_lmode); +# endif /* TERMIO */ +#endif /* POSIX */ +} +#endif /* DEBUG */ |