diff options
author | kraxel <kraxel> | 2006-04-06 15:18:48 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-04-06 15:18:48 +0000 |
commit | e16b25e7d718809a3eddfa9cae63a20a1b1c20ac (patch) | |
tree | f84d8056df0003ba808919049a834c5ea9a5725c /apps.c | |
parent | 1131de02524b7d4d87c804cc18f8ec0337b20e70 (diff) | |
download | xenwatch-e16b25e7d718809a3eddfa9cae63a20a1b1c20ac.tar.gz |
desktop detection, app start reorganization
Diffstat (limited to 'apps.c')
-rw-r--r-- | apps.c | 237 |
1 files changed, 237 insertions, 0 deletions
@@ -0,0 +1,237 @@ +#include <stdio.h> +#include <stdlib.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 "apps.h" + +#define array_size(x) (sizeof(x)/sizeof(*x)) + +/* ------------------------------------------------------------------ */ + +static int debug = 1; + +int desktop_kde; +int desktop_gnome; + +int app_have_screen; +int app_have_xenconsole; +int app_have_krdc; +int app_have_vncviewer; +int app_have_kfmclient; +int app_have_firefox; +char app_error[256]; + +/* ------------------------------------------------------------------ */ + +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; +} + +void detect_applications(void) +{ + app_have_screen = have_binary("screen"); + app_have_xenconsole = have_binary(XENCONSOLE); + app_have_krdc = have_binary("krdc"); + app_have_vncviewer = have_binary("vncviewer"); + app_have_kfmclient = have_binary("kfmclient"); + app_have_firefox = have_binary("firefox"); +} + +/* ------------------------------------------------------------------ */ + +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; +} + +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; + return 0; +} + +#define INIT_ATOM(dpy,atom) atom = XInternAtom(dpy,#atom,False) +static Atom _NET_SUPPORTED; +static Atom _NET_WM_STATE_ABOVE; +static Atom KWIN_RUNNING; + +void detect_desktop(void) +{ + Display *dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); + Window root = DefaultRootWindow(dpy); + + if (0) { + INIT_ATOM(dpy, _NET_SUPPORTED); + INIT_ATOM(dpy, _NET_WM_STATE_ABOVE); + check_wm_capability(dpy, root, _NET_SUPPORTED, _NET_WM_STATE_ABOVE); + } + + INIT_ATOM(dpy, KWIN_RUNNING); + if (0 == check_atom_present(dpy, root, KWIN_RUNNING)) + desktop_kde = 1; + + if (desktop_kde) + fprintf(stderr,"Desktop: KDE\n"); + if (desktop_gnome) + fprintf(stderr,"Desktop: gnome\n"); +} + +/* ------------------------------------------------------------------ */ + +int run_application(int do_wait, const char *app, ...) +{ + va_list args; + char *argv[64]; + int status, rc, i; + pid_t pid; + + while (waitpid(-1, &status, WNOHANG) > 0) + /* collect zombies */; + + 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); + } + + if (!do_wait) + return 0; + + 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); +} + +int open_vnc_session(char *host, int screen) +{ + char display[64]; + char httpurl[64]; + + snprintf(display, sizeof(display), "%s:%d", host, screen); + snprintf(httpurl, sizeof(httpurl), "http://%s:%d/", host, 5800 + screen); + + if (app_have_vncviewer) + return run_application(0, "vncviewer", "vncviewer", display, NULL); + if (app_have_krdc) + return run_application(0, "krdc", "krdc", display, NULL); + + if (app_have_kfmclient) + return run_application(0, "kfmclient", "kfmclient", "openURL", httpurl, NULL); + if (app_have_firefox) + return run_application(0, "firefox", "firefox", httpurl, NULL); + + snprintf(app_error, sizeof(app_error), + "need vncviewer or krdc, please install\n"); + return -1; +} |