console.cc Source File

Back to the index.

console.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2014 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * Generic console support functions.
29  *
30  * This module is used by individual device drivers, for example serial
31  * controllers, keyboards, or other devices which need to attach to the
32  * emulator's real stdin/stdout.
33  *
34  * The idea is that several input and output streams (console handles) are
35  * allowed. As long as the number of input streams is <= 1, then everything
36  * can be done in the emulator's default terminal window.
37  *
38  * If the number of inputs is more than 1, it is necessary to open up slave
39  * xterm windows for each input. (Otherwise the behaviour is undefined; i.e.
40  * which of two emulated serial controllers would get keyboard input?)
41  *
42  * (If the -x command line option is NOT used, then slaves are not opened up.
43  * Instead, a warning message is printed, and input is not allowed.)
44  *
45  * Note that console handles that _allow_ input but are not yet used for
46  * output are not counted. This allows a machine to have, say, 2 serial ports
47  * which can be used for both input and output, and it will still be possible
48  * to run in the default terminal window as long as only one of those serial
49  * ports is actually used.
50  *
51  * xterms are opened up "on demand", when output is sent to them.
52  *
53  * The MAIN console handle (fixed as handle nr 0) is the one used by the
54  * default terminal window. A machine which registers a serial controller,
55  * which should be used as the main way of communicating with guest operating
56  * systems running on that machine, should set machine->main_console_handle
57  * to the handle of the correct port on that controller.
58  *
59  *
60  * NOTE: The code in this module is mostly non-reentrant.
61  */
62 
63 #include <errno.h>
64 #include <signal.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <termios.h>
69 #include <unistd.h>
70 #include <sys/select.h>
71 #include <sys/types.h>
72 #include <time.h>
73 
74 #include "console.h"
75 #include "emul.h"
76 #include "machine.h"
77 #include "settings.h"
78 
79 
80 extern char *progname;
81 extern int verbose;
82 extern struct settings *global_settings;
83 
84 
85 static struct termios console_oldtermios;
86 static struct termios console_curtermios;
87 
88 /* For 'slave' mode: */
89 static struct termios console_slave_tios;
90 static int console_slave_outputd;
91 
92 static int console_initialized = 0;
93 static struct settings *console_settings = NULL;
94 static int console_stdout_pending;
95 
96 #define CONSOLE_FIFO_LEN 4096
97 
98 static int console_mouse_x; /* absolute x, 0-based */
99 static int console_mouse_y; /* absolute y, 0-based */
100 static int console_mouse_fb_nr; /* framebuffer number of
101  host movement, 0-based */
102 static int console_mouse_buttons; /* left=4, middle=2, right=1 */
103 
104 static int allow_slaves = 0;
105 
107  int in_use;
113 
115  char *name;
116 
119 
120  unsigned char fifo[CONSOLE_FIFO_LEN];
123 };
124 
125 #define NOT_USING_XTERM 0
126 #define USING_XTERM_BUT_NOT_YET_OPEN 1
127 #define USING_XTERM 2
128 
129 /* A simple array of console_handles */
130 static struct console_handle *console_handles = NULL;
131 static int n_console_handles = 0;
132 
133 
134 /*
135  * console_deinit_main():
136  *
137  * Restore host's console settings.
138  */
140 {
141  if (!console_initialized)
142  return;
143 
144  tcsetattr(STDIN_FILENO, TCSANOW, &console_oldtermios);
145 
146  console_initialized = 0;
147 }
148 
149 
150 /*
151  * console_sigcont():
152  *
153  * If the user presses CTRL-Z (to stop the emulator process) and then
154  * continues, the termios settings might have been invalidated. This
155  * function restores them.
156  *
157  * (This function should be set as the SIGCONT signal handler in src/emul.c.)
158  */
159 void console_sigcont(int x)
160 {
161  if (!console_initialized)
162  return;
163 
164  /* Make sure that the correct (current) termios setting is active: */
165  tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
166 
167  /* Reset the signal handler: */
168  signal(SIGCONT, console_sigcont);
169 }
170 
171 
172 /*
173  * start_xterm():
174  *
175  * When using X11 (well, when allow_slaves is set), this routine tries to
176  * start up an xterm, with another copy of gxemul inside. The other gxemul
177  * copy is given arguments that will cause it to run console_slave().
178  *
179  * TODO: This is ugly and hardcoded. Clean it up.
180  */
181 static void start_xterm(int handle)
182 {
183  int filedes[2];
184  int filedesB[2];
185  int res;
186  size_t mlen;
187  char **a;
188  pid_t p;
189 
190  res = pipe(filedes);
191  if (res) {
192  printf("[ start_xterm(): pipe(): %i ]\n", errno);
193  exit(1);
194  }
195 
196  res = pipe(filedesB);
197  if (res) {
198  printf("[ start_xterm(): pipe(): %i ]\n", errno);
199  exit(1);
200  }
201 
202  /* printf("filedes = %i,%i\n", filedes[0], filedes[1]); */
203  /* printf("filedesB = %i,%i\n", filedesB[0], filedesB[1]); */
204 
205  /* NOTE/warning: Hardcoded max nr of args! */
206  CHECK_ALLOCATION(a = (char **) malloc(sizeof(char *) * 20));
207 
208  a[0] = getenv("XTERM");
209  if (a[0] == NULL)
210  a[0] = strdup("xterm");
211  a[1] = strdup("-geometry");
212  a[2] = strdup("80x25");
213  a[3] = strdup("-title");
214  mlen = strlen(console_handles[handle].name) +
215  strlen(console_handles[handle].machine_name) + 30;
216  CHECK_ALLOCATION(a[4] = (char *) malloc(mlen));
217  snprintf(a[4], mlen, "GXemul: %s %s",
218  console_handles[handle].machine_name,
219  console_handles[handle].name);
220  a[5] = strdup("-e");
221  a[6] = progname;
222  CHECK_ALLOCATION(a[7] = (char *) malloc(80));
223  snprintf(a[7], 80, "-WW@S%i,%i", filedes[0], filedesB[1]);
224  a[8] = NULL;
225 
226  p = fork();
227  if (p == -1) {
228  printf("[ start_xterm(): ERROR while trying to "
229  "fork(): %i ]\n", errno);
230  exit(1);
231  } else if (p == 0) {
232  close(filedes[1]);
233  close(filedesB[0]);
234 
235  p = setsid();
236  if (p < 0)
237  printf("[ start_xterm(): ERROR while trying "
238  "to do a setsid(): %i ]\n", errno);
239 
240  res = execvp(a[0], a);
241  printf("[ start_xterm(): ERROR while trying to "
242  "execvp(\"");
243  while (a[0] != NULL) {
244  printf("%s", a[0]);
245  if (a[1] != NULL)
246  printf(" ");
247  a++;
248  }
249  printf("\"): %i ]\n", errno);
250  if (errno == ENOENT)
251  printf("[ Most probably you don't have xterm"
252  " in your PATH. Try again. ]\n");
253  exit(1);
254  }
255 
256  /* TODO: free a and a[*] */
257 
258  close(filedes[0]);
259  close(filedesB[1]);
260 
261  console_handles[handle].using_xterm = USING_XTERM;
262 
263  /*
264  * write to filedes[1], read from filedesB[0]
265  */
266 
267  console_handles[handle].w_descriptor = filedes[1];
268  console_handles[handle].r_descriptor = filedesB[0];
269 }
270 
271 
272 /*
273  * d_avail():
274  *
275  * Returns 1 if anything is available on a descriptor.
276  */
277 static int d_avail(int d)
278 {
279  fd_set rfds;
280  struct timeval tv;
281 
282  FD_ZERO(&rfds);
283  FD_SET(d, &rfds);
284  tv.tv_sec = 0;
285  tv.tv_usec = 0;
286  return select(d+1, &rfds, NULL, NULL, &tv);
287 }
288 
289 
290 /*
291  * console_makeavail():
292  *
293  * Put a character in the queue, so that it will be avaiable,
294  * by inserting it into the char fifo.
295  */
296 void console_makeavail(int handle, char ch)
297 {
298  console_handles[handle].fifo[
299  console_handles[handle].fifo_head] = ch;
300  console_handles[handle].fifo_head = (
301  console_handles[handle].fifo_head + 1) % CONSOLE_FIFO_LEN;
302 
303  if (console_handles[handle].fifo_head ==
304  console_handles[handle].fifo_tail)
305  fatal("[ WARNING: console fifo overrun, handle %i ]\n", handle);
306 }
307 
308 
309 /*
310  * console_stdin_avail():
311  *
312  * Returns 1 if a char is available from a handle's read descriptor,
313  * 0 otherwise.
314  */
315 static int console_stdin_avail(int handle)
316 {
317  if (!console_handles[handle].in_use_for_input)
318  return 0;
319 
320  if (!allow_slaves)
321  return d_avail(STDIN_FILENO);
322 
323  if (console_handles[handle].using_xterm ==
325  return 0;
326 
327  return d_avail(console_handles[handle].r_descriptor);
328 }
329 
330 
331 /*
332  * console_charavail():
333  *
334  * Returns 1 if a char is available in the fifo, 0 otherwise.
335  */
336 int console_charavail(int handle)
337 {
338  while (console_stdin_avail(handle)) {
339  unsigned char ch[100]; /* = getchar(); */
340  ssize_t len;
341  int i, d;
342 
343  // If adding more would lead to a full FIFO, then let's
344  // wait.
345  int roomLeftInFIFO = console_handles[handle].fifo_tail - console_handles[handle].fifo_head;
346  if (roomLeftInFIFO <= 0)
347  roomLeftInFIFO += CONSOLE_FIFO_LEN;
348  if (roomLeftInFIFO < (int)sizeof(ch) + 1)
349  break;
350 
351  if (!allow_slaves)
352  d = STDIN_FILENO;
353  else
354  d = console_handles[handle].r_descriptor;
355 
356  len = read(d, ch, sizeof(ch));
357 
358  for (i=0; i<len; i++) {
359  /* printf("[ %i: %i ]\n", i, ch[i]); */
360 
361  if (!allow_slaves) {
362  /* Ugly hack: convert ctrl-b into ctrl-c.
363  (TODO: fix) */
364  if (ch[i] == 2)
365  ch[i] = 3;
366  }
367 
368  console_makeavail(handle, ch[i]);
369  }
370  }
371 
372  if (console_handles[handle].fifo_head ==
373  console_handles[handle].fifo_tail)
374  return 0;
375 
376  return 1;
377 }
378 
379 
380 /*
381  * console_readchar():
382  *
383  * Returns 0..255 if a char was available, -1 otherwise.
384  */
385 int console_readchar(int handle)
386 {
387  int ch;
388 
389  if (!console_charavail(handle))
390  return -1;
391 
392  ch = console_handles[handle].fifo[console_handles[handle].fifo_tail];
393  console_handles[handle].fifo_tail ++;
394  console_handles[handle].fifo_tail %= CONSOLE_FIFO_LEN;
395 
396  return ch;
397 }
398 
399 
400 /*
401  * console_putchar():
402  *
403  * Prints a char to stdout, and sets the console_stdout_pending flag.
404  */
405 void console_putchar(int handle, int ch)
406 {
407  char buf[1];
408 
409  if (!console_handles[handle].in_use_for_input &&
410  !console_handles[handle].outputonly)
411  console_change_inputability(handle, 1);
412 
413  if (!allow_slaves) {
414  /* stdout: */
415  putchar(ch);
416 
417  /* Assume flushes by OS or libc on newlines: */
418  if (ch == '\n')
419  console_stdout_pending = 0;
420  else
421  console_stdout_pending = 1;
422 
423  return;
424  }
425 
426  if (!console_handles[handle].in_use) {
427  printf("[ console_putchar(): handle %i not in"
428  " use! ]\n", handle);
429  return;
430  }
431 
432  if (console_handles[handle].using_xterm ==
434  start_xterm(handle);
435 
436  buf[0] = ch;
437  if (write(console_handles[handle].w_descriptor, buf, 1) != 1)
438  perror("error writing to console handle");
439 }
440 
441 
442 /*
443  * console_flush():
444  *
445  * Flushes stdout, if necessary, and resets console_stdout_pending to zero.
446  */
447 void console_flush(void)
448 {
449  if (console_stdout_pending)
450  fflush(stdout);
451 
452  console_stdout_pending = 0;
453 }
454 
455 
456 /*
457  * console_mouse_coordinates():
458  *
459  * Sets mouse coordinates. Called by for example an X11 event handler.
460  * x and y are absolute coordinates, fb_nr is where the mouse movement
461  * took place.
462  */
463 void console_mouse_coordinates(int x, int y, int fb_nr)
464 {
465  /* TODO: fb_nr isn't used yet. */
466 
467  console_mouse_x = x;
468  console_mouse_y = y;
469  console_mouse_fb_nr = fb_nr;
470 }
471 
472 
473 /*
474  * console_mouse_button():
475  *
476  * Sets a mouse button to be pressed or released. Called by for example an
477  * X11 event handler. button is 1 (left), 2 (middle), or 3 (right), and
478  * pressed = 1 for pressed, 0 for not pressed.
479  */
480 void console_mouse_button(int button, int pressed)
481 {
482  int mask = 1 << (3-button);
483 
484  if (pressed)
485  console_mouse_buttons |= mask;
486  else
487  console_mouse_buttons &= ~mask;
488 }
489 
490 
491 /*
492  * console_getmouse():
493  *
494  * Puts current mouse data into the variables pointed to by
495  * the arguments.
496  */
497 void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
498 {
499  *x = console_mouse_x;
500  *y = console_mouse_y;
501  *buttons = console_mouse_buttons;
502  *fb_nr = console_mouse_fb_nr;
503 }
504 
505 
506 /*
507  * console_slave_sigint():
508  */
509 static void console_slave_sigint(int x)
510 {
511  char buf[1];
512 
513  /* Send a ctrl-c: */
514  buf[0] = 3;
515  if (write(console_slave_outputd, buf, sizeof(buf)) != sizeof(buf))
516  perror("error writing to console handle");
517 
518  /* Reset the signal handler: */
519  signal(SIGINT, console_slave_sigint);
520 }
521 
522 
523 /*
524  * console_slave_sigcont():
525  *
526  * See comment for console_sigcont. This is for used by console_slave().
527  */
528 static void console_slave_sigcont(int x)
529 {
530  /* Make sure our 'current' termios setting is active: */
531  tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
532 
533  /* Reset the signal handler: */
534  signal(SIGCONT, console_slave_sigcont);
535 }
536 
537 
538 /*
539  * console_slave():
540  *
541  * This function is used when running with X11, and gxemul opens up
542  * separate xterms for each emulated terminal or serial port.
543  */
544 void console_slave(const char *arg)
545 {
546  int inputd;
547  int len;
548  const char *p;
549  char buf[16384];
550 
551  /* arg = '3,6' or similar, input and output descriptors */
552  /* printf("console_slave(): arg = '%s'\n", arg); */
553 
554  inputd = atoi(arg);
555  p = strchr(arg, ',');
556  if (p == NULL) {
557  printf("console_slave(): bad arg '%s'\n", arg);
558  sleep(5);
559  exit(1);
560  }
561  console_slave_outputd = atoi(p+1);
562 
563  /* Set the terminal to raw mode: */
564  tcgetattr(STDIN_FILENO, &console_slave_tios);
565 
566  console_slave_tios.c_lflag &= ~ICANON;
567  console_slave_tios.c_cc[VTIME] = 0;
568  console_slave_tios.c_cc[VMIN] = 1;
569  console_slave_tios.c_lflag &= ~ECHO;
570  console_slave_tios.c_iflag &= ~ICRNL;
571  tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
572 
573  signal(SIGINT, console_slave_sigint);
574  signal(SIGCONT, console_slave_sigcont);
575 
576  for (;;) {
577  /* TODO: select() on both inputd and stdin */
578 
579  if (d_avail(inputd)) {
580  len = read(inputd, buf, sizeof(buf) - 1);
581  if (len < 1)
582  exit(0);
583  buf[len] = '\0';
584  printf("%s", buf);
585  fflush(stdout);
586  }
587 
588  if (d_avail(STDIN_FILENO)) {
589  len = read(STDIN_FILENO, buf, sizeof(buf));
590  if (len < 1)
591  exit(0);
592  if (write(console_slave_outputd, buf, len) != len)
593  perror("error writing to console handle");
594  }
595 
596  usleep(10000);
597  }
598 }
599 
600 
601 /*
602  * console_new_handle():
603  *
604  * Allocates a new console_handle struct, and returns a pointer to it.
605  *
606  * For internal use.
607  */
608 static struct console_handle *console_new_handle(const char *name, int *handlep)
609 {
610  struct console_handle *chp;
611  int i, n, found_free = -1;
612 
613  /* Reuse an old slot, if possible: */
614  n = n_console_handles;
615  for (i=0; i<n; i++)
616  if (!console_handles[i].in_use) {
617  found_free = i;
618  break;
619  }
620 
621  if (found_free == -1) {
622  /* Let's realloc console_handles[], to make room
623  for the new one: */
624  CHECK_ALLOCATION(console_handles = (struct console_handle *)
625  realloc(console_handles, sizeof(
626  struct console_handle) * (n_console_handles + 1)));
627  found_free = n_console_handles;
628  n_console_handles ++;
629  }
630 
631  chp = &console_handles[found_free];
632  memset(chp, 0, sizeof(struct console_handle));
633 
634  chp->in_use = 1;
635  chp->machine_name = strdup("");
636  CHECK_ALLOCATION(chp->name = strdup(name));
637 
638  *handlep = found_free;
639  return chp;
640 }
641 
642 
643 /*
644  * console_start_slave():
645  *
646  * When using X11:
647  *
648  * This routine tries to start up an xterm, with another copy of gxemul
649  * inside. The other gxemul copy is given arguments that will cause it
650  * to run console_slave().
651  *
652  * When not using X11: Things will seem to work the same way without X11,
653  * but no xterm will actually be started.
654  *
655  * consolename should be something like "serial 0".
656  *
657  * If use_for_input is 1, input is allowed right from the start. (This
658  * can be upgraded later from 0 to 1 using the console_change_inputability()
659  * function.)
660  *
661  * If use_for_input is CONSOLE_OUTPUT_ONLY, then this is an output-only stream.
662  *
663  * On success, an integer >= 0 is returned. This can then be used as a
664  * 'handle' when writing to or reading from an emulated console.
665  *
666  * On failure, -1 is returned.
667  */
668 int console_start_slave(struct machine *machine, const char *consolename,
669  int use_for_input)
670 {
671  struct console_handle *chp;
672  int handle;
673 
674  if (machine == NULL || consolename == NULL) {
675  printf("console_start_slave(): NULL ptr\n");
676  exit(1);
677  }
678 
679  chp = console_new_handle(consolename, &handle);
680  chp->in_use_for_input = use_for_input;
681  if (use_for_input == CONSOLE_OUTPUT_ONLY) {
682  chp->outputonly = 1;
683  chp->in_use_for_input = 0;
684  }
685 
686  if (machine->machine_name != NULL) {
688  strdup(machine->machine_name));
689  } else {
690  CHECK_ALLOCATION(chp->machine_name = strdup(""));
691  }
692 
693  CHECK_ALLOCATION(chp->name = strdup(consolename));
694 
695  if (allow_slaves)
697 
698  return handle;
699 }
700 
701 
702 /*
703  * console_start_slave_inputonly():
704  *
705  * Similar to console_start_slave(), but doesn't open an xterm. This is
706  * useful for devices such as keyboard controllers, that need to have an
707  * input queue, but no xterm window associated with it.
708  *
709  * On success, an integer >= 0 is returned. This can then be used as a
710  * 'handle' when writing to or reading from an emulated console.
711  *
712  * On failure, -1 is returned.
713  */
714 int console_start_slave_inputonly(struct machine *machine, const char *consolename,
715  int use_for_input)
716 {
717  struct console_handle *chp;
718  int handle;
719 
720  if (machine == NULL || consolename == NULL) {
721  printf("console_start_slave(): NULL ptr\n");
722  exit(1);
723  }
724 
725  chp = console_new_handle(consolename, &handle);
726  chp->inputonly = 1;
727  chp->in_use_for_input = use_for_input;
728 
729  if (machine->name != NULL) {
730  CHECK_ALLOCATION(chp->machine_name = strdup(machine->name));
731  } else {
732  CHECK_ALLOCATION(chp->machine_name = strdup(""));
733  }
734 
735  CHECK_ALLOCATION(chp->name = strdup(consolename));
736 
737  return handle;
738 }
739 
740 
741 /*
742  * console_change_inputability():
743  *
744  * Sets whether or not a console handle can be used for input. Return value
745  * is 1 if the change took place, 0 otherwise.
746  */
747 int console_change_inputability(int handle, int inputability)
748 {
749  int old;
750 
751  if (handle < 0 || handle >= n_console_handles) {
752  fatal("console_change_inputability(): bad handle %i\n",
753  handle);
754  exit(1);
755  }
756 
757  old = console_handles[handle].in_use_for_input;
758  console_handles[handle].in_use_for_input = inputability;
759 
760  if (inputability != 0) {
762  console_handles[handle].in_use_for_input = old;
763  if (!console_handles[handle].warning_printed) {
764  fatal("%%\n%% WARNING! Input to console ha"
765  "ndle \"%s\" wasn't enabled,\n%% because "
766  "it", console_handles[handle].name);
767  fatal(" would interfere with other inputs,\n"
768  "%% and you did not use the -x command "
769  "line option!\n%%\n");
770  }
771  console_handles[handle].warning_printed = 1;
772  return 0;
773  }
774  }
775 
776  return 1;
777 }
778 
779 
780 /*
781  * console_init_main():
782  *
783  * Puts the host's console into single-character (non-canonical) mode.
784  */
786 {
787  int i, tra;
788 
789  if (console_initialized)
790  return;
791 
792  tcgetattr(STDIN_FILENO, &console_oldtermios);
793  memcpy(&console_curtermios, &console_oldtermios,
794  sizeof (struct termios));
795 
796  console_curtermios.c_lflag &= ~ICANON;
797  console_curtermios.c_cc[VTIME] = 0;
798  console_curtermios.c_cc[VMIN] = 1;
799 
800  console_curtermios.c_lflag &= ~ECHO;
801 
802  /*
803  * Most guest OSes seem to work ok without ~ICRNL, but Linux on
804  * DECstation requires it to be usable. Unfortunately, clearing
805  * out ICRNL makes tracing with '-t ... |more' akward, as you
806  * might need to use CTRL-J instead of the enter key. Hence,
807  * this bit is only cleared if we're not tracing:
808  */
809  tra = 0;
810  for (i=0; i<emul->n_machines; i++)
811  if (emul->machines[i]->show_trace_tree ||
812  emul->machines[i]->instruction_trace ||
813  emul->machines[i]->register_dump)
814  tra = 1;
815  if (!tra)
816  console_curtermios.c_iflag &= ~ICRNL;
817 
818  tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
819 
820  console_stdout_pending = 1;
821  console_handles[MAIN_CONSOLE].fifo_head = 0;
822  console_handles[MAIN_CONSOLE].fifo_tail = 0;
823 
824  console_mouse_x = 0;
825  console_mouse_y = 0;
826  console_mouse_buttons = 0;
827 
828  console_initialized = 1;
829 }
830 
831 
832 /*
833  * console_debug_dump():
834  *
835  * Dump debug info, if verbose >= 2.
836  */
838 {
839  int i, iadd = DEBUG_INDENTATION, listed_main = 0;
840 
841  if (verbose < 2)
842  return;
843 
844  debug("console slaves (xterms): %s\n", allow_slaves?
845  "yes" : "no");
846 
847  debug("console handles:\n");
848  debug_indentation(iadd);
849 
850  for (i=0; i<n_console_handles; i++) {
851  if (!console_handles[i].in_use)
852  continue;
853  debug("%i: \"%s\"", i, console_handles[i].name);
854  if (console_handles[i].using_xterm)
855  debug(" [xterm]");
856  if (console_handles[i].inputonly)
857  debug(" [inputonly]");
858  if (console_handles[i].outputonly)
859  debug(" [outputonly]");
860  if (i == machine->main_console_handle) {
861  debug(" [MAIN CONSOLE]");
862  listed_main = 1;
863  }
864  debug("\n");
865  }
866 
867  debug_indentation(-iadd);
868 
869  if (!listed_main)
870  fatal("WARNING! no main console handle?\n");
871 }
872 
873 
874 /*
875  * console_allow_slaves():
876  *
877  * This function tells the console subsystem whether or not to open up
878  * slave xterms for each emulated serial controller.
879  */
880 void console_allow_slaves(int allow)
881 {
882  allow_slaves = allow;
883 }
884 
885 
886 /*
887  * console_are_slaves_allowed():
888  *
889  * Returns the value of allow_slaves.
890  */
892 {
893  return allow_slaves;
894 }
895 
896 
897 /*
898  * console_warn_if_slaves_are_needed():
899  *
900  * Prints an error (during startup of the emulator) if slave xterms are needed
901  * (i.e. there is more than one console handle in use which is used for
902  * INPUT), but they are not currently allowed.
903  *
904  * This function should be called during startup (with init = 1), and every
905  * time a console handle changes/upgrades its in_use_for_input from 0 to 1.
906  *
907  * If init is non-zero, this function doesn't return if there was a warning.
908  *
909  * If init is zero, no warning is printed. 1 is returned if there were more
910  * than one input, 0 otherwise.
911  */
913 {
914  int i, n = 0;
915 
916  if (allow_slaves)
917  return 0;
918 
919  for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
920  if (console_handles[i].in_use &&
921  console_handles[i].in_use_for_input &&
922  !console_handles[i].using_xterm)
923  n ++;
924 
925  if (n > 1) {
926  if (init) {
927  fatal("#\n# ERROR! More than one console input is "
928  "in use,\n# but xterm slaves are not enabled.\n"
929  "#\n");
930  fatal("# Use -x to enable slave xterms.)\n#\n");
931  for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
932  if (console_handles[i].in_use &&
933  console_handles[i].in_use_for_input &&
934  !console_handles[i].using_xterm)
935  fatal("# console handle %i: '%s'\n",
936  i, console_handles[i].name);
937  fatal("#\n");
938  exit(1);
939  }
940  return 1;
941  }
942 
943  return 0;
944 }
945 
946 
947 /*
948  * console_init():
949  *
950  * This function should be called before any other console_*() function
951  * is used.
952  */
953 void console_init(void)
954 {
955  int handle;
956  struct console_handle *chp;
957 
958  console_settings = settings_new();
959 
960  settings_add(global_settings, "console", 1,
961  SETTINGS_TYPE_SUBSETTINGS, 0, console_settings);
962 
963  settings_add(console_settings, "allow_slaves", 0,
964  SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&allow_slaves);
965 
966  chp = console_new_handle("MAIN", &handle);
967  if (handle != MAIN_CONSOLE) {
968  printf("console_init(): fatal error: could not create"
969  " console 0: handle = %i\n", handle);
970  exit(1);
971  }
972 
973  chp->in_use_for_input = 1;
974 }
975 
976 
977 /*
978  * console_deinit():
979  *
980  * Unregister settings registered by console_init().
981  */
982 void console_deinit(void)
983 {
984  settings_remove(console_settings, "allow_slaves");
985  settings_remove(global_settings, "console");
986 }
987 
void console_init(void)
Definition: console.cc:953
void fatal(const char *fmt,...)
Definition: main.cc:152
int console_start_slave_inputonly(struct machine *machine, const char *consolename, int use_for_input)
Definition: console.cc:714
#define DEBUG_INDENTATION
Definition: misc.h:212
void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
Definition: console.cc:497
#define SETTINGS_FORMAT_YESNO
Definition: settings.h:58
struct settings * settings_new(void)
Definition: settings.cc:88
int n_machines
Definition: emul.h:45
int main_console_handle
Definition: machine.h:128
unsigned char fifo[CONSOLE_FIFO_LEN]
Definition: console.cc:120
void console_init_main(struct emul *emul)
Definition: console.cc:785
int w_descriptor
Definition: console.cc:117
int r_descriptor
Definition: console.cc:118
#define USING_XTERM
Definition: console.cc:127
int console_warn_if_slaves_are_needed(int init)
Definition: console.cc:912
int console_are_slaves_allowed(void)
Definition: console.cc:891
int verbose
Definition: main.cc:77
void console_makeavail(int handle, char ch)
Definition: console.cc:296
void console_putchar(int handle, int ch)
Definition: console.cc:405
int console_readchar(int handle)
Definition: console.cc:385
void console_sigcont(int x)
Definition: console.cc:159
void console_mouse_coordinates(int x, int y, int fb_nr)
Definition: console.cc:463
void console_mouse_button(int button, int pressed)
Definition: console.cc:480
char * machine_name
Definition: console.cc:114
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
void console_slave(const char *arg)
Definition: console.cc:544
int console_charavail(int handle)
Definition: console.cc:336
struct settings * global_settings
Definition: main.cc:59
int console_change_inputability(int handle, int inputability)
Definition: console.cc:747
int instruction_trace
Definition: machine.h:162
void settings_remove(struct settings *settings, const char *name)
Definition: settings.cc:383
#define CONSOLE_FIFO_LEN
Definition: console.cc:96
void console_allow_slaves(int allow)
Definition: console.cc:880
Definition: emul.h:37
#define debug
Definition: dev_adb.cc:57
#define SETTINGS_TYPE_SUBSETTINGS
Definition: settings.h:38
int warning_printed
Definition: console.cc:112
void console_deinit_main(void)
Definition: console.cc:139
void console_flush(void)
Definition: console.cc:447
int in_use_for_input
Definition: console.cc:108
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
int register_dump
Definition: machine.h:150
void console_deinit(void)
Definition: console.cc:982
void debug_indentation(int diff)
Definition: main.cc:120
int console_start_slave(struct machine *machine, const char *consolename, int use_for_input)
Definition: console.cc:668
char * name
Definition: console.cc:115
void settings_add(struct settings *settings, const char *name, int writable, int type, int format, void *ptr)
Definition: settings.cc:334
struct machine ** machines
Definition: emul.h:46
const char * name
Definition: machine.h:105
#define SETTINGS_TYPE_INT
Definition: settings.h:40
#define MAIN_CONSOLE
Definition: console.h:37
void console_debug_dump(struct machine *machine)
Definition: console.cc:837
int show_trace_tree
Definition: machine.h:164
#define USING_XTERM_BUT_NOT_YET_OPEN
Definition: console.cc:126
const char * machine_name
Definition: machine.h:115
#define CONSOLE_OUTPUT_ONLY
Definition: console.h:39
char * progname
Definition: main.cc:63

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13