#include #include #include #include #include #include #include #include #include "list.h" #include "apps.h" /* ------------------------------------------------------------------ */ enum desktop_type desktop_type = DESKTOP_OTHER; char app_error[256]; /* ------------------------------------------------------------------ */ static int debug = 0; struct have_app { char *name; int present; struct list_head next; }; static LIST_HEAD(apps); /* ------------------------------------------------------------------ */ static struct have_app *find_app_entry(char *name) { struct list_head *item; struct have_app *app; list_for_each(item, &apps) { app = list_entry(item, struct have_app, next); if (0 == strcmp(app->name, name)) return app; } app = malloc(sizeof(*app)); memset(app,0,sizeof(*app)); app->name = strdup(name); app->present = -1; list_add_tail(&app->next, &apps); return app; } int have_application(char *name) { struct have_app *app; char *path, *elem, *binary; struct stat st; int rc; app = find_app_entry(name); if (-1 != app->present) goto done; app->present = 0; if (strchr(name,'/')) { /* path specified ... */ if (-1 == stat(name, &st)) goto done; if (!S_ISREG(st.st_mode)) goto done; if (!(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) goto done; app->present = 1; goto done; } /* walk $PATH */ path = getenv("PATH"); if (NULL == path) goto done; 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; app->present = 1; break; } free(path); done: return app->present; } /* ------------------------------------------------------------------ */ int run_application_va(int do_wait, const char *app, char **argv) { int status, rc; pid_t pid; while (waitpid(-1, &status, WNOHANG) > 0) /* collect zombies */; 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 run_application(int do_wait, const char *app, ...) { va_list args; char *argv[64]; int i; 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; } return run_application_va(do_wait, app, argv); } int run_cmdline(int do_wait, char *line) { char *argbuf, *token, *h; char *argv[64]; int rc = -1, argc = 0; h = argbuf = strdup(line); for (;;) { while (' ' == *h || '\t' == *h) h++; if ('\0' == *h) break; if ('"' == *h) { /* quoted string */ h++; token = h; while ('\0' != *h && '"' != *h) h++; } else { /* normal string */ token = h; while ('\0' != *h && ' ' != *h && '\t' != *h) h++; } if ('\0' != *h) { *h = 0; h++; } argv[argc++] = token; if (argc == array_size(argv)-1) { fprintf(stderr,"%s: oops: argv too small\n", __FUNCTION__); goto out; } } if (!argc) goto out; argv[argc++] = NULL; rc = run_application_va(do_wait, argv[0], argv); out: free(argbuf); return rc; } int run_cmdline_replace(int do_wait, char *str, ...) { va_list args; char *tag, *val; char *src, *dst, *pos; int start, end, cont, rc = 0; va_start(args, str); src = strdup(str); for (;;) { tag = va_arg(args, char*); if (NULL == tag) break; val = va_arg(args, char*); if (NULL == val) break; for (cont = 0;;) { if (NULL == (pos = strstr(src + cont, tag))) break; start = pos - src; end = start + strlen(tag); cont = start + strlen(val); dst = malloc(strlen(src) + strlen(val)); strncpy(dst, src, start); strcpy(dst + start, val); strcpy(dst + cont, src + end); free(src); src = dst; } } va_end(args); if (1 || debug) fprintf(stderr,"run: %s\n", src); rc = run_cmdline(do_wait, src); free(src); return rc; } /* ------------------------------------------------------------------ */ int open_vnc_session(char *host, int tcpport) { char display[64]; char javaurl[64]; char vncurl[64]; snprintf(display, sizeof(display), "%s::%d", host, tcpport); snprintf(javaurl, sizeof(javaurl), "http://%s:%d/", host, tcpport - 100); snprintf(vncurl, sizeof(vncurl), "vnc://%s:%d/", host, tcpport); /* --- 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); /* --- try web browser (java applet client) --- */ if (DESKTOP_KDE == desktop_type && have_application("kfmclient")) /* open new konqueror window */ return run_application(0, "kfmclient", "kfmclient", "openURL", javaurl, NULL); if (have_application("firefox")) return run_application(0, "firefox", "firefox", javaurl, NULL); snprintf(app_error, sizeof(app_error), "no vnc client found, please install one\n"); return -1; }