diff options
Diffstat (limited to 'tty.c.dist')
-rw-r--r-- | tty.c.dist | 1333 |
1 files changed, 1084 insertions, 249 deletions
@@ -42,6 +42,9 @@ RCS_ID("$Id: tty.sh,v 1.13 1994/05/31 12:33:17 mlschroe Exp $ FAU") # include <sys/ttold.h> /* needed for TIOCEXCL */ # endif #endif +#ifdef __hpux +# include <sys/modem.h> +#endif #ifdef ISC # include <sys/tty.h> @@ -50,11 +53,27 @@ RCS_ID("$Id: tty.sh,v 1.13 1994/05/31 12:33:17 mlschroe Exp $ FAU") #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) +extern struct win *console_window; +static void consredir_readev_fn __P((struct event *, char *)); +#endif + +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 @@ -67,6 +86,18 @@ extern int iflag; #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 { @@ -75,27 +106,41 @@ SigAlrmDummy SIGDEFARG } /* - * Carefully open a charcter device. Not used to open ttys. + * 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) -char *line; +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, 0)) == -1) + if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) { - Msg(errno, "Cannot open line '%s' for R/W", line); + 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; } -#ifdef I_POP + 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) ; @@ -109,7 +154,7 @@ char *line; errno = 0; if (ioctl(f, TIOCEXCL, (char *) 0) < 0) Msg(errno, "%s: ioctl TIOCEXCL failed", line); - debug3("%d %d %d\n", (int)getuid(), (int)geteuid(), (int)getpid()); + debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* @@ -119,22 +164,18 @@ char *line; if (display) { debug1("OpenTTY: using mode of display for %s\n", line); - SetTTY(f, &D_NewMode); -#ifdef DEBUG - DebugTTY(&D_NewMode); -#endif + Mode = D_NewMode; } else -#endif - { - struct mode Mode; - - InitTTY(&Mode, TTY_FLAG_PLAIN); +#endif + InitTTY(&Mode, W_TYPE_PLAIN); + + SttyMode(&Mode, opt); #ifdef DEBUG - DebugTTY(&Mode); + DebugTTY(&Mode); #endif - SetTTY(f, &Mode); - } + SetTTY(f, &Mode); + brktty(f); alarm(0); signal(SIGALRM, sigalrm); @@ -152,7 +193,7 @@ int intrc, origintrc = VDISABLE; /* display? */ #else int intrc, origintrc = -1; /* display? */ #endif -static startc, stopc; /* display? */ +static int startc, stopc; /* display? */ void @@ -165,151 +206,196 @@ int ttyflag; /* struct termios tio * defaults, as seen on SunOS 4.1.3 */ - debug1("InitTTY: POSIX: termios defaults a la SunOS 4.1.3 (%d)\n", ttyflag); + debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); #if defined(BRKINT) - m->tio.c_iflag |= BRKINT; + m->tio.c_iflag |= BRKINT; #endif /* BRKINT */ #if defined(IGNPAR) - m->tio.c_iflag |= IGNPAR; + m->tio.c_iflag |= IGNPAR; #endif /* IGNPAR */ -#if defined(ISTRIP) - m->tio.c_iflag |= ISTRIP; -#endif /* ISTRIP */ +/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ #if defined(IXON) - m->tio.c_iflag |= IXON; + m->tio.c_iflag |= IXON; #endif /* IXON */ -#if defined(IMAXBEL) - m->tio.c_iflag |= IMAXBEL; -#endif /* IMAXBEL */ +/* 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; + m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #if defined(ONLCR) - m->tio.c_oflag |= ONLCR; + m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) - m->tio.c_oflag |= TAB3; + m->tio.c_oflag |= TAB3; #endif /* TAB3 */ -#if defined(PARENB) - m->tio.c_cflag |= PARENB; -#endif /* PARENB */ +#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; + 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) - m->tio.c_cflag |= B9600; + cfsetospeed(&m->tio, B9600); #endif /* B9600 */ +#if defined(B9600) + cfsetispeed(&m->tio, B9600); +#endif /* B9600 */ + #if defined(CS8) - m->tio.c_cflag |= CS8; + m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(CREAD) - m->tio.c_cflag |= CREAD; + m->tio.c_cflag |= CREAD; #endif /* CREAD */ -#if defined(IBSHIFT) && defined(B9600) - m->tio.c_cflag |= B9600 << IBSHIFT; -#endif /* IBSHIFT) && defined(B9600 */ -/* IF{CLOCAL} m->tio.c_cflag |= CLOCAL; */ +#if defined(CLOCAL) + m->tio.c_cflag |= CLOCAL; +#endif /* CLOCAL */ #if defined(ECHOCTL) - m->tio.c_lflag |= ECHOCTL; + m->tio.c_lflag |= ECHOCTL; #endif /* ECHOCTL */ #if defined(ECHOKE) - m->tio.c_lflag |= ECHOKE; + m->tio.c_lflag |= ECHOKE; #endif /* ECHOKE */ if (!ttyflag) { #if defined(ISIG) - m->tio.c_lflag |= ISIG; + m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) - m->tio.c_lflag |= ICANON; + m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) - m->tio.c_lflag |= ECHO; + m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) - m->tio.c_lflag |= ECHOE; + m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) - m->tio.c_lflag |= ECHOK; + m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ #if defined(IEXTEN) - m->tio.c_lflag |= IEXTEN; + m->tio.c_lflag |= IEXTEN; #endif /* IEXTEN */ -#if defined(VINTR) && VINTR < MAXCC - m->tio.c_cc[VINTR] = Ctrl('C'); +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif #endif /* VINTR */ -#if defined(VQUIT) && VQUIT < MAXCC - m->tio.c_cc[VQUIT] = Ctrl('\\'); +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif #endif /* VQUIT */ -#if defined(VERASE) && VERASE < MAXCC - m->tio.c_cc[VERASE] = 0x7f; /* DEL */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0x7f; /* DEL */ +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - m->tio.c_cc[VKILL] = Ctrl('H'); +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif #endif /* VKILL */ -#if defined(VEOF) && VEOF < MAXCC - m->tio.c_cc[VEOF] = Ctrl('D'); +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif #endif /* VEOF */ -#if defined(VEOL) && VEOL < MAXCC - m->tio.c_cc[VEOL] = 0000; +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0000; +#endif #endif /* VEOL */ -#if defined(VEOL2) && VEOL2 < MAXCC - m->tio.c_cc[VEOL2] = 0000; +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0000; +#endif #endif /* VEOL2 */ -#if defined(VSWTCH) && VSWTCH < MAXCC - m->tio.c_cc[VSWTCH] = 0000; +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif #endif /* VSWTCH */ -#if defined(VSTART) && VSTART < MAXCC - m->tio.c_cc[VSTART] = Ctrl('Q'); +#if defined(VSTART) +#if (VSTART < MAXCC) + m->tio.c_cc[VSTART] = Ctrl('Q'); +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - m->tio.c_cc[VSTOP] = Ctrl('S'); +#if defined(VSTOP) +#if (VSTOP < MAXCC) + m->tio.c_cc[VSTOP] = Ctrl('S'); +#endif #endif /* VSTOP */ -#if defined(VSUSP) && VSUSP < MAXCC - m->tio.c_cc[VSUSP] = Ctrl('Z'); +#if defined(VSUSP) +#if (VSUSP < MAXCC) + m->tio.c_cc[VSUSP] = Ctrl('Z'); +#endif #endif /* VSUSP */ -#if defined(VDSUSP) && VDSUSP < MAXCC - m->tio.c_cc[VDSUSP] = Ctrl('Y'); +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + m->tio.c_cc[VDSUSP] = Ctrl('Y'); +#endif #endif /* VDSUSP */ -#if defined(VREPRINT) && VREPRINT < MAXCC - m->tio.c_cc[VREPRINT] = Ctrl('R'); +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + m->tio.c_cc[VREPRINT] = Ctrl('R'); +#endif #endif /* VREPRINT */ -#if defined(VDISCARD) && VDISCARD < MAXCC - m->tio.c_cc[VDISCARD] = Ctrl('O'); +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + m->tio.c_cc[VDISCARD] = Ctrl('O'); +#endif #endif /* VDISCARD */ -#if defined(VWERASE) && VWERASE < MAXCC - m->tio.c_cc[VWERASE] = Ctrl('W'); +#if defined(VWERASE) +#if (VWERASE < MAXCC) + m->tio.c_cc[VWERASE] = Ctrl('W'); +#endif #endif /* VWERASE */ -#if defined(VLNEXT) && VLNEXT < MAXCC - m->tio.c_cc[VLNEXT] = Ctrl('V'); +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + m->tio.c_cc[VLNEXT] = Ctrl('V'); +#endif #endif /* VLNEXT */ -#if defined(VSTATUS) && VSTATUS < MAXCC - m->tio.c_cc[VSTATUS] = Ctrl('T'); +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + m->tio.c_cc[VSTATUS] = Ctrl('T'); +#endif #endif /* VSTATUS */ if (ttyflag) { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; } -# ifdef hpux + +# 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 */ +# endif /* HPUX_LTCHARS_HACK */ #else /* POSIX */ @@ -323,87 +409,109 @@ int ttyflag; * local: enable signals, erase/kill processing, echo on. */ #if defined(ISTRIP) - m->tio.c_iflag |= ISTRIP; + m->tio.c_iflag |= ISTRIP; #endif /* ISTRIP */ #if defined(IXON) - m->tio.c_iflag |= IXON; + m->tio.c_iflag |= IXON; #endif /* IXON */ #if defined(OPOST) - m->tio.c_oflag |= OPOST; + m->tio.c_oflag |= OPOST; #endif /* OPOST */ if (!ttyflag) /* may not even be good for ptys.. */ { #if defined(ICRNL) - m->tio.c_iflag |= ICRNL; + m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #if defined(ONLCR) - m->tio.c_oflag |= ONLCR; + m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) - m->tio.c_oflag |= TAB3; + m->tio.c_oflag |= TAB3; #endif /* TAB3 */ } +#ifdef __bsdi__ + )-: cannot handle BSDI without POSIX +#else #if defined(B9600) - m->tio.c_cflag = B9600; + m->tio.c_cflag = B9600; #endif /* B9600 */ +#endif #if defined(CS8) - m->tio.c_cflag |= CS8; + m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(CREAD) - m->tio.c_cflag |= CREAD; + m->tio.c_cflag |= CREAD; #endif /* CREAD */ if (!ttyflag) { #if defined(ISIG) - m->tio.c_lflag |= ISIG; + m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) - m->tio.c_lflag |= ICANON; + m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) - m->tio.c_lflag |= ECHO; + m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) - m->tio.c_lflag |= ECHOE; + m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) - m->tio.c_lflag |= ECHOK; + m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ -#if defined(VINTR) && VINTR < MAXCC - m->tio.c_cc[VINTR] = Ctrl('C'); +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif #endif /* VINTR */ -#if defined(VQUIT) && VQUIT < MAXCC - m->tio.c_cc[VQUIT] = Ctrl('\\'); +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif #endif /* VQUIT */ -#if defined(VERASE) && VERASE < MAXCC - m->tio.c_cc[VERASE] = 0177; /* DEL */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0177; /* DEL */ +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - m->tio.c_cc[VKILL] = Ctrl('H'); +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif #endif /* VKILL */ -#if defined(VEOF) && VEOF < MAXCC - m->tio.c_cc[VEOF] = Ctrl('D'); +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif #endif /* VEOF */ -#if defined(VEOL) && VEOL < MAXCC - m->tio.c_cc[VEOL] = 0377; +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0377; +#endif #endif /* VEOL */ -#if defined(VEOL2) && VEOL2 < MAXCC - m->tio.c_cc[VEOL2] = 0377; +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0377; +#endif #endif /* VEOL2 */ -#if defined(VSWTCH) && VSWTCH < MAXCC - m->tio.c_cc[VSWTCH] = 0000; +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif #endif /* VSWTCH */ + if (ttyflag) - { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; - } + { + 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; @@ -413,13 +521,13 @@ int ttyflag; if (!ttyflag) m->m_ttyb.sg_flags = CRMOD | ECHO #if defined(ANYP) - | ANYP + | ANYP #endif /* ANYP */ ; else m->m_ttyb.sg_flags = CBREAK #if defined(ANYP) - | ANYP + | ANYP #endif /* ANYP */ ; @@ -438,33 +546,33 @@ int ttyflag; m->m_ltchars.t_lnextc = Ctrl('V'); #if defined(NTTYDISC) - m->m_ldisc = NTTYDISC; + m->m_ldisc = NTTYDISC; #endif /* NTTYDISC */ m->m_lmode = 0 #if defined(LDECCTQ) - | LDECCTQ + | LDECCTQ #endif /* LDECCTQ */ #if defined(LCTLECH) - | LCTLECH + | LCTLECH #endif /* LCTLECH */ #if defined(LPASS8) - | LPASS8 + | LPASS8 #endif /* LPASS8 */ #if defined(LCRTKIL) - | LCRTKIL + | LCRTKIL #endif /* LCRTKIL */ #if defined(LCRTERA) - | LCRTERA + | LCRTERA #endif /* LCRTERA */ #if defined(LCRTBS) - | LCRTBS + | LCRTBS #endif /* LCRTBS */ -; + ; # endif /* TERMIO */ #endif /* POSIX */ -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; @@ -479,7 +587,7 @@ struct mode *mp; errno = 0; #ifdef POSIX tcsetattr(fd, TCSADRAIN, &mp->tio); -# ifdef hpux +# ifdef HPUX_LTCHARS_HACK ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); # endif #else @@ -502,7 +610,7 @@ struct mode *mp; ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif @@ -518,7 +626,7 @@ struct mode *mp; errno = 0; #ifdef POSIX tcgetattr(fd, &mp->tio); -# ifdef hpux +# ifdef HPUX_LTCHARS_HACK ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); # endif #else @@ -546,7 +654,7 @@ struct mode *mp; ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif @@ -554,9 +662,13 @@ struct mode *mp; Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } +/* + * needs interrupt = iflag and flow = d->d_flow + */ void -SetMode(op, np) +SetMode(op, np, flow, interrupt) struct mode *op, *np; +int flow, interrupt; { *np = *op; @@ -567,17 +679,21 @@ struct mode *op, *np; np->tio.c_line = 0; # endif #if defined(ICRNL) - np->tio.c_iflag &= ~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; + 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; + np->tio.c_lflag &= ~IEXTEN; #endif /* IEXTEN */ /* @@ -589,23 +705,31 @@ struct mode *op, *np; * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ - if (iflag) + 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 defined(VSTART) && VSTART < MAXCC - startc = op->tio.c_cc[VSTART]; +#if defined(VSTART) +#if (VSTART < MAXCC) + startc = op->tio.c_cc[VSTART]; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - stopc = op->tio.c_cc[VSTOP]; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + stopc = op->tio.c_cc[VSTOP]; +#endif #endif /* VSTOP */ - if (iflag) + if (interrupt) origintrc = intrc = op->tio.c_cc[VINTR]; else { @@ -613,57 +737,79 @@ struct mode *op, *np; intrc = np->tio.c_cc[VINTR] = VDISABLE; } np->tio.c_cc[VQUIT] = VDISABLE; - if (D_flow == 0) + if (flow == 0) { np->tio.c_cc[VINTR] = VDISABLE; -#if defined(VSTART) && VSTART < MAXCC - np->tio.c_cc[VSTART] = VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + np->tio.c_cc[VSTART] = VDISABLE; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - np->tio.c_cc[VSTOP] = VDISABLE; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + np->tio.c_cc[VSTOP] = VDISABLE; +#endif #endif /* VSTOP */ np->tio.c_iflag &= ~IXON; } -#if defined(VDISCARD) && VDISCARD < MAXCC - np->tio.c_cc[VDISCARD] = VDISABLE; +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + np->tio.c_cc[VDISCARD] = VDISABLE; +#endif #endif /* VDISCARD */ -#if defined(VLNEXT) && VLNEXT < MAXCC - np->tio.c_cc[VLNEXT] = VDISABLE; +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + np->tio.c_cc[VLNEXT] = VDISABLE; +#endif #endif /* VLNEXT */ -#if defined(VSTATUS) && VSTATUS < MAXCC - np->tio.c_cc[VSTATUS] = VDISABLE; +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + np->tio.c_cc[VSTATUS] = VDISABLE; +#endif #endif /* VSTATUS */ -#if defined(VSUSP) && VSUSP < MAXCC - np->tio.c_cc[VSUSP] = VDISABLE; +#if defined(VSUSP) +#if (VSUSP < MAXCC) + np->tio.c_cc[VSUSP] = VDISABLE; +#endif #endif /* VSUSP */ -#if defined(VERASE) && VERASE < MAXCC - np->tio.c_cc[VERASE] = VDISABLE; +#if defined(VERASE) +#if (VERASE < MAXCC) + np->tio.c_cc[VERASE] = VDISABLE; +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - np->tio.c_cc[VKILL] = VDISABLE; +#if defined(VKILL) +#if (VKILL < MAXCC) + np->tio.c_cc[VKILL] = VDISABLE; +#endif #endif /* VKILL */ -# ifdef hpux +# 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 */ -#if defined(VDSUSP) && VDSUSP < MAXCC - np->tio.c_cc[VDSUSP] = VDISABLE; +# else /* HPUX_LTCHARS_HACK */ +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + np->tio.c_cc[VDSUSP] = VDISABLE; +#endif #endif /* VDSUSP */ -#if defined(VREPRINT) && VREPRINT < MAXCC - np->tio.c_cc[VREPRINT] = VDISABLE; +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + np->tio.c_cc[VREPRINT] = VDISABLE; +#endif #endif /* VREPRINT */ -#if defined(VWERASE) && VWERASE < MAXCC - np->tio.c_cc[VWERASE] = VDISABLE; +#if defined(VWERASE) +#if (VWERASE < MAXCC) + np->tio.c_cc[VWERASE] = VDISABLE; +#endif #endif /* VWERASE */ -# endif /* hpux */ +# endif /* HPUX_LTCHARS_HACK */ #else /* TERMIO || POSIX */ startc = op->m_tchars.t_startc; stopc = op->m_tchars.t_stopc; - if (iflag) + if (interrupt) origintrc = intrc = op->m_tchars.t_intrc; else { @@ -677,7 +823,7 @@ struct mode *op, *np; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; - if (D_flow == 0) + if (flow == 0) { np->m_tchars.t_intrc = -1; np->m_tchars.t_startc = -1; @@ -690,6 +836,7 @@ struct mode *op, *np; #endif /* defined(TERMIO) || defined(POSIX) */ } +/* operates on display */ void SetFlow(on) int on; @@ -701,22 +848,30 @@ int on; if (on) { D_NewMode.tio.c_cc[VINTR] = intrc; -#if defined(VSTART) && VSTART < MAXCC - D_NewMode.tio.c_cc[VSTART] = startc; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = startc; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - D_NewMode.tio.c_cc[VSTOP] = stopc; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = stopc; +#endif #endif /* VSTOP */ D_NewMode.tio.c_iflag |= IXON; } else { D_NewMode.tio.c_cc[VINTR] = VDISABLE; -#if defined(VSTART) && VSTART < MAXCC - D_NewMode.tio.c_cc[VSTART] = VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = VDISABLE; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - D_NewMode.tio.c_cc[VSTOP] = VDISABLE; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = VDISABLE; +#endif #endif /* VSTOP */ D_NewMode.tio.c_iflag &= ~IXON; } @@ -745,6 +900,97 @@ int on; 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 + return -1; + while (*opt && !index(sep, *opt)) opt++; + } + return 0; +} /* * Job control handling @@ -792,6 +1038,9 @@ int fd; /* 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) setsid(); /* should be already done */ @@ -818,19 +1067,154 @@ int fd; 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; + + 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) +void +SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { - if ((wp->w_t.flags & TTY_FLAG_PLAIN) == 0) + 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 @@ -838,11 +1222,12 @@ int n, closeopen; (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); # endif /* TIOCFLUSH */ #endif /* POSIX */ + if (closeopen) { close(wp->w_ptyfd); - sleep((n + 3) / 4); - if ((wp->w_ptyfd = OpenTTY(wp->w_tty)) < 1) + 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; @@ -851,56 +1236,56 @@ int n, closeopen; } else { -#ifdef POSIX - debug("tcsendbreak\n"); - if (tcsendbreak(wp->w_ptyfd, n) < 0) - { - Msg(errno, "cannot send BREAK"); - return; - } -#else - if (!n) - n++; -# ifdef TCSBRK - debug("TCSBRK\n"); - { - int i; - for (i = 0; i < n; i++) - if (ioctl(wp->w_ptyfd, TCSBRK, (char *)0) < 0) - { - Msg(errno, "Cannot send BREAK"); - return; - } - } -# else /* TCSBRK */ -# if defined(TIOCSBRK) && defined(TIOCCBRK) - debug("TIOCSBRK TIOCCBRK\n"); - if (ioctl(wp->w_ptyfd, TIOCSBRK, (char *)0) < 0) - { - Msg(errno, "Can't send BREAK"); - return; - } - sleep((n + 3) / 4); - if (ioctl(wp->w_ptyfd, TIOCCBRK, (char *)0) < 0) - { - Msg(errno, "BREAK stuck!!! -- HELP!"); - return; - } -# else /* TIOCSBRK && TIOCCBRK */ - Msg(0, "Break not simulated yet"); - return; -# endif /* TIOCSBRK && TIOCCBRK */ -# endif /* TCSBRK */ -#endif /* POSIX */ - debug(" broken\n"); + 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) + +struct event consredir_ev; +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) @@ -908,12 +1293,32 @@ int fd, on; char *rc_name; { #ifdef TIOCCONS - char *slave; - int sfd = -1, ret = 0; struct display *d; + int ret = 0; + int sfd = -1; + + if (on < 0) + return; /* 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); @@ -926,7 +1331,24 @@ char *rc_name; return -1; } } - else + 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 +# ifdef SRIOCSREDIR + struct display *d; + int cfd; + + if (on > 0) { if (displays == 0) { @@ -942,23 +1364,434 @@ char *rc_name; 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) + if (consredirfd[0] >= 0) { - close(sfd); - close(fd); + evdeq(&consredir_ev); + close(consredirfd[0]); + close(consredirfd[1]); + consredirfd[0] = consredirfd[1] = -1; } - return ret; -#else /* TIOCCONS */ - Msg(0, "%s: no TIOCCONS on this machine", rc_name); + if (on <= 0) + return 0; + 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; + } + + consredir_ev.fd = consredirfd[0]; + consredir_ev.type = EV_READ; + consredir_ev.handler = consredir_readev_fn; + evenq(&consredir_ev); + close(cfd); + return 0; +# else + if (on > 0) + Msg(0, "%s: don't know how to grab the console", rc_name); return -1; -#endif /* TIOCCONS */ +# 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 +#ifdef CLOCAL + if (mtio.tio.c_cflag & CLOCAL) + { + clocal = 1; + *p++ = '{'; + } + else +#endif + clocal = 0; + +#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, TIOCMODG, &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 + 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) +# ifdef TIOCGSOFTCAR + if (softcar) + { + *p++ = '('; + s = "!CD) "; + } + else +# endif + s = "!CD "; +# 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 @@ -977,18 +1810,20 @@ struct mode *m; 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 +# 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 */ +# endif /* HPUX_LTCHARS_HACK */ #else /* POSIX */ # ifdef TERMIO debug("struct termio tio:\n"); |