aboutsummaryrefslogtreecommitdiffstats
path: root/apps.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-04-06 15:18:48 +0000
committerkraxel <kraxel>2006-04-06 15:18:48 +0000
commite16b25e7d718809a3eddfa9cae63a20a1b1c20ac (patch)
treef84d8056df0003ba808919049a834c5ea9a5725c /apps.c
parent1131de02524b7d4d87c804cc18f8ec0337b20e70 (diff)
downloadxenwatch-e16b25e7d718809a3eddfa9cae63a20a1b1c20ac.tar.gz
desktop detection, app start reorganization
Diffstat (limited to 'apps.c')
-rw-r--r--apps.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/apps.c b/apps.c
new file mode 100644
index 0000000..7cbcb72
--- /dev/null
+++ b/apps.c
@@ -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;
+}