1 /** \file   uimon-fallback.c
2  * \brief   Fallback implementation for the ML-Monitor for when the VTE library
3  *          is not available
4  *
5  * \author  Fabrizio Gennari <fabrizio.ge@tiscali.it>
6  */
7 
8 /*
9  * This file is part of VICE, the Versatile Commodore Emulator.
10  * See README for copyright notice.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25  *  02111-1307  USA.
26  *
27  */
28 
29 /* FIXME: this code can probably be shared between GTK3/SDL */
30 
31 #include "vice.h"
32 
33 #include "debug_gtk3.h"
34 #include <stdlib.h>
35 #include <string.h>
36 #include <dirent.h>
37 #include <ctype.h>
38 #include <unistd.h>
39 
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 
44 #if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
45 #include <sys/stat.h>
46 #endif
47 
48 #ifdef WIN32_COMPILE
49 #include <windows.h>
50 #include <winternl.h>
51 #endif
52 
53 #include "console.h"
54 #include "lib.h"
55 #include "log.h"
56 #include "ui.h"
57 #include "uimon.h"
58 #include "uimon-fallback.h"
59 
60 
61 static console_t *console_log_local = NULL;
62 
63 #if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
64 #include <readline/readline.h>
65 #include <readline/history.h>
66 #else
67 static FILE *mon_input, *mon_output;
68 #endif
69 
70 /** \brief  NOP
71  *
72  * \return  0
73  */
consolefb_close_all(void)74 int consolefb_close_all(void)
75 {
76     /* This is a no-op on GNOME, should be fine here too */
77     return 0;
78 }
79 
80 
81 /** \brief  NOP
82  *
83  * \return  0
84  */
consolefb_init(void)85 int consolefb_init(void)
86 {
87     NOT_IMPLEMENTED_WARN_ONLY();
88     return 0;
89 }
90 
91 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
consolefb_out(console_t * log,const char * format,...)92 int consolefb_out(console_t *log, const char *format, ...)
93 {
94     va_list ap;
95 
96     va_start(ap, format);
97     vfprintf(mon_output, format, ap);
98     va_end(ap);
99 
100     return 0;
101 }
102 #endif
103 
104 #ifdef WIN32_COMPILE
vice_ismsystty(int fd)105 static int vice_ismsystty(int fd)
106 {
107     intptr_t h_stdin = _get_osfhandle(fd);
108     char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)];
109     OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes;
110     NTSTATUS status;
111     ULONG ntfn_size = sizeof(ntfn_bytes);
112     USHORT i, l;
113     wchar_t c, *s0;
114 
115     memset(ntfn, 0, ntfn_size);
116     status = NtQueryObject((HANDLE)h_stdin, ObjectNameInformation, ntfn, ntfn_size, &ntfn_size);
117 
118     if (!NT_SUCCESS(status)) {
119         return 0;
120     }
121 
122     l = ntfn->Name.Length;
123     s0 = ntfn->Name.Buffer;
124     /* Check for "\Device\NamedPipe" */
125     {
126         USHORT l1 = l;
127         wchar_t *s1 = s0;
128         wchar_t expect[] = L"\\Device\\NamedPipe\\";
129 
130         if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') {
131             l1 -= 4;
132             s1 += 4;
133         }
134         for (i = 0; i < l1; i++) {
135             wchar_t e = expect[i];
136             c = s1[i];
137             if (!e) {
138                 break;
139             }
140             if (c != e) {
141                 return 0;
142             }
143         }
144     }
145     /* Look for "-pty%d-" */
146     for (i = 0; i < l; i++) {
147         c = s0[i];
148         if (c == '-') {
149             wchar_t *s = s0 + i + 1;
150             if (s[0] == 'p' && s[1] == 't' && s[2] == 'y' && (c = s[3]) && (c >= '0') && (c <= '9'))
151             {
152                 s += 4;
153                 while ((c = *s) && (c >= '0') && (c <= '9')) {
154                     s++;
155                 }
156                 if (c == '-' || c == 0) {
157                     return 1;
158                 }
159             }
160         }
161     }
162 
163     return 0;
164 }
165 
vice_isatty(int fd)166 static int vice_isatty(int fd)
167 {
168     if (!isatty(fileno(stdin))) {
169         return vice_ismsystty(fileno(stdin));
170     }
171     return 1;
172 }
173 #else
174 #define vice_isatty isatty
175 #endif
176 
uimonfb_window_open(void)177 console_t *uimonfb_window_open(void)
178 {
179 #ifdef HAVE_SYS_IOCTL_H
180     struct winsize w;
181 #endif
182 
183     if (!vice_isatty(fileno(stdin))) {
184         log_error(LOG_DEFAULT, "console_open: stdin is not a tty.");
185         console_log_local = NULL;
186         return NULL;
187     }
188     if (!vice_isatty(fileno(stdout))) {
189         log_error(LOG_DEFAULT, "console_open: stdout is not a tty.");
190         console_log_local = NULL;
191         return NULL;
192     }
193     console_log_local = lib_malloc(sizeof(console_t));
194     /* change window title for console identification purposes */
195     if (getenv("WINDOWID") == NULL) {
196         printf("\033]2;VICE monitor console (%d)\007", (int)getpid());
197     }
198 
199 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
200     mon_input = stdin;
201     mon_output = stdout;
202 #endif
203 
204 #ifdef HAVE_SYS_IOCTL_H
205     if (ioctl(fileno(stdin), TIOCGWINSZ, &w)) {
206         console_log_local->console_xres = 80;
207         console_log_local->console_yres = 25;
208     } else {
209         console_log_local->console_xres = w.ws_col >= 40 ? w.ws_col : 40;
210         console_log_local->console_yres = w.ws_row >= 22 ? w.ws_row : 22;
211     }
212 #else
213     console_log_local->console_xres = 80;
214     console_log_local->console_yres = 25;
215 #endif
216     console_log_local->console_can_stay_open = 1;
217     console_log_local->console_cannot_output = 0;
218 
219     /* partially implemented */
220     INCOMPLETE_IMPLEMENTATION();
221 #ifdef HAVE_MOUSE
222     /* ui_restore_mouse(); */
223 #endif
224     /* ui_focus_monitor(); */
225     return console_log_local;
226 }
227 
uimonfb_window_close(void)228 void uimonfb_window_close(void)
229 {
230     lib_free(console_log_local);
231     console_log_local = NULL;
232 
233     uimon_window_suspend();
234 }
235 
uimonfb_window_suspend(void)236 void uimonfb_window_suspend( void )
237 {
238     /* ui_restore_focus(); */
239 #ifdef HAVE_MOUSE
240     /* ui_check_mouse_cursor(); */
241 #endif
242     NOT_IMPLEMENTED_WARN_ONLY();
243 }
244 
uimonfb_window_resume(void)245 console_t *uimonfb_window_resume(void)
246 {
247     if (console_log_local) {
248         /* partially implemented */
249         INCOMPLETE_IMPLEMENTATION();
250 #ifdef HAVE_MOUSE
251         /* ui_restore_mouse(); */
252 #endif
253         /* ui_focus_monitor(); */
254         return console_log_local;
255     }
256     log_error(LOG_DEFAULT, "uimon_window_resume: log was not opened.");
257     return uimon_window_open();
258 }
259 
uimonfb_out(const char * buffer)260 int uimonfb_out(const char *buffer)
261 {
262     fprintf(stdout, "%s", buffer);
263     return 0;
264 }
265 
266 #if !defined(HAVE_READLINE) || !defined(HAVE_READLINE_READLINE_H)
readline(const char * prompt)267 char *readline(const char *prompt)
268 {
269     char *p = malloc(1024);
270 
271     consolefb_out(NULL, "%s", prompt);
272 
273     fflush(mon_output);
274     if (fgets(p, 1024, mon_input) == NULL) {
275         /* FIXME: handle error */
276     }
277 
278     /* Remove trailing newlines.  */
279     {
280         int len;
281 
282         for (len = strlen(p); len > 0 && (p[len - 1] == '\r' || p[len - 1] == '\n'); len--) {
283             p[len - 1] = '\0';
284         }
285     }
286 
287     return p;
288 }
289 #endif
290 
uimonfb_get_in(char ** ppchCommandLine,const char * prompt)291 char *uimonfb_get_in(char **ppchCommandLine, const char *prompt)
292 {
293     char *p, *ret_sting;
294 
295     p = readline(prompt);
296 #if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
297     if (p && *p) {
298         add_history(p);
299     }
300 #endif
301     ret_sting = lib_stralloc(p);
302     free(p);
303 
304     return ret_sting;
305 }
306 
uimonfb_notify_change(void)307 void uimonfb_notify_change( void )
308 {
309 }
310 
uimonfb_set_interface(struct monitor_interface_s ** monitor_interface_init,int count)311 void uimonfb_set_interface(struct monitor_interface_s **monitor_interface_init, int count)
312 {
313 }
314