static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
{
- GIOStatus status;
- size_t offset;
+ size_t offset = 0;
+ GIOStatus status = G_IO_STATUS_NORMAL;
- offset = 0;
- while (offset < len) {
- gsize bytes_written;
+ while (offset < len && status == G_IO_STATUS_NORMAL) {
+ gsize bytes_written = 0;
status = g_io_channel_write_chars(fd, buf + offset, len - offset,
&bytes_written, NULL);
- if (status != G_IO_STATUS_NORMAL) {
- if (status == G_IO_STATUS_AGAIN) {
- /* If we've written any data, return a partial write. */
- if (offset) {
- break;
- }
- errno = EAGAIN;
- } else {
- errno = EINVAL;
- }
-
- return -1;
- } else if (status == G_IO_STATUS_EOF) {
- break;
- }
-
offset += bytes_written;
}
- return offset;
+ if (offset > 0) {
+ return offset;
+ }
+ switch (status) {
+ case G_IO_STATUS_NORMAL:
+ g_assert(len == 0);
+ return 0;
+ case G_IO_STATUS_AGAIN:
+ errno = EAGAIN;
+ return -1;
+ default:
+ break;
+ }
+ errno = EINVAL;
+ return -1;
}
#ifndef _WIN32
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
}
- /* if graphical mode, we allow Ctrl-C handling */
if (!stdio_allow_signal)
tty.c_lflag &= ~ISIG;
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
chr->chr_set_echo = qemu_chr_set_echo_stdio;
- stdio_allow_signal = display_type != DT_NOGRAPHIC;
if (opts->has_signal) {
stdio_allow_signal = opts->signal;
}
fd = inet_dgram_opts(opts, &local_err);
if (fd < 0) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return NULL;
}
return qemu_chr_open_udp_fd(fd);
if (strstart(filename, "mon:", &p)) {
filename = p;
qemu_opt_set(opts, "mux", "on");
+ if (strcmp(filename, "stdio") == 0) {
+ /* Monitor is muxed to stdio: do not exit on Ctrl+C by default
+ * but pass it to the guest. Handle this only for compat syntax,
+ * for -chardev syntax we have special option for this.
+ * This is what -nographic did, redirecting+muxing serial+monitor
+ * to stdio causing Ctrl+C to be passed to guest. */
+ qemu_opt_set(opts, "signal", "off");
+ }
}
if (strcmp(filename, "null") == 0 ||
{
backend->stdio = g_new0(ChardevStdio, 1);
backend->stdio->has_signal = true;
- backend->stdio->signal =
- qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
+ backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
}
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
backend->memory = g_new0(ChardevMemory, 1);
- val = qemu_opt_get_number(opts, "size", 0);
+ val = qemu_opt_get_size(opts, "size", 0);
if (val != 0) {
backend->memory->has_size = true;
backend->memory->size = val;
}
}
+static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *chardev = qemu_opt_get(opts, "chardev");
+
+ if (chardev == NULL) {
+ error_setg(errp, "chardev: mux: no chardev given");
+ return;
+ }
+ backend->mux = g_new0(ChardevMux, 1);
+ backend->mux->chardev = g_strdup(chardev);
+}
+
typedef struct CharDriver {
const char *name;
/* old, pre qapi */
CharDriverState *(*open)(QemuOpts *opts);
/* new, qapi-based */
- int kind;
+ ChardevBackendKind kind;
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
} CharDriver;
backends = g_slist_append(backends, s);
}
-void register_char_driver_qapi(const char *name, int kind,
+void register_char_driver_qapi(const char *name, ChardevBackendKind kind,
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp))
{
CharDriver *s;
ChardevBackend *backend = g_new0(ChardevBackend, 1);
ChardevReturn *ret = NULL;
const char *id = qemu_opts_id(opts);
- const char *bid = NULL;
+ char *bid = NULL;
if (qemu_opt_get_bool(opts, "mux", 0)) {
bid = g_strdup_printf("%s-base", id);
backend->kind = CHARDEV_BACKEND_KIND_MUX;
backend->mux->chardev = g_strdup(bid);
ret = qmp_chardev_add(id, backend, errp);
- if (error_is_set(errp)) {
- goto qapi_out;
- }
+ assert(!error_is_set(errp));
}
chr = qemu_chr_find(id);
+ chr->opts = opts;
qapi_out:
qapi_free_ChardevBackend(backend);
qapi_free_ChardevReturn(ret);
+ g_free(bid);
return chr;
}
},{
.name = "size",
.type = QEMU_OPT_SIZE,
+ },{
+ .name = "chardev",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE,
qemu_chr_parse_pipe);
+ register_char_driver_qapi("mux", CHARDEV_BACKEND_KIND_MUX,
+ qemu_chr_parse_mux);
}
type_init(register_types);