1 /* $NetBSD: tty.c,v 1.9 2017/06/30 04:41:19 kamil Exp $ */ 2 3 #include <sys/cdefs.h> 4 5 #ifndef lint 6 __RCSID("$NetBSD: tty.c,v 1.9 2017/06/30 04:41:19 kamil Exp $"); 7 #endif 8 9 #include <sys/stat.h> 10 11 #include "sh.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 ret = ioctl(fd, TIOCSETN, &ts->sgttyb); 78 # ifdef TIOCGATC 79 if (ioctl(fd, TIOCSATC, &ts->lchars) < 0) 80 ret = -1; 81 # else 82 if (ioctl(fd, TIOCSETC, &ts->tchars) < 0) 83 ret = -1; 84 # ifdef TIOCGLTC 85 if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0) 86 ret = -1; 87 # endif /* TIOCGLTC */ 88 # endif /* TIOCGATC */ 89 # endif /* HAVE_TERMIO_H */ 90 # endif /* HAVE_TERIOS_H */ 91 return ret; 92 } 93 94 95 /* Initialize tty_fd. Used for saving/reseting tty modes upon 96 * foreground job completion and for setting up tty process group. 97 */ 98 void 99 tty_init(init_ttystate) 100 int init_ttystate; 101 { 102 int do_close = 1; 103 int tfd; 104 const char *devtty = _PATH_TTY; 105 106 if (tty_fd >= 0) { 107 close(tty_fd); 108 tty_fd = -1; 109 } 110 tty_devtty = 1; 111 112 if ((tfd = open(devtty, O_RDWR, 0)) < 0) { 113 if (tfd < 0) { 114 tty_devtty = 0; 115 warningf(false, 116 "No controlling tty (open %s: %s)", 117 devtty, strerror(errno)); 118 } 119 } 120 121 if (tfd < 0) { 122 do_close = 0; 123 if (isatty(0)) 124 tfd = 0; 125 else if (isatty(2)) 126 tfd = 2; 127 else { 128 warningf(false, "Can't find tty file descriptor"); 129 return; 130 } 131 } 132 if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) { 133 warningf(false, "j_ttyinit: dup of tty fd failed: %s", 134 strerror(errno)); 135 } else if (fd_clexec(tty_fd) < 0) { 136 warningf(false, "j_ttyinit: can't set close-on-exec flag: %s", 137 strerror(errno)); 138 close(tty_fd); 139 tty_fd = -1; 140 } else if (init_ttystate) 141 get_tty(tty_fd, &tty_state); 142 if (do_close) 143 close(tfd); 144 } 145 146 void 147 tty_close() 148 { 149 if (tty_fd >= 0) { 150 close(tty_fd); 151 tty_fd = -1; 152 } 153 } 154