summaryrefslogtreecommitdiff
path: root/bin/ksh/tty.c
blob: 00a94cd3ae6880cc135974a2164aa781d006323b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*	$OpenBSD: tty.c,v 1.2 1996/10/01 02:05:51 downsj Exp $	*/

#include "sh.h"
#include "ksh_stat.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 */
#   if defined(__mips) && (defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
	/* Under RISC/os 5.00, bsd43 environment, after a tty driver
	 * generated interrupt (eg, INTR, TSTP), all output to tty is
	 * lost until a SETP is done (there must be a better way of
	 * doing this...).
	 */
	if (flags & TF_MIPSKLUDGE)
		ret = ioctl(fd, TIOCSETP, &ts->sgttyb);
	else
#   endif /* _SYSTYPE_BSD43 */
	    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;

	if (tty_fd >= 0) {
		close(tty_fd);
		tty_fd = -1;
	}
	tty_devtty = 1;

	/* SCO can't job control on /dev/tty, so don't try... */
#if !defined(__SCO__)
	if ((tfd = open("/dev/tty", O_RDWR, 0)) < 0) {
#ifdef __NeXT
		/* rlogin on NeXT boxes does not set up the controlling tty,
		 * so force it to be done here...
		 */
		{
			extern char *ttyname ARGS((int));
			char *s = ttyname(isatty(2) ? 2 : 0);
			int fd;

			if (s && (fd = open(s, O_RDWR, 0)) >= 0) {
				close(fd);
				tfd = open("/dev/tty", O_RDWR, 0);
			}
		}
#endif /* __NeXT */

/* X11R5 xterm on mips doesn't set controlling tty properly - temporary hack */
# if !defined(__mips) || !(defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43))
		if (tfd < 0) {
			tty_devtty = 0;
			warningf(FALSE,
				"No controlling tty (open /dev/tty: %s)",
				strerror(errno));
		}
# endif /* __mips  */
	}
#else /* !__SCO__ */
	tfd = -1;
#endif /* __SCO__ */

	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;
	}
}