1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
25 * NOTICE: tty.c is automatically generated from tty.sh
26 * Do not change anything here. If you then change tty.sh.
29 #include <sys/types.h>
33 # include <sys/file.h>
35 #if !defined(sun) || defined(SUNOS3)
36 # include <sys/ioctl.h> /* collosions with termios.h */
39 # include <sys/ttold.h> /* needed for TIOCEXCL */
43 # include <sys/modem.h>
48 # include <sys/sioctl.h>
54 #include <sys/stropts.h> /* for I_POP */
60 #if !defined(TIOCCONS) && defined(sun) && defined(SVR4)
61 # include <sys/strredir.h>
64 extern struct display *display, *displays;
66 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
67 extern struct win *console_window;
68 static void consredir_readev_fn __P((struct event *, char *));
71 int separate_sids = 1;
73 static void DoSendBreak __P((int, int, int));
74 static sigret_t SigAlrmDummy __P(SIGPROTOARG);
77 /* Frank Schulz (fschulz@pyramid.com):
78 * I have no idea why VSTART is not defined and my fix is probably not
79 * the cleanest, but it works.
81 #if !defined(VSTART) && defined(_VSTART)
82 #define VSTART _VSTART
84 #if !defined(VSTOP) && defined(_VSTOP)
101 SigAlrmDummy SIGDEFARG
103 debug("SigAlrmDummy()\n");
108 * Carefully open a charcter device. Not used to open display ttys.
109 * The second parameter is parsed for a few stty style options.
118 sigret_t (*sigalrm)__P(SIGPROTOARG);
120 sigalrm = signal(SIGALRM, SigAlrmDummy);
123 /* this open only succeeds, if real uid is allowed */
124 if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1)
127 Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line);
129 Msg(errno, "Cannot open line '%s' for R/W", line);
131 signal(SIGALRM, sigalrm);
136 Msg(0, "'%s' is not a tty", line);
138 signal(SIGALRM, sigalrm);
142 #if defined(I_POP) && defined(POP_TTYMODULES)
143 debug("OpenTTY I_POP\n");
144 while (ioctl(f, I_POP, (char *)0) >= 0)
148 * We come here exclusively. This is to stop all kermit and cu type things
149 * accessing the same tty line.
150 * Perhaps we should better create a lock in some /usr/spool/locks directory?
154 if (ioctl(f, TIOCEXCL, (char *) 0) < 0)
155 Msg(errno, "%s: ioctl TIOCEXCL failed", line);
156 debug3("%d %d %d\n", getuid(), geteuid(), getpid());
157 debug2("%s TIOCEXCL errno %d\n", line, errno);
158 #endif /* TIOCEXCL */
160 * We create a sane tty mode. We do not copy things from the display tty
162 #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE
165 debug1("OpenTTY: using mode of display for %s\n", line);
170 InitTTY(&Mode, W_TYPE_PLAIN);
172 SttyMode(&Mode, opt);
178 #if defined(linux) && defined(TIOCMSET)
181 ioctl(f, TIOCMGET, &mcs);
183 ioctl(f, TIOCMSET, &mcs);
189 signal(SIGALRM, sigalrm);
190 debug2("'%s' CONNECT fd=%d.\n", line, f);
204 bzero((char *)m, sizeof(*m));
206 /* struct termios tio
207 * defaults, as seen on SunOS 4.1.3
209 debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag);
211 m->tio.c_iflag |= BRKINT;
214 m->tio.c_iflag |= IGNPAR;
216 /* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */
218 m->tio.c_iflag |= IXON;
220 /* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */
222 if (!ttyflag) /* may not even be good for ptys.. */
225 m->tio.c_iflag |= ICRNL;
228 m->tio.c_oflag |= ONLCR;
231 m->tio.c_oflag |= TAB3;
234 m->tio.c_oflag |= OXTABS;
236 /* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */
238 m->tio.c_oflag |= OPOST;
244 * Or-ing the speed into c_cflags is dangerous.
245 * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs.
247 * IF{B9600} m->tio.c_cflag |= B9600;
248 * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT;
250 * We hope that we have the posix calls to do it right:
251 * If these are not available you might try the above.
254 cfsetospeed(&m->tio, B9600);
257 cfsetispeed(&m->tio, B9600);
261 m->tio.c_cflag |= CS8;
264 m->tio.c_cflag |= CREAD;
267 m->tio.c_cflag |= CLOCAL;
271 m->tio.c_lflag |= ECHOCTL;
274 m->tio.c_lflag |= ECHOKE;
280 m->tio.c_lflag |= ISIG;
283 m->tio.c_lflag |= ICANON;
286 m->tio.c_lflag |= ECHO;
290 m->tio.c_lflag |= ECHOE;
293 m->tio.c_lflag |= ECHOK;
296 m->tio.c_lflag |= IEXTEN;
301 m->tio.c_cc[VINTR] = Ctrl('C');
306 m->tio.c_cc[VQUIT] = Ctrl('\\');
311 m->tio.c_cc[VERASE] = 0x7f; /* DEL */
316 m->tio.c_cc[VKILL] = Ctrl('H');
321 m->tio.c_cc[VEOF] = Ctrl('D');
326 m->tio.c_cc[VEOL] = 0000;
331 m->tio.c_cc[VEOL2] = 0000;
336 m->tio.c_cc[VSWTCH] = 0000;
341 m->tio.c_cc[VSTART] = Ctrl('Q');
346 m->tio.c_cc[VSTOP] = Ctrl('S');
351 m->tio.c_cc[VSUSP] = Ctrl('Z');
356 m->tio.c_cc[VDSUSP] = Ctrl('Y');
359 #if defined(VREPRINT)
360 #if (VREPRINT < MAXCC)
361 m->tio.c_cc[VREPRINT] = Ctrl('R');
363 #endif /* VREPRINT */
364 #if defined(VDISCARD)
365 #if (VDISCARD < MAXCC)
366 m->tio.c_cc[VDISCARD] = Ctrl('O');
368 #endif /* VDISCARD */
370 #if (VWERASE < MAXCC)
371 m->tio.c_cc[VWERASE] = Ctrl('W');
376 m->tio.c_cc[VLNEXT] = Ctrl('V');
380 #if (VSTATUS < MAXCC)
381 m->tio.c_cc[VSTATUS] = Ctrl('T');
387 m->tio.c_cc[VMIN] = TTYVMIN;
388 m->tio.c_cc[VTIME] = TTYVTIME;
391 # ifdef HPUX_LTCHARS_HACK
392 m->m_ltchars.t_suspc = Ctrl('Z');
393 m->m_ltchars.t_dsuspc = Ctrl('Y');
394 m->m_ltchars.t_rprntc = Ctrl('R');
395 m->m_ltchars.t_flushc = Ctrl('O');
396 m->m_ltchars.t_werasc = Ctrl('W');
397 m->m_ltchars.t_lnextc = Ctrl('V');
398 # endif /* HPUX_LTCHARS_HACK */
403 debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag);
405 * defaults, as seen on Mototola SYSV68:
406 * input: 7bit, CR->NL, ^S/^Q flow control
407 * output: POSTprocessing: NL->NL-CR, Tabs to spaces
408 * control: 9600baud, 8bit CSIZE, enable input
409 * local: enable signals, erase/kill processing, echo on.
412 m->tio.c_iflag |= ISTRIP;
415 m->tio.c_iflag |= IXON;
418 if (!ttyflag) /* may not even be good for ptys.. */
421 m->tio.c_oflag |= OPOST;
424 m->tio.c_iflag |= ICRNL;
427 m->tio.c_oflag |= ONLCR;
430 m->tio.c_oflag |= TAB3;
435 )-: cannot handle BSDI without POSIX
438 m->tio.c_cflag = B9600;
442 m->tio.c_cflag |= CS8;
445 m->tio.c_cflag |= CREAD;
451 m->tio.c_lflag |= ISIG;
454 m->tio.c_lflag |= ICANON;
457 m->tio.c_lflag |= ECHO;
461 m->tio.c_lflag |= ECHOE;
464 m->tio.c_lflag |= ECHOK;
469 m->tio.c_cc[VINTR] = Ctrl('C');
474 m->tio.c_cc[VQUIT] = Ctrl('\\');
479 m->tio.c_cc[VERASE] = 0177; /* DEL */
484 m->tio.c_cc[VKILL] = Ctrl('H');
489 m->tio.c_cc[VEOF] = Ctrl('D');
494 m->tio.c_cc[VEOL] = 0377;
499 m->tio.c_cc[VEOL2] = 0377;
504 m->tio.c_cc[VSWTCH] = 0000;
510 m->tio.c_cc[VMIN] = TTYVMIN;
511 m->tio.c_cc[VTIME] = TTYVTIME;
515 debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag);
516 m->m_ttyb.sg_ispeed = B9600;
517 m->m_ttyb.sg_ospeed = B9600;
518 m->m_ttyb.sg_erase = 0177; /*DEL */
519 m->m_ttyb.sg_kill = Ctrl('H');
521 m->m_ttyb.sg_flags = CRMOD | ECHO
527 m->m_ttyb.sg_flags = CBREAK
533 m->m_tchars.t_intrc = Ctrl('C');
534 m->m_tchars.t_quitc = Ctrl('\\');
535 m->m_tchars.t_startc = Ctrl('Q');
536 m->m_tchars.t_stopc = Ctrl('S');
537 m->m_tchars.t_eofc = Ctrl('D');
538 m->m_tchars.t_brkc = -1;
540 m->m_ltchars.t_suspc = Ctrl('Z');
541 m->m_ltchars.t_dsuspc = Ctrl('Y');
542 m->m_ltchars.t_rprntc = Ctrl('R');
543 m->m_ltchars.t_flushc = Ctrl('O');
544 m->m_ltchars.t_werasc = Ctrl('W');
545 m->m_ltchars.t_lnextc = Ctrl('V');
547 #if defined(NTTYDISC)
548 m->m_ldisc = NTTYDISC;
549 #endif /* NTTYDISC */
574 #if defined(ENCODINGS) && defined(TIOCKSET)
575 m->m_jtchars.t_ascii = 'J';
576 m->m_jtchars.t_kanji = 'B';
577 m->m_knjmode = KM_ASCII | KM_SYSSJIS;
588 tcsetattr(fd, TCSADRAIN, &mp->tio);
589 # ifdef HPUX_LTCHARS_HACK
590 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars);
594 ioctl(fd, TCSETAW, (char *)&mp->tio);
596 if (mp->tio.c_line == 3)
598 ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey);
599 ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen);
600 ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace);
604 /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */
605 ioctl(fd, TIOCSETC, (char *)&mp->m_tchars);
606 ioctl(fd, TIOCLSET, (char *)&mp->m_lmode);
607 ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc);
608 ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb);
609 ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */
612 #if defined(ENCODINGS) && defined(TIOCKSET)
613 ioctl(fd, TIOCKSETC, &mp->m_jtchars);
614 ioctl(fd, TIOCKSET, &mp->m_knjmode);
617 Msg(errno, "SetTTY (fd %d): ioctl failed", fd);
627 tcgetattr(fd, &mp->tio);
628 # ifdef HPUX_LTCHARS_HACK
629 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
633 ioctl(fd, TCGETA, (char *)&mp->tio);
635 if (mp->tio.c_line == 3)
637 ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey);
638 ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen);
639 ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace);
643 mp->m_mapkey = NOMAPKEY;
644 mp->m_mapscreen = NOMAPSCREEN;
645 mp->m_backspace = '\b';
649 ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb);
650 ioctl(fd, TIOCGETC, (char *)&mp->m_tchars);
651 ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars);
652 ioctl(fd, TIOCLGET, (char *)&mp->m_lmode);
653 ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc);
656 #if defined(ENCODINGS) && defined(TIOCKSET)
657 ioctl(fd, TIOCKGETC, &mp->m_jtchars);
658 ioctl(fd, TIOCKGET, &mp->m_knjmode);
661 Msg(errno, "GetTTY (fd %d): ioctl failed", fd);
665 * needs interrupt = iflag and flow = d->d_flow
668 SetMode(op, np, flow, interrupt)
669 struct mode *op, *np;
675 #if defined(TERMIO) || defined(POSIX)
677 np->m_mapkey = NOMAPKEY;
678 np->m_mapscreen = NOMAPSCREEN;
682 np->tio.c_iflag &= ~ICRNL;
685 np->tio.c_iflag &= ~ISTRIP;
688 np->tio.c_oflag &= ~ONLCR;
690 np->tio.c_lflag &= ~(ICANON | ECHO);
692 * From Andrew Myers (andru@tonic.lcs.mit.edu)
693 * to avoid ^V^V-Problem on OSF1
696 np->tio.c_lflag &= ~IEXTEN;
700 * Unfortunately, the master process never will get SIGINT if the real
701 * terminal is different from the one on which it was originaly started
702 * (process group membership has not been restored or the new tty could not
703 * be made controlling again). In my solution, it is the attacher who
704 * receives SIGINT (because it is always correctly associated with the real
705 * tty) and forwards it to the master [kill(MasterPid, SIGINT)].
706 * Marc Boucher (marc@CAM.ORG)
709 np->tio.c_lflag |= ISIG;
711 np->tio.c_lflag &= ~ISIG;
713 * careful, careful catche monkey..
714 * never set VMIN and VTIME to zero, if you want blocking io.
716 * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to
717 * reduce interrupt frequency. But then we would not know how to
718 * handle read returning 0. jw.
720 np->tio.c_cc[VMIN] = 1;
721 np->tio.c_cc[VTIME] = 0;
722 if (!interrupt || !flow)
723 np->tio.c_cc[VINTR] = VDISABLE;
724 np->tio.c_cc[VQUIT] = VDISABLE;
729 np->tio.c_cc[VSTART] = VDISABLE;
734 np->tio.c_cc[VSTOP] = VDISABLE;
737 np->tio.c_iflag &= ~IXON;
739 #if defined(VDISCARD)
740 #if (VDISCARD < MAXCC)
741 np->tio.c_cc[VDISCARD] = VDISABLE;
743 #endif /* VDISCARD */
746 np->tio.c_cc[VLNEXT] = VDISABLE;
750 #if (VSTATUS < MAXCC)
751 np->tio.c_cc[VSTATUS] = VDISABLE;
756 np->tio.c_cc[VSUSP] = VDISABLE;
761 np->tio.c_cc[VERASE] = VDISABLE;
766 np->tio.c_cc[VKILL] = VDISABLE;
769 # ifdef HPUX_LTCHARS_HACK
770 np->m_ltchars.t_suspc = VDISABLE;
771 np->m_ltchars.t_dsuspc = VDISABLE;
772 np->m_ltchars.t_rprntc = VDISABLE;
773 np->m_ltchars.t_flushc = VDISABLE;
774 np->m_ltchars.t_werasc = VDISABLE;
775 np->m_ltchars.t_lnextc = VDISABLE;
776 # else /* HPUX_LTCHARS_HACK */
779 np->tio.c_cc[VDSUSP] = VDISABLE;
782 #if defined(VREPRINT)
783 #if (VREPRINT < MAXCC)
784 np->tio.c_cc[VREPRINT] = VDISABLE;
786 #endif /* VREPRINT */
788 #if (VWERASE < MAXCC)
789 np->tio.c_cc[VWERASE] = VDISABLE;
792 # endif /* HPUX_LTCHARS_HACK */
793 #else /* TERMIO || POSIX */
794 if (!interrupt || !flow)
795 np->m_tchars.t_intrc = -1;
796 np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
797 np->m_ttyb.sg_flags |= CBREAK;
798 # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS)
799 np->m_ttyb.sg_flags &= ~CSTYLE;
800 np->m_ttyb.sg_flags |= CS_8BITS;
802 np->m_tchars.t_quitc = -1;
805 np->m_tchars.t_startc = -1;
806 np->m_tchars.t_stopc = -1;
808 np->m_ltchars.t_suspc = -1;
809 np->m_ltchars.t_dsuspc = -1;
810 np->m_ltchars.t_flushc = -1;
811 np->m_ltchars.t_lnextc = -1;
812 #endif /* defined(TERMIO) || defined(POSIX) */
815 /* operates on display */
823 #if defined(TERMIO) || defined(POSIX)
826 D_NewMode.tio.c_cc[VINTR] = iflag ? D_OldMode.tio.c_cc[VINTR] : VDISABLE;
829 D_NewMode.tio.c_cc[VSTART] = D_OldMode.tio.c_cc[VSTART];
834 D_NewMode.tio.c_cc[VSTOP] = D_OldMode.tio.c_cc[VSTOP];
837 D_NewMode.tio.c_iflag |= D_OldMode.tio.c_iflag & IXON;
841 D_NewMode.tio.c_cc[VINTR] = VDISABLE;
844 D_NewMode.tio.c_cc[VSTART] = VDISABLE;
849 D_NewMode.tio.c_cc[VSTOP] = VDISABLE;
852 D_NewMode.tio.c_iflag &= ~IXON;
855 if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio))
857 if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0)
859 debug1("SetFlow: ioctl errno %d\n", errno);
860 #else /* POSIX || TERMIO */
863 D_NewMode.m_tchars.t_intrc = iflag ? D_OldMode.m_tchars.t_intrc : -1;
864 D_NewMode.m_tchars.t_startc = D_OldMode.m_tchars.t_startc;
865 D_NewMode.m_tchars.t_stopc = D_OldMode.m_tchars.t_stopc;
869 D_NewMode.m_tchars.t_intrc = -1;
870 D_NewMode.m_tchars.t_startc = -1;
871 D_NewMode.m_tchars.t_stopc = -1;
873 if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0)
874 debug1("SetFlow: ioctl errno %d\n", errno);
875 #endif /* POSIX || TERMIO */
879 /* parse commands from opt and modify m */
885 static const char sep[] = " \t:;,";
892 while (index(sep, *opt)) opt++;
893 if (*opt >= '0' && *opt <= '9')
895 if (SetBaud(m, atoi(opt), atoi(opt)))
898 else if (!strncmp("cs7", opt, 3))
900 #if defined(POSIX) || defined(TERMIO)
901 m->tio.c_cflag &= ~CSIZE;
902 m->tio.c_cflag |= CS7;
904 m->m_lmode &= ~LPASS8;
907 else if (!strncmp("cs8", opt, 3))
909 #if defined(POSIX) || defined(TERMIO)
910 m->tio.c_cflag &= ~CSIZE;
911 m->tio.c_cflag |= CS8;
913 m->m_lmode |= LPASS8;
916 else if (!strncmp("istrip", opt, 6))
918 #if defined(POSIX) || defined(TERMIO)
919 m->tio.c_iflag |= ISTRIP;
921 m->m_lmode &= ~LPASS8;
924 else if (!strncmp("-istrip", opt, 7))
926 #if defined(POSIX) || defined(TERMIO)
927 m->tio.c_iflag &= ~ISTRIP;
929 m->m_lmode |= LPASS8;
932 else if (!strncmp("ixon", opt, 4))
934 #if defined(POSIX) || defined(TERMIO)
935 m->tio.c_iflag |= IXON;
937 debug("SttyMode: no ixon in old bsd land.\n");
940 else if (!strncmp("-ixon", opt, 5))
942 #if defined(POSIX) || defined(TERMIO)
943 m->tio.c_iflag &= ~IXON;
945 debug("SttyMode: no -ixon in old bsd land.\n");
948 else if (!strncmp("ixoff", opt, 5))
950 #if defined(POSIX) || defined(TERMIO)
951 m->tio.c_iflag |= IXOFF;
953 m->m_ttyb.sg_flags |= TANDEM;
956 else if (!strncmp("-ixoff", opt, 6))
958 #if defined(POSIX) || defined(TERMIO)
959 m->tio.c_iflag &= ~IXOFF;
961 m->m_ttyb.sg_flags &= ~TANDEM;
964 else if (!strncmp("crtscts", opt, 7))
966 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
967 m->tio.c_cflag |= CRTSCTS;
970 else if (!strncmp("-crtscts", opt, 8))
972 #if (defined(POSIX) || defined(TERMIO)) && defined(CRTSCTS)
973 m->tio.c_cflag &= ~CRTSCTS;
978 while (*opt && !index(sep, *opt)) opt++;
984 * Job control handling
986 * Somehow the ultrix session handling is broken, so use
987 * the bsdish variant.
995 #if defined(POSIX) && !defined(ultrix)
997 setsid(); /* will break terminal affiliation */
998 /* GNU added for Hurd systems 2001-10-10 */
999 # if defined(BSD) && defined(TIOCSCTTY) && !defined(__GNU__)
1000 ioctl(fd, TIOCSCTTY, (char *)0);
1001 # endif /* BSD && TIOCSCTTY */
1005 setpgrp(); /* will break terminal affiliation */
1010 if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0)
1012 if (ioctl(devtty, TIOCNOTTY, (char *)0))
1013 debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno);
1016 # endif /* BSDJOBS */
1030 /* The next lines should be obsolete. Can anybody check if they
1031 * are really needed on the BSD platforms?
1033 * this is to avoid the message:
1034 * fgtty: Not a typewriter (25)
1036 # if defined(__osf__) || (BSD >= 199103) || defined(ISC)
1038 setsid(); /* should be already done */
1040 ioctl(fd, TIOCSCTTY, (char *)0);
1046 if (tcsetpgrp(fd, mypid))
1048 debug1("fgtty: tcsetpgrp: %d\n", errno);
1052 if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0)
1053 debug1("fgtty: TIOSETPGRP: %d\n", errno);
1054 # ifndef SYSV /* Already done in brktty():setpgrp() */
1056 if (setpgrp(fd, mypid))
1057 debug1("fgtty: setpgrp: %d\n", errno);
1060 #endif /* BSDJOBS */
1065 * The alm boards on our sparc center 1000 have a lousy driver.
1066 * We cannot generate long breaks unless we use the most ugly form
1079 #if defined(sun) && !defined(SVR4)
1080 # define HAVE_SUPER_TCSENDBREAK
1085 * 0: TIOCSBRK / TIOCCBRK
1088 * n: approximate duration in 1/4 seconds.
1091 DoSendBreak(fd, n, type)
1096 case 2: /* tcsendbreak() =============================== */
1098 # ifdef HAVE_SUPER_TCSENDBREAK
1099 /* There is one rare case that I have tested, where tcsendbreak works
1100 * really great: this was an alm driver that came with SunOS 4.1.3
1101 * If you have this one, define the above symbol.
1102 * here we can use the second parameter to specify the duration.
1104 debug2("tcsendbreak(fd=%d, %d)\n", fd, n);
1105 if (tcsendbreak(fd, n) < 0)
1106 Msg(errno, "cannot send BREAK (tcsendbreak)");
1109 * here we hope, that multiple calls to tcsendbreak() can
1110 * be concatenated to form a long break, as we do not know
1111 * what exact interpretation the second parameter has:
1113 * - sunos 4: duration in quarter seconds
1114 * - sunos 5: 0 a short break, nonzero a tcdrain()
1115 * - hpux, irix: ignored
1116 * - mot88: duration in milliseconds
1117 * - aix: duration in milliseconds, but 0 is 25 milliseconds.
1119 debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd);
1125 for (i = 0; i < n; i++)
1126 if (tcsendbreak(fd, 0) < 0)
1128 Msg(errno, "cannot send BREAK (tcsendbreak SVR4)");
1134 Msg(0, "tcsendbreak() not available, change breaktype");
1138 case 1: /* TCSBRK ======================================= */
1143 * Here too, we assume that short breaks can be concatenated to
1144 * perform long breaks. But for SOLARIS, this is not true, of course.
1146 debug2("%d * TCSBRK fd=%d\n", n, fd);
1150 for (i = 0; i < n; i++)
1151 if (ioctl(fd, TCSBRK, (char *)0) < 0)
1153 Msg(errno, "Cannot send BREAK (TCSBRK)");
1158 Msg(0, "TCSBRK not available, change breaktype");
1162 case 0: /* TIOCSBRK / TIOCCBRK ========================== */
1163 #if defined(TIOCSBRK) && defined(TIOCCBRK)
1165 * This is very rude. Screen actively celebrates the break.
1166 * But it may be the only save way to issue long breaks.
1168 debug("TIOCSBRK TIOCCBRK\n");
1169 if (ioctl(fd, TIOCSBRK, (char *)0) < 0)
1171 Msg(errno, "Can't send BREAK (TIOCSBRK)");
1174 sleep1000(n ? n * 250 : 250);
1175 if (ioctl(fd, TIOCCBRK, (char *)0) < 0)
1177 Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)");
1180 #else /* TIOCSBRK && TIOCCBRK */
1181 Msg(0, "TIOCSBRK/CBRK not available, change breaktype");
1182 #endif /* TIOCSBRK && TIOCCBRK */
1185 default: /* unknown ========================== */
1186 Msg(0, "Internal SendBreak error: method %d unknown", type);
1191 * Send a break for n * 0.25 seconds. Tty must be PLAIN.
1192 * The longest possible break allowed here is 15 seconds.
1196 SendBreak(wp, n, closeopen)
1200 sigret_t (*sigalrm)__P(SIGPROTOARG);
1202 #ifdef BUILTIN_TELNET
1203 if (wp->w_type == W_TYPE_TELNET)
1209 if (wp->w_type != W_TYPE_PLAIN)
1212 debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd);
1215 (void) tcflush(wp->w_ptyfd, TCIOFLUSH);
1218 (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0);
1219 # endif /* TIOCFLUSH */
1225 sleep1000(n ? n * 250 : 250);
1226 if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1)
1228 Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty);
1231 (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK);
1235 sigalrm = signal(SIGALRM, SigAlrmDummy);
1238 DoSendBreak(wp->w_ptyfd, n, breaktype);
1241 signal(SIGALRM, sigalrm);
1243 debug(" broken.\n");
1250 #if (!defined(TIOCCONS) && defined(SRIOCSREDIR)) || defined(linux)
1252 static struct event consredir_ev;
1253 static int consredirfd[2] = {-1, -1};
1256 consredir_readev_fn(ev, data)
1260 char *p, *n, buf[256];
1263 if (!console_window || (l = read(consredirfd[0], buf, sizeof(buf))) <= 0)
1265 close(consredirfd[0]);
1266 close(consredirfd[1]);
1267 consredirfd[0] = consredirfd[1] = -1;
1271 for (p = n = buf; l > 0; n++, l--)
1275 WriteString(console_window, p, n - p);
1276 WriteString(console_window, "\r\n", 2);
1280 WriteString(console_window, p, n - p);
1287 TtyGrabConsole(fd, on, rc_name)
1291 #if defined(TIOCCONS) && !defined(linux)
1297 return 0; /* pty close will ungrab */
1302 Msg(0, "I need a display");
1305 for (d = displays; d; d = d->d_next)
1306 if (strcmp(d->d_usertty, "/dev/console") == 0)
1310 Msg(0, "too dangerous - screen is running on /dev/console");
1318 if ((fd = OpenPTY(&slave)) < 0)
1320 Msg(errno, "%s: could not open detach pty master", rc_name);
1323 if ((sfd = open(slave, O_RDWR | O_NOCTTY)) < 0)
1325 Msg(errno, "%s: could not open detach pty slave", rc_name);
1330 if (UserContext() == 1)
1331 UserReturn(ioctl(fd, TIOCCONS, (char *)&on));
1334 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1343 # if defined(SRIOCSREDIR) || defined(linux)
1348 struct mode new1, new2;
1356 Msg(0, "I need a display");
1359 for (d = displays; d; d = d->d_next)
1360 if (strcmp(d->d_usertty, "/dev/console") == 0)
1364 Msg(0, "too dangerous - screen is running on /dev/console");
1368 if (consredirfd[0] >= 0)
1370 evdeq(&consredir_ev);
1371 close(consredirfd[0]);
1372 close(consredirfd[1]);
1373 consredirfd[0] = consredirfd[1] = -1;
1378 if ((cfd = secopen("/dev/console", O_RDWR|O_NOCTTY, 0)) == -1)
1380 Msg(errno, "/dev/console");
1383 if (pipe(consredirfd))
1387 consredirfd[0] = consredirfd[1] = -1;
1390 if (ioctl(cfd, SRIOCSREDIR, consredirfd[1]))
1392 Msg(errno, "SRIOCSREDIR ioctl");
1394 close(consredirfd[0]);
1395 close(consredirfd[1]);
1396 consredirfd[0] = consredirfd[1] = -1;
1401 /* special linux workaround for a too restrictive kernel */
1402 if ((consredirfd[0] = OpenPTY(&slave)) < 0)
1404 Msg(errno, "%s: could not open detach pty master", rc_name);
1407 if ((consredirfd[1] = open(slave, O_RDWR | O_NOCTTY)) < 0)
1409 Msg(errno, "%s: could not open detach pty slave", rc_name);
1410 close(consredirfd[0]);
1414 SetMode(&new1, &new2, 0, 0);
1415 SetTTY(consredirfd[1], &new2);
1416 if (UserContext() == 1)
1417 UserReturn(ioctl(consredirfd[1], TIOCCONS, (char *)&on));
1420 Msg(errno, "%s: ioctl TIOCCONS failed", rc_name);
1421 close(consredirfd[0]);
1422 close(consredirfd[1]);
1426 consredir_ev.fd = consredirfd[0];
1427 consredir_ev.type = EV_READ;
1428 consredir_ev.handler = consredir_readev_fn;
1429 evenq(&consredir_ev);
1433 Msg(0, "%s: don't know how to grab the console", rc_name);
1440 * Read modem control lines of a physical tty and write them to buf
1441 * in a readable format.
1442 * Will not write more than 256 characters to buf.
1446 TtyGetModemStatus(fd, buf)
1452 unsigned int softcar;
1454 #if defined(TIOCMGET) || defined(TIOCMODG)
1455 unsigned int mflags;
1458 /* this is yet another interface, found on hpux. grrr */
1461 # define TIOCM_DTR MDTR
1464 # define TIOCM_RTS MRTS
1467 # define TIOCM_DSR MDSR
1470 # define TIOCM_CAR MDCD
1473 # define TIOCM_RNG MRI
1476 # define TIOCM_CTS MCTS
1480 #if defined(CLOCAL) || defined(CRTSCTS)
1481 struct mode mtio; /* screen.h */
1483 #if defined(CRTSCTS) || defined(TIOCM_CTS)
1488 #if defined(CLOCAL) || defined(CRTSCTS)
1493 if (mtio.tio.c_cflag & CLOCAL)
1502 if (!(mtio.tio.c_cflag & CRTSCTS))
1505 # endif /* CRTSCTS */
1507 #endif /* TIOCM_CTS */
1510 if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0)
1514 #if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA)
1516 if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0)
1519 if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0)
1521 if (ioctl(fd, MCGETA, &mflags) < 0)
1526 sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD");
1528 sprintf(p, "NO-TTY?");
1537 if (!(mflags & TIOCM_LE))
1538 for (s = "!LE "; *s; *p++ = *s++);
1540 # endif /* FANCY_MODEM */
1543 s = "!RTS "; if (mflags & TIOCM_RTS) s++;
1544 while (*s) *p++ = *s++;
1553 if (mflags & TIOCM_CTS) s++;
1554 while (*s) *p++ = *s++;
1558 s = "!DTR "; if (mflags & TIOCM_DTR) s++;
1559 while (*s) *p++ = *s++;
1562 s = "!DSR "; if (mflags & TIOCM_DSR) s++;
1563 while (*s) *p++ = *s++;
1565 # if defined(TIOCM_CD) || defined(TIOCM_CAR)
1567 # ifdef TIOCGSOFTCAR
1575 if (mflags & TIOCM_CD) s++;
1577 if (mflags & TIOCM_CAR) s++;
1579 while (*s) *p++ = *s++;
1581 # if defined(TIOCM_RI) || defined(TIOCM_RNG)
1583 if (mflags & TIOCM_RI)
1585 if (mflags & TIOCM_RNG)
1587 for (s = "RI "; *s; *p++ = *s++);
1591 s = "!ST "; if (mflags & TIOCM_ST) s++;
1592 while (*s) *p++ = *s++;
1595 s = "!SR "; if (mflags & TIOCM_SR) s++;
1596 while (*s) *p++ = *s++;
1598 # endif /* FANCY_MODEM */
1599 if (p > buf && p[-1] == ' ')
1604 # ifdef TIOCGSOFTCAR
1605 sprintf(p, " %s", softcar ? "(CD)", "CD");
1616 * Old bsd-ish machines may not have any of the baudrate B... symbols.
1617 * We hope to detect them here, so that the btable[] below always has
1622 # if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300)
1676 * On hpux, idx and sym will be different.
1677 * Rumor has it that, we need idx in D_dospeed to make tputs
1679 * Frequently used entries come first.
1681 static struct baud_values btable[] =
1684 { 13, 9600, B9600 },
1687 { 14, 19200, B19200 },
1690 { 14, 19200, EXTA },
1693 { 15, 38400, B38400 },
1696 { 15, 38400, EXTB },
1699 { 16, 57600, B57600 },
1701 #if defined(B115200)
1702 { 17, 115200, B115200 },
1703 #endif /* B115200 */
1704 #if defined(B230400)
1705 { 18, 230400, B230400 },
1706 #endif /* B230400 */
1707 #if defined(B460800)
1708 { 19, 460800, B460800 },
1709 #endif /* B460800 */
1711 { 13, 7200, B7200 },
1714 { 12, 4800, B4800 },
1717 { 12, 3600, B3600 },
1720 { 11, 2400, B2400 },
1723 { 10, 1800, B1800 },
1762 * baud may either be a bits-per-second value or a symbolic
1763 * value as returned by cfget?speed()
1765 struct baud_values *
1769 struct baud_values *p;
1771 for (p = btable; p->idx >= 0; p++)
1772 if (baud == p->bps || baud == p->sym)
1778 * change the baud rate in a mode structure.
1779 * ibaud and obaud are given in bit/second, or at your option as
1780 * termio B... symbols as defined in e.g. suns sys/ttydev.h
1781 * -1 means don't change.
1784 SetBaud(m, ibaud, obaud)
1788 struct baud_values *ip, *op;
1790 if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) ||
1791 (!(op = lookup_baud(obaud)) && obaud != -1))
1795 if (ip) cfsetispeed(&m->tio, ip->sym);
1796 if (op) cfsetospeed(&m->tio, op->sym);
1802 m->tio.c_cflag &= ~(CBAUD << IBSHIFT);
1803 m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT;
1804 # else /* IBSHIFT */
1807 # endif /* IBSHIFT */
1811 m->tio.c_cflag &= ~CBAUD;
1812 m->tio.c_cflag |= op->sym & CBAUD;
1815 if (ip) m->m_ttyb.sg_ispeed = ip->idx;
1816 if (op) m->m_ttyb.sg_ospeed = op->idx;
1817 # endif /* TERMIO */
1823 * Write out the mode struct in a readable form
1834 debug("struct termios tio:\n");
1835 debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag);
1836 debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag);
1837 debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag);
1838 debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag);
1839 debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio));
1840 debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio));
1841 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1843 debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]);
1845 # ifdef HPUX_LTCHARS_HACK
1846 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc);
1847 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc);
1848 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc);
1849 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc);
1850 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc);
1851 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc);
1852 # endif /* HPUX_LTCHARS_HACK */
1855 debug("struct termio tio:\n");
1856 debug1("c_iflag = %04o\n", m->tio.c_iflag);
1857 debug1("c_oflag = %04o\n", m->tio.c_oflag);
1858 debug1("c_cflag = %04o\n", m->tio.c_cflag);
1859 debug1("c_lflag = %04o\n", m->tio.c_lflag);
1860 for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++)
1862 debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]);
1865 debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed);
1866 debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed);
1867 debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase);
1868 debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill);
1869 debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags);
1870 debug1("intrc = %#02x\n", m->m_tchars.t_intrc);
1871 debug1("quitc = %#02x\n", m->m_tchars.t_quitc);
1872 debug1("startc = %#02x\n", m->m_tchars.t_startc);
1873 debug1("stopc = %#02x\n", m->m_tchars.t_stopc);
1874 debug1("eofc = %#02x\n", m->m_tchars.t_eofc);
1875 debug1("brkc = %#02x\n", m->m_tchars.t_brkc);
1876 debug1("suspc = %#02x\n", m->m_ltchars.t_suspc);
1877 debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc);
1878 debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc);
1879 debug1("flushc = %#02x\n", m->m_ltchars.t_flushc);
1880 debug1("werasc = %#02x\n", m->m_ltchars.t_werasc);
1881 debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc);
1882 debug1("ldisc = %d\n", m->m_ldisc);
1883 debug1("lmode = %#x\n", m->m_lmode);
1884 # endif /* TERMIO */