* ssa.c: In mono_ssa_rename_vars, forced the creation of a new SSA
[mono.git] / mono / metadata / console-io.c
1 /*
2  * console-io.c: ConsoleDriver internal calls
3  *
4  * Author:
5  *      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6  *
7  * Copyright (C) 2005 Novell, Inc. (http://www.novell.com)
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <signal.h>
16 #include <unistd.h>
17 #ifdef HAVE_TERMIOS_H
18 #include <termios.h>
19 #endif
20 #ifdef HAVE_TERM_H
21 #include <term.h>
22 #endif
23 #ifndef PLATFORM_WIN32
24 #ifndef TIOCGWINSZ
25 #include <sys/ioctl.h>
26 #endif
27 #endif
28
29 #include <mono/metadata/console-io.h>
30 #include <mono/metadata/exception.h>
31
32 static gboolean setup_finished;
33 static gboolean atexit_called;
34 static gchar *teardown_str;
35
36 #ifdef PLATFORM_WIN32
37 MonoBoolean
38 ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
39 {
40         MONO_ARCH_SAVE_REGS;
41
42         return (GetFileType (handle) == FILE_TYPE_CHAR);
43 }
44
45 MonoBoolean
46 ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo)
47 {
48         return FALSE;
49 }
50
51 MonoBoolean
52 ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break)
53 {
54         return FALSE;
55 }
56
57 gint32
58 ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout)
59 {
60         return FALSE;
61 }
62
63 MonoBoolean
64 ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown)
65 {
66         return FALSE;
67 }
68
69 #else
70 static struct termios initial_attr;
71
72 MonoBoolean
73 ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
74 {
75         MONO_ARCH_SAVE_REGS;
76
77         return isatty (GPOINTER_TO_INT (handle));
78 }
79
80 static MonoBoolean
81 set_property (gint property, gboolean value)
82 {
83         struct termios attr;
84         gboolean callset = FALSE;
85         gboolean check;
86         
87         MONO_ARCH_SAVE_REGS;
88
89         if (tcgetattr (STDIN_FILENO, &attr) == -1)
90                 return FALSE;
91
92         check = (attr.c_lflag & property) != 0;
93         if ((value || check) && !(value && check)) {
94                 callset = TRUE;
95                 if (value)
96                         attr.c_lflag |= property;
97                 else
98                         attr.c_lflag &= ~property;
99         }
100
101         if (!callset)
102                 return TRUE;
103
104         if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1)
105                 return FALSE;
106
107         return TRUE;
108 }
109
110 MonoBoolean
111 ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo)
112 {
113         return set_property (ECHO, want_echo);
114 }
115
116 MonoBoolean
117 ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break)
118 {
119         return set_property (IGNBRK, !want_break);
120 }
121
122 gint32
123 ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout)
124 {
125         fd_set rfds;
126         struct timeval tv;
127         struct timeval *tvptr;
128         div_t divvy;
129         int ret, nbytes;
130
131         MONO_ARCH_SAVE_REGS;
132
133         do {
134                 FD_ZERO (&rfds);
135                 FD_SET (STDIN_FILENO, &rfds);
136                 if (timeout >= 0) {
137                         divvy = div (timeout, 1000);
138                         tv.tv_sec = divvy.quot;
139                         tv.tv_usec = divvy.rem;
140                         tvptr = &tv;
141                 } else {
142                         tvptr = NULL;
143                 }
144                 ret = select (STDIN_FILENO + 1, &rfds, NULL, NULL, tvptr);
145         } while (ret == -1 && errno == EINTR);
146
147         if (ret > 0) {
148                 nbytes = 0;
149                 ret = ioctl (STDIN_FILENO, FIONREAD, &nbytes);
150                 if (ret >= 0)
151                         ret = nbytes;
152         }
153
154         return (ret > 0) ? ret : 0;
155 }
156
157 static void
158 tty_teardown (void)
159 {
160         MONO_ARCH_SAVE_REGS;
161
162         if (!setup_finished)
163                 return;
164
165         if (teardown_str != NULL) {
166                 write (STDOUT_FILENO, teardown_str, strlen (teardown_str));
167                 g_free (teardown_str);
168                 teardown_str = NULL;
169         }
170
171         tcflush (STDIN_FILENO, TCIFLUSH);
172         tcsetattr (STDIN_FILENO, TCSANOW, &initial_attr);
173         setup_finished = FALSE;
174 }
175
176 MonoBoolean
177 ves_icall_System_ConsoleDriver_TtySetup (MonoString *teardown)
178 {
179         struct termios attr;
180         
181         MONO_ARCH_SAVE_REGS;
182
183         if (tcgetattr (STDIN_FILENO, &initial_attr) == -1)
184                 return FALSE;
185
186         attr = initial_attr;
187         attr.c_lflag &= ~ICANON;
188         attr.c_cc [VMIN] = 1;
189         attr.c_cc [VTIME] = 0;
190         if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1)
191                 return FALSE;
192
193         setup_finished = TRUE;
194         if (!atexit_called) {
195                 if (teardown != NULL)
196                         teardown_str = mono_string_to_utf8 (teardown);
197
198                 atexit (tty_teardown);
199         }
200
201         return TRUE;
202 }
203 #endif
204