]>
Commit | Line | Data |
---|---|---|
1fd5e000 CF |
1 | /* tty.cc |
2 | ||
cc01c77f | 3 | Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, |
61522196 | 4 | 2010, 2011, 2012 Red Hat, Inc. |
1fd5e000 CF |
5 | |
6 | This file is part of Cygwin. | |
7 | ||
8 | This software is a copyrighted work licensed under the terms of the | |
9 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
10 | details. */ | |
11 | ||
4c8d72de | 12 | #include "winsup.h" |
ade47a34 | 13 | #include "miscfuncs.h" |
1fd5e000 CF |
14 | #include <unistd.h> |
15 | #include <utmp.h> | |
f0338f54 | 16 | #include <sys/cygwin.h> |
bccd5e0d | 17 | #include "cygerrno.h" |
6b91b8d5 | 18 | #include "security.h" |
47063f00 | 19 | #include "path.h" |
7ac61736 | 20 | #include "fhandler.h" |
e2ebe117 | 21 | #include "dtable.h" |
0381fec6 | 22 | #include "cygheap.h" |
e2ebe117 | 23 | #include "pinfo.h" |
29ac7f89 | 24 | #include "shared_info.h" |
1fd5e000 | 25 | |
c75b5b2d | 26 | HANDLE NO_COPY tty_list::mutex = NULL; |
1fd5e000 | 27 | |
d5f3e0ba YS |
28 | extern "C" int |
29 | getpt (void) | |
30 | { | |
31 | return open ("/dev/ptmx", O_RDWR | O_NOCTTY); | |
32 | } | |
33 | ||
70e476d2 CV |
34 | extern "C" int |
35 | posix_openpt (int oflags) | |
36 | { | |
37 | return open ("/dev/ptmx", oflags); | |
38 | } | |
39 | ||
c367dfd0 | 40 | extern "C" int |
8db71e01 | 41 | grantpt (int fd) |
1fd5e000 | 42 | { |
36b63207 CF |
43 | cygheap_fdget cfd (fd); |
44 | return cfd < 0 ? -1 : 0; | |
1fd5e000 CF |
45 | } |
46 | ||
c367dfd0 | 47 | extern "C" int |
8db71e01 | 48 | unlockpt (int fd) |
1fd5e000 | 49 | { |
36b63207 CF |
50 | cygheap_fdget cfd (fd); |
51 | return cfd < 0 ? -1 : 0; | |
1fd5e000 CF |
52 | } |
53 | ||
34a1d63d CV |
54 | extern "C" int |
55 | revoke (char *ttyname) | |
56 | { | |
57 | set_errno (ENOSYS); | |
58 | return -1; | |
59 | } | |
60 | ||
c367dfd0 | 61 | extern "C" int |
1fd5e000 CF |
62 | ttyslot (void) |
63 | { | |
c75b5b2d | 64 | if (myself->ctty <= 0 || iscons_dev (myself->ctty)) |
1fd5e000 | 65 | return -1; |
44d2fc0a | 66 | return device::minor (myself->ctty); |
1fd5e000 CF |
67 | } |
68 | ||
69 | void __stdcall | |
71d59a92 CF |
70 | tty_list::init_session () |
71 | { | |
495571e5 | 72 | char mutex_name[MAX_PATH]; |
71d59a92 | 73 | char *name = shared_name (mutex_name, "tty_list::mutex", 0); |
c75b5b2d CF |
74 | |
75 | /* tty_list::mutex is used while searching for a tty slot */ | |
71d59a92 CF |
76 | if (!(mutex = CreateMutex (&sec_all_nih, FALSE, name))) |
77 | api_fatal ("can't create tty_list::mutex '%s', %E", name); | |
78 | ProtectHandle (mutex); | |
79 | } | |
80 | ||
81 | void __stdcall | |
82 | tty::init_session () | |
1fd5e000 | 83 | { |
8cb359d9 | 84 | if (!myself->cygstarted && NOTSTATE (myself, PID_CYGPARENT)) |
083abe54 | 85 | cygheap->fdtab.get_debugger_info (); |
1fd5e000 CF |
86 | } |
87 | ||
1fd5e000 | 88 | int __stdcall |
44d2fc0a | 89 | tty_list::attach (int n) |
1fd5e000 | 90 | { |
44d2fc0a CF |
91 | int res; |
92 | if (iscons_dev (n)) | |
93 | res = -1; | |
94 | else if (n != -1) | |
95 | res = connect (device::minor (n)); | |
44d2fc0a CF |
96 | else |
97 | res = -1; | |
98 | return res; | |
1fd5e000 CF |
99 | } |
100 | ||
1fd5e000 | 101 | int |
71d59a92 | 102 | tty_list::connect (int ttynum) |
1fd5e000 CF |
103 | { |
104 | if (ttynum < 0 || ttynum >= NTTYS) | |
105 | { | |
106 | termios_printf ("ttynum (%d) out of range", ttynum); | |
107 | return -1; | |
108 | } | |
109 | if (!ttys[ttynum].exists ()) | |
110 | { | |
23771fa1 | 111 | termios_printf ("pty %d was not allocated", ttynum); |
be96a30c | 112 | set_errno (ENXIO); |
1fd5e000 CF |
113 | return -1; |
114 | } | |
115 | ||
116 | return ttynum; | |
117 | } | |
118 | ||
119 | void | |
2f9ae2ed | 120 | tty_list::init () |
1fd5e000 CF |
121 | { |
122 | for (int i = 0; i < NTTYS; i++) | |
123 | { | |
124 | ttys[i].init (); | |
38d732a1 | 125 | ttys[i].setntty (DEV_PTYS_MAJOR, i); |
1fd5e000 CF |
126 | } |
127 | } | |
128 | ||
c75b5b2d | 129 | /* Search for a free tty and allocate it. |
1fd5e000 | 130 | Return tty number or -1 if error. |
1fd5e000 CF |
131 | */ |
132 | int | |
23771fa1 | 133 | tty_list::allocate (HANDLE& r, HANDLE& w) |
1fd5e000 | 134 | { |
71d59a92 | 135 | lock_ttys here; |
c75b5b2d | 136 | int freetty = -1; |
641654f7 | 137 | |
c75b5b2d | 138 | tty *t = NULL; |
1fd5e000 | 139 | for (int i = 0; i < NTTYS; i++) |
23771fa1 | 140 | if (ttys[i].not_allocated (r, w)) |
c75b5b2d CF |
141 | { |
142 | t = ttys + i; | |
143 | t->init (); | |
144 | t->setsid (-1); | |
145 | freetty = i; | |
146 | break; | |
147 | } | |
1fd5e000 | 148 | |
23771fa1 CF |
149 | if (freetty >= 0) |
150 | termios_printf ("pty%d allocated", freetty); | |
c75b5b2d | 151 | else |
bfa76897 | 152 | { |
23771fa1 CF |
153 | system_printf ("No pty allocated"); |
154 | r = w = NULL; | |
bfa76897 | 155 | } |
23771fa1 | 156 | |
1fd5e000 CF |
157 | return freetty; |
158 | } | |
159 | ||
3c4f2024 | 160 | bool |
23771fa1 | 161 | tty::not_allocated (HANDLE& r, HANDLE& w) |
3c4f2024 CF |
162 | { |
163 | /* Attempt to open the from-master side of the tty. If it is accessible | |
23771fa1 CF |
164 | then it exists although we may not have privileges to actually use it. */ |
165 | char pipename[sizeof("ptyNNNN-from-master")]; | |
61522196 | 166 | __small_sprintf (pipename, "pty%d-from-master", get_minor ()); |
9f65451e CF |
167 | /* fhandler_pipe::create returns 0 when creation succeeds */ |
168 | return fhandler_pipe::create (&sec_none, &r, &w, | |
169 | fhandler_pty_common::pipesize, pipename, | |
170 | 0) == 0; | |
23771fa1 | 171 | } |
3c4f2024 | 172 | |
23771fa1 CF |
173 | bool |
174 | tty::exists () | |
175 | { | |
176 | HANDLE r, w; | |
177 | bool res; | |
178 | if (!not_allocated (r, w)) | |
179 | res = true; | |
3c4f2024 | 180 | |
23771fa1 | 181 | else |
3c4f2024 | 182 | { |
23771fa1 CF |
183 | /* Handles are left open when not_allocated finds a non-open "tty" */ |
184 | CloseHandle (r); | |
185 | CloseHandle (w); | |
186 | res = false; | |
3c4f2024 | 187 | } |
23771fa1 CF |
188 | debug_printf ("exists %d", res); |
189 | return res; | |
3c4f2024 CF |
190 | } |
191 | ||
2e008fb9 | 192 | bool |
cc01c77f | 193 | tty::slave_alive () |
1fd5e000 CF |
194 | { |
195 | HANDLE ev; | |
cc01c77f | 196 | if ((ev = open_inuse (READ_CONTROL))) |
1fd5e000 CF |
197 | CloseHandle (ev); |
198 | return ev != NULL; | |
199 | } | |
200 | ||
e3778517 | 201 | HANDLE |
cc01c77f | 202 | tty::open_mutex (const char *mutex, ACCESS_MASK access) |
8bdfa78a | 203 | { |
cc01c77f | 204 | char buf[MAX_PATH]; |
61522196 | 205 | shared_name (buf, mutex, get_minor ()); |
cc01c77f | 206 | return OpenMutex (access, TRUE, buf); |
e3778517 | 207 | } |
8bdfa78a | 208 | |
e3778517 | 209 | HANDLE |
cc01c77f | 210 | tty::open_inuse (ACCESS_MASK access) |
8bdfa78a | 211 | { |
495571e5 | 212 | char buf[MAX_PATH]; |
61522196 | 213 | shared_name (buf, TTY_SLAVE_ALIVE, get_minor ()); |
cc01c77f | 214 | return OpenEvent (access, FALSE, buf); |
8bdfa78a PH |
215 | } |
216 | ||
1fd5e000 | 217 | HANDLE |
cc01c77f | 218 | tty::create_inuse (PSECURITY_ATTRIBUTES sa) |
1fd5e000 CF |
219 | { |
220 | HANDLE h; | |
495571e5 | 221 | char buf[MAX_PATH]; |
1fd5e000 | 222 | |
61522196 | 223 | shared_name (buf, TTY_SLAVE_ALIVE, get_minor ()); |
cc01c77f | 224 | h = CreateEvent (sa, TRUE, FALSE, buf); |
0cd9f74f | 225 | termios_printf ("%s %p", buf, h); |
1fd5e000 | 226 | if (!h) |
61522196 | 227 | termios_printf ("couldn't open inuse event %s, %E", buf); |
1fd5e000 CF |
228 | return h; |
229 | } | |
230 | ||
231 | void | |
2f9ae2ed | 232 | tty::init () |
1fd5e000 | 233 | { |
b98ebf54 | 234 | output_stopped = 0; |
1fd5e000 CF |
235 | setsid (0); |
236 | pgid = 0; | |
c75b5b2d | 237 | was_opened = false; |
dad3ae73 | 238 | master_pid = 0; |
c75b5b2d | 239 | is_console = false; |
1fd5e000 CF |
240 | } |
241 | ||
242 | HANDLE | |
cc01c77f | 243 | tty::get_event (const char *fmt, PSECURITY_ATTRIBUTES sa, BOOL manual_reset) |
1fd5e000 CF |
244 | { |
245 | HANDLE hev; | |
495571e5 | 246 | char buf[MAX_PATH]; |
1fd5e000 | 247 | |
61522196 | 248 | shared_name (buf, fmt, get_minor ()); |
cc01c77f CV |
249 | if (!sa) |
250 | sa = &sec_all; | |
251 | if (!(hev = CreateEvent (sa, manual_reset, FALSE, buf))) | |
1fd5e000 CF |
252 | { |
253 | termios_printf ("couldn't create %s", buf); | |
254 | set_errno (ENOENT); /* FIXME this can't be the right errno */ | |
255 | return NULL; | |
256 | } | |
257 | ||
258 | termios_printf ("created event %s", buf); | |
259 | return hev; | |
260 | } | |
71d59a92 CF |
261 | |
262 | lock_ttys::lock_ttys (DWORD howlong): release_me (true) | |
263 | { | |
264 | if (WaitForSingleObject (tty_list::mutex, howlong) == WAIT_FAILED) | |
265 | { | |
266 | termios_printf ("WFSO for mutex %p failed, %E", tty_list::mutex); | |
267 | release_me = false; | |
268 | } | |
269 | } | |
270 | ||
271 | void | |
272 | lock_ttys::release () | |
273 | { | |
274 | ReleaseMutex (tty_list::mutex); | |
275 | } | |
44d2fc0a CF |
276 | |
277 | const char * | |
278 | tty_min::ttyname () | |
279 | { | |
280 | device d; | |
281 | d.parse (ntty); | |
282 | return d.name; | |
283 | } |