From e16b25e7d718809a3eddfa9cae63a20a1b1c20ac Mon Sep 17 00:00:00 2001 From: kraxel Date: Thu, 6 Apr 2006 15:18:48 +0000 Subject: desktop detection, app start reorganization --- apps.c | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 apps.c (limited to 'apps.c') 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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; +} -- cgit