X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fconsole-io.c;h=e3807feca84a350bb2ca7540e4f8752bf02e274d;hb=b50dc8d84850e0452a7a4d742ed0a0fa46fe491e;hp=98a86829c62241b60f01b8346af9ae1a3c3d9153;hpb=b5c4a503a24900428b2d1eb18ea7c0401bb22d88;p=mono.git diff --git a/mono/metadata/console-io.c b/mono/metadata/console-io.c index 98a86829c62..e3807feca84 100644 --- a/mono/metadata/console-io.c +++ b/mono/metadata/console-io.c @@ -13,13 +13,29 @@ #include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +/* On solaris, curses.h must come before both termios.h and term.h */ +#ifdef HAVE_CURSES_H +#include +#endif #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_TERM_H #include #endif +/* Needed for FIONREAD under solaris */ +#ifdef HAVE_SYS_FILIO_H +#include +#endif #ifndef PLATFORM_WIN32 #ifndef TIOCGWINSZ #include @@ -32,26 +48,60 @@ static gboolean setup_finished; static gboolean atexit_called; static gchar *teardown_str; -static struct termios initial_attr; +#ifdef PLATFORM_WIN32 MonoBoolean ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) { MONO_ARCH_SAVE_REGS; -#ifdef PLATFORM_WIN32 return (GetFileType (handle) == FILE_TYPE_CHAR); +} + +MonoBoolean +ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo) +{ + return FALSE; +} + +MonoBoolean +ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break) +{ + return FALSE; +} + +gint32 +ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) +{ + return FALSE; +} + +MonoBoolean +ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown, char *verase, char *vsusp, char *intr) +{ + return FALSE; +} + +MonoBoolean +ves_icall_System_ConsoleDriver_GetTtySize (HANDLE handle, gint32 *width, gint32 *height) +{ + return FALSE; +} + #else +static struct termios initial_attr; + +MonoBoolean +ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) +{ + MONO_ARCH_SAVE_REGS; + return isatty (GPOINTER_TO_INT (handle)); -#endif } static MonoBoolean set_property (gint property, gboolean value) { -#ifdef PLATFORM_WIN32 - return FALSE; -#else struct termios attr; gboolean callset = FALSE; gboolean check; @@ -77,7 +127,6 @@ set_property (gint property, gboolean value) return FALSE; return TRUE; -#endif } MonoBoolean @@ -95,9 +144,6 @@ ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break) gint32 ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) { -#ifdef PLATFORM_WIN32 - return FALSE; -#else fd_set rfds; struct timeval tv; struct timeval *tvptr; @@ -128,14 +174,11 @@ ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) } return (ret > 0) ? ret : 0; -#endif } static void tty_teardown (void) { -#ifdef PLATFORM_WIN32 -#else MONO_ARCH_SAVE_REGS; if (!setup_finished) @@ -149,23 +192,74 @@ tty_teardown (void) tcflush (STDIN_FILENO, TCIFLUSH); tcsetattr (STDIN_FILENO, TCSANOW, &initial_attr); + set_property (ECHO, TRUE); setup_finished = FALSE; -#endif +} + +static void +do_console_cancel_event (void) +{ + static MonoClassField *cancel_handler_field; + MonoDomain *domain = mono_domain_get (); + MonoClass *klass; + MonoDelegate *load_value; + MonoMethod *method; + MonoMethodMessage *msg; + MonoMethod *im; + + if (!domain->domain) + return; + + klass = mono_class_from_name (mono_defaults.corlib, "System", "Console"); + if (klass == NULL) + return; + + if (cancel_handler_field == NULL) { + cancel_handler_field = mono_class_get_field_from_name (klass, "cancel_handler"); + g_assert (cancel_handler_field); + } + + mono_field_static_get_value (mono_class_vtable (domain, klass), cancel_handler_field, &load_value); + if (load_value == NULL) + return; + + klass = load_value->object.vtable->klass; + method = mono_class_get_method_from_name (klass, "BeginInvoke", -1); + g_assert (method != NULL); + im = mono_get_delegate_invoke (method->klass); + msg = mono_method_call_message_new (method, NULL, im, NULL, NULL); + mono_thread_pool_add ((MonoObject *) load_value, msg, NULL, NULL); +} + +static gboolean in_sigint; +static void +sigint_handler (int signo) +{ + MONO_ARCH_SAVE_REGS; + + if (in_sigint) + return; + + in_sigint = TRUE; + do_console_cancel_event (); + in_sigint = FALSE; } MonoBoolean -ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown) +ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown, char *verase, char *vsusp, char*intr) { -#ifdef PLATFORM_WIN32 - return FALSE; -#else struct termios attr; MONO_ARCH_SAVE_REGS; + + *verase = '\0'; + *vsusp = '\0'; + *intr = '\0'; if (tcgetattr (STDIN_FILENO, &initial_attr) == -1) return FALSE; + /* TODO: handle SIGTSTP - Ctrl-Z */ attr = initial_attr; attr.c_lflag &= ~ICANON; attr.c_cc [VMIN] = 1; @@ -173,6 +267,14 @@ ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown) if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1) return FALSE; + *verase = initial_attr.c_cc [VERASE]; + *vsusp = initial_attr.c_cc [VSUSP]; + *intr = initial_attr.c_cc [VINTR]; + /* If initialized from another appdomain... */ + if (setup_finished) + return TRUE; + + signal (SIGINT, sigint_handler); setup_finished = TRUE; if (!atexit_called) { if (teardown != NULL) @@ -182,6 +284,29 @@ ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown) } return TRUE; +} + +MonoBoolean +ves_icall_System_ConsoleDriver_GetTtySize (HANDLE handle, gint32 *width, gint32 *height) +{ +#ifdef TIOCGWINSZ + struct winsize ws; + int res; + + MONO_ARCH_SAVE_REGS; + + res = ioctl (GPOINTER_TO_INT (handle), TIOCGWINSZ, &ws); + + if (!res) { + *width = ws.ws_col; + *height = ws.ws_row; + return TRUE; + } + else + return FALSE; +#else + return FALSE; #endif } +#endif /* !PLATFORM_WIN32 */