aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-07-03 12:00:31 +0000
committerkraxel <kraxel>2006-07-03 12:00:31 +0000
commit8f4db7fb5130a0b327154eddc62b161fb66af688 (patch)
treecb43a91e2fdd769e7285c8f7fa76e0a4e83173fb
parenta27248c91a6a7a48ce794efc4ed51cc9a6e7172b (diff)
downloadxenwatch-8f4db7fb5130a0b327154eddc62b161fb66af688.tar.gz
xen screen management tool
-rw-r--r--.cvsignore1
-rw-r--r--GNUmakefile17
-rw-r--r--apps-x11.c88
-rw-r--r--apps.c94
-rw-r--r--xenlog.c56
-rw-r--r--xenscreen.c273
-rw-r--r--xenscreenrc16
-rw-r--r--xenstore.c60
-rw-r--r--xenstore.h4
9 files changed, 471 insertions, 138 deletions
diff --git a/.cvsignore b/.cvsignore
index 273c710..1cbe79e 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,5 +1,6 @@
Make.config
xenlog
+xenscreen
xenwatch
mdns-browser
mdns-publish-xendom
diff --git a/GNUmakefile b/GNUmakefile
index cfe8f0e..aa6b11a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -6,11 +6,11 @@ include mk/Variables.mk
CFLAGS += -DVERSION='"$(VERSION)"' -DLIB='"$(LIB)"'
# build
-TARGETS := xenlog
+TARGETS := xenlog xenscreen
BUILD_GTK := xenwatch mdns-browser
BUILD_MDNS := mdns-publish-xendom
-NEEDS_XENSTORE := xenlog xenwatch mdns-publish-xendom
+NEEDS_XENSTORE := xenlog xenscreen xenwatch mdns-publish-xendom
NEEDS_GTK := xenwatch mdns-browser
NEEDS_MDNS := xenwatch mdns-browser mdns-publish-xendom
@@ -62,8 +62,9 @@ $(NEEDS_XENSTORE) : LDLIBS += -lxenstore
build: $(TARGETS)
install: build
- install -d $(bindir)
- install -s $(TARGETS) $(bindir)
+ $(INSTALL_DIR) -d /etc/xen # $(bindir)
+ $(INSTALL_DATA) xenscreenrc /etc/xen
+ $(INSTALL_BINARY) -s $(TARGETS) $(bindir)
clean:
-rm -f *.o *~ $(depfiles)
@@ -74,9 +75,11 @@ realclean distclean: clean
#############################################
-xenlog: xenlog.o
-xenwatch: xenwatch.o xs_view.o xs_store.o xd_view.o xd_store.o apps.o tcp.o mdns.o
-mdns-browser: mdns-browser.o mdns.o apps.o
+xenlog: xenlog.o xenstore.o
+xenscreen: xenscreen.o xenstore.o apps.o
+xenwatch: xenwatch.o xs_view.o xs_store.o xd_view.o xd_store.o \
+ apps.o apps-x11.o tcp.o mdns.o
+mdns-browser: mdns-browser.o mdns.o apps.o apps-x11.o
mdns-publish-xendom: mdns-publish-xendom.o
include mk/Compile.mk
diff --git a/apps-x11.c b/apps-x11.c
new file mode 100644
index 0000000..3ed61dc
--- /dev/null
+++ b/apps-x11.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <xs.h>
+
+#include "apps.h"
+
+/* ------------------------------------------------------------------ */
+
+#if 0
+/* check_wm_capability(dpy, root, _NET_SUPPORTED, _NET_WM_whatever); */
+static int
+check_wm_capability(Display *dpy, Window root, Atom list, Atom wanted)
+{
+ Atom type;
+ int format;
+ unsigned int i;
+ unsigned long nitems, bytesafter;
+ unsigned char *args;
+ unsigned long *ldata;
+ char *name;
+ int retval = -1;
+
+ if (Success != XGetWindowProperty
+ (dpy, root, list, 0, (65536 / sizeof(long)), False,
+ AnyPropertyType, &type, &format, &nitems, &bytesafter, &args))
+ return -1;
+ if (type != XA_ATOM)
+ return -1;
+ ldata = (unsigned long*)args;
+ for (i = 0; i < nitems; i++) {
+ if (ldata[i] == wanted)
+ retval = 0;
+ if (debug) {
+ name = XGetAtomName(dpy,ldata[i]);
+ fprintf(stderr,"wm cap: %s\n",name);
+ XFree(name);
+ }
+ }
+ XFree(ldata);
+ return retval;
+}
+#endif
+
+static int
+check_atom_present(Display *dpy, Window root, Atom check)
+{
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ unsigned char *args;
+
+ if (Success != XGetWindowProperty
+ (dpy, root, check, 0, (65536 / sizeof(long)), False,
+ AnyPropertyType, &type, &format, &nitems, &bytesafter, &args))
+ return -1;
+ if (NULL == args)
+ return -1;
+ return 0;
+}
+
+#define INIT_ATOM(dpy,atom) atom = XInternAtom(dpy,#atom,False)
+static Atom KWIN_RUNNING;
+static Atom _METACITY_SENTINEL;
+
+void detect_desktop(void)
+{
+ Display *dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
+ Window root = DefaultRootWindow(dpy);
+
+ INIT_ATOM(dpy, KWIN_RUNNING);
+ INIT_ATOM(dpy, _METACITY_SENTINEL);
+
+ if (0 == check_atom_present(dpy, root, KWIN_RUNNING)) {
+ fprintf(stderr,"Desktop: KDE\n");
+ desktop_type = DESKTOP_KDE;
+ }
+ if (0 == check_atom_present(dpy, root, _METACITY_SENTINEL)) {
+ fprintf(stderr,"Desktop: Gnome\n");
+ desktop_type = DESKTOP_GNOME;
+ }
+}
diff --git a/apps.c b/apps.c
index e8f39c0..fab3c4d 100644
--- a/apps.c
+++ b/apps.c
@@ -1,18 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-#include <xs.h>
-
#include "list.h"
#include "apps.h"
@@ -23,11 +17,11 @@ char app_error[256];
/* ------------------------------------------------------------------ */
-static int debug = 1;
+static int debug = 0;
struct have_app {
char *name;
- gboolean present;
+ int present;
struct list_head next;
};
static LIST_HEAD(apps);
@@ -103,82 +97,6 @@ int have_application(char *name)
/* ------------------------------------------------------------------ */
-#if 0
-/* check_wm_capability(dpy, root, _NET_SUPPORTED, _NET_WM_whatever); */
-static int
-check_wm_capability(Display *dpy, Window root, Atom list, Atom wanted)
-{
- Atom type;
- int format;
- unsigned int i;
- unsigned long nitems, bytesafter;
- unsigned char *args;
- unsigned long *ldata;
- char *name;
- int retval = -1;
-
- if (Success != XGetWindowProperty
- (dpy, root, list, 0, (65536 / sizeof(long)), False,
- AnyPropertyType, &type, &format, &nitems, &bytesafter, &args))
- return -1;
- if (type != XA_ATOM)
- return -1;
- ldata = (unsigned long*)args;
- for (i = 0; i < nitems; i++) {
- if (ldata[i] == wanted)
- retval = 0;
- if (debug) {
- name = XGetAtomName(dpy,ldata[i]);
- fprintf(stderr,"wm cap: %s\n",name);
- XFree(name);
- }
- }
- XFree(ldata);
- return retval;
-}
-#endif
-
-static int
-check_atom_present(Display *dpy, Window root, Atom check)
-{
- Atom type;
- int format;
- unsigned long nitems, bytesafter;
- unsigned char *args;
-
- if (Success != XGetWindowProperty
- (dpy, root, check, 0, (65536 / sizeof(long)), False,
- AnyPropertyType, &type, &format, &nitems, &bytesafter, &args))
- return -1;
- if (NULL == args)
- return -1;
- return 0;
-}
-
-#define INIT_ATOM(dpy,atom) atom = XInternAtom(dpy,#atom,False)
-static Atom KWIN_RUNNING;
-static Atom _METACITY_SENTINEL;
-
-void detect_desktop(void)
-{
- Display *dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
- Window root = DefaultRootWindow(dpy);
-
- INIT_ATOM(dpy, KWIN_RUNNING);
- INIT_ATOM(dpy, _METACITY_SENTINEL);
-
- if (0 == check_atom_present(dpy, root, KWIN_RUNNING)) {
- fprintf(stderr,"Desktop: KDE\n");
- desktop_type = DESKTOP_KDE;
- }
- if (0 == check_atom_present(dpy, root, _METACITY_SENTINEL)) {
- fprintf(stderr,"Desktop: Gnome\n");
- desktop_type = DESKTOP_GNOME;
- }
-}
-
-/* ------------------------------------------------------------------ */
-
int run_application_va(int do_wait, const char *app, char **argv)
{
int status, rc;
@@ -335,11 +253,13 @@ int open_vnc_session(char *host, int screen)
snprintf(vncurl, sizeof(vncurl), "vnc://%s:%d/", host, 5900 + screen);
/* --- try client apps --- */
+ if (have_application("vncviewer"))
+ return run_application(0, "vncviewer", "vncviewer",
+ "-xrm", "vncviewer*passwordDialog: true",
+ display, NULL);
if (have_application("krdc"))
/* KDE remote desktop client */
return run_application(0, "krdc", "krdc", display, NULL);
- if (have_application("vncviewer"))
- return run_application(0, "vncviewer", "vncviewer", display, NULL);
/* --- try web browser (java applet client) --- */
if (DESKTOP_KDE == desktop_type && have_application("kfmclient"))
diff --git a/xenlog.c b/xenlog.c
index d7e951c..b93bdd4 100644
--- a/xenlog.c
+++ b/xenlog.c
@@ -1,42 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <xs.h>
+#include "xenstore.h"
+
/* ------------------------------------------------------------- */
int main(int argc, char *argv[])
{
struct xs_handle *xenstore = NULL;
- xs_transaction_t xst;
- char *xs_value = NULL, **vec;
- char *value;
- unsigned int count;
-
- if (NULL == xenstore) {
- xenstore = xs_daemon_open_readonly();
- if (NULL == xenstore)
- fprintf(stderr,"can't connect to %s\n",xs_daemon_socket_ro());
- else
- printf("connected to %s\n", xs_daemon_socket_ro());
- }
-
- if (NULL == xenstore) {
- xenstore = xs_daemon_open();
- if (NULL == xenstore)
- fprintf(stderr,"can't connect to %s\n",xs_daemon_socket());
- else
- printf("connected to %s\n", xs_daemon_socket());
- }
-
- if (NULL == xenstore) {
- xenstore = xs_domain_open();
- if (NULL == xenstore)
- fprintf(stderr, "can't connect to %s\n", xs_domain_dev());
- else
- printf("connected to %s\n", xs_domain_dev());
- }
+ char **vec;
+ char value[256];
+ unsigned int count, rc;
+ xenstore = xenstore_open(1,1,1,1);
if (NULL == xenstore) {
fprintf(stderr, "can't access xenstore, exiting\n");
exit(1);
@@ -51,29 +30,18 @@ int main(int argc, char *argv[])
}
switch (vec[XS_WATCH_PATH][0]) {
case '/':
- xst = xs_transaction_start(xenstore);
- if (xst) {
- xs_value = xs_read(xenstore, xst, vec[XS_WATCH_PATH], NULL);
- xs_transaction_end(xenstore, xst, 0);
- if (NULL == xs_value)
- value = "<deleted>";
- else
- value = xs_value;
- } else {
- value = "<error>";
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ switch (rc) {
+ case -1: strcpy(value, "<error>"); break;
+ case -2: strcpy(value, "<deleted>"); break;
}
break;
default:
- value = "<null>";
+ strcpy(value, "<null>");
break;
}
printf("%-64s : \"%s\"\n", vec[XS_WATCH_PATH], value);
fflush(stdout);
-
- if (xs_value) {
- free(xs_value);
- xs_value = NULL;
- }
free(vec);
}
}
diff --git a/xenscreen.c b/xenscreen.c
new file mode 100644
index 0000000..e091976
--- /dev/null
+++ b/xenscreen.c
@@ -0,0 +1,273 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+
+#include <xs.h>
+
+#include "list.h"
+#include "xenstore.h"
+#include "apps.h"
+
+/* ------------------------------------------------------------- */
+
+#define BUFSIZE 64
+
+struct dom {
+ int domid;
+ char name[BUFSIZE];
+ char tty[BUFSIZE];
+ int connected;
+ int destroyed;
+ struct list_head next;
+};
+static LIST_HEAD(doms);
+static int domcnt;
+
+//static char *screenrc = "/etc/xen/xenscreenrc";
+static char *screenrc = "/home/kraxel/projects/xenwatch/xenscreenrc";
+static char *screen_session = "xencon";
+static char *screen_title = "watch";
+
+/* ------------------------------------------------------------- */
+
+static struct dom *find_dom(int domid)
+{
+ struct dom *dom;
+ struct list_head *item;
+
+ list_for_each(item, &doms) {
+ dom = list_entry(item, struct dom, next);
+ if (dom->domid == domid)
+ return dom;
+ }
+ return NULL;
+}
+
+static struct dom *get_dom(int domid)
+{
+ struct dom *dom;
+
+ dom = find_dom(domid);
+ if (!dom) {
+ dom = malloc(sizeof(*dom));
+ memset(dom,0,sizeof(*dom));
+ dom->domid = domid;
+ list_add_tail(&dom->next, &doms);
+ }
+ return dom;
+}
+
+/* ------------------------------------------------------------- */
+
+static int termsig;
+
+static void catchsig(int sig)
+{
+ termsig = sig;
+}
+
+static void try_attach_screen(struct dom *dom)
+{
+ int rc;
+
+ if (dom->connected)
+ return;
+ if (!strlen(dom->name))
+ return;
+ if (!strlen(dom->tty))
+ return;
+
+ fprintf(stderr," conn: %s (%d) @ %s\n",
+ dom->name, dom->domid, dom->tty);
+
+ if (0 != access(dom->tty, R_OK)) {
+ fprintf(stderr, " error: no access to tty %s\n", dom->tty);
+ return;
+ }
+
+ rc = run_application(1, "fuser", "fuser", "-s", dom->tty, NULL);
+ if (0 == rc) {
+ fprintf(stderr," error: tty %s already in use\n", dom->tty);
+ return;
+ }
+
+ rc = run_application(1, "screen", "screen",
+ "-X", "-S", screen_session,
+ "screen", "-t", dom->name, dom->tty,
+ NULL);
+ dom->connected = 1;
+ domcnt++;
+}
+
+static void try_release_domain(struct dom *dom)
+{
+ if (!dom->destroyed)
+ return;
+ fprintf(stderr," gone: %s (%d)%s\n", dom->name, dom->domid,
+ dom->connected ? " [conn]" : "");
+ if (dom->connected)
+ domcnt--;
+ list_del(&dom->next);
+ free(dom);
+}
+
+/* ------------------------------------------------------------- */
+
+int main(int argc, char *argv[])
+{
+ struct sigaction act,old;
+ fd_set set;
+ struct xs_handle *xenstore = NULL;
+ xs_transaction_t xst;
+ char **vec = NULL;
+ int domid;
+ char path[BUFSIZE], value[BUFSIZE];
+ unsigned int count, i, rc;
+ struct dom *dom;
+ time_t last_ctrl_c = 0;
+
+ if (!have_application("screen")) {
+ fprintf(stderr, "screen not installed, exiting\n");
+ exit(1);
+ }
+
+ if (NULL == getenv("STY") || NULL == strstr(getenv("STY"),screen_session)) {
+ /* not running inside screen, try to attach */
+ rc = run_application(1, "screen", "screen",
+ "-S", screen_session,
+ "-r", "-p", "=",
+ NULL);
+ if (0 == rc)
+ exit(0);
+ /* failing that, start a new screen session */
+ rc = run_application(1,"screen", "screen",
+ "-d", "-m",
+ "-S", screen_session,
+ "-c", screenrc,
+ "-t", screen_title, argv[0],
+ NULL);
+ execlp("screen", "screen",
+ "-S", screen_session,
+ "-r", "-p", "=",
+ NULL);
+ perror("execlp(screen)");
+ exit(1);
+ }
+
+ /* setup signal handler */
+ memset(&act,0,sizeof(act));
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = catchsig;
+ sigaction(SIGTERM,&act,&old);
+ sigaction(SIGINT,&act,&old);
+
+ fprintf(stderr,
+ "###\n"
+ "### Xen consoles in screen\n"
+ "### This is the watch process\n"
+ "###\n"
+ "\n");
+
+ /* connect to xenstore */
+ xenstore = xenstore_open(1,1,1,1);
+ if (NULL == xenstore) {
+ fprintf(stderr, "can't access xenstore, exiting\n");
+ exit(1);
+ }
+ xs_watch(xenstore, "/local/domain", "token");
+
+ /* look for running domains */
+ if (!(xst = xs_transaction_start(xenstore))) {
+ fprintf(stderr,"Oops, can't start xenstore transaction\n");
+ exit(1);
+ }
+ vec = xs_directory(xenstore, xst, "/local/domain", &count);
+ xs_transaction_end(xenstore, xst, 0);
+
+ fprintf(stderr,"looking for existing domains ...\n");
+ for (i = 0; i < count; i++) {
+ domid = atoi(vec[i]);
+ dom = get_dom(domid);
+ snprintf(path, sizeof(path), "/local/domain/%d/name", domid);
+ xenstore_read(xenstore, path, dom->name, sizeof(dom->name));
+ snprintf(path, sizeof(path), "/local/domain/%d/console/tty", domid);
+ xenstore_read(xenstore, path, dom->tty, sizeof(dom->tty));
+ try_attach_screen(dom);
+ }
+
+ /* main loop */
+ fprintf(stderr,"... done, watching for new ones appear\n");
+ for (;;) {
+ if (termsig) {
+ if (!domcnt)
+ break;
+ if (time(NULL) - last_ctrl_c < 3)
+ break;
+ fprintf(stderr,"Still %d domain(s) active - not quitting.\n", domcnt);
+ fprintf(stderr,"Better try detach instead (Ctrl-A d).\n");
+ fprintf(stderr,"Hit Ctrl-C within 3 secs again to quit nevertheless.\n");
+ last_ctrl_c = time(NULL);
+ termsig = 0;
+ }
+
+ FD_ZERO(&set);
+ FD_SET(xs_fileno(xenstore), &set);
+ switch (select(xs_fileno(xenstore)+1, &set, NULL, NULL, NULL)) {
+ case -1:
+ if (EINTR == errno)
+ continue; /* termsig check */
+ perror("select");
+ break;
+ case 0:
+ fprintf(stderr,"Huh, select() timeout?\n");
+ exit(1);
+ break;
+ default:
+ break;
+ }
+
+ if (vec)
+ free(vec);
+ vec = xs_read_watch(xenstore, &count);
+ if (NULL == vec) {
+ fprintf(stderr,"xs_read_watch() failed\n");
+ exit(1);
+ }
+ if (2 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d/%64s", &domid, path)) {
+ if (1 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d", &domid))
+ continue;
+ strcpy(path, "");
+ }
+ dom = get_dom(domid);
+
+ if (0 == strcmp(path,"")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ dom->destroyed = 1;
+
+ } else if (0 == strcmp(path, "console/tty")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ continue;
+ strcpy(dom->tty, value);
+
+ } else if (0 == strcmp(path, "name")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ continue;
+ strcpy(dom->name, value);
+ fprintf(stderr," boot: %s (%d)\n", dom->name, dom->domid);
+
+ } else {
+ continue;
+
+ }
+
+ try_attach_screen(dom);
+ try_release_domain(dom);
+ }
+ return 0;
+}
diff --git a/xenscreenrc b/xenscreenrc
new file mode 100644
index 0000000..c735310
--- /dev/null
+++ b/xenscreenrc
@@ -0,0 +1,16 @@
+multiuser on
+shell /bin/bash
+defscrollback 5000
+compacthist on
+defutf8 on
+termcapinfo xterm hs@
+
+# status line
+hardstatus alwayslastline "%{=b bw} xen |%{-} %-w%{= yb} %50>%n* %t %{-}%+w%<"
+sorendition =s wb
+
+# log files
+#logfile /var/log/screen/screenlog.%t
+#logtstamp string "-- %n:%t -- time-stamp -- %Y-%m-%d %0c:%s --^J"
+#logtstamp on
+
diff --git a/xenstore.c b/xenstore.c
new file mode 100644
index 0000000..f43b9d2
--- /dev/null
+++ b/xenstore.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <xs.h>
+
+#include "xenstore.h"
+
+/* ------------------------------------------------------------- */
+
+struct xs_handle *xenstore_open(int daemon, int domain,
+ int readonly_ok, int verbose)
+{
+ struct xs_handle *xenstore = NULL;
+
+ if (NULL == xenstore && daemon && readonly_ok) {
+ xenstore = xs_daemon_open_readonly();
+ if (NULL == xenstore)
+ fprintf(stderr,"can't connect to %s\n",xs_daemon_socket_ro());
+ else
+ if (verbose)
+ printf("connected to %s\n", xs_daemon_socket_ro());
+ }
+
+ if (NULL == xenstore && daemon) {
+ xenstore = xs_daemon_open();
+ if (NULL == xenstore)
+ fprintf(stderr,"can't connect to %s\n",xs_daemon_socket());
+ else
+ if (verbose)
+ printf("connected to %s\n", xs_daemon_socket());
+ }
+
+ if (NULL == xenstore && domain) {
+ xenstore = xs_domain_open();
+ if (NULL == xenstore)
+ fprintf(stderr, "can't connect to %s\n", xs_domain_dev());
+ else
+ if (verbose)
+ printf("connected to %s\n", xs_domain_dev());
+ }
+ return xenstore;
+}
+
+int xenstore_read(struct xs_handle *xenstore, char *path, char *dst, size_t size)
+{
+ xs_transaction_t xst;
+ char *xs_value = NULL;
+
+ xst = xs_transaction_start(xenstore);
+ if (!xst)
+ return -1;
+
+ xs_value = xs_read(xenstore, xst, path, NULL);
+ xs_transaction_end(xenstore, xst, 0);
+ if (NULL == xs_value)
+ return -2;
+ snprintf(dst, size, "%s", xs_value);
+ free(xs_value);
+ return 0;
+}
diff --git a/xenstore.h b/xenstore.h
new file mode 100644
index 0000000..047563b
--- /dev/null
+++ b/xenstore.h
@@ -0,0 +1,4 @@
+struct xs_handle * xenstore_open(int daemon, int domain,
+ int readonly_ok, int verbose);
+int xenstore_read(struct xs_handle *xenstore, char *path,
+ char *dst, size_t size);