diff options
author | kraxel <kraxel> | 2005-12-09 17:17:29 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2005-12-09 17:17:29 +0000 |
commit | 7e6f3f2478ddb5194dc842a016658319dad1099d (patch) | |
tree | 18469353a85a397eb24980807901fe06ec1459f6 /xd_view.c | |
parent | af7c08b6378fb64958b7092de541d24bbee0805e (diff) | |
download | xenwatch-7e6f3f2478ddb5194dc842a016658319dad1099d.tar.gz |
- add console support.
Diffstat (limited to 'xd_view.c')
-rw-r--r-- | xd_view.c | 263 |
1 files changed, 263 insertions, 0 deletions
@@ -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(); |