aboutsummaryrefslogtreecommitdiffstats
path: root/xenscreen.c
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 /xenscreen.c
parenta27248c91a6a7a48ce794efc4ed51cc9a6e7172b (diff)
downloadxenwatch-8f4db7fb5130a0b327154eddc62b161fb66af688.tar.gz
xen screen management tool
Diffstat (limited to 'xenscreen.c')
-rw-r--r--xenscreen.c273
1 files changed, 273 insertions, 0 deletions
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;
+}