Revision ed7a1540
b/qemu-char.c | ||
---|---|---|
539 | 539 |
} |
540 | 540 |
#endif /* !_WIN32 */ |
541 | 541 |
|
542 |
#define STDIO_MAX_CLIENTS 1 |
|
543 |
static int stdio_nb_clients; |
|
544 |
|
|
545 | 542 |
#ifndef _WIN32 |
546 | 543 |
|
547 | 544 |
typedef struct { |
... | ... | |
594 | 591 |
FDCharDriver *s = chr->opaque; |
595 | 592 |
|
596 | 593 |
if (s->fd_in >= 0) { |
597 |
if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { |
|
598 |
} else { |
|
599 |
qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, |
|
600 |
fd_chr_read, NULL, chr); |
|
601 |
} |
|
594 |
qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, |
|
595 |
fd_chr_read, NULL, chr); |
|
602 | 596 |
} |
603 | 597 |
} |
604 | 598 |
|
... | ... | |
607 | 601 |
FDCharDriver *s = chr->opaque; |
608 | 602 |
|
609 | 603 |
if (s->fd_in >= 0) { |
610 |
if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { |
|
611 |
} else { |
|
612 |
qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); |
|
613 |
} |
|
604 |
qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); |
|
614 | 605 |
} |
615 | 606 |
|
616 | 607 |
g_free(s); |
... | ... | |
677 | 668 |
return qemu_chr_open_fd(fd_in, fd_out); |
678 | 669 |
} |
679 | 670 |
|
680 |
|
|
681 |
/* for STDIO, we handle the case where several clients use it |
|
682 |
(nographic mode) */ |
|
683 |
|
|
684 |
#define TERM_FIFO_MAX_SIZE 1 |
|
685 |
|
|
686 |
static uint8_t term_fifo[TERM_FIFO_MAX_SIZE]; |
|
687 |
static int term_fifo_size; |
|
688 |
|
|
689 |
static int stdio_read_poll(void *opaque) |
|
690 |
{ |
|
691 |
CharDriverState *chr = opaque; |
|
692 |
|
|
693 |
/* try to flush the queue if needed */ |
|
694 |
if (term_fifo_size != 0 && qemu_chr_be_can_write(chr) > 0) { |
|
695 |
qemu_chr_be_write(chr, term_fifo, 1); |
|
696 |
term_fifo_size = 0; |
|
697 |
} |
|
698 |
/* see if we can absorb more chars */ |
|
699 |
if (term_fifo_size == 0) |
|
700 |
return 1; |
|
701 |
else |
|
702 |
return 0; |
|
703 |
} |
|
704 |
|
|
705 |
static void stdio_read(void *opaque) |
|
706 |
{ |
|
707 |
int size; |
|
708 |
uint8_t buf[1]; |
|
709 |
CharDriverState *chr = opaque; |
|
710 |
|
|
711 |
size = read(0, buf, 1); |
|
712 |
if (size == 0) { |
|
713 |
/* stdin has been closed. Remove it from the active list. */ |
|
714 |
qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); |
|
715 |
qemu_chr_be_event(chr, CHR_EVENT_CLOSED); |
|
716 |
return; |
|
717 |
} |
|
718 |
if (size > 0) { |
|
719 |
if (qemu_chr_be_can_write(chr) > 0) { |
|
720 |
qemu_chr_be_write(chr, buf, 1); |
|
721 |
} else if (term_fifo_size == 0) { |
|
722 |
term_fifo[term_fifo_size++] = buf[0]; |
|
723 |
} |
|
724 |
} |
|
725 |
} |
|
726 |
|
|
727 | 671 |
/* init terminal so that we can grab keys */ |
728 | 672 |
static struct termios oldtty; |
729 | 673 |
static int old_fd0_flags; |
... | ... | |
760 | 704 |
static void qemu_chr_close_stdio(struct CharDriverState *chr) |
761 | 705 |
{ |
762 | 706 |
term_exit(); |
763 |
stdio_nb_clients--; |
|
764 |
qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); |
|
765 | 707 |
fd_chr_close(chr); |
766 | 708 |
} |
767 | 709 |
|
... | ... | |
769 | 711 |
{ |
770 | 712 |
CharDriverState *chr; |
771 | 713 |
|
772 |
if (stdio_nb_clients >= STDIO_MAX_CLIENTS) { |
|
773 |
return NULL; |
|
774 |
} |
|
775 | 714 |
if (is_daemonized()) { |
776 | 715 |
error_report("cannot use stdio with -daemonize"); |
777 | 716 |
return NULL; |
778 | 717 |
} |
779 |
if (stdio_nb_clients == 0) { |
|
780 |
old_fd0_flags = fcntl(0, F_GETFL); |
|
781 |
tcgetattr (0, &oldtty); |
|
782 |
fcntl(0, F_SETFL, O_NONBLOCK); |
|
783 |
atexit(term_exit); |
|
784 |
} |
|
718 |
old_fd0_flags = fcntl(0, F_GETFL); |
|
719 |
tcgetattr (0, &oldtty); |
|
720 |
fcntl(0, F_SETFL, O_NONBLOCK); |
|
721 |
atexit(term_exit); |
|
785 | 722 |
|
786 | 723 |
chr = qemu_chr_open_fd(0, 1); |
787 | 724 |
chr->chr_close = qemu_chr_close_stdio; |
788 | 725 |
chr->chr_set_echo = qemu_chr_set_echo_stdio; |
789 |
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); |
|
790 |
stdio_nb_clients++; |
|
791 | 726 |
stdio_allow_signal = qemu_opt_get_bool(opts, "signal", |
792 | 727 |
display_type != DT_NOGRAPHIC); |
793 | 728 |
qemu_chr_fe_set_echo(chr, false); |
... | ... | |
1448 | 1383 |
|
1449 | 1384 |
#else /* _WIN32 */ |
1450 | 1385 |
|
1451 |
static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS]; |
|
1452 |
|
|
1453 | 1386 |
typedef struct { |
1454 | 1387 |
int max_size; |
1455 | 1388 |
HANDLE hcom, hrecv, hsend; |
... | ... | |
1951 | 1884 |
|
1952 | 1885 |
g_free(chr->opaque); |
1953 | 1886 |
g_free(chr); |
1954 |
stdio_nb_clients--; |
|
1955 | 1887 |
} |
1956 | 1888 |
|
1957 | 1889 |
static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts) |
... | ... | |
1961 | 1893 |
DWORD dwMode; |
1962 | 1894 |
int is_console = 0; |
1963 | 1895 |
|
1964 |
if (stdio_nb_clients >= STDIO_MAX_CLIENTS |
|
1965 |
|| ((display_type != DT_NOGRAPHIC) && (stdio_nb_clients != 0))) { |
|
1966 |
return NULL; |
|
1967 |
} |
|
1968 |
|
|
1969 | 1896 |
chr = g_malloc0(sizeof(CharDriverState)); |
1970 | 1897 |
stdio = g_malloc0(sizeof(WinStdioCharState)); |
1971 | 1898 |
|
... | ... | |
1981 | 1908 |
chr->chr_write = win_stdio_write; |
1982 | 1909 |
chr->chr_close = win_stdio_close; |
1983 | 1910 |
|
1984 |
if (stdio_nb_clients == 0) { |
|
1985 |
if (is_console) { |
|
1986 |
if (qemu_add_wait_object(stdio->hStdIn, |
|
1987 |
win_stdio_wait_func, chr)) { |
|
1988 |
fprintf(stderr, "qemu_add_wait_object: failed\n"); |
|
1989 |
} |
|
1990 |
} else { |
|
1991 |
DWORD dwId; |
|
1992 |
|
|
1993 |
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
1994 |
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
1995 |
stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread, |
|
1996 |
chr, 0, &dwId); |
|
1997 |
|
|
1998 |
if (stdio->hInputThread == INVALID_HANDLE_VALUE |
|
1999 |
|| stdio->hInputReadyEvent == INVALID_HANDLE_VALUE |
|
2000 |
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) { |
|
2001 |
fprintf(stderr, "cannot create stdio thread or event\n"); |
|
2002 |
exit(1); |
|
2003 |
} |
|
2004 |
if (qemu_add_wait_object(stdio->hInputReadyEvent, |
|
2005 |
win_stdio_thread_wait_func, chr)) { |
|
2006 |
fprintf(stderr, "qemu_add_wait_object: failed\n"); |
|
2007 |
} |
|
1911 |
if (is_console) { |
|
1912 |
if (qemu_add_wait_object(stdio->hStdIn, |
|
1913 |
win_stdio_wait_func, chr)) { |
|
1914 |
fprintf(stderr, "qemu_add_wait_object: failed\n"); |
|
1915 |
} |
|
1916 |
} else { |
|
1917 |
DWORD dwId; |
|
1918 |
|
|
1919 |
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
1920 |
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
1921 |
stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread, |
|
1922 |
chr, 0, &dwId); |
|
1923 |
|
|
1924 |
if (stdio->hInputThread == INVALID_HANDLE_VALUE |
|
1925 |
|| stdio->hInputReadyEvent == INVALID_HANDLE_VALUE |
|
1926 |
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) { |
|
1927 |
fprintf(stderr, "cannot create stdio thread or event\n"); |
|
1928 |
exit(1); |
|
1929 |
} |
|
1930 |
if (qemu_add_wait_object(stdio->hInputReadyEvent, |
|
1931 |
win_stdio_thread_wait_func, chr)) { |
|
1932 |
fprintf(stderr, "qemu_add_wait_object: failed\n"); |
|
2008 | 1933 |
} |
2009 | 1934 |
} |
2010 | 1935 |
|
2011 | 1936 |
dwMode |= ENABLE_LINE_INPUT; |
2012 | 1937 |
|
2013 |
stdio_clients[stdio_nb_clients++] = chr; |
|
2014 |
if (stdio_nb_clients == 1 && is_console) { |
|
1938 |
if (is_console) { |
|
2015 | 1939 |
/* set the terminal in raw mode */ |
2016 | 1940 |
/* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */ |
2017 | 1941 |
dwMode |= ENABLE_PROCESSED_INPUT; |
Also available in: Unified diff