aboutsummaryrefslogtreecommitdiffstats
path: root/xd_view.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2005-12-09 17:17:29 +0000
committerkraxel <kraxel>2005-12-09 17:17:29 +0000
commit7e6f3f2478ddb5194dc842a016658319dad1099d (patch)
tree18469353a85a397eb24980807901fe06ec1459f6 /xd_view.c
parentaf7c08b6378fb64958b7092de541d24bbee0805e (diff)
downloadxenwatch-7e6f3f2478ddb5194dc842a016658319dad1099d.tar.gz
- add console support.
Diffstat (limited to 'xd_view.c')
-rw-r--r--xd_view.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/xd_view.c b/xd_view.c
index 16d3889..6611d07 100644
--- a/xd_view.c
+++ b/xd_view.c
@@ -3,6 +3,9 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include <gtk/gtk.h>
#include <xs.h>
@@ -10,6 +13,10 @@
#include "xd_store.h"
#include "xenviews.h"
+#define XENCONSOLE "/usr/lib/xen/bin/xenconsole"
+
+#define array_size(x) (sizeof(x)/sizeof(*x))
+
/* ------------------------------------------------------------------ */
GtkWidget *xd_toplevel;
@@ -20,6 +27,194 @@ static GtkWidget *view;
/* ------------------------------------------------------------------ */
+static gboolean have_binary(char *name)
+{
+ char *path, *elem, *binary;
+ struct stat st;
+ int rc;
+
+ if (strchr(name,'/')) {
+ /* path specified ... */
+ if (-1 == stat(name, &st))
+ return false;
+ if (!S_ISREG(st.st_mode))
+ return false;
+ if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return false;
+ return true;
+ }
+
+ /* walk $PATH */
+ path = getenv("PATH");
+ if (NULL == path)
+ return false;
+ path = strdup(path);
+ for (elem = strtok(path, ":"); NULL != elem; elem = strtok(NULL, ":")) {
+ binary = malloc(strlen(elem)+strlen(name)+2);
+ sprintf(binary, "%s/%s", elem, name);
+ rc = stat(binary, &st);
+ free(binary);
+ if (-1 == rc)
+ continue;
+ if (!S_ISREG(st.st_mode))
+ continue;
+ if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ continue;
+ free(path);
+ return true;
+ }
+ free(path);
+ return false;
+}
+
+static int run_and_wait(const char *app, ...)
+{
+ static int debug = 0;
+ va_list args;
+ char *argv[64];
+ int status, rc, i;
+ pid_t pid;
+
+ if (debug)
+ fprintf(stderr,"%s: %s |", __FUNCTION__, app);
+ va_start(args, app);
+ for (i = 0; i < array_size(argv); i++) {
+ argv[i] = va_arg(args, char*);
+ if (NULL == argv[i])
+ break;
+ if (debug)
+ fprintf(stderr,"%s \"%s\"", (0 == i) ? "" : ",", argv[i]);
+ }
+ va_end(args);
+ if (debug)
+ fprintf(stderr,"\n");
+
+ if (array_size(argv) == i) {
+ fprintf(stderr,"%s: oops: argv too small\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (0 == (pid = fork())) {
+ /* child */
+ execvp(app, argv);
+ fprintf(stderr,"%s: execvp(%s): %s\n", __FUNCTION__,
+ app, strerror(errno));
+ exit(1);
+ }
+
+ rc = waitpid(pid, &status, 0);
+ if (rc != pid) {
+ /* Huh? */
+ fprintf(stderr,"%s: waidpid(%d): %s\n", __FUNCTION__,
+ pid, strerror(errno));
+ exit(1);
+ }
+ if (!WIFEXITED(status))
+ return -1;
+ return WEXITSTATUS(status);
+}
+
+static void open_screen(gint id, char *name, char *tty)
+{
+ int rc;
+
+ /* try attaching to a running screen ... */
+ rc = run_and_wait("screen", "screen",
+ "-X", "-S", "xenconsole",
+ "screen", "-t", name, tty,
+ NULL);
+ if (0 == rc)
+ return;
+
+ /* ... failing that start a new one ... */
+ rc = run_and_wait("screen", "screen",
+ "-d", "-m", "-S", "xenconsole", "-t", name, tty,
+ NULL);
+ if (0 != rc) {
+ fprintf(stderr, "ERROR: creating screen session failed\n");
+ return;
+ }
+
+ /* ... configure ... */
+ rc = run_and_wait("screen", "screen",
+ "-X", "-S", "xenconsole",
+ "hardstatus", "lastline",
+ " xen | %-w%{wR} %n %t* %{-}%+w",
+ NULL);
+ if (0 != rc) {
+ fprintf(stderr, "ERROR: configuring screen session failed\n");
+ return;
+ }
+
+ /* ... and start xterm and attach to new screen */
+ if (0 == fork()) {
+ execlp("xterm", "xterm",
+ "-name", "xenconsole",
+ "-title", "xen consoles via screen",
+ "-e", "screen", "-R", "xenconsole",
+ NULL);
+ exit(1);
+ }
+}
+
+static void open_xenconsole(gint id, char *name, char *tty)
+{
+ char title[64], ids[8];
+ pid_t pid;
+
+ snprintf(title, sizeof(title), "xen console: %s (%d)", name, id);
+ snprintf(ids, sizeof(ids), "%d", id);
+ if (0 == (pid = fork())) {
+ execlp("xterm", "xterm",
+ "-name", "xenconsole",
+ "-title", title,
+ "-e", XENCONSOLE, ids,
+ NULL);
+ exit(1);
+ }
+}
+
+static void open_tty(gint id, char *name, char *tty)
+{
+ static int first = 1;
+ static int have_screen;
+ static int have_xenconsole;
+
+ int rc;
+
+ /* first-time init */
+ if (first) {
+ fprintf(stderr, "first\n");
+ first = 0;
+ have_screen = have_binary("screen");
+ have_xenconsole = have_binary(XENCONSOLE);
+ }
+
+ /* sanity checks */
+ if (0 != access(tty, R_OK)) {
+ fprintf(stderr,"ERROR: no access to tty %s\n", tty);
+ return;
+ }
+
+ rc = run_and_wait("fuser", "fuser", "-s", tty, NULL);
+ if (0 == rc) {
+ fprintf(stderr,"ERROR: tty %s already in use\n", tty);
+ return;
+ }
+
+ /* open terminal */
+ if (have_screen) {
+ open_screen(id, name, tty);
+ return;
+ }
+ if (have_xenconsole) {
+ open_xenconsole(id, name, tty);
+ return;
+ }
+}
+
+/* ------------------------------------------------------------------ */
+
static void menu_cb_quit(void)
{
gtk_widget_destroy(xd_toplevel);
@@ -32,6 +227,47 @@ static void menu_cb_xenstore(void)
gtk_widget_show_all(xs_toplevel);
}
+static void menu_cb_open_tty(void)
+{
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *name, *tty;
+ gint id = -1;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ if (!gtk_tree_selection_get_selected(sel, &model, &iter))
+ return;
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+ XEN_DOMS_COL_I_ID, &id,
+ XEN_DOMS_COL_S_NAME, &name,
+ XEN_DOMS_COL_S_TERMINAL, &tty,
+ -1);
+
+ fprintf(stderr, "%s: %d\n", __FUNCTION__, id);
+ open_tty(id, name, tty);
+}
+
+static void menu_cb_open_vnc(void)
+{
+ GtkTreeSelection *sel;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *name, *tty;
+ gint id = -1;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+ if (!gtk_tree_selection_get_selected(sel, &model, &iter))
+ return;
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+ XEN_DOMS_COL_I_ID, &id,
+ XEN_DOMS_COL_S_NAME, &name,
+ XEN_DOMS_COL_S_TERMINAL, &tty,
+ -1);
+
+ fprintf(stderr, "%s: %d\n", __FUNCTION__, id);
+}
+
static void menu_cb_about(void)
{
static char *comments = "xen domain monitor";
@@ -79,6 +315,20 @@ static const GtkActionEntry entries[] = {
.callback = menu_cb_xenstore,
},{
+ .name = "ActionMenu",
+ .label = "_Action",
+ },{
+ .name = "OpenTTY",
+ .label = "_Terminal",
+ .accelerator = "<control>T",
+ .callback = menu_cb_open_tty,
+ },{
+ .name = "OpenVNC",
+ .label = "_VNC",
+ .accelerator = "<control>V",
+ .callback = menu_cb_open_vnc,
+ },{
+
.name = "HelpMenu",
.label = "_Help",
},{
@@ -97,11 +347,18 @@ static char ui_xml[] =
" <menu action='ViewMenu'>"
" <menuitem action='Xenstore'/>"
" </menu>"
+" <menu action='ActionMenu'>"
+" <menuitem action='OpenTTY'/>"
+" <menuitem action='OpenVNC'/>"
+" </menu>"
" <menu action='HelpMenu'>"
" <menuitem action='About'/>"
" </menu>"
" </menubar>"
" <toolbar action='ToolBar'>"
+" <toolitem action='OpenTTY'/>"
+" <toolitem action='OpenVNC'/>"
+" <separator/>"
" <toolitem action='Quit'/>"
" </toolbar>"
"</ui>";
@@ -192,6 +449,12 @@ static GtkWidget *xen_doms_create_view(XenDoms *store)
"text", XEN_DOMS_COL_S_OSTYPE,
NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW(view), -1, _("tty"), renderer,
+ "text", XEN_DOMS_COL_S_TERMINAL,
+ NULL);
+
/* fill remaining space */
renderer = gtk_cell_renderer_text_new();