3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 #include "miscfuncs.h"
13 #include <sys/cygwin.h>
21 #include "shared_info.h"
23 HANDLE NO_COPY
tty_list::mutex
= NULL
;
28 return open ("/dev/ptmx", O_RDWR
| O_NOCTTY
);
32 posix_openpt (int oflags
)
34 return open ("/dev/ptmx", oflags
);
40 cygheap_fdget
cfd (fd
);
41 return cfd
< 0 ? -1 : 0;
47 cygheap_fdget
cfd (fd
);
48 return cfd
< 0 ? -1 : 0;
52 revoke (char *ttyname
)
61 if (!CTTY_IS_VALID (myself
->ctty
) || iscons_dev (myself
->ctty
))
63 return device::minor (myself
->ctty
);
67 tty_list::init_session ()
69 char mutex_name
[MAX_PATH
];
70 char *name
= shared_name (mutex_name
, "tty_list::mutex", 0);
72 /* tty_list::mutex is used while searching for a tty slot */
73 if (!(mutex
= CreateMutex (&sec_all_nih
, FALSE
, name
)))
74 api_fatal ("can't create tty_list::mutex '%s', %E", name
);
75 ProtectHandle (mutex
);
81 if (!myself
->cygstarted
&& NOTSTATE (myself
, PID_CYGPARENT
))
82 cygheap
->fdtab
.get_debugger_info ();
86 tty_list::attach (int n
)
92 res
= connect (device::minor (n
));
99 tty_list::connect (int ttynum
)
101 if (ttynum
< 0 || ttynum
>= NTTYS
)
103 termios_printf ("ttynum (%d) out of range", ttynum
);
106 if (!ttys
[ttynum
].exists ())
108 termios_printf ("pty %d was not allocated", ttynum
);
119 for (int i
= 0; i
< NTTYS
; i
++)
122 ttys
[i
].setntty (DEV_PTYS_MAJOR
, i
);
126 /* Search for a free tty and allocate it.
127 Return tty number or -1 if error.
130 tty_list::allocate (HANDLE
& r
, HANDLE
& w
)
136 for (int i
= 0; i
< NTTYS
; i
++)
137 if (ttys
[i
].not_allocated (r
, w
))
147 termios_printf ("pty%d allocated", freetty
);
150 system_printf ("No pty allocated");
158 tty::not_allocated (HANDLE
& r
, HANDLE
& w
)
160 /* Attempt to open the from-master side of the tty. If it is accessible
161 then it exists although we may not have privileges to actually use it. */
162 char pipename
[sizeof("ptyNNNN-from-master")];
163 __small_sprintf (pipename
, "pty%d-from-master", get_minor ());
164 /* fhandler_pipe::create returns 0 when creation succeeds */
165 return fhandler_pipe::create (&sec_none
, &r
, &w
,
166 fhandler_pty_common::pipesize
, pipename
,
175 if (!not_allocated (r
, w
))
180 /* Handles are left open when not_allocated finds a non-open "tty" */
185 debug_printf ("exists %d", res
);
193 if ((ev
= open_inuse (READ_CONTROL
)))
199 tty::open_mutex (const char *mutex
, ACCESS_MASK access
)
202 shared_name (buf
, mutex
, get_minor ());
203 return OpenMutex (access
, TRUE
, buf
);
207 tty::open_inuse (ACCESS_MASK access
)
210 shared_name (buf
, TTY_SLAVE_ALIVE
, get_minor ());
211 return OpenEvent (access
, FALSE
, buf
);
215 tty::create_inuse (PSECURITY_ATTRIBUTES sa
)
220 shared_name (buf
, TTY_SLAVE_ALIVE
, get_minor ());
221 h
= CreateEvent (sa
, TRUE
, FALSE
, buf
);
222 termios_printf ("%s %p", buf
, h
);
224 termios_printf ("couldn't open inuse event %s, %E", buf
);
238 pcon_activated
= false;
239 switch_to_nat_pipe
= false;
240 nat_pipe_owner_pid
= 0;
243 fwd_not_empty
= false;
246 pcon_cap_checked
= false;
248 need_invisible_console
= false;
249 invisible_console_pid
= 0;
250 previous_code_page
= 0;
251 previous_output_code_page
= 0;
252 master_is_running_as_service
= false;
253 req_xfer_input
= false;
254 pty_input_state
= to_cyg
;
257 discard_input
= false;
258 stop_fwd_thread
= false;
262 tty::get_event (const char *fmt
, PSECURITY_ATTRIBUTES sa
, BOOL manual_reset
)
267 shared_name (buf
, fmt
, get_minor ());
270 if (!(hev
= CreateEvent (sa
, manual_reset
, FALSE
, buf
)))
272 termios_printf ("couldn't create %s", buf
);
273 set_errno (ENOENT
); /* FIXME this can't be the right errno */
277 termios_printf ("created event %s", buf
);
281 lock_ttys::lock_ttys (DWORD howlong
): release_me (true)
283 if (WaitForSingleObject (tty_list::mutex
, howlong
) == WAIT_FAILED
)
285 termios_printf ("WFSO for mutex %p failed, %E", tty_list::mutex
);
291 lock_ttys::release ()
293 ReleaseMutex (tty_list::mutex
);
304 extern DWORD mutex_timeout
; /* defined in fhandler_termios.cc */
307 tty_min::setpgid (int pid
)
310 ::cygheap
->ctty
->setpgid_aux (pid
);
318 /* The forwarding in pseudo console sometimes stops for
319 16-32 msec even if it already has data to transfer.
320 If the time without transfer exceeds 32 msec, the
321 forwarding is supposed to be finished. fwd_last_time
322 is reset to GetTickCount64() in pty master forwarding
323 thread when the last data is transfered. */
324 const ULONGLONG sleep_in_nat_pipe
= 16;
325 const ULONGLONG time_to_wait
= sleep_in_nat_pipe
* 2 + 1/* margine */;
326 ULONGLONG elapsed
= 0;
328 || (elapsed
= GetTickCount64 () - fwd_last_time
) < time_to_wait
)
330 int tw
= fwd_not_empty
? 10 : (time_to_wait
- elapsed
);
336 tty::nat_fg (pid_t pgid
)
338 /* Check if the terminal pgid matches with the pgid of the
339 non-cygwin process. */
340 winpids
pids ((DWORD
) 0);
341 for (unsigned i
= 0; i
< pids
.npids
; i
++)
344 if (p
->ctty
== ntty
&& p
->pgid
== pgid
345 && ((p
->process_state
& PID_NOTCYGWIN
)
346 /* Below is true for GDB with non-cygwin inferior */
347 || p
->exec_dwProcessId
== p
->dwProcessId
))