/[gxemul]/upstream/0.3.7/src/console.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.3.7/src/console.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (hide annotations)
Mon Oct 8 16:19:28 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 19157 byte(s)
0.3.7
1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 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 dpavlin 20 * $Id: console.c,v 1.10 2005/11/23 02:17:00 debug Exp $
29 dpavlin 2 *
30     * Generic console support functions.
31     *
32     * This is used by individual device drivers, for example serial controllers,
33     * to attach stdin/stdout of the host system to a specific device.
34     *
35     * NOTE: This stuff is non-reentrant.
36     */
37    
38     #include <errno.h>
39     #include <signal.h>
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43     #include <termios.h>
44     #include <unistd.h>
45     #include <sys/types.h>
46    
47     #include "console.h"
48     #include "emul.h"
49     #include "machine.h"
50     #include "memory.h"
51     #include "misc.h"
52    
53    
54     extern char *progname;
55    
56    
57     static struct termios console_oldtermios;
58     static struct termios console_curtermios;
59    
60     /* For 'slave' mode: */
61     static struct termios console_slave_tios;
62     static int console_slave_outputd;
63    
64     static int console_initialized = 0;
65     static int console_stdout_pending;
66    
67     #define CONSOLE_FIFO_LEN 4096
68    
69     /* Mouse coordinates: */
70     static int console_framebuffer_mouse_x; /* absolute x, 0-based */
71     static int console_framebuffer_mouse_y; /* absolute y, 0-based */
72     static int console_framebuffer_mouse_fb_nr; /* fb_number of last
73     framebuffer cursor update */
74    
75     static int console_mouse_x; /* absolute x, 0-based */
76     static int console_mouse_y; /* absolute y, 0-based */
77     static int console_mouse_fb_nr; /* framebuffer number of
78     host movement, 0-based */
79     static int console_mouse_buttons; /* left=4, middle=2, right=1 */
80    
81     static int allow_slaves = 0;
82    
83     struct console_handle {
84     int in_use;
85     int using_xterm;
86     int inputonly;
87    
88     char *name;
89    
90     int w_descriptor;
91     int r_descriptor;
92    
93     unsigned char fifo[CONSOLE_FIFO_LEN];
94     int fifo_head;
95     int fifo_tail;
96     };
97    
98     #define NOT_USING_XTERM 0
99     #define USING_XTERM_BUT_NOT_YET_OPEN 1
100     #define USING_XTERM 2
101    
102     /* A simple array of console_handles */
103     static struct console_handle *console_handles = NULL;
104     static int n_console_handles = 0;
105    
106    
107     /*
108     * console_deinit():
109     *
110     * Restore host's console settings.
111     */
112     void console_deinit(void)
113     {
114     if (!console_initialized)
115     return;
116    
117     tcsetattr(STDIN_FILENO, TCSANOW, &console_oldtermios);
118    
119     console_initialized = 0;
120     }
121    
122    
123     /*
124     * console_sigcont():
125     *
126     * If the user presses CTRL-Z (to stop the emulator process) and then
127     * continues, we have to make sure that the right termios settings are
128     * active. (This should be set as the SIGCONT signal handler in src/emul.c.)
129     */
130     void console_sigcont(int x)
131     {
132     if (!console_initialized)
133     return;
134    
135     /* Make sure our 'current' termios setting is active: */
136     tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
137    
138     /* Reset the signal handler: */
139     signal(SIGCONT, console_sigcont);
140     }
141    
142    
143     /*
144     * start_xterm():
145     *
146     * When using X11, this routine tries to start up an xterm, with another
147     * copy of gxemul inside. The other gxemul copy is given arguments
148     * that will cause it to run console_slave().
149     */
150     static void start_xterm(int handle)
151     {
152     int filedes[2];
153     int filedesB[2];
154     int res;
155     char **a;
156     pid_t p;
157    
158     res = pipe(filedes);
159     if (res) {
160     printf("[ start_xterm(): pipe(): %i ]\n", errno);
161     exit(1);
162     }
163    
164     res = pipe(filedesB);
165     if (res) {
166     printf("[ start_xterm(): pipe(): %i ]\n", errno);
167     exit(1);
168     }
169    
170     /* printf("filedes = %i,%i\n", filedes[0], filedes[1]); */
171     /* printf("filedesB = %i,%i\n", filedesB[0], filedesB[1]); */
172    
173     /* NOTE/warning: Hardcoded max nr of args! */
174     a = malloc(sizeof(char *) * 20);
175     if (a == NULL) {
176     fprintf(stderr, "console_start_slave(): out of memory\n");
177     exit(1);
178     }
179    
180     a[0] = getenv("XTERM");
181     if (a[0] == NULL)
182     a[0] = "xterm";
183 dpavlin 6 a[1] = "-geometry";
184     a[2] = "80x25";
185     a[3] = "-title";
186     a[4] = console_handles[handle].name;
187     a[5] = "-e";
188     a[6] = progname;
189 dpavlin 10 a[7] = malloc(80);
190     snprintf(a[7], 80, "-WW@S%i,%i", filedes[0], filedesB[1]);
191 dpavlin 6 a[8] = NULL;
192 dpavlin 2
193     p = fork();
194     if (p == -1) {
195     printf("[ console_start_slave(): ERROR while trying to "
196     "fork(): %i ]\n", errno);
197     exit(1);
198     } else if (p == 0) {
199     close(filedes[1]);
200     close(filedesB[0]);
201    
202     p = setsid();
203     if (p < 0)
204     printf("[ console_start_slave(): ERROR while trying "
205     "to do a setsid(): %i ]\n", errno);
206    
207     res = execvp(a[0], a);
208     printf("[ console_start_slave(): ERROR while trying to "
209     "execvp(\"");
210     while (a[0] != NULL) {
211     printf("%s", a[0]);
212     if (a[1] != NULL)
213     printf(" ");
214     a++;
215     }
216     printf("\"): %i ]\n", errno);
217     exit(1);
218     }
219    
220     /* TODO: free a and a[*] */
221    
222     close(filedes[0]);
223     close(filedesB[1]);
224    
225     console_handles[handle].using_xterm = USING_XTERM;
226    
227     /*
228     * write to filedes[1], read from filedesB[0]
229     */
230    
231     console_handles[handle].w_descriptor = filedes[1];
232     console_handles[handle].r_descriptor = filedesB[0];
233     }
234    
235    
236     /*
237     * d_avail():
238     *
239     * Returns 1 if anything is available on a descriptor.
240     */
241     static int d_avail(int d)
242     {
243     fd_set rfds;
244     struct timeval tv;
245    
246     FD_ZERO(&rfds);
247     FD_SET(d, &rfds);
248     tv.tv_sec = 0;
249     tv.tv_usec = 0;
250     return select(d+1, &rfds, NULL, NULL, &tv);
251     }
252    
253    
254     /*
255     * console_makeavail():
256     *
257     * Put a character in the queue, so that it will be avaiable,
258     * by inserting it into the char fifo.
259     */
260     void console_makeavail(int handle, char ch)
261     {
262     console_handles[handle].fifo[
263     console_handles[handle].fifo_head] = ch;
264     console_handles[handle].fifo_head = (
265     console_handles[handle].fifo_head + 1) % CONSOLE_FIFO_LEN;
266    
267     if (console_handles[handle].fifo_head ==
268     console_handles[handle].fifo_tail)
269     fatal("[ WARNING: console fifo overrun, handle %i ]\n", handle);
270     }
271    
272    
273     /*
274     * console_stdin_avail():
275     *
276     * Returns 1 if a char is available from a handle's read descriptor,
277     * 0 otherwise.
278     */
279     static int console_stdin_avail(int handle)
280     {
281     if (!allow_slaves)
282     return d_avail(STDIN_FILENO);
283    
284     if (console_handles[handle].using_xterm ==
285     USING_XTERM_BUT_NOT_YET_OPEN)
286     return 0;
287    
288     return d_avail(console_handles[handle].r_descriptor);
289     }
290    
291    
292     /*
293     * console_charavail():
294     *
295     * Returns 1 if a char is available in the fifo, 0 otherwise.
296     */
297     int console_charavail(int handle)
298     {
299     while (console_stdin_avail(handle)) {
300     unsigned char ch[100]; /* = getchar(); */
301     ssize_t len;
302     int i, d;
303    
304     if (!allow_slaves)
305     d = STDIN_FILENO;
306     else
307     d = console_handles[handle].r_descriptor;
308    
309     len = read(d, ch, sizeof(ch));
310    
311     for (i=0; i<len; i++) {
312     /* printf("[ %i: %i ]\n", i, ch[i]); */
313    
314     if (!allow_slaves) {
315     /* Ugly hack: convert ctrl-b into ctrl-c.
316     (TODO: fix) */
317     if (ch[i] == 2)
318     ch[i] = 3;
319     }
320    
321     console_makeavail(handle, ch[i]);
322     }
323     }
324    
325     if (console_handles[handle].fifo_head ==
326     console_handles[handle].fifo_tail)
327     return 0;
328    
329     return 1;
330     }
331    
332    
333     /*
334     * console_readchar():
335     *
336     * Returns 0..255 if a char was available, -1 otherwise.
337     */
338     int console_readchar(int handle)
339     {
340     int ch;
341    
342     if (!console_charavail(handle))
343     return -1;
344    
345     ch = console_handles[handle].fifo[console_handles[handle].fifo_tail];
346     console_handles[handle].fifo_tail ++;
347     console_handles[handle].fifo_tail %= CONSOLE_FIFO_LEN;
348    
349     return ch;
350     }
351    
352    
353     /*
354     * console_putchar():
355     *
356     * Prints a char to stdout, and sets the console_stdout_pending flag.
357     */
358     void console_putchar(int handle, int ch)
359     {
360     char buf[1];
361    
362     if (!allow_slaves) {
363     /* stdout: */
364     putchar(ch);
365    
366     /* Assume flushes by OS or libc on newlines: */
367     if (ch == '\n')
368     console_stdout_pending = 0;
369     else
370     console_stdout_pending = 1;
371    
372     return;
373     }
374    
375     if (!console_handles[handle].in_use) {
376     printf("[ console_putchar(): handle %i not in"
377     " use! ]\n", handle);
378     return;
379     }
380    
381     if (console_handles[handle].using_xterm ==
382     USING_XTERM_BUT_NOT_YET_OPEN)
383     start_xterm(handle);
384    
385     buf[0] = ch;
386     write(console_handles[handle].w_descriptor, buf, 1);
387     }
388    
389    
390     /*
391     * console_flush():
392     *
393     * Flushes stdout, if necessary, and resets console_stdout_pending to zero.
394     */
395     void console_flush(void)
396     {
397     if (console_stdout_pending)
398     fflush(stdout);
399    
400     console_stdout_pending = 0;
401     }
402    
403    
404     /*
405     * console_mouse_coordinates():
406     *
407     * Sets mouse coordinates. Called by for example an X11 event handler.
408     * x and y are absolute coordinates, fb_nr is where the mouse movement
409     * took place.
410     */
411     void console_mouse_coordinates(int x, int y, int fb_nr)
412     {
413     /* TODO: fb_nr isn't used yet. */
414    
415     console_mouse_x = x;
416     console_mouse_y = y;
417     console_mouse_fb_nr = fb_nr;
418     }
419    
420    
421     /*
422     * console_mouse_button():
423     *
424     * Sets a mouse button to be pressed or released. Called by for example an
425     * X11 event handler. button is 1 (left), 2 (middle), or 3 (right), and
426     * pressed = 1 for pressed, 0 for not pressed.
427     */
428     void console_mouse_button(int button, int pressed)
429     {
430     int mask = 1 << (3-button);
431    
432     if (pressed)
433     console_mouse_buttons |= mask;
434     else
435     console_mouse_buttons &= ~mask;
436     }
437    
438    
439     /*
440     * console_get_framebuffer_mouse():
441     *
442     * TODO: Comment
443     */
444     void console_get_framebuffer_mouse(int *x, int *y, int *fb_nr)
445     {
446     *x = console_framebuffer_mouse_x;
447     *y = console_framebuffer_mouse_y;
448     *fb_nr = console_framebuffer_mouse_fb_nr;
449     }
450    
451    
452     /*
453     * console_set_framebuffer_mouse():
454     *
455     * A framebuffer device calls this function when it sets the
456     * position of a cursor (ie a mouse cursor).
457     */
458     void console_set_framebuffer_mouse(int x, int y, int fb_nr)
459     {
460     console_framebuffer_mouse_x = x;
461     console_framebuffer_mouse_y = y;
462     console_framebuffer_mouse_fb_nr = fb_nr;
463     }
464    
465    
466     /*
467     * console_getmouse():
468     *
469     * Puts current mouse data into the variables pointed to by
470     * the arguments.
471     */
472     void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
473     {
474     *x = console_mouse_x;
475     *y = console_mouse_y;
476     *buttons = console_mouse_buttons;
477     *fb_nr = console_mouse_fb_nr;
478     }
479    
480    
481     /*
482     * console_slave_sigint():
483     */
484     static void console_slave_sigint(int x)
485     {
486     char buf[1];
487    
488     /* Send a ctrl-c: */
489     buf[0] = 3;
490     write(console_slave_outputd, buf, sizeof(buf));
491    
492     /* Reset the signal handler: */
493     signal(SIGINT, console_slave_sigint);
494     }
495    
496    
497     /*
498     * console_slave_sigcont():
499     *
500     * See comment for console_sigcont. This is for used by console_slave().
501     */
502     static void console_slave_sigcont(int x)
503     {
504     /* Make sure our 'current' termios setting is active: */
505     tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
506    
507     /* Reset the signal handler: */
508     signal(SIGCONT, console_slave_sigcont);
509     }
510    
511    
512     /*
513     * console_slave():
514     *
515     * This function is used when running with X11, and gxemul opens up
516     * separate xterms for each emulated terminal or serial port.
517     */
518     void console_slave(char *arg)
519     {
520     int inputd;
521     int len;
522     char *p;
523     char buf[400];
524    
525     /* arg = '3,6' or similar, input and output descriptors */
526     /* printf("console_slave(): arg = '%s'\n", arg); */
527    
528     inputd = atoi(arg);
529     p = strchr(arg, ',');
530     if (p == NULL) {
531     printf("console_slave(): bad arg '%s'\n", arg);
532     sleep(5);
533     exit(1);
534     }
535     console_slave_outputd = atoi(p+1);
536    
537     /* Set the terminal to raw mode: */
538     tcgetattr(STDIN_FILENO, &console_slave_tios);
539    
540     console_slave_tios.c_lflag &= ~ICANON;
541     console_slave_tios.c_cc[VTIME] = 0;
542     console_slave_tios.c_cc[VMIN] = 1;
543     console_slave_tios.c_lflag &= ~ECHO;
544     console_slave_tios.c_iflag &= ~ICRNL;
545     tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
546    
547     signal(SIGINT, console_slave_sigint);
548     signal(SIGCONT, console_slave_sigcont);
549    
550     for (;;) {
551     /* TODO: select() on both inputd and stdin */
552    
553     if (d_avail(inputd)) {
554     len = read(inputd, buf, sizeof(buf) - 1);
555     if (len < 1)
556     exit(0);
557     buf[len] = '\0';
558     printf("%s", buf);
559     fflush(stdout);
560     }
561    
562     if (d_avail(STDIN_FILENO)) {
563     len = read(STDIN_FILENO, buf, sizeof(buf));
564     if (len < 1)
565     exit(0);
566     write(console_slave_outputd, buf, len);
567     }
568    
569     usleep(100);
570     }
571     }
572    
573    
574     /*
575     * console_new_handle():
576     *
577     * Allocates a new console_handle struct, and returns a pointer to it.
578     *
579     * For internal use.
580     */
581     static struct console_handle *console_new_handle(char *name, int *handlep)
582     {
583     struct console_handle *chp;
584     int i, n, found_free = -1;
585    
586     /* Reuse an old slot, if possible: */
587     n = n_console_handles;
588     for (i=0; i<n; i++)
589     if (!console_handles[i].in_use) {
590     found_free = i;
591     break;
592     }
593    
594     if (found_free == -1) {
595     /* Let's realloc console_handles[], to make room
596     for the new one: */
597     console_handles = realloc(console_handles, sizeof(
598     struct console_handle) * (n_console_handles + 1));
599     if (console_handles == NULL) {
600     printf("console_new_handle(): out of memory\n");
601     exit(1);
602     }
603     found_free = n_console_handles;
604     n_console_handles ++;
605     }
606    
607     chp = &console_handles[found_free];
608     memset(chp, 0, sizeof(struct console_handle));
609    
610     chp->in_use = 1;
611     chp->name = strdup(name);
612     if (chp->name == NULL) {
613     printf("console_new_handle(): out of memory\n");
614     exit(1);
615     }
616    
617     *handlep = found_free;
618     return chp;
619     }
620    
621    
622     /*
623     * console_start_slave():
624     *
625     * When using X11:
626     *
627     * This routine tries to start up an xterm, with another copy of gxemul
628     * inside. The other gxemul copy is given arguments that will cause it
629     * to run console_slave().
630     *
631     * When not using X11: Things will seem to work the same way without X11,
632     * but no xterm will actually be started.
633     *
634     * consolename should be something like "serial 0".
635     *
636     * On success, an integer >= 0 is returned. This can then be used as a
637     * 'handle' when writing to or reading from an emulated console.
638     *
639     * On failure, -1 is returned.
640     */
641     int console_start_slave(struct machine *machine, char *consolename)
642     {
643     int handle;
644 dpavlin 10 size_t mlen;
645 dpavlin 2 struct console_handle *chp;
646    
647     if (machine == NULL || consolename == NULL) {
648     printf("console_start_slave(): NULL ptr\n");
649     exit(1);
650     }
651    
652     chp = console_new_handle(consolename, &handle);
653    
654 dpavlin 10 mlen = strlen(machine->name) + strlen(consolename) + 40;
655     chp->name = malloc(mlen);
656 dpavlin 2 if (chp->name == NULL) {
657     printf("out of memory\n");
658     exit(1);
659     }
660 dpavlin 10 snprintf(chp->name, mlen, "GXemul: '%s' %s",
661     machine->name, consolename);
662 dpavlin 2
663     #if 0
664     if (!machine->use_x11) {
665     return handle;
666     }
667     #endif
668     chp->using_xterm = USING_XTERM_BUT_NOT_YET_OPEN;
669    
670     return handle;
671     }
672    
673    
674     /*
675     * console_start_slave_inputonly():
676     *
677     * Similar to console_start_slave(), but doesn't open an xterm. This is
678     * useful for devices such as keyboard controllers, that need to have an
679     * input queue, but no xterm window associated with it.
680     *
681     * On success, an integer >= 0 is returned. This can then be used as a
682     * 'handle' when writing to or reading from an emulated console.
683     *
684     * On failure, -1 is returned.
685     */
686     int console_start_slave_inputonly(struct machine *machine, char *consolename)
687     {
688     struct console_handle *chp;
689     int handle;
690 dpavlin 10 size_t mlen;
691 dpavlin 2
692     if (machine == NULL || consolename == NULL) {
693     printf("console_start_slave(): NULL ptr\n");
694     exit(1);
695     }
696    
697     chp = console_new_handle(consolename, &handle);
698     chp->inputonly = 1;
699    
700 dpavlin 10 mlen = strlen(machine->name) + strlen(consolename) + 40;
701     chp->name = malloc(mlen);
702 dpavlin 2 if (chp->name == NULL) {
703     printf("out of memory\n");
704     exit(1);
705     }
706 dpavlin 10 snprintf(chp->name, mlen, "GXemul: '%s' %s",
707     machine->name, consolename);
708 dpavlin 2
709     return handle;
710     }
711    
712    
713     /*
714     * console_init_main():
715     *
716     * Put host's console into single-character (non-canonical) mode.
717     */
718     void console_init_main(struct emul *emul)
719     {
720     int i, tra;
721    
722     if (console_initialized)
723     return;
724    
725     tcgetattr(STDIN_FILENO, &console_oldtermios);
726     memcpy(&console_curtermios, &console_oldtermios,
727     sizeof (struct termios));
728    
729     console_curtermios.c_lflag &= ~ICANON;
730     console_curtermios.c_cc[VTIME] = 0;
731     console_curtermios.c_cc[VMIN] = 1;
732    
733     console_curtermios.c_lflag &= ~ECHO;
734    
735     /*
736     * Most guest OSes seem to work ok without ~ICRNL, but Linux on
737     * DECstation requires it to be usable. Unfortunately, clearing
738     * out ICRNL makes tracing with '-t ... |more' akward, as you
739     * might need to use CTRL-J instead of the enter key. Hence,
740     * this bit is only cleared if we're not tracing:
741     */
742     tra = 0;
743     for (i=0; i<emul->n_machines; i++)
744     if (emul->machines[i]->show_trace_tree ||
745     emul->machines[i]->instruction_trace ||
746     emul->machines[i]->register_dump)
747     tra = 1;
748     if (!tra)
749     console_curtermios.c_iflag &= ~ICRNL;
750    
751     tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
752    
753     console_stdout_pending = 1;
754     console_handles[MAIN_CONSOLE].fifo_head = 0;
755     console_handles[MAIN_CONSOLE].fifo_tail = 0;
756    
757     console_mouse_x = 0;
758     console_mouse_y = 0;
759     console_mouse_buttons = 0;
760    
761     console_initialized = 1;
762     }
763    
764    
765     /*
766     * console_allow_slaves():
767     *
768     * This function tells the console subsystem whether or not to open up
769     * slave xterms for each emulated serial controller.
770     */
771     void console_allow_slaves(int allow)
772     {
773     allow_slaves = allow;
774     }
775    
776    
777     /*
778 dpavlin 20 * console_are_slaves_allowed():
779     *
780     * Returns the value of allow_slaves.
781     */
782     int console_are_slaves_allowed(void)
783     {
784     return allow_slaves;
785     }
786    
787    
788     /*
789     * console_warn_if_slaves_are_needed():
790     *
791     * Prints a warning if slave xterms are needed (i.e. there is more than one
792     * console handle in use), but they are not currently allowed.
793     */
794     void console_warn_if_slaves_are_needed(void)
795     {
796     int i, n = 0;
797     for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
798     if (console_handles[i].in_use &&
799     !console_handles[i].using_xterm)
800     n ++;
801    
802     if (!allow_slaves && n > 1) {
803     fatal("#\n# WARNING! More than one console output is in use,"
804     "\n# but xterm slaves are not enabled. Behaviour will\n"
805     "# be undefined. (Use -x to enable slave xterms.)\n#\n");
806     for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
807     if (console_handles[i].in_use &&
808     !console_handles[i].using_xterm)
809     fatal("# console handle %i: '%s'\n",
810     i, console_handles[i].name);
811     fatal("#\n");
812     }
813     }
814    
815    
816     /*
817 dpavlin 2 * console_init():
818     *
819     * This function should be called before any other console_*() function
820     * is used.
821     */
822     void console_init(void)
823     {
824     int handle;
825     struct console_handle *chp;
826    
827     chp = console_new_handle("MAIN", &handle);
828     if (handle != MAIN_CONSOLE) {
829     printf("console_init(): fatal error: could not create"
830     " console 0: handle = %i\n", handle);
831     exit(1);
832     }
833     }
834    

  ViewVC Help
Powered by ViewVC 1.1.26