diff options
Diffstat (limited to 'tty.sh')
-rw-r--r-- | tty.sh | 904 |
1 files changed, 785 insertions, 119 deletions
@@ -3,13 +3,22 @@ # This inserts all the needed #ifdefs for IF{} statements # and generates tty.c +# +# Stupid cpp on A/UX barfs on ``#if defined(FOO) && FOO < 17'' when +# FOO is undefined. Reported by Robert C. Tindall (rtindall@uidaho.edu) +# rm -f $1 -sed -e '1,17d' \ --e 's%^IF{\(.*\)}\(.*\)%#if defined(\1)\ - \2\ +sed -e '1,26d' \ +-e 's%^IF{\([^}]*\)}\(.*\)%#if defined(\1)\ +\2\ #endif /* \1 */%' \ --e 's%^XIF{\(.*\)}\(.*\)%#if defined(\1) \&\& \1 < MAXCC\ - \2\ +-e 's%^IFN{\([^}]*\)}\(.*\)%#if !defined(\1)\ +\2\ +#endif /* \1 */%' \ +-e 's%^XIF{\([^}]*\)}\(.*\)%#if defined(\1)\ +#if (\1 < MAXCC)\ +\2\ +#endif \ #endif /* \1 */%' \ < $0 > $1 chmod -w $1 @@ -59,6 +68,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> @@ -67,11 +79,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 @@ -84,6 +112,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 { @@ -92,27 +132,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) + { + 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(errno, "Cannot open line '%s' for R/W", line); + Msg(0, "'%s' is not a tty", line); alarm(0); signal(SIGALRM, sigalrm); + close(f); return -1; } -#ifdef I_POP +#if defined(I_POP) && defined(POP_TTYMODULES) debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; @@ -126,7 +180,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 */ /* @@ -136,22 +190,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); @@ -169,7 +219,7 @@ int intrc, origintrc = VDISABLE; /* display? */ #else int intrc, origintrc = -1; /* display? */ #endif -static startc, stopc; /* display? */ +static int startc, stopc; /* display? */ void @@ -182,28 +232,40 @@ 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{BRKINT} m->tio.c_iflag |= BRKINT; IF{IGNPAR} m->tio.c_iflag |= IGNPAR; -IF{ISTRIP} m->tio.c_iflag |= ISTRIP; +/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ IF{IXON} m->tio.c_iflag |= IXON; -IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; +/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ if (!ttyflag) /* may not even be good for ptys.. */ { IF{ICRNL} m->tio.c_iflag |= ICRNL; IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; -IF{PARENB} m->tio.c_cflag |= PARENB; +IF{OXTABS} m->tio.c_oflag |= OXTABS; +/* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ } IF{OPOST} m->tio.c_oflag |= OPOST; -IF{B9600} m->tio.c_cflag |= B9600; +/* + * 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{B9600} cfsetospeed(&m->tio, B9600); +IF{B9600} cfsetispeed(&m->tio, B9600); + IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; -IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; -/* IF{CLOCAL} m->tio.c_cflag |= CLOCAL; */ +IF{CLOCAL} m->tio.c_cflag |= CLOCAL; IF{ECHOCTL} m->tio.c_lflag |= ECHOCTL; IF{ECHOKE} m->tio.c_lflag |= ECHOKE; @@ -238,17 +300,18 @@ XIF{VSTATUS} m->tio.c_cc[VSTATUS] = Ctrl('T'); 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 */ @@ -273,7 +336,11 @@ IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; } +#ifdef __bsdi__ + )-: cannot handle BSDI without POSIX +#else IF{B9600} m->tio.c_cflag = B9600; +#endif IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; @@ -294,11 +361,13 @@ XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D'); XIF{VEOL} m->tio.c_cc[VEOL] = 0377; XIF{VEOL2} m->tio.c_cc[VEOL2] = 0377; XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000; + 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; @@ -337,11 +406,11 @@ IF{LPASS8} | LPASS8 IF{LCRTKIL} | LCRTKIL IF{LCRTERA} | LCRTERA IF{LCRTBS} | 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; @@ -356,7 +425,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 @@ -379,7 +448,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 @@ -395,7 +464,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 @@ -423,7 +492,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 @@ -431,9 +500,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; @@ -444,10 +517,12 @@ struct mode *op, *np; np->tio.c_line = 0; # endif IF{ICRNL} np->tio.c_iflag &= ~ICRNL; +IF{ISTRIP} np->tio.c_iflag &= ~ISTRIP; IF{ONLCR} np->tio.c_oflag &= ~ONLCR; np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) + * to avoid ^V^V-Problem on OSF1 */ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; @@ -460,19 +535,23 @@ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; * 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; XIF{VSTART} startc = op->tio.c_cc[VSTART]; XIF{VSTOP} stopc = op->tio.c_cc[VSTOP]; - if (iflag) + if (interrupt) origintrc = intrc = op->tio.c_cc[VINTR]; else { @@ -480,7 +559,7 @@ XIF{VSTOP} stopc = op->tio.c_cc[VSTOP]; 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; XIF{VSTART} np->tio.c_cc[VSTART] = VDISABLE; @@ -493,22 +572,22 @@ XIF{VSTATUS} np->tio.c_cc[VSTATUS] = VDISABLE; XIF{VSUSP} np->tio.c_cc[VSUSP] = VDISABLE; XIF{VERASE} np->tio.c_cc[VERASE] = VDISABLE; XIF{VKILL} np->tio.c_cc[VKILL] = VDISABLE; -# 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 */ +# else /* HPUX_LTCHARS_HACK */ XIF{VDSUSP} np->tio.c_cc[VDSUSP] = VDISABLE; XIF{VREPRINT} np->tio.c_cc[VREPRINT] = VDISABLE; XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; -# 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 { @@ -522,7 +601,7 @@ XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; 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; @@ -535,6 +614,7 @@ XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; #endif /* defined(TERMIO) || defined(POSIX) */ } +/* operates on display */ void SetFlow(on) int on; @@ -582,6 +662,97 @@ XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = VDISABLE; 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 @@ -629,6 +800,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 */ @@ -655,19 +829,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 @@ -675,11 +984,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; @@ -688,56 +998,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) @@ -745,12 +1055,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); @@ -763,7 +1093,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) { @@ -779,23 +1126,340 @@ 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{MDTR}# define TIOCM_DTR MDTR +IF{MRTS}# define TIOCM_RTS MRTS +IF{MDSR}# define TIOCM_DSR MDSR +IF{MDCD}# define TIOCM_CAR MDCD +IF{MRI}# define TIOCM_RNG MRI +IF{MCTS}# define TIOCM_CTS 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) +IFN{B0}#define B0 0 +IFN{B50}#define B50 1 +IFN{B75}#define B75 2 +IFN{B110}#define B110 3 +IFN{B134}#define B134 4 +IFN{B150}#define B150 5 +IFN{B200}#define B200 6 +IFN{B300}#define B300 7 +IFN{B600}#define B600 8 +IFN{B1200}#define B1200 9 +IFN{B1800}#define B1800 10 +IFN{B2400}#define B2400 11 +IFN{B4800}#define B4800 12 +IFN{B9600}#define B9600 13 +IFN{EXTA}#define EXTA 14 +IFN{EXTB}#define EXTB 15 +# 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{B9600} { 13, 9600, B9600 }, +IF{B19200} { 14, 19200, B19200 }, +IF{EXTA} { 14, 19200, EXTA }, +IF{B38400} { 15, 38400, B38400 }, +IF{EXTB} { 15, 38400, EXTB }, +IF{B57600} { 16, 57600, B57600 }, +IF{B115200} { 17, 115200, B115200 }, +IF{B230400} { 18, 230400, B230400 }, +IF{B460800} { 19, 460800, B460800 }, +IF{B7200} { 13, 7200, B7200 }, +IF{B4800} { 12, 4800, B4800 }, +IF{B3600} { 12, 3600, B3600 }, +IF{B2400} { 11, 2400, B2400 }, +IF{B1800} { 10, 1800, B1800 }, +IF{B1200} { 9, 1200, B1200 }, +IF{B900} { 9, 900, B900 }, +IF{B600} { 8, 600, B600 }, +IF{B300} { 7, 300, B300 }, +IF{B200} { 6, 200, B200 }, +IF{B150} { 5, 150, B150 }, +IF{B134} { 4, 134, B134 }, +IF{B110} { 3, 110, B110 }, +IF{B75} { 2, 75, B75 }, +IF{B50} { 1, 50, B50 }, +IF{B0} { 0, 0, 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 @@ -814,18 +1478,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"); |