diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 186bad32a..dacf7aae6 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +Thu Sep 7 12:14:43 2000 Christopher Faylor + + Split out tty and shared_info stuff into their own headers and use + throughout. Include sys/termios.h for files which need it. + * tty.h: New file. + * shared_info.h: New file. + * fhandler.h: Move inline methods that rely on tty stuff to + fhandler_console.cc. + * fhandler_tty.cc (fhandler_pty_master::process_slave_output): Set + output_done_event immediately after reading data to speed up tty output + processing. + (process_output): Set write_error to errno or zero. + (fhandler_tty_slave::write): Check previous write error prior to + writing to slave end of pipe. This allows tty output to be slightly + less synchronous. + * fhandler_console.cc (fhandler_console::tcsetpgrp): Moved here from + fhandler.h. + (fhandler_console::set_input_state): Ditto. + Wed Sep 6 21:11:13 2000 Christopher Faylor * exceptions.cc (signal_exit): Reset all mutos owned by the main diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 3c02ee2b2..4121d89f9 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -28,6 +28,8 @@ details. */ #include "path.h" #include "dtable.h" #include "thread.h" +#include "tty.h" +#include "shared_info.h" #define MAX_AT_FILE_LEVEL 10 diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 3395a1eea..8b133cc8c 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -20,6 +20,8 @@ details. */ #include "cygerrno.h" #include "thread.h" #include "perthread.h" +#include "tty.h" +#include "shared_info.h" char debugger_command[2 * MAX_PATH + 20]; diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index bfc4f1b25..64a3acf02 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -16,6 +16,8 @@ details. */ #include "sigproc.h" #include "pinfo.h" #include +#include "tty.h" +#include "shared_info.h" static external_pinfo * fillout_pinfo (pid_t pid, int winpid) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index c69d5f316..e5a903c37 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -18,6 +18,8 @@ details. */ #include "cygerrno.h" #include "fhandler.h" #include "path.h" +#include "tty.h" +#include "shared_info.h" static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index a7f942a7e..b25665873 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -511,6 +511,8 @@ public: #define release_output_mutex() \ __release_output_mutex (__PRETTY_FUNCTION__, __LINE__); +class tty; +class tty_min; class fhandler_termios: public fhandler_base { protected: @@ -594,7 +596,7 @@ public: int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); - int tcsetpgrp (const pid_t pid) { tc->pgid = pid; return 0; } + int tcsetpgrp (const pid_t pid); /* Special dup as we must dup two handles */ int dup (fhandler_base *child); @@ -609,11 +611,7 @@ public: void fixup_after_exec (HANDLE); void set_close_on_exec (int val); void fixup_after_fork (HANDLE parent); - void set_input_state () - { - if (TTYISSETF (RSTCONS)) - input_tcsetattr (0, &tc->ti); - } + void set_input_state (); }; class fhandler_tty_common: public fhandler_termios diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 33bf18b58..ff70bb4b0 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -24,6 +24,8 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "tty.h" +#include "shared_info.h" /* * Scroll the screen context. @@ -249,6 +251,21 @@ fhandler_console::read (void *pv, size_t buflen) return copied_chars; } +int +fhandler_console::tcsetpgrp (pid_t pid) +{ + tc->pgid = pid; + return 0; +} + +void +fhandler_console::set_input_state () +{ + if (TTYISSETF (RSTCONS)) + input_tcsetattr (0, &tc->ti); +} + + static struct { SHORT winTop; diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc index e68e34e11..1f31cd61e 100644 --- a/winsup/cygwin/fhandler_serial.cc +++ b/winsup/cygwin/fhandler_serial.cc @@ -18,6 +18,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include /**********************************************************************/ /* fhandler_serial */ diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index 486e47918..72b2e998d 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -19,6 +19,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "tty.h" /* Common functions shared by tty/console */ diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 6c7e3605e..c78f2bad6 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -23,6 +23,8 @@ details. */ #include "sigproc.h" #include "pinfo.h" #include "cygheap.h" +#include "tty.h" +#include "shared_info.h" /* Tty master stuff */ @@ -285,14 +287,12 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on } termios_printf ("bytes read %u", n); + get_ttyp ()->write_error = 0; + if (output_done_event != NULL) + SetEvent (output_done_event); if (get_ttyp ()->ti.c_lflag & FLUSHO) - { - get_ttyp ()->write_retval = n; - if (output_done_event != NULL) - SetEvent (output_done_event); - continue; - } + continue; char *optr; optr = buf; @@ -389,8 +389,7 @@ process_output (void *) ExitThread (0); } n = tty_master->console->write ((void *) buf, (size_t) n); - tty_master->get_ttyp ()->write_retval = n == -1 ? -get_errno () : n; - SetEvent (tty_master->output_done_event); + tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0; } } @@ -554,6 +553,16 @@ fhandler_tty_slave::write (const void *ptr, size_t len) ptr = (char *) ptr + n; len -= n; + /* Previous write may have set write_error to != 0. Check it here. + This is less than optimal, but the alternative slows down tty + writes enormously. */ + if (get_ttyp ()->write_error) + { + set_errno (get_ttyp ()->write_error); + towrite = (DWORD) -1; + break; + } + if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE) { DWORD err = GetLastError (); @@ -577,13 +586,6 @@ fhandler_tty_slave::write (const void *ptr, size_t len) rc = WaitForSingleObject (output_done_event, x); termios_printf("waited %d ms for output_done_event, WFSO %d", x, rc); } - - if (get_ttyp ()->write_retval < 0) - { - set_errno (-get_ttyp ()->write_retval); - towrite = (DWORD) -1; - break; - } } release_output_mutex (); return towrite; @@ -931,12 +933,7 @@ fhandler_pty_master::write (const void *ptr, size_t len) int fhandler_pty_master::read (void *ptr, size_t len) { - int x = process_slave_output ((char *) ptr, len, pktmode); - - if (output_done_event != NULL) - SetEvent (output_done_event); - - return x; + return process_slave_output ((char *) ptr, len, pktmode); } int diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index d1408eb7b..1ad80a2a5 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -15,6 +15,8 @@ details. */ #include "sigproc.h" #include "pinfo.h" #include "heap.h" +#include "tty.h" +#include "shared_info.h" #define assert(x) diff --git a/winsup/cygwin/ioctl.cc b/winsup/cygwin/ioctl.cc index 5e198b828..50bed772b 100644 --- a/winsup/cygwin/ioctl.cc +++ b/winsup/cygwin/ioctl.cc @@ -17,6 +17,7 @@ details. */ #include "cygerrno.h" #include "fhandler.h" #include "dtable.h" +#include extern "C" int ioctl (int fd, int cmd, void *buf) diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index a29a8a433..29e912699 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -20,6 +20,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include /* Read /etc/passwd only once for better performance. This is done on the first call that needs information from it. */ diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index f322a6fa7..307ab62e1 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -65,6 +65,8 @@ details. */ #include "sigproc.h" #include "pinfo.h" #include "cygheap.h" +#include "tty.h" +#include "shared_info.h" static int normalize_win32_path (const char *src, char *dst); static void slashify (const char *src, char *dst, int trailing_slash_p); diff --git a/winsup/cygwin/registry.cc b/winsup/cygwin/registry.cc index ebe6bb3c6..82acc6981 100644 --- a/winsup/cygwin/registry.cc +++ b/winsup/cygwin/registry.cc @@ -9,6 +9,8 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" +#include "tty.h" +#include "shared_info.h" char cygnus_class[] = "cygnus"; diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index c7181fb53..b52471a0e 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -39,6 +39,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "perthread.h" +#include "tty.h" /* * All these defines below should be in sys/types.h diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 1cb8e6e9c..aab2b1a9e 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -17,6 +17,8 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "tty.h" +#include "shared_info.h" #define SHAREDVER (unsigned)(cygwin_version.api_major << 16 | \ cygwin_version.api_minor) diff --git a/winsup/cygwin/shared.h b/winsup/cygwin/shared.h index ed0b83fc3..bd88ca772 100644 --- a/winsup/cygwin/shared.h +++ b/winsup/cygwin/shared.h @@ -80,270 +80,14 @@ public: char *__stdcall get_registry_hive_path (const PSID psid, char *path); void __stdcall load_registry_hive (PSID psid); -/******** Mount Table ********/ - -/* Mount table entry */ - -class mount_item -{ -public: - /* FIXME: Nasty static allocation. Need to have a heap in the shared - area [with the user being able to configure at runtime the max size]. */ - - /* Win32-style mounted partition source ("C:\foo\bar"). - native_path[0] == 0 for unused entries. */ - char native_path[MAX_PATH]; - int native_pathlen; - - /* POSIX-style mount point ("/foo/bar") */ - char posix_path[MAX_PATH]; - int posix_pathlen; - - unsigned flags; - - void init (const char *dev, const char *path, unsigned flags); - - struct mntent *getmntent (); -}; - -/* Warning: Decreasing this value will cause cygwin.dll to ignore existing - higher numbered registry entries. Don't change this number willy-nilly. - What we need is to have a more dynamic allocation scheme, but the current - scheme should be satisfactory for a long while yet. */ -#define MAX_MOUNTS 30 - -class mount_info -{ - int posix_sorted[MAX_MOUNTS]; - int native_sorted[MAX_MOUNTS]; -public: - int nmounts; - mount_item mount[MAX_MOUNTS]; - - /* Strings used by getmntent(). */ - char mnt_type[20]; - char mnt_opts[20]; - char mnt_fsname[MAX_PATH]; - char mnt_dir[MAX_PATH]; - - /* cygdrive_prefix is used as the root of the path automatically - prepended to a path when the path has no associated mount. - cygdrive_flags are the default flags for the cygdrives. */ - char cygdrive[MAX_PATH]; - size_t cygdrive_len; - unsigned cygdrive_flags; - - /* Increment when setting up a reg_key if mounts area had to be - created so we know when we need to import old mount tables. */ - int had_to_create_mount_areas; - - void init (); - int add_item (const char *dev, const char *path, unsigned flags, int reg_p); - int del_item (const char *path, unsigned flags, int reg_p); - - void from_registry (); - int add_reg_mount (const char * native_path, const char * posix_path, - unsigned mountflags); - int del_reg_mount (const char * posix_path, unsigned mountflags); - - unsigned set_flags_from_win32_path (const char *path); - int conv_to_win32_path (const char *src_path, char *win32_path, - char *full_win32_path, DWORD &devn, int &unit, - unsigned *flags = NULL); - int conv_to_posix_path (const char *src_path, char *posix_path, - int keep_rel_p); - struct mntent *getmntent (int x); - - int write_cygdrive_info_to_registry (const char *cygdrive_prefix, unsigned flags); - int remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags); - int get_cygdrive_prefixes (char *user, char *system); - - void import_v1_mounts (); - -private: - - void sort (); - void read_mounts (reg_key& r); - void read_v1_mounts (reg_key r, unsigned which); - void mount_slash (); - void to_registry (); - - int cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p); - void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); - void slash_drive_to_win32_path (const char *path, char *buf, int trailing_slash_p); - void read_cygdrive_info_from_registry (); -}; - -/******** TTY Support ********/ - -/* tty tables */ - -#define INP_BUFFER_SIZE 256 -#define OUT_BUFFER_SIZE 256 -#define NTTYS 128 -#define TTY_CONSOLE 0x40000000 -#define tty_attached(p) ((p)->ctty >= 0 && (p)->ctty != TTY_CONSOLE) - -/* Input/Output/ioctl events */ - -#define OUTPUT_DONE_EVENT "cygtty%d.output.done" -#define IOCTL_REQUEST_EVENT "cygtty%d.ioctl.request" -#define IOCTL_DONE_EVENT "cygtty%d.ioctl.done" -#define RESTART_OUTPUT_EVENT "cygtty%d.output.restart" -#define OUTPUT_MUTEX "cygtty%d.output.mutex" -#define TTY_SLAVE_ALIVE "cygtty%x.slave_alive" -#define TTY_MASTER_ALIVE "cygtty%x.master_alive" - -#include - -enum -{ - TTY_INITIALIZED = 1, /* Set if tty is initialized */ - TTY_RSTCONS = 2 /* Set if console needs to be set to "non-cooked" */ -}; - -#define TTYISSETF(x) __ISSETF (tc, x, TTY) -#define TTYSETF(x) __SETF (tc, x, TTY) -#define TTYCLEARF(x) __CLEARF (tc, x, TTY) -#define TTYCONDSETF(n, x) __CONDSETF(n, tc, x, TTY) - -#ifndef MIN_CTRL_C_SLOP -#define MIN_CTRL_C_SLOP 50 -#endif - -class tty_min -{ - pid_t sid; /* Session ID of tty */ -public: - DWORD status; - pid_t pgid; - int OutputStopped; - int ntty; - DWORD last_ctrl_c; // tick count of last ctrl-c - - tty_min (int t = -1, pid_t s = -1) : sid (s), ntty (t) {} - void setntty (int n) {ntty = n;} - pid_t getpgid () {return pgid;} - void setpgid (int pid) {pgid = pid;} - int getsid () {return sid;} - void setsid (pid_t tsid) {sid = tsid;} - struct termios ti; - struct winsize winsize; - - /* ioctl requests buffer */ - int cmd; - union - { - struct termios termios; - struct winsize winsize; - int value; - pid_t pid; - } arg; - /* XXX_retval variables holds master's completion codes. Error are stored as - * -ERRNO - */ - int ioctl_retval; - - int write_retval; -}; - -class fhandler_pty_master; - -class tty: public tty_min -{ - HANDLE get_event (const char *fmt, BOOL inherit); -public: - HWND hwnd; /* Console window handle tty belongs to */ - - DWORD master_pid; /* Win32 PID of tty master process */ - - HANDLE from_master, to_slave; - HANDLE from_slave, to_master; - - int read_retval; - BOOL was_opened; /* True if opened at least once. */ - - void init (); - HANDLE create_inuse (const char *); - BOOL common_init (fhandler_pty_master *); - BOOL alive (const char *fmt); - BOOL slave_alive (); - BOOL master_alive (); - HWND gethwnd () {return hwnd;} - void sethwnd (HWND wnd) {hwnd = wnd;} - int make_pipes (fhandler_pty_master *ptym); - HANDLE open_output_mutex (BOOL inherit = FALSE) - { - char buf[80]; - __small_sprintf (buf, OUTPUT_MUTEX, ntty); - return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf); - } - BOOL exists () - { - HANDLE h = open_output_mutex (); - if (h) - { - CloseHandle (h); - return 1; - } - return slave_alive (); - } -}; - -class tty_list -{ - tty ttys[NTTYS]; - -public: - tty * operator [](int n) {return ttys + n;} - int allocate_tty (int n); /* n non zero if allocate a tty, pty otherwise */ - int connect_tty (int); - void terminate (); - void init (); - tty_min *get_tty (int n); -}; - -void __stdcall tty_init (); -void __stdcall tty_terminate (); -int __stdcall attach_tty (int); -void __stdcall create_tty_master (int); -extern "C" int ttyslot (void); - -/******** Shared Info ********/ -/* Data accessible to all tasks */ - -class shared_info -{ - DWORD inited; - -public: - /* FIXME: Doesn't work if more than one user on system. */ - mount_info mount; - - int heap_chunk_in_mb; - unsigned heap_chunk_size (void); - - tty_list tty; - delqueue_list delqueue; - void initialize (void); -}; /* Various types of security attributes for use in Create* functions. */ extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih; extern SECURITY_ATTRIBUTES *__stdcall sec_user (PVOID sa_buf, PSID sid2 = NULL, BOOL inherit = TRUE); extern SECURITY_ATTRIBUTES *__stdcall sec_user_nih (PVOID sa_buf, PSID sid2 = NULL); -extern shared_info *cygwin_shared; -extern HANDLE cygwin_shared_h; -extern HANDLE console_shared_h; extern int __stdcall set_console_state_for_spawn (); -void __stdcall shared_init (void); -void __stdcall shared_terminate (void); - -char *__stdcall shared_name (const char *, int); -void *__stdcall open_shared (const char *name, HANDLE &shared_h, DWORD size, void *addr); - extern "C" { /* This is for programs that want to access the shared data. */ class shared_info *cygwin_getshared (void); diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h new file mode 100644 index 000000000..52c055989 --- /dev/null +++ b/winsup/cygwin/shared_info.h @@ -0,0 +1,130 @@ +/* shared_sec.h: shared info for cygwin + + Copyright 1998, 1999, 2000 Cygnus Solutions. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +/* Mount table entry */ + +class mount_item +{ +public: + /* FIXME: Nasty static allocation. Need to have a heap in the shared + area [with the user being able to configure at runtime the max size]. */ + + /* Win32-style mounted partition source ("C:\foo\bar"). + native_path[0] == 0 for unused entries. */ + char native_path[MAX_PATH]; + int native_pathlen; + + /* POSIX-style mount point ("/foo/bar") */ + char posix_path[MAX_PATH]; + int posix_pathlen; + + unsigned flags; + + void init (const char *dev, const char *path, unsigned flags); + + struct mntent *getmntent (); +}; + +/* Warning: Decreasing this value will cause cygwin.dll to ignore existing + higher numbered registry entries. Don't change this number willy-nilly. + What we need is to have a more dynamic allocation scheme, but the current + scheme should be satisfactory for a long while yet. */ +#define MAX_MOUNTS 30 + +class mount_info +{ + int posix_sorted[MAX_MOUNTS]; + int native_sorted[MAX_MOUNTS]; +public: + int nmounts; + mount_item mount[MAX_MOUNTS]; + + /* Strings used by getmntent(). */ + char mnt_type[20]; + char mnt_opts[20]; + char mnt_fsname[MAX_PATH]; + char mnt_dir[MAX_PATH]; + + /* cygdrive_prefix is used as the root of the path automatically + prepended to a path when the path has no associated mount. + cygdrive_flags are the default flags for the cygdrives. */ + char cygdrive[MAX_PATH]; + size_t cygdrive_len; + unsigned cygdrive_flags; + + /* Increment when setting up a reg_key if mounts area had to be + created so we know when we need to import old mount tables. */ + int had_to_create_mount_areas; + + void init (); + int add_item (const char *dev, const char *path, unsigned flags, int reg_p); + int del_item (const char *path, unsigned flags, int reg_p); + + void from_registry (); + int add_reg_mount (const char * native_path, const char * posix_path, + unsigned mountflags); + int del_reg_mount (const char * posix_path, unsigned mountflags); + + unsigned set_flags_from_win32_path (const char *path); + int conv_to_win32_path (const char *src_path, char *win32_path, + char *full_win32_path, DWORD &devn, int &unit, + unsigned *flags = NULL); + int conv_to_posix_path (const char *src_path, char *posix_path, + int keep_rel_p); + struct mntent *getmntent (int x); + + int write_cygdrive_info_to_registry (const char *cygdrive_prefix, unsigned flags); + int remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags); + int get_cygdrive_prefixes (char *user, char *system); + + void import_v1_mounts (); + +private: + + void sort (); + void read_mounts (reg_key& r); + void read_v1_mounts (reg_key r, unsigned which); + void mount_slash (); + void to_registry (); + + int cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p); + void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); + void slash_drive_to_win32_path (const char *path, char *buf, int trailing_slash_p); + void read_cygdrive_info_from_registry (); +}; + +/******** Shared Info ********/ +/* Data accessible to all tasks */ + +class shared_info +{ + DWORD inited; + +public: + /* FIXME: Doesn't work if more than one user on system. */ + mount_info mount; + + int heap_chunk_in_mb; + unsigned heap_chunk_size (void); + + tty_list tty; + delqueue_list delqueue; + void initialize (void); +}; + +extern shared_info *cygwin_shared; +extern HANDLE cygwin_shared_h; +extern HANDLE console_shared_h; + +void __stdcall shared_init (void); +void __stdcall shared_terminate (void); + +char *__stdcall shared_name (const char *, int); +void *__stdcall open_shared (const char *name, HANDLE &shared_h, DWORD size, void *addr); diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 50b8495ed..87b29c361 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -24,6 +24,8 @@ details. */ #include "child_info.h" #include "perthread.h" #include +#include "tty.h" +#include "shared_info.h" /* * Convenience defines diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index c95eef38b..dd24f9787 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -32,6 +32,8 @@ details. */ #include "sigproc.h" #include "pinfo.h" #include +#include "tty.h" +#include "shared_info.h" extern BOOL allow_ntsec; diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc index 52fe489ee..07fa998da 100644 --- a/winsup/cygwin/termios.cc +++ b/winsup/cygwin/termios.cc @@ -16,10 +16,10 @@ details. */ #include "cygerrno.h" #include "fhandler.h" #include "dtable.h" +#include /* tcsendbreak: POSIX 7.2.2.1 */ -extern "C" -int +extern "C" int tcsendbreak (int fd, int duration) { int res = -1; @@ -47,8 +47,7 @@ out: } /* tcdrain: POSIX 7.2.2.1 */ -extern "C" -int +extern "C" int tcdrain (int fd) { int res = -1; @@ -78,8 +77,7 @@ out: } /* tcflush: POSIX 7.2.2.1 */ -extern "C" -int +extern "C" int tcflush (int fd, int queue) { int res = -1; @@ -107,8 +105,7 @@ out: } /* tcflow: POSIX 7.2.2.1 */ -extern "C" -int +extern "C" int tcflow (int fd, int action) { int res = -1; @@ -136,8 +133,7 @@ out: } /* tcsetattr: POSIX96 7.2.1.1 */ -extern "C" -int +extern "C" int tcsetattr (int fd, int a, const struct termios *t) { int res = -1; @@ -169,8 +165,7 @@ out: } /* tcgetattr: POSIX 7.2.1.1 */ -extern "C" -int +extern "C" int tcgetattr (int fd, struct termios *in_t) { int res = -1; @@ -197,8 +192,7 @@ tcgetattr (int fd, struct termios *in_t) } /* tcgetpgrp: POSIX 7.2.3.1 */ -extern "C" -int +extern "C" int tcgetpgrp (int fd) { int res = -1; @@ -215,8 +209,7 @@ tcgetpgrp (int fd) } /* tcsetpgrp: POSIX 7.2.4.1 */ -extern "C" -int +extern "C" int tcsetpgrp (int fd, pid_t pgid) { int res = -1; @@ -239,24 +232,21 @@ tcsetpgrp (int fd, pid_t pgid) #undef cfsetispeed /* cfgetospeed: POSIX96 7.1.3.1 */ -extern "C" -speed_t +extern "C" speed_t cfgetospeed (struct termios *tp) { return __tonew_termios(tp)->c_ospeed; } /* cfgetispeed: POSIX96 7.1.3.1 */ -extern "C" -speed_t +extern "C" speed_t cfgetispeed (struct termios *tp) { return __tonew_termios(tp)->c_ispeed; } /* cfsetospeed: POSIX96 7.1.3.1 */ -extern "C" -int +extern "C" int cfsetospeed (struct termios *in_tp, speed_t speed) { struct termios *tp = __tonew_termios (in_tp); @@ -266,8 +256,7 @@ cfsetospeed (struct termios *in_tp, speed_t speed) } /* cfsetispeed: POSIX96 7.1.3.1 */ -extern "C" -int +extern "C" int cfsetispeed (struct termios *in_tp, speed_t speed) { struct termios *tp = __tonew_termios (in_tp); diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index d619a030c..4dbe72c1a 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -20,6 +20,8 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "tty.h" +#include "shared_info.h" extern fhandler_tty_master *tty_master; diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h new file mode 100644 index 000000000..f4fa67102 --- /dev/null +++ b/winsup/cygwin/tty.h @@ -0,0 +1,143 @@ +/* tty.h: shared info for cygwin + + Copyright 2000 Cygnus Solutions. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + + +/* tty tables */ + +#define INP_BUFFER_SIZE 256 +#define OUT_BUFFER_SIZE 256 +#define NTTYS 128 +#define TTY_CONSOLE 0x40000000 +#define tty_attached(p) ((p)->ctty >= 0 && (p)->ctty != TTY_CONSOLE) + +/* Input/Output/ioctl events */ + +#define OUTPUT_DONE_EVENT "cygtty%d.output.done" +#define IOCTL_REQUEST_EVENT "cygtty%d.ioctl.request" +#define IOCTL_DONE_EVENT "cygtty%d.ioctl.done" +#define RESTART_OUTPUT_EVENT "cygtty%d.output.restart" +#define OUTPUT_MUTEX "cygtty%d.output.mutex" +#define TTY_SLAVE_ALIVE "cygtty%x.slave_alive" +#define TTY_MASTER_ALIVE "cygtty%x.master_alive" + +#include + +enum +{ + TTY_INITIALIZED = 1, /* Set if tty is initialized */ + TTY_RSTCONS = 2 /* Set if console needs to be set to "non-cooked" */ +}; + +#define TTYISSETF(x) __ISSETF (tc, x, TTY) +#define TTYSETF(x) __SETF (tc, x, TTY) +#define TTYCLEARF(x) __CLEARF (tc, x, TTY) +#define TTYCONDSETF(n, x) __CONDSETF(n, tc, x, TTY) + +#ifndef MIN_CTRL_C_SLOP +#define MIN_CTRL_C_SLOP 50 +#endif + +class tty_min +{ + pid_t sid; /* Session ID of tty */ +public: + DWORD status; + pid_t pgid; + int OutputStopped; + int ntty; + DWORD last_ctrl_c; // tick count of last ctrl-c + + tty_min (int t = -1, pid_t s = -1) : sid (s), ntty (t) {} + void setntty (int n) {ntty = n;} + pid_t getpgid () {return pgid;} + void setpgid (int pid) {pgid = pid;} + int getsid () {return sid;} + void setsid (pid_t tsid) {sid = tsid;} + struct termios ti; + struct winsize winsize; + + /* ioctl requests buffer */ + int cmd; + union + { + struct termios termios; + struct winsize winsize; + int value; + pid_t pid; + } arg; + /* XXX_retval variables holds master's completion codes. Error are stored as + * -ERRNO + */ + int ioctl_retval; + + int write_error; +}; + +class fhandler_pty_master; + +class tty: public tty_min +{ + HANDLE get_event (const char *fmt, BOOL inherit); +public: + HWND hwnd; /* Console window handle tty belongs to */ + + DWORD master_pid; /* Win32 PID of tty master process */ + + HANDLE from_master, to_slave; + HANDLE from_slave, to_master; + + int read_retval; + BOOL was_opened; /* True if opened at least once. */ + + void init (); + HANDLE create_inuse (const char *); + BOOL common_init (fhandler_pty_master *); + BOOL alive (const char *fmt); + BOOL slave_alive (); + BOOL master_alive (); + HWND gethwnd () {return hwnd;} + void sethwnd (HWND wnd) {hwnd = wnd;} + int make_pipes (fhandler_pty_master *ptym); + HANDLE open_output_mutex (BOOL inherit = FALSE) + { + char buf[80]; + __small_sprintf (buf, OUTPUT_MUTEX, ntty); + return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf); + } + BOOL exists () + { + HANDLE h = open_output_mutex (); + if (h) + { + CloseHandle (h); + return 1; + } + return slave_alive (); + } +}; + +class tty_list +{ + tty ttys[NTTYS]; + +public: + tty * operator [](int n) {return ttys + n;} + int allocate_tty (int n); /* n non zero if allocate a tty, pty otherwise */ + int connect_tty (int); + void terminate (); + void init (); + tty_min *get_tty (int n); +}; + +void __stdcall tty_init (); +void __stdcall tty_terminate (); +int __stdcall attach_tty (int); +void __stdcall create_tty_master (int); +extern "C" int ttyslot (void);