static gboolean gvir_sandbox_console_raw_detach(GVirSandboxConsole *console, GError **error) { GVirSandboxConsoleRawPrivate *priv = GVIR_SANDBOX_CONSOLE_RAW(console)->priv; gboolean ret = FALSE; if (!priv->console) { return TRUE; #if 0 g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0, "%s", _("Console is not attached to a stream")); return FALSE; #endif } if (priv->localStdin && !gvir_sandbox_console_raw_stop_term(GVIR_SANDBOX_CONSOLE_RAW(console), priv->localStdin, error)) return FALSE; if (priv->console) { g_object_unref(priv->console); priv->console = NULL; priv->consoleToLocalOffset = priv->consoleToLocalLength = 0; priv->localToConsoleOffset = priv->localToConsoleLength = 0; g_free(priv->consoleToLocal); g_free(priv->localToConsole); priv->consoleToLocal = priv->localToConsole = NULL; } if (priv->localStdinSource) g_source_unref(priv->localStdinSource); if (priv->localStdoutSource) g_source_unref(priv->localStdoutSource); if (priv->localStderrSource) g_source_unref(priv->localStderrSource); if (priv->consoleWatch) g_source_remove(priv->consoleWatch); priv->localStdinSource = priv->localStdoutSource = priv->localStderrSource = NULL; priv->consoleWatch = 0; if (priv->localStdin) g_object_unref(priv->localStdin); if (priv->localStdout) g_object_unref(priv->localStdout); g_object_unref(priv->localStderr); priv->localStdin = NULL; priv->localStdout = NULL; priv->localStderr = NULL; ret = TRUE; //cleanup: return ret; }
static gboolean do_console_raw_console_write(GObject *stream, gpointer opaque) { GUnixOutputStream *consoleOutput = G_UNIX_OUTPUT_STREAM(stream); GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(opaque); GVirSandboxConsoleRawPrivate *priv = console->priv; GError *err = NULL; gssize ret = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM(consoleOutput), priv->consoleToLocal, priv->consoleToLocalOffset, NULL, &err); if (ret < 0) { g_debug("Error from console write %s", err ? err->message : ""); do_console_raw_close(console, err); g_error_free(err); goto cleanup; } if (priv->consoleToLocalOffset != ret) memmove(priv->consoleToLocal, priv->consoleToLocal + ret, priv->consoleToLocalOffset - ret); priv->consoleToLocalOffset -= ret; priv->consoleOutputSource = NULL; do_console_raw_update_events(console); cleanup: return FALSE; }
static gboolean do_console_raw_local_read(GObject *stream, gpointer opaque) { GUnixInputStream *localStdin = G_UNIX_INPUT_STREAM(stream); GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(opaque); GVirSandboxConsoleRawPrivate *priv = console->priv; GError *err = NULL; gssize ret = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM(localStdin), priv->localToConsole + priv->localToConsoleOffset, priv->localToConsoleLength - priv->localToConsoleOffset, NULL, &err); if (ret < 0) { g_debug("Error from local read %s", err ? err->message : ""); do_console_raw_close(console, err); g_error_free(err); goto cleanup; } if (ret == 0) priv->localEOF = TRUE; else if (priv->localToConsole[priv->localToConsoleOffset] == CONTROL(gvir_sandbox_console_get_escape(GVIR_SANDBOX_CONSOLE(console)))) { do_console_raw_close(console, err); goto cleanup; } priv->localToConsoleOffset += ret; priv->localStdinSource = NULL; do_console_raw_update_events(console); cleanup: return FALSE; }
static gboolean gvir_sandbox_console_raw_attach(GVirSandboxConsole *console, GUnixInputStream *localStdin, GUnixOutputStream *localStdout, GUnixOutputStream *localStderr, GError **error) { GVirSandboxConsoleRawPrivate *priv = GVIR_SANDBOX_CONSOLE_RAW(console)->priv; gboolean ret = FALSE; if (priv->attached) { g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0, "%s", _("Console is already attached to a stream")); return FALSE; } if (localStdin && !gvir_sandbox_console_raw_start_term(GVIR_SANDBOX_CONSOLE_RAW(console), localStdin, error)) return FALSE; priv->localStdin = localStdin ? g_object_ref(localStdin) : NULL; priv->localStdout = localStdout ? g_object_ref(localStdout) : NULL; priv->localStderr = g_object_ref(localStderr); if (!gvir_sandbox_console_open_remote(GVIR_SANDBOX_CONSOLE_RAW(console), error)) goto cleanup; priv->consoleToLocalLength = 4096; priv->consoleToLocal = g_new0(gchar, priv->consoleToLocalLength); if (localStdin) { priv->localToConsoleLength = 4096; priv->localToConsole = g_new0(gchar, priv->localToConsoleLength); } priv->attached = TRUE; do_console_raw_update_events(GVIR_SANDBOX_CONSOLE_RAW(console)); ret = TRUE; cleanup: if (!ret && localStdin) gvir_sandbox_console_raw_stop_term(GVIR_SANDBOX_CONSOLE_RAW(console), localStdin, NULL); return ret; }
/** * gvir_sandbox_console_raw_new: * @connection: (transfer none): the libvirt connection * @domain: (transfer none): the libvirt domain whose console_raw to run * @devname: the console to connect to * * Create a new sandbox raw console from the specified configuration * * Returns: (transfer full): a new sandbox console object */ GVirSandboxConsoleRaw *gvir_sandbox_console_raw_new(GVirConnection *connection, GVirDomain *domain, const char *devname) { return GVIR_SANDBOX_CONSOLE_RAW(g_object_new(GVIR_SANDBOX_TYPE_CONSOLE_RAW, "connection", connection, "domain", domain, "devname", devname, NULL)); }
static void gvir_sandbox_console_raw_finalize(GObject *object) { GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(object); GVirSandboxConsoleRawPrivate *priv = console->priv; if (priv->attached) gvir_sandbox_console_detach(GVIR_SANDBOX_CONSOLE(console), NULL); /* All other private fields are free'd by the detach call */ G_OBJECT_CLASS(gvir_sandbox_console_raw_parent_class)->finalize(object); }
static gboolean gvir_sandbox_console_raw_detach(GVirSandboxConsole *console, GError **error) { GVirSandboxConsoleRawPrivate *priv = GVIR_SANDBOX_CONSOLE_RAW(console)->priv; gboolean ret = FALSE; if (!priv->attached) return TRUE; if (priv->localStdin && !gvir_sandbox_console_raw_stop_term(GVIR_SANDBOX_CONSOLE_RAW(console), priv->localStdin, error)) return FALSE; priv->consoleToLocalOffset = priv->consoleToLocalLength = 0; priv->localToConsoleOffset = priv->localToConsoleLength = 0; g_free(priv->consoleToLocal); g_free(priv->localToConsole); priv->consoleToLocal = priv->localToConsole = NULL; if (priv->localStdinSource) g_source_unref(priv->localStdinSource); if (priv->localStdoutSource) g_source_unref(priv->localStdoutSource); if (priv->localStderrSource) g_source_unref(priv->localStderrSource); if (priv->consoleWatch) g_source_remove(priv->consoleWatch); if (priv->consoleInputSource) g_source_unref(priv->consoleInputSource); if (priv->consoleOutputSource) g_source_unref(priv->consoleOutputSource); priv->localStdinSource = priv->localStdoutSource = priv->localStderrSource = NULL; priv->consoleWatch = 0; priv->consoleInputSource = priv->consoleOutputSource = NULL; if (priv->console) { g_object_unref(priv->console); priv->console = NULL; } if (priv->consoleInput) { g_object_unref(priv->consoleInput); priv->consoleInput = NULL; } if (priv->consoleOutput) { g_object_unref(priv->consoleOutput); priv->consoleOutput = NULL; } if (priv->localStdin) g_object_unref(priv->localStdin); if (priv->localStdout) g_object_unref(priv->localStdout); g_object_unref(priv->localStderr); priv->localStdin = NULL; priv->localStdout = NULL; priv->localStderr = NULL; priv->attached = FALSE; ret = TRUE; //cleanup: return ret; }
static gboolean do_console_raw_stream_readwrite(GVirStream *stream, GVirStreamIOCondition cond, gpointer opaque) { GVirSandboxConsoleRaw *console = GVIR_SANDBOX_CONSOLE_RAW(opaque); GVirSandboxConsoleRawPrivate *priv = console->priv; if (cond & GVIR_STREAM_IO_CONDITION_READABLE) { GError *err = NULL; gssize ret = gvir_stream_receive (stream, priv->consoleToLocal + priv->consoleToLocalOffset, priv->consoleToLocalLength - priv->consoleToLocalOffset, NULL, &err); if (ret < 0) { if (err && err->code == G_IO_ERROR_WOULD_BLOCK) { /* Shouldn't get this, but you never know */ g_error_free(err); goto done; } else { g_debug("Error from stream recv %s", err ? err->message : ""); do_console_raw_close(console, err); g_error_free(err); goto cleanup; } } if (ret == 0) { /* EOF */ do_console_raw_close(console, NULL); goto done; } priv->consoleToLocalOffset += ret; } if (cond & GVIR_STREAM_IO_CONDITION_WRITABLE) { GError *err = NULL; gssize ret = gvir_stream_send(stream, priv->localToConsole, priv->localToConsoleOffset, NULL, &err); if (ret < 0) { g_debug("Error from stream send %s", err ? err->message : ""); do_console_raw_close(console, err); g_error_free(err); goto cleanup; } if (priv->localToConsoleOffset != ret) memmove(priv->localToConsole, priv->localToConsole + ret, priv->localToConsoleOffset - ret); priv->localToConsoleOffset -= ret; } done: priv->consoleWatch = 0; do_console_raw_update_events(console); cleanup: return FALSE; }
static gboolean gvir_sandbox_console_raw_attach(GVirSandboxConsole *console, GUnixInputStream *localStdin, GUnixOutputStream *localStdout, GUnixOutputStream *localStderr, GError **error) { GVirSandboxConsoleRawPrivate *priv = GVIR_SANDBOX_CONSOLE_RAW(console)->priv; gboolean ret = FALSE; GVirConnection *conn = NULL; GVirDomain *dom = NULL; gchar *devname = NULL; if (priv->console) { g_set_error(error, GVIR_SANDBOX_CONSOLE_RAW_ERROR, 0, "%s", _("Console is already attached to a stream")); return FALSE; } if (localStdin && !gvir_sandbox_console_raw_start_term(GVIR_SANDBOX_CONSOLE_RAW(console), localStdin, error)) return FALSE; priv->localStdin = localStdin ? g_object_ref(localStdin) : NULL; priv->localStdout = localStdout ? g_object_ref(localStdout) : NULL; priv->localStderr = g_object_ref(localStderr); g_object_get(console, "connection", &conn, "domain", &dom, "devname", &devname, NULL); priv->console = gvir_connection_get_stream(conn, 0); if (!gvir_domain_open_console(dom, priv->console, devname, 0, error)) goto cleanup; priv->consoleToLocalLength = 4096; priv->consoleToLocal = g_new0(gchar, priv->consoleToLocalLength); if (localStdin) { priv->localToConsoleLength = 4096; priv->localToConsole = g_new0(gchar, priv->localToConsoleLength); } do_console_raw_update_events(GVIR_SANDBOX_CONSOLE_RAW(console)); ret = TRUE; cleanup: if (!ret && localStdin) gvir_sandbox_console_raw_stop_term(GVIR_SANDBOX_CONSOLE_RAW(console), localStdin, NULL); if (conn) g_object_unref(conn); if (dom) g_object_unref(dom); g_free(devname); return ret; }