* dcrt0.cc (dll_crt0_0): Call tty_list::init_session here.
(dll_crt0_1): Reflect renaming from tty_init to tty::init_session. (do_exit): Reflect moving of tty_terminate into tty_list. * exceptions.cc (events_init): Move tty_mutex stuff elsewhere. * fhandler_console.cc (set_console_title): Use lock_ttys class. * fhandler_termios.cc (fhandler_termios::bg_check): Make debug output more accurate. * fhandler_tty.cc (fhandler_tty_slave::open): Reflect move of attach_tty into tty_list class. Don't attempt to grab master end of pty if master doesn't exist. (fhandler_pty_master::open): Reflect move of allocate_tty into tty_list class. Use lock_ttys::release to release mutex. Improve debugging output. (fhandler_pty_master::setup): Remove if 0'ed block. Fix argument to SetNamedPipeHandleState. * pinfo.cc (_pinfo::set_ctty): Lock ttys before setting sid/pgid. Improve debugging. Add temporary debugging. * tty.cc (tty_list::init_session): New function. (tty::init_session): Rename from tty_init. Reflect move of attach_tty to tty_list class. (tty::create_master): Rename from create_tty_master. (tty_list::attach): Rename from attach_tty. Reflect renaming of connect_tty to connect. Ditto for allocate_tty. (tty_terminate): Delete. (tty_list::terminate): Subsume tty_terminate. Use lock_ttys rather than manipulating mutex directly. (tty_list::allocate): Rename from allocate_tty. Use lock_ttys rather than manipulating mutex directly. Don't set sid here since linux apparently doesn't do this. Reflect move of create_tty_master into tty. (lock_ttys::lock_ttys): Define new constructor. (lock_ttys::release): New function. * tty.h (tty::exists): Return false immediately if !master_pid. (tty::set_master_closed): Define new function. (tty::create_master): Ditto. (tty::init_session): Ditto. (tty_list::mutex): New field. (tty_list::allocate): Define new function. (tty_list::connect): Ditto. (tty_list::attach): Ditto. (tty_list::init_session): Ditto. (lock_ttys): New class. (tty_init): Delete declaration. (tty_terminate): Ditto. (attach_tty): Ditto. (create_tty_master): Ditto.
This commit is contained in:
parent
a615ed8023
commit
71d59a926f
|
@ -1,3 +1,52 @@
|
|||
2006-06-03 Christopher Faylor <cgf@timesys.com>
|
||||
|
||||
* dcrt0.cc (dll_crt0_0): Call tty_list::init_session here.
|
||||
(dll_crt0_1): Reflect renaming from tty_init to tty::init_session.
|
||||
(do_exit): Reflect moving of tty_terminate into tty_list.
|
||||
* exceptions.cc (events_init): Move tty_mutex stuff elsewhere.
|
||||
* fhandler_console.cc (set_console_title): Use lock_ttys class.
|
||||
* fhandler_termios.cc (fhandler_termios::bg_check): Make debug output
|
||||
more accurate.
|
||||
* fhandler_tty.cc (fhandler_tty_slave::open): Reflect move of
|
||||
attach_tty into tty_list class. Don't attempt to grab master end of
|
||||
pty if master doesn't exist.
|
||||
(fhandler_pty_master::open): Reflect move of allocate_tty into tty_list
|
||||
class. Use lock_ttys::release to release mutex. Improve debugging
|
||||
output.
|
||||
(fhandler_pty_master::setup): Remove if 0'ed block. Fix argument to
|
||||
SetNamedPipeHandleState.
|
||||
* pinfo.cc (_pinfo::set_ctty): Lock ttys before setting sid/pgid.
|
||||
Improve debugging. Add temporary debugging.
|
||||
* tty.cc (tty_list::init_session): New function.
|
||||
(tty::init_session): Rename from tty_init. Reflect move of attach_tty
|
||||
to tty_list class.
|
||||
(tty::create_master): Rename from create_tty_master.
|
||||
(tty_list::attach): Rename from attach_tty. Reflect renaming of
|
||||
connect_tty to connect. Ditto for allocate_tty.
|
||||
(tty_terminate): Delete.
|
||||
(tty_list::terminate): Subsume tty_terminate. Use lock_ttys rather
|
||||
than manipulating mutex directly.
|
||||
(tty_list::allocate): Rename from allocate_tty. Use lock_ttys rather
|
||||
than manipulating mutex directly. Don't set sid here since linux
|
||||
apparently doesn't do this. Reflect move of create_tty_master into
|
||||
tty.
|
||||
(lock_ttys::lock_ttys): Define new constructor.
|
||||
(lock_ttys::release): New function.
|
||||
* tty.h (tty::exists): Return false immediately if !master_pid.
|
||||
(tty::set_master_closed): Define new function.
|
||||
(tty::create_master): Ditto.
|
||||
(tty::init_session): Ditto.
|
||||
(tty_list::mutex): New field.
|
||||
(tty_list::allocate): Define new function.
|
||||
(tty_list::connect): Ditto.
|
||||
(tty_list::attach): Ditto.
|
||||
(tty_list::init_session): Ditto.
|
||||
(lock_ttys): New class.
|
||||
(tty_init): Delete declaration.
|
||||
(tty_terminate): Ditto.
|
||||
(attach_tty): Ditto.
|
||||
(create_tty_master): Ditto.
|
||||
|
||||
2006-06-03 Christopher Faylor <cgf@timesys.com>
|
||||
|
||||
* Makefile.in (libdl.a): New library.
|
||||
|
|
|
@ -768,6 +768,7 @@ dll_crt0_0 ()
|
|||
|
||||
/* Initialize events */
|
||||
events_init ();
|
||||
tty_list::init_session ();
|
||||
|
||||
cygheap->cwd.init ();
|
||||
|
||||
|
@ -867,9 +868,8 @@ dll_crt0_1 (void *)
|
|||
if (!threadfunc_ix)
|
||||
system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
|
||||
|
||||
|
||||
/* Connect to tty. */
|
||||
tty_init ();
|
||||
tty::init_session ();
|
||||
|
||||
if (!__argc)
|
||||
{
|
||||
|
@ -1110,7 +1110,7 @@ do_exit (int status)
|
|||
if (exit_state < ES_TTY_TERMINATE)
|
||||
{
|
||||
exit_state = ES_TTY_TERMINATE;
|
||||
tty_terminate ();
|
||||
cygwin_shared->tty.terminate ();
|
||||
}
|
||||
|
||||
myself.exit (n);
|
||||
|
|
|
@ -369,7 +369,7 @@ try_to_debug (bool waitloop)
|
|||
/* if any of these mutexes is owned, we will fail to start any cygwin app
|
||||
until trapped app exits */
|
||||
|
||||
ReleaseMutex (tty_mutex);
|
||||
lock_ttys::release ();
|
||||
|
||||
/* prevent recursive exception handling */
|
||||
char* rawenv = GetEnvironmentStrings () ;
|
||||
|
@ -1297,22 +1297,9 @@ _cygtls::signal_exit (int rc)
|
|||
do_exit (rc);
|
||||
}
|
||||
|
||||
HANDLE NO_COPY tty_mutex = NULL;
|
||||
|
||||
void
|
||||
events_init ()
|
||||
{
|
||||
char *name;
|
||||
char mutex_name[CYG_MAX_PATH];
|
||||
/* tty_mutex is on while searching for a tty slot. It's necessary
|
||||
while finding console window handle */
|
||||
|
||||
if (!(tty_mutex = CreateMutex (&sec_all_nih, FALSE,
|
||||
name = shared_name (mutex_name,
|
||||
"tty_mutex", 0))))
|
||||
api_fatal ("can't create title mutex '%s', %E", name);
|
||||
|
||||
ProtectHandle (tty_mutex);
|
||||
mask_sync.init ("mask_sync");
|
||||
windows_system_directory[0] = '\0';
|
||||
GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
|
||||
|
@ -1393,7 +1380,7 @@ _cygtls::copy_context (CONTEXT *c)
|
|||
void
|
||||
_cygtls::signal_debugger (int sig)
|
||||
{
|
||||
if (being_debugged ())
|
||||
if (isinitialized () && being_debugged ())
|
||||
{
|
||||
char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffff")];
|
||||
__small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %p %p", sig, thread_id, &thread_context);
|
||||
|
|
|
@ -1781,14 +1781,11 @@ fhandler_console::set_close_on_exec (bool val)
|
|||
void __stdcall
|
||||
set_console_title (char *title)
|
||||
{
|
||||
int rc;
|
||||
char buf[257];
|
||||
strncpy (buf, title, sizeof (buf) - 1);
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
if ((rc = WaitForSingleObject (tty_mutex, 15000)) != WAIT_OBJECT_0)
|
||||
sigproc_printf ("wait for title mutex failed rc %d, %E", rc);
|
||||
lock_ttys here (15000);
|
||||
SetConsoleTitle (buf);
|
||||
ReleaseMutex (tty_mutex);
|
||||
debug_printf ("title '%s'", buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,8 +138,8 @@ fhandler_termios::bg_check (int sig)
|
|||
if (sig < 0)
|
||||
sig = -sig;
|
||||
|
||||
termios_printf ("bg I/O pgid %d, tpgid %d, %s", myself->pgid, tc->getpgid (),
|
||||
myctty ());
|
||||
termios_printf ("bg I/O pgid %d, tpgid %d, %s, ntty tty%d", myself->pgid, tc->getpgid (),
|
||||
myctty (), tc->ntty);
|
||||
|
||||
if (tc->getsid () == 0)
|
||||
{
|
||||
|
|
|
@ -471,7 +471,7 @@ fhandler_tty_slave::open (int flags, mode_t)
|
|||
|
||||
tcinit (cygwin_shared->tty[get_unit ()]);
|
||||
|
||||
attach_tty (get_unit ());
|
||||
cygwin_shared->tty.attach (get_unit ());
|
||||
|
||||
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
||||
/* Create synchronisation events */
|
||||
|
@ -537,6 +537,12 @@ fhandler_tty_slave::open (int flags, mode_t)
|
|||
|| !cygserver_attach_tty (&from_master_local, &to_master_local))
|
||||
#endif
|
||||
{
|
||||
if (get_ttyp ()->master_pid < 0)
|
||||
{
|
||||
set_errno (EAGAIN);
|
||||
termios_printf ("*** master is closed");
|
||||
return 0;
|
||||
}
|
||||
pinfo p (get_ttyp ()->master_pid);
|
||||
if (!p)
|
||||
{
|
||||
|
@ -1087,7 +1093,8 @@ fhandler_pty_master::open (int flags, mode_t)
|
|||
goto out;
|
||||
}
|
||||
|
||||
int ntty = cygwin_shared->tty.allocate_tty (false);
|
||||
int ntty;
|
||||
ntty = cygwin_shared->tty.allocate (false);
|
||||
if (ntty < 0)
|
||||
return 0;
|
||||
|
||||
|
@ -1095,10 +1102,10 @@ fhandler_pty_master::open (int flags, mode_t)
|
|||
slave.setunit (ntty);
|
||||
if (!setup (*cygwin_shared->tty[ntty]))
|
||||
{
|
||||
ReleaseMutex (tty_mutex); // lock was set in allocate_tty
|
||||
lock_ttys::release ();
|
||||
return 0;
|
||||
}
|
||||
ReleaseMutex (tty_mutex); // lock was set in allocate_tty
|
||||
lock_ttys::release ();
|
||||
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
||||
set_open_status ();
|
||||
//
|
||||
|
@ -1112,8 +1119,9 @@ fhandler_pty_master::open (int flags, mode_t)
|
|||
out:
|
||||
usecount = 0;
|
||||
arch->usecount++;
|
||||
report_tty_counts (this, "opened master", "");
|
||||
termios_printf ("opened pty master tty%d", get_unit ());
|
||||
char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
|
||||
__small_sprintf (buf, "opened pty master for tty%d", get_unit ());
|
||||
report_tty_counts (this, buf, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1184,8 +1192,10 @@ fhandler_pty_master::close ()
|
|||
}
|
||||
fhandler_tty_common::close ();
|
||||
|
||||
if (!hExeced && get_ttyp ()->master_pid == myself->pid)
|
||||
get_ttyp ()->init ();
|
||||
if (hExeced || get_ttyp ()->master_pid != myself->pid)
|
||||
termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid);
|
||||
else
|
||||
get_ttyp ()->set_master_closed ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1337,11 +1347,6 @@ fhandler_pty_master::setup (tty& t)
|
|||
|
||||
/* Create communication pipes */
|
||||
|
||||
#if 0 // CGF: don't think this is needed since it is handled by the constructor
|
||||
input_handle = io_handle = output_done_event = ioctl_done_event =
|
||||
ioctl_request_event = input_available_event = output_mutex = input_mutex NULL;
|
||||
#endif
|
||||
|
||||
/* FIXME: should this be sec_none_nih? */
|
||||
if (!CreatePipe (&from_master, &get_output_handle (), &sec_all, 128 * 1024))
|
||||
{
|
||||
|
@ -1355,7 +1360,7 @@ fhandler_pty_master::setup (tty& t)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (!SetNamedPipeHandleState (&get_output_handle (), &pipe_mode, NULL, NULL))
|
||||
if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
|
||||
termios_printf ("can't set output_handle(%p) to non-blocking mode",
|
||||
get_output_handle ());
|
||||
|
||||
|
|
|
@ -331,14 +331,20 @@ _pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch)
|
|||
if ((ctty < 0 || ctty == tc->ntty) && !(flags & O_NOCTTY))
|
||||
{
|
||||
ctty = tc->ntty;
|
||||
syscall_printf ("attached %s sid %d, pid %d, tty->pgid %d, tty->sid %d",
|
||||
__ctty (), sid, pid, pgid, tc->getsid ());
|
||||
lock_ttys here;
|
||||
syscall_printf ("attaching %s sid %d, pid %d, pgid %d, tty->pgid %d, tty->sid %d",
|
||||
__ctty (), sid, pid, pgid, tc->getpgid (), tc->getsid ());
|
||||
|
||||
pinfo p (tc->getsid ());
|
||||
if (sid == pid && (!p || p->pid == pid || !p->exists ()))
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
debug_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.",
|
||||
__ctty (), tc->getsid (), sid, tc->getpgid (), pgid);
|
||||
#else
|
||||
paranoid_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.",
|
||||
__ctty (), tc->getsid (), sid, tc->getpgid (), pgid);
|
||||
#endif
|
||||
/* We are the session leader */
|
||||
tc->setsid (sid);
|
||||
tc->setpgid (pgid);
|
||||
|
@ -346,7 +352,9 @@ _pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch)
|
|||
else
|
||||
sid = tc->getsid ();
|
||||
if (tc->getpgid () == 0)
|
||||
{debug_printf ("setting pgid to %d", pgid);
|
||||
tc->setpgid (pgid);
|
||||
}
|
||||
if (cygheap->ctty != arch)
|
||||
{
|
||||
debug_printf ("cygheap->ctty %p, arch %p", cygheap->ctty, arch);
|
||||
|
|
|
@ -54,8 +54,23 @@ ttyslot (void)
|
|||
return myself->ctty;
|
||||
}
|
||||
|
||||
HANDLE NO_COPY tty_list::mutex = NULL;
|
||||
|
||||
void __stdcall
|
||||
tty_init ()
|
||||
tty_list::init_session ()
|
||||
{
|
||||
char mutex_name[CYG_MAX_PATH];
|
||||
/* tty_list::mutex is used while searching for a tty slot. It's necessary
|
||||
while finding console window handle */
|
||||
|
||||
char *name = shared_name (mutex_name, "tty_list::mutex", 0);
|
||||
if (!(mutex = CreateMutex (&sec_all_nih, FALSE, name)))
|
||||
api_fatal ("can't create tty_list::mutex '%s', %E", name);
|
||||
ProtectHandle (mutex);
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
tty::init_session ()
|
||||
{
|
||||
if (!myself->cygstarted && NOTSTATE (myself, PID_CYGPARENT))
|
||||
cygheap->fdtab.get_debugger_info ();
|
||||
|
@ -64,7 +79,7 @@ tty_init ()
|
|||
return;
|
||||
if (myself->ctty == -1)
|
||||
if (NOTSTATE (myself, PID_CYGPARENT))
|
||||
myself->ctty = attach_tty (myself->ctty);
|
||||
myself->ctty = cygwin_shared->tty.attach (myself->ctty);
|
||||
else
|
||||
return;
|
||||
if (myself->ctty == -1)
|
||||
|
@ -74,7 +89,7 @@ tty_init ()
|
|||
/* Create session's master tty */
|
||||
|
||||
void __stdcall
|
||||
create_tty_master (int ttynum)
|
||||
tty::create_master (int ttynum)
|
||||
{
|
||||
device ttym = *ttym_dev;
|
||||
ttym.setunit (ttynum); /* CGF FIXME device */
|
||||
|
@ -104,29 +119,23 @@ create_tty_master (int ttynum)
|
|||
}
|
||||
}
|
||||
|
||||
void __stdcall
|
||||
tty_terminate ()
|
||||
{
|
||||
if (NOTSTATE (myself, PID_USETTY))
|
||||
return;
|
||||
cygwin_shared->tty.terminate ();
|
||||
}
|
||||
|
||||
int __stdcall
|
||||
attach_tty (int num)
|
||||
tty_list::attach (int num)
|
||||
{
|
||||
if (num != -1)
|
||||
{
|
||||
return cygwin_shared->tty.connect_tty (num);
|
||||
return connect (num);
|
||||
}
|
||||
if (NOTSTATE (myself, PID_USETTY))
|
||||
return -1;
|
||||
return cygwin_shared->tty.allocate_tty (true);
|
||||
return allocate (true);
|
||||
}
|
||||
|
||||
void
|
||||
tty_list::terminate ()
|
||||
{
|
||||
if (NOTSTATE (myself, PID_USETTY))
|
||||
return;
|
||||
int ttynum = myself->ctty;
|
||||
|
||||
/* Keep master running till there are connected clients */
|
||||
|
@ -151,8 +160,7 @@ tty_list::terminate ()
|
|||
low_priority_sleep (200);
|
||||
}
|
||||
|
||||
if (WaitForSingleObject (tty_mutex, INFINITE) == WAIT_FAILED)
|
||||
termios_printf ("WFSO for tty_mutex %p failed, %E", tty_mutex);
|
||||
lock_ttys here ();
|
||||
|
||||
termios_printf ("tty %d master about to finish", ttynum);
|
||||
CloseHandle (tty_master->get_io_handle ());
|
||||
|
@ -163,13 +171,11 @@ tty_list::terminate ()
|
|||
char buf[20];
|
||||
__small_sprintf (buf, "tty%d", ttynum);
|
||||
logout (buf);
|
||||
|
||||
ReleaseMutex (tty_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tty_list::connect_tty (int ttynum)
|
||||
tty_list::connect (int ttynum)
|
||||
{
|
||||
if (ttynum < 0 || ttynum >= NTTYS)
|
||||
{
|
||||
|
@ -201,7 +207,7 @@ tty_list::init ()
|
|||
If flag == 0, just find a free tty.
|
||||
*/
|
||||
int
|
||||
tty_list::allocate_tty (bool with_console)
|
||||
tty_list::allocate (bool with_console)
|
||||
{
|
||||
HWND console;
|
||||
int freetty = -1;
|
||||
|
@ -209,8 +215,7 @@ tty_list::allocate_tty (bool with_console)
|
|||
|
||||
/* FIXME: This whole function needs a protective mutex. */
|
||||
|
||||
if (WaitForSingleObject (tty_mutex, INFINITE) == WAIT_FAILED)
|
||||
termios_printf ("WFSO for tty_mutex %p failed, %E", tty_mutex);
|
||||
lock_ttys here;
|
||||
|
||||
if (!with_console)
|
||||
console = NULL;
|
||||
|
@ -282,26 +287,21 @@ tty_list::allocate_tty (bool with_console)
|
|||
t = ttys + freetty;
|
||||
t->init ();
|
||||
t->setsid (-1);
|
||||
t->setpgid (myself->pgid);
|
||||
t->sethwnd (console);
|
||||
|
||||
out:
|
||||
if (freetty < 0)
|
||||
{
|
||||
ReleaseMutex (tty_mutex);
|
||||
system_printf ("No tty allocated");
|
||||
}
|
||||
else if (!with_console)
|
||||
{
|
||||
termios_printf ("tty%d allocated", freetty);
|
||||
/* exit with tty_mutex still held -- caller has more work to do */
|
||||
here.dont_release (); /* exit with mutex still held -- caller has more work to do */
|
||||
}
|
||||
else
|
||||
{
|
||||
termios_printf ("console %p associated with tty%d", console, freetty);
|
||||
if (!hmaster)
|
||||
create_tty_master (freetty);
|
||||
ReleaseMutex (tty_mutex);
|
||||
tty::create_master (freetty);
|
||||
}
|
||||
return freetty;
|
||||
}
|
||||
|
@ -386,3 +386,18 @@ tty::get_event (const char *fmt, BOOL manual_reset)
|
|||
termios_printf ("created event %s", buf);
|
||||
return hev;
|
||||
}
|
||||
|
||||
lock_ttys::lock_ttys (DWORD howlong): release_me (true)
|
||||
{
|
||||
if (WaitForSingleObject (tty_list::mutex, howlong) == WAIT_FAILED)
|
||||
{
|
||||
termios_printf ("WFSO for mutex %p failed, %E", tty_list::mutex);
|
||||
release_me = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lock_ttys::release ()
|
||||
{
|
||||
ReleaseMutex (tty_list::mutex);
|
||||
}
|
||||
|
|
|
@ -105,6 +105,8 @@ public:
|
|||
HANDLE open_input_mutex ();
|
||||
bool exists ()
|
||||
{
|
||||
if (!master_pid)
|
||||
return false;
|
||||
HANDLE h = open_output_mutex ();
|
||||
if (h)
|
||||
{
|
||||
|
@ -113,24 +115,41 @@ public:
|
|||
}
|
||||
return slave_alive ();
|
||||
}
|
||||
void set_master_closed () {master_pid = -1;}
|
||||
static void __stdcall create_master (int);
|
||||
static void __stdcall init_session ();
|
||||
friend class fhandler_pty_master;
|
||||
};
|
||||
|
||||
class tty_list
|
||||
{
|
||||
tty ttys[NTTYS];
|
||||
static HANDLE mutex;
|
||||
|
||||
public:
|
||||
tty * operator [](int n) {return ttys + n;}
|
||||
int allocate_tty (bool); /* true if allocate a tty, pty otherwise */
|
||||
int connect_tty (int);
|
||||
int allocate (bool); /* true if allocate a tty, pty otherwise */
|
||||
int connect (int);
|
||||
void terminate ();
|
||||
void init ();
|
||||
tty_min *get_tty (int n);
|
||||
int __stdcall attach (int);
|
||||
static void __stdcall init_session ();
|
||||
friend class lock_ttys;
|
||||
};
|
||||
|
||||
class lock_ttys
|
||||
{
|
||||
bool release_me;
|
||||
public:
|
||||
lock_ttys (DWORD = INFINITE);
|
||||
static void release ();
|
||||
void dont_release () {release_me = false;}
|
||||
~lock_ttys ()
|
||||
{
|
||||
if (release_me)
|
||||
release ();
|
||||
}
|
||||
};
|
||||
|
||||
void __stdcall tty_init ();
|
||||
void __stdcall tty_terminate ();
|
||||
int __stdcall attach_tty (int);
|
||||
void __stdcall create_tty_master (int);
|
||||
extern "C" int ttyslot (void);
|
||||
|
|
Loading…
Reference in New Issue