Home | History | Annotate | Line # | Download | only in ksh
tty.c revision 1.4
      1 /*	$NetBSD: tty.c,v 1.4 2003/06/23 11:39:06 agc Exp $	*/
      2 
      3 #include <sys/cdefs.h>
      4 
      5 #ifndef lint
      6 __RCSID("$NetBSD: tty.c,v 1.4 2003/06/23 11:39:06 agc Exp $");
      7 #endif
      8 
      9 
     10 #include "sh.h"
     11 #include "ksh_stat.h"
     12 #define EXTERN
     13 #include "tty.h"
     14 #undef EXTERN
     15 
     16 int
     17 get_tty(fd, ts)
     18 	int fd;
     19 	TTY_state *ts;
     20 {
     21 	int ret;
     22 
     23 # ifdef HAVE_TERMIOS_H
     24 	ret = tcgetattr(fd, ts);
     25 # else /* HAVE_TERIOS_H */
     26 #  ifdef HAVE_TERMIO_H
     27 	ret = ioctl(fd, TCGETA, ts);
     28 #  else /* HAVE_TERMIO_H */
     29 	ret = ioctl(fd, TIOCGETP, &ts->sgttyb);
     30 #   ifdef TIOCGATC
     31 	if (ioctl(fd, TIOCGATC, &ts->lchars) < 0)
     32 		ret = -1;
     33 #   else
     34 	if (ioctl(fd, TIOCGETC, &ts->tchars) < 0)
     35 		ret = -1;
     36 #    ifdef TIOCGLTC
     37 	if (ioctl(fd, TIOCGLTC, &ts->ltchars) < 0)
     38 		ret = -1;
     39 #    endif /* TIOCGLTC */
     40 #   endif /* TIOCGATC */
     41 #  endif /* HAVE_TERMIO_H */
     42 # endif /* HAVE_TERIOS_H */
     43 	return ret;
     44 }
     45 
     46 int
     47 set_tty(fd, ts, flags)
     48 	int fd;
     49 	TTY_state *ts;
     50 	int flags;
     51 {
     52 	int ret = 0;
     53 
     54 # ifdef HAVE_TERMIOS_H
     55 	ret = tcsetattr(fd, TCSADRAIN, ts);
     56 # else /* HAVE_TERIOS_H */
     57 #  ifdef HAVE_TERMIO_H
     58 #   ifndef TCSETAW				/* e.g. Cray-2 */
     59 		/* first wait for output to drain */
     60 #    ifdef TCSBRK
     61 		if (ioctl(tty_fd, TCSBRK, 1) < 0)
     62 			ret = -1;
     63 #    else /* the following kludge is minimally intrusive, but sometimes fails */
     64 		if (flags & TF_WAIT)
     65 			sleep((unsigned)1);	/* fake it */
     66 #    endif
     67 #   endif /* !TCSETAW */
     68 #   if defined(_BSD_SYSV) || !defined(TCSETAW)
     69 /* _BSD_SYSV must force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
     70 		if (ioctl(tty_fd, TCSETA, ts) < 0)
     71 			ret = -1;
     72 #   else
     73 		if (ioctl(tty_fd, TCSETAW, ts) < 0)
     74 			ret = -1;
     75 #   endif
     76 #  else /* HAVE_TERMIO_H */
     77 #   if defined(__mips) && (defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
     78 	/* Under RISC/os 5.00, bsd43 environment, after a tty driver
     79 	 * generated interrupt (eg, INTR, TSTP), all output to tty is
     80 	 * lost until a SETP is done (there must be a better way of
     81 	 * doing this...).
     82 	 */
     83 	if (flags & TF_MIPSKLUDGE)
     84 		ret = ioctl(fd, TIOCSETP, &ts->sgttyb);
     85 	else
     86 #   endif /* _SYSTYPE_BSD43 */
     87 	    ret = ioctl(fd, TIOCSETN, &ts->sgttyb);
     88 #   ifdef TIOCGATC
     89 	if (ioctl(fd, TIOCSATC, &ts->lchars) < 0)
     90 		ret = -1;
     91 #   else
     92 	if (ioctl(fd, TIOCSETC, &ts->tchars) < 0)
     93 		ret = -1;
     94 #    ifdef TIOCGLTC
     95 	if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0)
     96 		ret = -1;
     97 #    endif /* TIOCGLTC */
     98 #   endif /* TIOCGATC */
     99 #  endif /* HAVE_TERMIO_H */
    100 # endif /* HAVE_TERIOS_H */
    101 	return ret;
    102 }
    103 
    104 
    105 /* Initialize tty_fd.  Used for saving/reseting tty modes upon
    106  * foreground job completion and for setting up tty process group.
    107  */
    108 void
    109 tty_init(init_ttystate)
    110 	int init_ttystate;
    111 {
    112 	int	do_close = 1;
    113 	int	tfd;
    114 	const char	*devtty = _PATH_TTY;
    115 
    116 	if (tty_fd >= 0) {
    117 		close(tty_fd);
    118 		tty_fd = -1;
    119 	}
    120 	tty_devtty = 1;
    121 
    122 	/* SCO can't job control on /dev/tty, so don't try... */
    123 #if !defined(__SCO__)
    124 	if ((tfd = open(devtty, O_RDWR, 0)) < 0) {
    125 #ifdef __NeXT
    126 		/* rlogin on NeXT boxes does not set up the controlling tty,
    127 		 * so force it to be done here...
    128 		 */
    129 		{
    130 			extern char *ttyname ARGS((int));
    131 			char *s = ttyname(isatty(2) ? 2 : 0);
    132 			int fd;
    133 
    134 			if (s && (fd = open(s, O_RDWR, 0)) >= 0) {
    135 				close(fd);
    136 				tfd = open(devtty, O_RDWR, 0);
    137 			}
    138 		}
    139 #endif /* __NeXT */
    140 
    141 /* X11R5 xterm on mips doesn't set controlling tty properly - temporary hack */
    142 # if !defined(__mips) || !(defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
    143 		if (tfd < 0) {
    144 			tty_devtty = 0;
    145 			warningf(FALSE,
    146 				"No controlling tty (open %s: %s)",
    147 				devtty, strerror(errno));
    148 		}
    149 # endif /* __mips  */
    150 	}
    151 #else /* !__SCO__ */
    152 	tfd = -1;
    153 #endif /* __SCO__ */
    154 
    155 	if (tfd < 0) {
    156 		do_close = 0;
    157 		if (isatty(0))
    158 			tfd = 0;
    159 		else if (isatty(2))
    160 			tfd = 2;
    161 		else {
    162 			warningf(FALSE, "Can't find tty file descriptor");
    163 			return;
    164 		}
    165 	}
    166 	if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) {
    167 		warningf(FALSE, "j_ttyinit: dup of tty fd failed: %s",
    168 			strerror(errno));
    169 	} else if (fd_clexec(tty_fd) < 0) {
    170 		warningf(FALSE, "j_ttyinit: can't set close-on-exec flag: %s",
    171 			strerror(errno));
    172 		close(tty_fd);
    173 		tty_fd = -1;
    174 	} else if (init_ttystate)
    175 		get_tty(tty_fd, &tty_state);
    176 	if (do_close)
    177 		close(tfd);
    178 }
    179 
    180 void
    181 tty_close()
    182 {
    183 	if (tty_fd >= 0) {
    184 		close(tty_fd);
    185 		tty_fd = -1;
    186 	}
    187 }
    188