/* $NetBSD: tty.c,v 1.9 2017/06/30 04:41:19 kamil Exp $ */ #include #ifndef lint __RCSID("$NetBSD: tty.c,v 1.9 2017/06/30 04:41:19 kamil Exp $"); #endif #include #include "sh.h" #define EXTERN #include "tty.h" #undef EXTERN int get_tty(fd, ts) int fd; TTY_state *ts; { int ret; # ifdef HAVE_TERMIOS_H ret = tcgetattr(fd, ts); # else /* HAVE_TERIOS_H */ # ifdef HAVE_TERMIO_H ret = ioctl(fd, TCGETA, ts); # else /* HAVE_TERMIO_H */ ret = ioctl(fd, TIOCGETP, &ts->sgttyb); # ifdef TIOCGATC if (ioctl(fd, TIOCGATC, &ts->lchars) < 0) ret = -1; # else if (ioctl(fd, TIOCGETC, &ts->tchars) < 0) ret = -1; # ifdef TIOCGLTC if (ioctl(fd, TIOCGLTC, &ts->ltchars) < 0) ret = -1; # endif /* TIOCGLTC */ # endif /* TIOCGATC */ # endif /* HAVE_TERMIO_H */ # endif /* HAVE_TERIOS_H */ return ret; } int set_tty(fd, ts, flags) int fd; TTY_state *ts; int flags; { int ret = 0; # ifdef HAVE_TERMIOS_H ret = tcsetattr(fd, TCSADRAIN, ts); # else /* HAVE_TERIOS_H */ # ifdef HAVE_TERMIO_H # ifndef TCSETAW /* e.g. Cray-2 */ /* first wait for output to drain */ # ifdef TCSBRK if (ioctl(tty_fd, TCSBRK, 1) < 0) ret = -1; # else /* the following kludge is minimally intrusive, but sometimes fails */ if (flags & TF_WAIT) sleep((unsigned)1); /* fake it */ # endif # endif /* !TCSETAW */ # if defined(_BSD_SYSV) || !defined(TCSETAW) /* _BSD_SYSV must force TIOCSETN instead of TIOCSETP (preserve type-ahead) */ if (ioctl(tty_fd, TCSETA, ts) < 0) ret = -1; # else if (ioctl(tty_fd, TCSETAW, ts) < 0) ret = -1; # endif # else /* HAVE_TERMIO_H */ ret = ioctl(fd, TIOCSETN, &ts->sgttyb); # ifdef TIOCGATC if (ioctl(fd, TIOCSATC, &ts->lchars) < 0) ret = -1; # else if (ioctl(fd, TIOCSETC, &ts->tchars) < 0) ret = -1; # ifdef TIOCGLTC if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0) ret = -1; # endif /* TIOCGLTC */ # endif /* TIOCGATC */ # endif /* HAVE_TERMIO_H */ # endif /* HAVE_TERIOS_H */ return ret; } /* Initialize tty_fd. Used for saving/reseting tty modes upon * foreground job completion and for setting up tty process group. */ void tty_init(init_ttystate) int init_ttystate; { int do_close = 1; int tfd; const char *devtty = _PATH_TTY; if (tty_fd >= 0) { close(tty_fd); tty_fd = -1; } tty_devtty = 1; if ((tfd = open(devtty, O_RDWR, 0)) < 0) { if (tfd < 0) { tty_devtty = 0; warningf(false, "No controlling tty (open %s: %s)", devtty, strerror(errno)); } } if (tfd < 0) { do_close = 0; if (isatty(0)) tfd = 0; else if (isatty(2)) tfd = 2; else { warningf(false, "Can't find tty file descriptor"); return; } } if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) { warningf(false, "j_ttyinit: dup of tty fd failed: %s", strerror(errno)); } else if (fd_clexec(tty_fd) < 0) { warningf(false, "j_ttyinit: can't set close-on-exec flag: %s", strerror(errno)); close(tty_fd); tty_fd = -1; } else if (init_ttystate) get_tty(tty_fd, &tty_state); if (do_close) close(tfd); } void tty_close() { if (tty_fd >= 0) { close(tty_fd); tty_fd = -1; } }