From: Miguel de Icaza Date: Wed, 22 Apr 2009 23:07:49 +0000 (-0000) Subject: 2009-04-22 Miguel de Icaza X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=d69eacde0a5769c00121eccabb8ac173d122e0e5;p=mono.git 2009-04-22 Miguel de Icaza * Makefile.am: Split the console support in platform specific code and put together a framework for making this easy in the future so that we can start splitting code instead of having a mess of PLATFORM_WIN32 svn path=/trunk/mono/; revision=132422 --- diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 8ca00b4cc6b..4330b7e2159 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,9 @@ +2009-04-22 Miguel de Icaza + + * Makefile.am: Split the console support in platform specific code + and put together a framework for making this easy in the future so + that we can start splitting code instead of having a mess of PLATFORM_WIN32 + 2009-04-21 Rodrigo Kumpera * verify.c (mono_delegate_type_equal): Compare valuetypes using diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 2aac38460f6..5553af536d2 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -1,4 +1,9 @@ if PLATFORM_WIN32 +win32_sources = \ + console-win32.c + +platform_sources = $(win32_sources) + # Use -m here. This will use / as directory separator (C:/WINNT). # The files that use MONO_ASSEMBLIES and/or MONO_CFG_DIR replace the # / by \ if running under WIN32. @@ -14,8 +19,13 @@ export HOST_CC # optimisation is required to actually inline them AM_CFLAGS = -O else + assembliesdir = $(exec_prefix)/lib confdir = $(sysconfdir) +unix_sources = \ + console-unix.c + +platform_sources = $(unix_sources) endif bin_PROGRAMS = pedump @@ -43,7 +53,11 @@ CLEANFILES = mono-bundle.stamp libmonoruntime_static_la_LIBADD = $(bundle_obj) $(libmonoruntime_la_LIBADD) +null_sources = \ + console-null.c + libmonoruntime_la_SOURCES = \ + $(platform_sources) \ appdomain.c \ assembly.c \ attach.h \ @@ -55,7 +69,6 @@ libmonoruntime_la_SOURCES = \ class-internals.h \ cominterop.c \ cominterop.h \ - console-io.c \ console-io.h \ coree.c \ coree.h \ @@ -197,5 +210,5 @@ pedump_SOURCES = \ pedump_LDADD = libmonoruntime.la ../io-layer/libwapi.la ../utils/libmonoutils.la \ $(LIBGC_LIBS) $(GLIB_LIBS) -lm $(PEDUMP_DTRACE_OBJECT) -EXTRA_DIST = make-bundle.pl sample-bundle +EXTRA_DIST = make-bundle.pl sample-bundle $(win32_sources) $(unix_sources) $(null_sources) diff --git a/mono/metadata/console-io.c b/mono/metadata/console-io.c deleted file mode 100644 index e9206ad5993..00000000000 --- a/mono/metadata/console-io.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * console-io.c: ConsoleDriver internal calls - * - * Author: - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com) - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#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 TIOCGWINSZ -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#endif - -#include -#include - -static gboolean setup_finished; -static gboolean atexit_called; - -/* The string used to return the terminal to its previous state */ -static gchar *teardown_str; - -/* The string used to set the terminal into keypad xmit mode after SIGCONT is received */ -static gchar *keypad_xmit_str; - -#ifdef HAVE_TERMIOS_H -/* This is the last state used by Mono, used after a CONT signal is received */ -static struct termios mono_attr; -#endif - -#if defined(PLATFORM_WIN32) -void -mono_console_init (void) -{ -} -#else -void -mono_console_init (void) -{ - int fd; - - /* Make sure the standard file descriptors are opened */ - fd = open ("/dev/null", O_RDWR); - while (fd >= 0 && fd < 3) { - fd = open ("/dev/null", O_RDWR); - } - close (fd); -} -#endif - -#if defined (PLATFORM_WIN32) || defined (MONO_NULL_TTYDRIVER) -MonoBoolean -ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) -{ - MONO_ARCH_SAVE_REGS; - - 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 *keypad, MonoString *teardown, MonoArray **control_chars, int **size) -{ - 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)); -} - -static MonoBoolean -set_property (gint property, gboolean value) -{ - struct termios attr; - gboolean callset = FALSE; - gboolean check; - - MONO_ARCH_SAVE_REGS; - - if (tcgetattr (STDIN_FILENO, &attr) == -1) - return FALSE; - - check = (attr.c_lflag & property) != 0; - if ((value || check) && !(value && check)) { - callset = TRUE; - if (value) - attr.c_lflag |= property; - else - attr.c_lflag &= ~property; - } - - if (!callset) - return TRUE; - - if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1) - return FALSE; - - mono_attr = attr; - return TRUE; -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo) -{ - - return set_property (ECHO, want_echo); -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break) -{ - return set_property (IGNBRK, !want_break); -} - -gint32 -ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) -{ - fd_set rfds; - struct timeval tv; - struct timeval *tvptr; - div_t divvy; - int ret, nbytes; - - MONO_ARCH_SAVE_REGS; - - do { - FD_ZERO (&rfds); - FD_SET (STDIN_FILENO, &rfds); - if (timeout >= 0) { - divvy = div (timeout, 1000); - tv.tv_sec = divvy.quot; - tv.tv_usec = divvy.rem; - tvptr = &tv; - } else { - tvptr = NULL; - } - ret = select (STDIN_FILENO + 1, &rfds, NULL, NULL, tvptr); - } while (ret == -1 && errno == EINTR); - - if (ret > 0) { - nbytes = 0; - ret = ioctl (STDIN_FILENO, FIONREAD, &nbytes); - if (ret >= 0) - ret = nbytes; - } - - return (ret > 0) ? ret : 0; -} - -static gint32 cols_and_lines; - -#ifdef TIOCGWINSZ -static int -terminal_get_dimensions (void) -{ - struct winsize ws; - - if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) == 0) - return (ws.ws_col << 16) | ws.ws_row; - - return -1; -} -#else -static int -terminal_get_dimensions (void) -{ - return -1; -} -#endif - -static void -tty_teardown (void) -{ - MONO_ARCH_SAVE_REGS; - - if (!setup_finished) - return; - - if (teardown_str != NULL) { - write (STDOUT_FILENO, teardown_str, strlen (teardown_str)); - g_free (teardown_str); - teardown_str = NULL; - } - - tcflush (STDIN_FILENO, TCIFLUSH); - tcsetattr (STDIN_FILENO, TCSANOW, &initial_attr); - set_property (ECHO, TRUE); - setup_finished = FALSE; -} - -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; -} - -static struct sigaction save_sigcont, save_sigint, save_sigwinch; - -static void -sigcont_handler (int signo, void *the_siginfo, void *data) -{ - // Ignore error, there is not much we can do in the sigcont handler. - tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr); - - if (keypad_xmit_str != NULL) - write (STDOUT_FILENO, keypad_xmit_str, strlen (keypad_xmit_str)); - - // Call previous handler - if (save_sigcont.sa_sigaction != NULL && - save_sigcont.sa_sigaction != (void *)SIG_DFL && - save_sigcont.sa_sigaction != (void *)SIG_IGN) - (*save_sigcont.sa_sigaction) (signo, the_siginfo, data); -} - -static void -sigwinch_handler (int signo, void *the_siginfo, void *data) -{ - int dims = terminal_get_dimensions (); - if (dims != -1) - cols_and_lines = dims; - - // Call previous handler - if (save_sigwinch.sa_sigaction != NULL && - save_sigwinch.sa_sigaction != (void *)SIG_DFL && - save_sigwinch.sa_sigaction != (void *)SIG_IGN) - (*save_sigwinch.sa_sigaction) (signo, the_siginfo, data); -} - -void -console_set_signal_handlers () -{ - struct sigaction sigcont, sigint, sigwinch; - - memset (&sigcont, 0, sizeof (struct sigaction)); - memset (&sigint, 0, sizeof (struct sigaction)); - memset (&sigwinch, 0, sizeof (struct sigaction)); - - // Continuing - sigcont.sa_handler = (void *) sigcont_handler; - sigcont.sa_flags = 0; - sigemptyset (&sigcont.sa_mask); - sigaction (SIGCONT, &sigcont, &save_sigcont); - - // Interrupt handler - sigint.sa_handler = sigint_handler; - sigint.sa_flags = 0; - sigemptyset (&sigint.sa_mask); - sigaction (SIGINT, &sigint, &save_sigint); - - // Window size changed - sigwinch.sa_handler = (void *) sigwinch_handler; - sigwinch.sa_flags = 0; - sigemptyset (&sigwinch.sa_mask); - sigaction (SIGWINCH, &sigwinch, &save_sigwinch); -} - -// -// Currently unused, should we ever call the restore handler? -// Perhaps before calling into Process.Start? -// -void -console_restore_signal_handlers () -{ - sigaction (SIGCONT, &save_sigcont, NULL); - sigaction (SIGINT, &save_sigint, NULL); - sigaction (SIGWINCH, &save_sigwinch, NULL); -} - -static void -set_control_chars (MonoArray *control_chars, const guchar *cc) -{ - /* The index into the array comes from corlib/System/ControlCharacters.cs */ -#ifdef VINTR - mono_array_set (control_chars, gchar, 0, cc [VINTR]); -#endif -#ifdef VQUIT - mono_array_set (control_chars, gchar, 1, cc [VQUIT]); -#endif -#ifdef VERASE - mono_array_set (control_chars, gchar, 2, cc [VERASE]); -#endif -#ifdef VKILL - mono_array_set (control_chars, gchar, 3, cc [VKILL]); -#endif -#ifdef VEOF - mono_array_set (control_chars, gchar, 4, cc [VEOF]); -#endif -#ifdef VTIME - mono_array_set (control_chars, gchar, 5, cc [VTIME]); -#endif -#ifdef VMIN - mono_array_set (control_chars, gchar, 6, cc [VMIN]); -#endif -#ifdef VSWTC - mono_array_set (control_chars, gchar, 7, cc [VSWTC]); -#endif -#ifdef VSTART - mono_array_set (control_chars, gchar, 8, cc [VSTART]); -#endif -#ifdef VSTOP - mono_array_set (control_chars, gchar, 9, cc [VSTOP]); -#endif -#ifdef VSUSP - mono_array_set (control_chars, gchar, 10, cc [VSUSP]); -#endif -#ifdef VEOL - mono_array_set (control_chars, gchar, 11, cc [VEOL]); -#endif -#ifdef VREPRINT - mono_array_set (control_chars, gchar, 12, cc [VREPRINT]); -#endif -#ifdef VDISCARD - mono_array_set (control_chars, gchar, 13, cc [VDISCARD]); -#endif -#ifdef VWERASE - mono_array_set (control_chars, gchar, 14, cc [VWERASE]); -#endif -#ifdef VLNEXT - mono_array_set (control_chars, gchar, 15, cc [VLNEXT]); -#endif -#ifdef VEOL2 - mono_array_set (control_chars, gchar, 16, cc [VEOL2]); -#endif -} - -MonoBoolean -ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardown, MonoArray **control_chars, int **size) -{ - int dims; - - MONO_ARCH_SAVE_REGS; - - dims = terminal_get_dimensions (); - if (dims == -1){ - int cols = 0, rows = 0; - - char *str = getenv ("COLUMNS"); - if (str != NULL) - cols = atoi (str); - str = getenv ("LINES"); - if (str != NULL) - rows = atoi (str); - - if (cols != 0 && rows != 0) - cols_and_lines = (cols << 16) | rows; - else - cols_and_lines = -1; - } else { - cols_and_lines = dims; - } - - *size = &cols_and_lines; - - /* 17 is the number of entries set in set_control_chars() above. - * NCCS is the total size, but, by now, we only care about those 17 values*/ - *control_chars = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 17); - if (tcgetattr (STDIN_FILENO, &initial_attr) == -1) - return FALSE; - - mono_attr = initial_attr; - mono_attr.c_lflag &= ~(ICANON); - mono_attr.c_iflag &= ~(IXON|IXOFF); - mono_attr.c_cc [VMIN] = 1; - mono_attr.c_cc [VTIME] = 0; - if (tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr) == -1) - return FALSE; - - set_control_chars (*control_chars, mono_attr.c_cc); - /* If initialized from another appdomain... */ - if (setup_finished) - return TRUE; - - keypad_xmit_str = keypad != NULL ? mono_string_to_utf8 (keypad) : NULL; - - console_set_signal_handlers (); - setup_finished = TRUE; - if (!atexit_called) { - if (teardown != NULL) - teardown_str = mono_string_to_utf8 (teardown); - - atexit (tty_teardown); - } - - return TRUE; -} - -#endif /* !PLATFORM_WIN32 */ diff --git a/mono/metadata/console-null.c b/mono/metadata/console-null.c new file mode 100644 index 00000000000..a50b2a37d20 --- /dev/null +++ b/mono/metadata/console-null.c @@ -0,0 +1,53 @@ +/* + * console-null.c: Null driver, does nothing. + * + * Author: + * Gonzalo Paniagua Javier (gonzalo@ximian.com) + * + * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com) + */ + +#include +#include +#include +#include + +#include +#include + +void +mono_console_init (void) +{ +} + +MonoBoolean +ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) +{ + MONO_ARCH_SAVE_REGS; + + 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 *keypad, MonoString *teardown, MonoArray **control_chars, int **size) +{ + return FALSE; +} diff --git a/mono/metadata/console-unix.c b/mono/metadata/console-unix.c index e9206ad5993..d113555e6af 100644 --- a/mono/metadata/console-unix.c +++ b/mono/metadata/console-unix.c @@ -1,5 +1,5 @@ /* - * console-io.c: ConsoleDriver internal calls + * console-io.c: ConsoleDriver internal calls for Unix systems. * * Author: * Gonzalo Paniagua Javier (gonzalo@ximian.com) @@ -15,11 +15,11 @@ #include #include #ifdef HAVE_SYS_TIME_H -#include +# include #endif #include #ifdef HAVE_UNISTD_H -#include +# include #endif #include #include @@ -27,24 +27,26 @@ #include #include #include + /* On solaris, curses.h must come before both termios.h and term.h */ #ifdef HAVE_CURSES_H -#include +# include #endif #ifdef HAVE_TERMIOS_H -#include +# include #endif #ifdef HAVE_TERM_H -#include +# include #endif + /* Needed for FIONREAD under solaris */ #ifdef HAVE_SYS_FILIO_H -#include +# include #endif #ifndef TIOCGWINSZ -#ifdef HAVE_SYS_IOCTL_H -#include -#endif +# ifdef HAVE_SYS_IOCTL_H +# include +# endif #endif #include @@ -64,12 +66,6 @@ static gchar *keypad_xmit_str; static struct termios mono_attr; #endif -#if defined(PLATFORM_WIN32) -void -mono_console_init (void) -{ -} -#else void mono_console_init (void) { @@ -82,42 +78,7 @@ mono_console_init (void) } close (fd); } -#endif - -#if defined (PLATFORM_WIN32) || defined (MONO_NULL_TTYDRIVER) -MonoBoolean -ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) -{ - MONO_ARCH_SAVE_REGS; - - 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 *keypad, MonoString *teardown, MonoArray **control_chars, int **size) -{ - return FALSE; -} - -#else static struct termios initial_attr; MonoBoolean @@ -486,5 +447,3 @@ ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardow return TRUE; } - -#endif /* !PLATFORM_WIN32 */ diff --git a/mono/metadata/console-win32.c b/mono/metadata/console-win32.c index e9206ad5993..56180991796 100644 --- a/mono/metadata/console-win32.c +++ b/mono/metadata/console-win32.c @@ -1,5 +1,5 @@ /* - * console-io.c: ConsoleDriver internal calls + * console-io.c: ConsoleDriver internal calls for Win32 * * Author: * Gonzalo Paniagua Javier (gonzalo@ximian.com) @@ -14,77 +14,27 @@ #include #include #include +#include + #ifdef HAVE_SYS_TIME_H #include #endif -#include -#ifdef HAVE_UNISTD_H -#include -#endif + #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 TIOCGWINSZ -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#endif #include #include -static gboolean setup_finished; -static gboolean atexit_called; - -/* The string used to return the terminal to its previous state */ -static gchar *teardown_str; - -/* The string used to set the terminal into keypad xmit mode after SIGCONT is received */ -static gchar *keypad_xmit_str; - -#ifdef HAVE_TERMIOS_H -/* This is the last state used by Mono, used after a CONT signal is received */ -static struct termios mono_attr; -#endif - -#if defined(PLATFORM_WIN32) -void -mono_console_init (void) -{ -} -#else void mono_console_init (void) { - int fd; - - /* Make sure the standard file descriptors are opened */ - fd = open ("/dev/null", O_RDWR); - while (fd >= 0 && fd < 3) { - fd = open ("/dev/null", O_RDWR); - } - close (fd); } -#endif -#if defined (PLATFORM_WIN32) || defined (MONO_NULL_TTYDRIVER) MonoBoolean ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) { @@ -116,375 +66,3 @@ ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardow { 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)); -} - -static MonoBoolean -set_property (gint property, gboolean value) -{ - struct termios attr; - gboolean callset = FALSE; - gboolean check; - - MONO_ARCH_SAVE_REGS; - - if (tcgetattr (STDIN_FILENO, &attr) == -1) - return FALSE; - - check = (attr.c_lflag & property) != 0; - if ((value || check) && !(value && check)) { - callset = TRUE; - if (value) - attr.c_lflag |= property; - else - attr.c_lflag &= ~property; - } - - if (!callset) - return TRUE; - - if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1) - return FALSE; - - mono_attr = attr; - return TRUE; -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo) -{ - - return set_property (ECHO, want_echo); -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break) -{ - return set_property (IGNBRK, !want_break); -} - -gint32 -ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) -{ - fd_set rfds; - struct timeval tv; - struct timeval *tvptr; - div_t divvy; - int ret, nbytes; - - MONO_ARCH_SAVE_REGS; - - do { - FD_ZERO (&rfds); - FD_SET (STDIN_FILENO, &rfds); - if (timeout >= 0) { - divvy = div (timeout, 1000); - tv.tv_sec = divvy.quot; - tv.tv_usec = divvy.rem; - tvptr = &tv; - } else { - tvptr = NULL; - } - ret = select (STDIN_FILENO + 1, &rfds, NULL, NULL, tvptr); - } while (ret == -1 && errno == EINTR); - - if (ret > 0) { - nbytes = 0; - ret = ioctl (STDIN_FILENO, FIONREAD, &nbytes); - if (ret >= 0) - ret = nbytes; - } - - return (ret > 0) ? ret : 0; -} - -static gint32 cols_and_lines; - -#ifdef TIOCGWINSZ -static int -terminal_get_dimensions (void) -{ - struct winsize ws; - - if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) == 0) - return (ws.ws_col << 16) | ws.ws_row; - - return -1; -} -#else -static int -terminal_get_dimensions (void) -{ - return -1; -} -#endif - -static void -tty_teardown (void) -{ - MONO_ARCH_SAVE_REGS; - - if (!setup_finished) - return; - - if (teardown_str != NULL) { - write (STDOUT_FILENO, teardown_str, strlen (teardown_str)); - g_free (teardown_str); - teardown_str = NULL; - } - - tcflush (STDIN_FILENO, TCIFLUSH); - tcsetattr (STDIN_FILENO, TCSANOW, &initial_attr); - set_property (ECHO, TRUE); - setup_finished = FALSE; -} - -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; -} - -static struct sigaction save_sigcont, save_sigint, save_sigwinch; - -static void -sigcont_handler (int signo, void *the_siginfo, void *data) -{ - // Ignore error, there is not much we can do in the sigcont handler. - tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr); - - if (keypad_xmit_str != NULL) - write (STDOUT_FILENO, keypad_xmit_str, strlen (keypad_xmit_str)); - - // Call previous handler - if (save_sigcont.sa_sigaction != NULL && - save_sigcont.sa_sigaction != (void *)SIG_DFL && - save_sigcont.sa_sigaction != (void *)SIG_IGN) - (*save_sigcont.sa_sigaction) (signo, the_siginfo, data); -} - -static void -sigwinch_handler (int signo, void *the_siginfo, void *data) -{ - int dims = terminal_get_dimensions (); - if (dims != -1) - cols_and_lines = dims; - - // Call previous handler - if (save_sigwinch.sa_sigaction != NULL && - save_sigwinch.sa_sigaction != (void *)SIG_DFL && - save_sigwinch.sa_sigaction != (void *)SIG_IGN) - (*save_sigwinch.sa_sigaction) (signo, the_siginfo, data); -} - -void -console_set_signal_handlers () -{ - struct sigaction sigcont, sigint, sigwinch; - - memset (&sigcont, 0, sizeof (struct sigaction)); - memset (&sigint, 0, sizeof (struct sigaction)); - memset (&sigwinch, 0, sizeof (struct sigaction)); - - // Continuing - sigcont.sa_handler = (void *) sigcont_handler; - sigcont.sa_flags = 0; - sigemptyset (&sigcont.sa_mask); - sigaction (SIGCONT, &sigcont, &save_sigcont); - - // Interrupt handler - sigint.sa_handler = sigint_handler; - sigint.sa_flags = 0; - sigemptyset (&sigint.sa_mask); - sigaction (SIGINT, &sigint, &save_sigint); - - // Window size changed - sigwinch.sa_handler = (void *) sigwinch_handler; - sigwinch.sa_flags = 0; - sigemptyset (&sigwinch.sa_mask); - sigaction (SIGWINCH, &sigwinch, &save_sigwinch); -} - -// -// Currently unused, should we ever call the restore handler? -// Perhaps before calling into Process.Start? -// -void -console_restore_signal_handlers () -{ - sigaction (SIGCONT, &save_sigcont, NULL); - sigaction (SIGINT, &save_sigint, NULL); - sigaction (SIGWINCH, &save_sigwinch, NULL); -} - -static void -set_control_chars (MonoArray *control_chars, const guchar *cc) -{ - /* The index into the array comes from corlib/System/ControlCharacters.cs */ -#ifdef VINTR - mono_array_set (control_chars, gchar, 0, cc [VINTR]); -#endif -#ifdef VQUIT - mono_array_set (control_chars, gchar, 1, cc [VQUIT]); -#endif -#ifdef VERASE - mono_array_set (control_chars, gchar, 2, cc [VERASE]); -#endif -#ifdef VKILL - mono_array_set (control_chars, gchar, 3, cc [VKILL]); -#endif -#ifdef VEOF - mono_array_set (control_chars, gchar, 4, cc [VEOF]); -#endif -#ifdef VTIME - mono_array_set (control_chars, gchar, 5, cc [VTIME]); -#endif -#ifdef VMIN - mono_array_set (control_chars, gchar, 6, cc [VMIN]); -#endif -#ifdef VSWTC - mono_array_set (control_chars, gchar, 7, cc [VSWTC]); -#endif -#ifdef VSTART - mono_array_set (control_chars, gchar, 8, cc [VSTART]); -#endif -#ifdef VSTOP - mono_array_set (control_chars, gchar, 9, cc [VSTOP]); -#endif -#ifdef VSUSP - mono_array_set (control_chars, gchar, 10, cc [VSUSP]); -#endif -#ifdef VEOL - mono_array_set (control_chars, gchar, 11, cc [VEOL]); -#endif -#ifdef VREPRINT - mono_array_set (control_chars, gchar, 12, cc [VREPRINT]); -#endif -#ifdef VDISCARD - mono_array_set (control_chars, gchar, 13, cc [VDISCARD]); -#endif -#ifdef VWERASE - mono_array_set (control_chars, gchar, 14, cc [VWERASE]); -#endif -#ifdef VLNEXT - mono_array_set (control_chars, gchar, 15, cc [VLNEXT]); -#endif -#ifdef VEOL2 - mono_array_set (control_chars, gchar, 16, cc [VEOL2]); -#endif -} - -MonoBoolean -ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardown, MonoArray **control_chars, int **size) -{ - int dims; - - MONO_ARCH_SAVE_REGS; - - dims = terminal_get_dimensions (); - if (dims == -1){ - int cols = 0, rows = 0; - - char *str = getenv ("COLUMNS"); - if (str != NULL) - cols = atoi (str); - str = getenv ("LINES"); - if (str != NULL) - rows = atoi (str); - - if (cols != 0 && rows != 0) - cols_and_lines = (cols << 16) | rows; - else - cols_and_lines = -1; - } else { - cols_and_lines = dims; - } - - *size = &cols_and_lines; - - /* 17 is the number of entries set in set_control_chars() above. - * NCCS is the total size, but, by now, we only care about those 17 values*/ - *control_chars = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 17); - if (tcgetattr (STDIN_FILENO, &initial_attr) == -1) - return FALSE; - - mono_attr = initial_attr; - mono_attr.c_lflag &= ~(ICANON); - mono_attr.c_iflag &= ~(IXON|IXOFF); - mono_attr.c_cc [VMIN] = 1; - mono_attr.c_cc [VTIME] = 0; - if (tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr) == -1) - return FALSE; - - set_control_chars (*control_chars, mono_attr.c_cc); - /* If initialized from another appdomain... */ - if (setup_finished) - return TRUE; - - keypad_xmit_str = keypad != NULL ? mono_string_to_utf8 (keypad) : NULL; - - console_set_signal_handlers (); - setup_finished = TRUE; - if (!atexit_called) { - if (teardown != NULL) - teardown_str = mono_string_to_utf8 (teardown); - - atexit (tty_teardown); - } - - return TRUE; -} - -#endif /* !PLATFORM_WIN32 */