[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] Support redirect -curses over a character driver
From: |
Anthony Liguori |
Subject: |
[Qemu-devel] [PATCH] Support redirect -curses over a character driver |
Date: |
Tue, 4 Mar 2008 20:34:18 -0600 |
I love the -curses feature but I really wanted to use it over a telnet:
character device. This patch enables this and changes the syntax of the
-curses argument to take a character device. 'stdio' is special cased to not
go through a character device. The rest use a pty to proxy the data to the
character device. curses insists on a pty so we limit this feature to
everything but WIN32 since I don't believe Windows supports ptys.
Using this patch, you can now do something like '-curses telnet::1028,nowait'.
To get the old behavior, just use '-curses stdio'.
Signed-off-by: Anthony Liguori <address@hidden>
diff --git a/console.h b/console.h
index b8a5c6d..43e1284 100644
--- a/console.h
+++ b/console.h
@@ -141,7 +141,7 @@ int vnc_display_password(DisplayState *ds, const char
*password);
void do_info_vnc(void);
/* curses.c */
-void curses_display_init(DisplayState *ds, int full_screen);
+void curses_display_init(DisplayState *ds, CharDriverState *chr, int
full_screen);
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff --git a/curses.c b/curses.c
index 87aa9b3..a020dd1 100644
--- a/curses.c
+++ b/curses.c
@@ -32,6 +32,7 @@
#include <signal.h>
#include <sys/ioctl.h>
#include <termios.h>
+#include <pty.h>
#endif
#define FONT_HEIGHT 16
@@ -41,6 +42,7 @@ static console_ch_t screen[160 * 100];
static WINDOW *screenpad = NULL;
static int width, height, gwidth, gheight, invalidate;
static int px, py, sminx, sminy, smaxx, smaxy;
+static int slave;
static void curses_update(DisplayState *ds, int x, int y, int w, int h)
{
@@ -278,16 +280,102 @@ static void curses_atexit(void)
curses_cleanup(NULL);
}
-static void curses_setup(void)
+#ifndef _WIN32
+static void pty_read_proxy(void *opaque)
+{
+ CharDriverState *chr = opaque;
+ char buffer[4096];
+ ssize_t len;
+
+ do {
+ len = read(slave, buffer, sizeof(buffer));
+ } while (len == -1 && errno == EINTR);
+
+ if (len > 0)
+ qemu_chr_write(chr, buffer, len);
+}
+
+static void chr_read_proxy(void *opaque, const uint8_t *buf, int size)
+{
+ ssize_t len;
+ size_t offset = 0;
+
+ do {
+ len = write(slave, buf + offset, size - offset);
+ if (len == -1 && (errno == EINTR || errno == EAGAIN))
+ continue;
+ if (len > 0)
+ offset += len;
+ } while (offset < size && len > 0);
+
+ if (offset != size)
+ fprintf(stderr, "curses: short write to slave pty\n");
+}
+
+static int chr_can_read_proxy(void *opaque)
+{
+ return 1024;
+}
+
+static void chr_event_proxy(void *opaque, int event)
+{
+ if (event == CHR_EVENT_RESET)
+ invalidate = 1;
+}
+#endif
+
+static void curses_setup(CharDriverState *chr)
{
int i, colour_default[8] = {
COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE,
};
+#ifndef _WIN32
+ if (chr) {
+ struct termios term;
+ FILE *fin, *fout;
+ SCREEN *screen;
+ int master;
+
+ if (openpty(&master, &slave, NULL, NULL, NULL) == -1) {
+ fprintf(stderr, "fatal: could not open pty\n");
+ exit(1);
+ }
+
+ tcgetattr(master, &term);
+ cfmakeraw(&term);
+ tcsetattr(master, 0, &term);
+
+ tcgetattr(slave, &term);
+ cfmakeraw(&term);
+ tcsetattr(slave, 0, &term);
+
+ fout = fdopen(master, "w");
+ fin = fdopen(master, "r");
+
+ if (fout == NULL || fin == NULL) {
+ fprintf(stderr, "fatal: could not reopen pty\n");
+ exit(1);
+ }
+
+ qemu_set_fd_handler2(slave, NULL, pty_read_proxy, NULL, chr);
+ qemu_chr_add_handlers(chr, chr_can_read_proxy, chr_read_proxy,
+ chr_event_proxy, chr);
+
+ screen = newterm(getenv("TERM"), fout, fin);
+ set_term(screen);
+
+ /* we won't get resizes so we need to start out telling curses the
+ proper size */
+ resize_term(25, 80);
+ } else
+#endif
+ initscr();
+
/* input as raw as possible, let everything be interpreted
* by the guest system */
- initscr(); noecho(); intrflush(stdscr, FALSE);
+ noecho(); intrflush(stdscr, FALSE);
nodelay(stdscr, TRUE); nonl(); keypad(stdscr, TRUE);
start_color(); raw(); scrollok(stdscr, FALSE);
@@ -332,7 +420,7 @@ static void curses_keyboard_setup(void)
}
}
-void curses_display_init(DisplayState *ds, int full_screen)
+void curses_display_init(DisplayState *ds, CharDriverState *chr, int
full_screen)
{
#ifndef _WIN32
if (!isatty(1)) {
@@ -341,7 +429,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
}
#endif
- curses_setup();
+ curses_setup(chr);
curses_keyboard_setup();
atexit(curses_atexit);
diff --git a/vl.c b/vl.c
index d5a1dbc..16c9900 100644
--- a/vl.c
+++ b/vl.c
@@ -172,7 +172,6 @@ BlockDriverState *bs_snapshots;
int vga_ram_size;
static DisplayState display_state;
int nographic;
-int curses;
const char* keyboard_layout = NULL;
int64_t ticks_per_sec;
int ram_size;
@@ -7691,7 +7690,7 @@ static void help(int exitcode)
"-no-acpi disable ACPI\n"
#endif
#ifdef CONFIG_CURSES
- "-curses use a curses/ncurses interface instead of SDL\n"
+ "-curses dev use a curses/ncurses to char driver 'dev' instead
of SDL\n"
#endif
"-no-reboot exit instead of rebooting\n"
"-loadvm file start right away with a saved state (loadvm in
monitor)\n"
@@ -7896,7 +7895,7 @@ const QEMUOption qemu_options[] = {
{ "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
#ifdef CONFIG_CURSES
- { "curses", 0, QEMU_OPTION_curses },
+ { "curses", HAS_ARG, QEMU_OPTION_curses },
#endif
/* temporary options */
@@ -8190,6 +8189,7 @@ int main(int argc, char **argv)
int fds[2];
const char *pid_file = NULL;
VLANState *vlan;
+ const char *curses_device = NULL;
LIST_INIT (&vm_change_state_head);
#ifndef _WIN32
@@ -8234,7 +8234,6 @@ int main(int argc, char **argv)
#endif
snapshot = 0;
nographic = 0;
- curses = 0;
kernel_filename = NULL;
kernel_cmdline = "";
cyls = heads = secs = 0;
@@ -8411,7 +8410,7 @@ int main(int argc, char **argv)
break;
#ifdef CONFIG_CURSES
case QEMU_OPTION_curses:
- curses = 1;
+ curses_device = optarg;
break;
#endif
case QEMU_OPTION_portrait:
@@ -8956,7 +8955,7 @@ int main(int argc, char **argv)
/* terminal init */
memset(&display_state, 0, sizeof(display_state));
if (nographic) {
- if (curses) {
+ if (curses_device) {
fprintf(stderr, "fatal: -nographic can't be used with -curses\n");
exit(1);
}
@@ -8968,8 +8967,19 @@ int main(int argc, char **argv)
exit(1);
} else
#if defined(CONFIG_CURSES)
- if (curses) {
- curses_display_init(ds, full_screen);
+ if (curses_device) {
+ CharDriverState *chr = NULL;
+
+#ifndef _WIN32
+ if (strcmp(curses_device, "stdio") != 0) {
+ chr = qemu_chr_open(curses_device);
+ if (chr == NULL) {
+ fprintf(stderr, "fatal: could not open curses device\n");
+ exit(1);
+ }
+ }
+#endif
+ curses_display_init(ds, chr, full_screen);
} else
#endif
{
- [Qemu-devel] [PATCH] Support redirect -curses over a character driver,
Anthony Liguori <=
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Ian Jackson, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Anthony Liguori, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Avi Kivity, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Anthony Liguori, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Avi Kivity, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Anthony Liguori, 2008/03/05
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Avi Kivity, 2008/03/06
- Re: [Qemu-devel] [PATCH] Support redirect -curses over a character driver, Anthony Liguori, 2008/03/06