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