diff options
Diffstat (limited to 'x11vnc/remote.c')
-rw-r--r-- | x11vnc/remote.c | 488 |
1 files changed, 461 insertions, 27 deletions
diff --git a/x11vnc/remote.c b/x11vnc/remote.c index d5ae366..3c6b42d 100644 --- a/x11vnc/remote.c +++ b/x11vnc/remote.c @@ -76,6 +76,7 @@ static void if_8bpp_do_new_fb(void); static void reset_httpport(int old, int new); static void reset_rfbport(int old, int new) ; +char *query_result = NULL; /* * for the wild-n-crazy -remote/-R interface. @@ -83,6 +84,11 @@ static void reset_rfbport(int old, int new) ; int send_remote_cmd(char *cmd, int query, int wait) { FILE *in = NULL; + if (query_result != NULL) { + free(query_result); + query_result = NULL; + } + if (client_connect_file) { umask(077); in = fopen(client_connect_file, "w"); @@ -118,13 +124,26 @@ int send_remote_cmd(char *cmd, int query, int wait) { if (query || wait) { char line[X11VNC_REMOTE_MAX]; - int rc=1, i=0, max=70, ms_sl=50; + int rc=1, i=0, max=140, ms_sl=25; if (!strcmp(cmd, "cmd=stop")) { - max = 20; + max = 40; + } + if (strstr(cmd, "script:")) { + max = 400; + } + if (strstr(cmd, "bcx_xattach:")) { + max = 400; + } + if (getenv("X11VNC_SYNC_TIMEOUT")) { + max = (int) ((1000. * atof(getenv("X11VNC_SYNC_TIMEOUT")))/ms_sl); } for (i=0; i<max; i++) { - usleep(ms_sl * 1000); + if (i==0) { + usleep(10 * 1000); + } else { + usleep(ms_sl * 1000); + } if (client_connect_file) { char *q; in = fopen(client_connect_file, "r"); @@ -147,8 +166,9 @@ int send_remote_cmd(char *cmd, int query, int wait) { strncpy(line, x11vnc_remote_str, X11VNC_REMOTE_MAX); } - if (strcmp(cmd, line)){ - if (query) { + if (strcmp(cmd, line)) { + if (query || wait) { + query_result = strdup(line); fprintf(stdout, "%s\n", line); fflush(stdout); } @@ -170,12 +190,20 @@ int send_remote_cmd(char *cmd, int query, int wait) { int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync, int qdefault) { char *rcmd = NULL, *qcmd = NULL; - int rc = 1; + int rc = 1, direct = 0; if (qdefault && !query_cmd) { query_cmd = remote_cmd; remote_cmd = NULL; } + if (remote_cmd && strstr(remote_cmd, "DIRECT:") == remote_cmd) { + direct = 1; + remote_cmd += strlen("DIRECT:"); + } + if (query_cmd && strstr(query_cmd, "DIRECT:") == query_cmd) { + direct = 1; + query_cmd += strlen("DIRECT:"); + } if (remote_cmd) { rcmd = (char *) malloc(strlen(remote_cmd) + 5); @@ -187,6 +215,19 @@ int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync, strcpy(qcmd, "qry="); strcat(qcmd, query_cmd); } + if (direct) { + char *res; + if (rcmd) { + res = process_remote_cmd(rcmd, 1); + fprintf(stdout, "%s\n", res); + } + if (qcmd) { + res = process_remote_cmd(qcmd, 1); + fprintf(stdout, "%s\n", res); + } + fflush(stdout); + return 0; + } if (qdefault) { char *res; if (!qcmd) { @@ -366,13 +407,17 @@ int check_httpdir(void) { len = strlen(prog) + 21 + 1; *q = '\0'; httpdir = (char *) malloc(len); - if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { + if (use_stunnel && http_ssl) { + snprintf(httpdir, len, "%s/../share/x11vnc/classes/ssl", prog); + } else if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { snprintf(httpdir, len, "%s/../share/x11vnc/classes/ssl", prog); } else { snprintf(httpdir, len, "%s/../share/x11vnc/classes", prog); } if (stat(httpdir, &sbuf) != 0) { - if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { + if (use_stunnel && http_ssl) { + snprintf(httpdir, len, "%s/../classes/ssl", prog); + } else if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { snprintf(httpdir, len, "%s/../classes/ssl", prog); } else { snprintf(httpdir, len, "%s/../classes", prog); @@ -400,7 +445,9 @@ int check_httpdir(void) { "/usr/share/x11vnc/classes/ssl", NULL }; - if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { + if (use_stunnel && http_ssl) { + use = ssllist; + } else if (!enc_str && (use_openssl || use_stunnel || http_ssl)) { use = ssllist; } else { use = list; @@ -445,6 +492,10 @@ void http_connections(int on) { if (check_httpdir()) { screen->httpDir = http_dir; rfbHttpInitSockets(screen); + if (screen->httpPort != 0 && screen->httpListenSock < 0) { + rfbLog("http_connections: failed to listen on http port: %d\n", screen->httpPort); + clean_up_exit(1); + } } } else { rfbLog("http_connections: turning off http service.\n"); @@ -474,6 +525,9 @@ static void reset_httpport(int old, int new) { rfbLog("reset_httpport: setting httpport %d -> %d.\n", old == -1 ? hp : old, hp); rfbHttpInitSockets(screen); + if (screen->httpPort != 0 && screen->httpListenSock < 0) { + rfbLog("reset_httpport: failed to listen on http port: %d\n", screen->httpPort); + } } } @@ -699,16 +753,95 @@ char *process_remote_cmd(char *cmd, int stringonly) { } } + strcpy(buf, ""); if (strstr(cmd, "cmd=") == cmd) { p += strlen("cmd="); + if (strstr(p, "script:") == p) { + char *s, *q, **pieces, tmp[1024]; + int k = 0, n = 0, dp = 1; + + p += strlen("script:"); + + if (strstr(p, "file=") == p) { + FILE *f; + struct stat sbuf; + + p += strlen("file="); + + rfbLog("reading script from file '%s'\n", p); + + if (stat(p, &sbuf) != 0) { + rfbLogPerror("stat"); + return NULL; + } + + f = fopen(p, "r"); + if (f == NULL) { + rfbLogPerror("fopen"); + return NULL; + } + + p = (char *) calloc(sbuf.st_size + 1, 1); + dp = 0; + while (fgets(tmp, 1024, f) != NULL) { + char *c = strchr(tmp, '#'); + if (c) *c = '\0'; + if (strlen(p) + strlen(tmp) > sbuf.st_size) { + break; + } + strcat(p, tmp); + } + fclose(f); + } + + pieces = (char **) malloc(strlen(p) * sizeof(char *)); + if (dp) { + s = strdup(p); + } else { + s = p; + } + q = strtok(s, ";"); + + while (q) { + char *t = lblanks(q); + if (strstr(t, "cmd=") != t && strstr(t, "qry=") != t) { + strcpy(tmp, "cmd="); + } else { + strcpy(tmp, ""); + } + strncat(tmp, t, 1000); + pieces[n] = strdup(tmp); + n++; + q = strtok(NULL, ";"); + } + free(s); + + for (k=0; k < n; k++) { + char *c = pieces[k]; + char *t = c + strlen(c) - 1; /* shortest is "cmd=" */ + while (isspace((unsigned char) (*t))) { + *t = '\0'; + if (t <= c) break; + t--; + } + if (k < n - 1) { + process_remote_cmd(c, 1); + } else { + process_remote_cmd(c, 0); + } + } + for (k=0; k<n; k++) { + free(pieces[k]); + } + free(pieces); + return NULL; + } } else if (strstr(cmd, "qry=") == cmd) { query = 1; if (strchr(cmd, ',')) { /* comma separated batch mode */ - char *s, *q, *res; - char tmp[512]; - char **pieces; + char *s, *q, *res, **pieces, tmp[1024]; int k = 0, n = 0; pieces = (char **) malloc(strlen(cmd) * sizeof(char *)); @@ -717,7 +850,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { while (q) { strcpy(tmp, "qry="); - strncat(tmp, q, 500); + strncat(tmp, q, 1000); pieces[n] = strdup(tmp); n++; q = strtok(NULL, ","); @@ -725,7 +858,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { free(s); strcpy(buf, ""); - for (k=0; k<n; k++) { + for (k=0; k < n; k++) { res = process_remote_cmd(pieces[k], 1); if (res && strlen(buf)+strlen(res) >= X11VNC_REMOTE_MAX - 1) { @@ -797,6 +930,11 @@ char *process_remote_cmd(char *cmd, int stringonly) { /* * Maybe add: passwdfile logfile bg rfbauth passwd... */ + if (!strcmp(p, "")) { /* skip-cmd-list */ + NOTAPP + rfbLog("remote_cmd: empty command.\n"); + goto done; + } if (strstr(p, "CR:") == p) { /* skip-cmd-list */ /* CR:WxH+X+Y,dx,dy */ int w, h, x, y, dx, dy; @@ -829,7 +967,8 @@ char *process_remote_cmd(char *cmd, int stringonly) { close_all_clients(); goto done; } - if (!strcmp(p, "ping")) { + if (!strcmp(p, "ping") + || strstr(p, "ping:") == p) { /* skip-cmd-list */ query = 1; if (rfb_desktop_name) { snprintf(buf, bufn, "ans=%s:%s", p, rfb_desktop_name); @@ -839,6 +978,21 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; goto done; } + if (!strcmp(p, "resend_cutbuffer")) { + NOTAPP + resend_selection("cutbuffer"); + goto done; + } + if (!strcmp(p, "resend_clipboard")) { + NOTAPP + resend_selection("clipboard"); + goto done; + } + if (!strcmp(p, "resend_primary")) { + NOTAPP + resend_selection("primary"); + goto done; + } if (!strcmp(p, "blacken") || !strcmp(p, "zero")) { NOTAPP push_black_screen(4); @@ -911,7 +1065,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("id:"); - if (*p == '\0' || !strcmp("root", p)) { + if (*p == '\0' || !strcmp("root", p)) { /* skip-cmd-list */ /* back to root win */ twin = 0x0; ok = 1; @@ -953,7 +1107,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("sid:"); - if (*p == '\0' || !strcmp("root", p)) { + if (*p == '\0' || !strcmp("root", p)) { /* skip-cmd-list */ /* back to root win */ twin = 0x0; ok = 1; @@ -1513,7 +1667,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { free(connect_proxy); connect_proxy = NULL; } - if (!strcmp(p, "") || !strcasecmp(p, "none")) { + if (!strcmp(p, "") || !strcasecmp(p, "none")) { /* skip-cmd-list */ rfbLog("remote_cmd: disabled -proxy\n"); } else { connect_proxy = strdup(p); @@ -3749,7 +3903,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto qry; } p += strlen("input:"); - if (allowed_input_str && !strcmp(p, allowed_input_str)) { + if (allowed_input_str && !strcmp(p, allowed_input_str)) { /* skip-cmd-list */ doit = 0; } rfbLog("remote_cmd: setting input %s\n", p); @@ -3957,28 +4111,260 @@ char *process_remote_cmd(char *cmd, int stringonly) { goto done; } if (strstr(p, "keycode") == p) { - int kc; + int kc, down = -1; + char *c; NOTAPP COLON_CHECK("keycode:") p += strlen("keycode:"); kc = atoi(p); if (kc < 0) kc = 0; kc = kc % 256; - rfbLog("remote_cmd: insert keycode %d\n", kc); + c = strchr(p, ','); + if (c) down = atoi(c+1); + rfbLog("remote_cmd: insert keycode %d down=%d\n", kc, down); if (macosx_console) { #ifdef MACOSX - macosxCG_keycode_inject(1, kc); - usleep(100*1000); - macosxCG_keycode_inject(0, kc); + if (down == -1) { + macosxCG_keycode_inject(1, kc); + usleep(50*1000); + macosxCG_keycode_inject(0, kc); + } else { + macosxCG_keycode_inject(down, kc); + } #endif } else { - XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime); - usleep(100*1000); - XTestFakeKeyEvent_wr(dpy, kc, 0, CurrentTime); + if (down == -1) { + XTestFakeKeyEvent_wr(dpy, kc, 1, CurrentTime); + usleep(50*1000); + XTestFakeKeyEvent_wr(dpy, kc, 0, CurrentTime); + } else { + XTestFakeKeyEvent_wr(dpy, kc, down, CurrentTime); + } } goto done; } + if (strstr(p, "keysym") == p) { + int down = -1; + unsigned int in; + KeySym ks; + char *c, *str; + NOTAPP + COLON_CHECK("keysym:") + p += strlen("keysym:"); + + c = strchr(p, ','); + if (c) { + down = atoi(c+1); + *c = '\0'; + } + + if (sscanf(p, "0x%x", &in) == 1) { + ks = (KeySym) in; + } else if (sscanf(p, "%u", &in) == 1) { + ks = (KeySym) in; + } else if ((ks = XStringToKeysym(p)) != NoSymbol) { + ; + } else { + rfbLog("remote_cmd: bad keysym: %s\n", p); + goto done; + } + str = XKeysymToString(ks); + str = str ? str : "NoSymbol"; + rfbLog("remote_cmd: insert keysym %s 0x%x '%s' down=%d\n", p, ks, str, down); + if (down == -1) { + keyboard(1, ks, NULL); + usleep(50*1000); + keyboard(0, ks, NULL); + } else { + keyboard(down, ks, NULL); + } + goto done; + } + if (strstr(p, "ptr") == p) { + int x, y, m = 0; + NOTAPP + COLON_CHECK("ptr:") + p += strlen("ptr:"); + rfbLog("remote_cmd: insert pointer event: %s\n", p); + if (sscanf(p, "%d,%d,%d", &x, &y, &m) == 3) { + pointer(m, x, y, NULL); + } else if (sscanf(p, "%d,%d", &x, &y) == 2) { + pointer(m, x, y, NULL); + } else { + rfbLog("remote_cmd: bad ptr:x,y,mask\n"); + } + + goto done; + } + if (strstr(p, "sleep") == p) { + NOTAPP + COLON_CHECK("sleep:") + p += strlen("sleep:"); + rfbLog("remote_cmd: sleeping: %s\n", p); + usleep((int) (1.0e+6 * atof(p))); + rfbLog("remote_cmd: done sleeping.\n"); + goto done; + } + if (strstr(p, "get_xprop") == p) { + char *res; + unsigned long id; + Window win = None; /* None implies root in get_xprop() */ + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "get_xprop:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("get_xprop:"); + + if (strstr(p, "id=") == p) { /* skip-cmd-list */ + p += strlen("id="); + if (scan_hexdec(p, &id)) { + win = (Window) id; + } + if (strchr(p, ':')) { + p = strchr(p, ':') + 1; + } + } + + res = get_xprop(p, win); + if (res == NULL) { + res = strdup("NULL"); + } + snprintf(buf, bufn, "ans=get_xprop:%s:%s", p, res); + free(res); + + goto qry; + } + if (strstr(p, "set_xprop") == p) { + char *q; + int rc = -2; + unsigned long id; + Window win = None; /* None implies root in set_xprop() */ + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "set_xprop:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("set_xprop:"); + + if (strstr(p, "id=") == p) { /* skip-cmd-list */ + p += strlen("id="); + if (scan_hexdec(p, &id)) { + win = (Window) id; + } + if (strchr(p, ':')) { + p = strchr(p, ':') + 1; + } + } + + q = strchr(p, ':'); + if (q) { + *q = '\0'; + rc = set_xprop(p, win, q+1); + *q = ':'; + } + snprintf(buf, bufn, "ans=set_xprop:%s:%d", p, rc); + + goto qry; + } + if (strstr(p, "wininfo") == p) { + char *res, *t = ""; + unsigned long id; + Window win = None; + int show_children = 0; + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "wininfo:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("wininfo:"); + + if (p[0] == '+') { + show_children = 1; + t = "+"; + p++; + } + if (!strcmp(p, "root")) { /* skip-cmd-list */ + win = rootwin; + } else if (scan_hexdec(p, &id)) { + win = (Window) id; + } + + res = wininfo(win, show_children); + if (res == NULL) { + res = strdup("NULL"); + } + snprintf(buf, bufn, "ans=wininfo:%s%s:%s", t, p, res); + free(res); + + goto qry; + } + if (strstr(p, "bcx_xattach") == p) { + char *res; + int pg_init = -1, kg_init = -1; + int try = 0, max_tries = 4; + + /* note we force query and assume the colon is there. */ + query = 1; + if (strstr(p, "bcx_xattach:") != p) { /* skip-cmd-list */ + snprintf(buf, bufn, "ans=%s:N/A", p); + goto qry; + } + p += strlen("bcx_xattach:"); + + if (strstr(p, "retry=")) { /* skip-cmd-list */ + int n; + char *q = strstr(p, "retry="); /* skip-cmd-list */ + if (sscanf(q, "retry=%d", &n) == 1) { + if (n < 0) n = 0; + max_tries = 1 + n; + } + } + + try_again: + + res = bcx_xattach(p, &pg_init, &kg_init); + try++; + if (res == NULL) { + res = strdup("NULL"); + } else if (strstr(res, "GRAB_FAIL_INIT")) { + rfbLog("bcx_xattach: failed grab check for '%s': %s. Final state OK, not Retrying.\n", p, res); + } else if (strstr(res, "GRAB_FAIL") && try < max_tries) { + rfbLog("bcx_xattach: failed grab check for '%s': %s. Retrying[%d]...\n", p, res, try); + free(res); + pointer(0, dpy_x/2 + try, dpy_y/2 + try, NULL); + XFlush_wr(dpy); +#if !NO_X11 + if (dpy) { + if (try == 2) { + XSync(dpy, False); + } else if (try == 3) { + XSync(dpy, True); + } + } +#endif + if (try == 1) { + usleep(250*1000); + } else if (try <= 4) { + usleep(try*400*1000); + } else { + usleep(4*500*1000); + } + goto try_again; + } + + snprintf(buf, bufn, "ans=bcx_xattach:%s:%s", p, res); + free(res); + + goto qry; + } if (strstr(p, "deferupdate") == p) { int d; COLON_CHECK("deferupdate:") @@ -4032,6 +4418,17 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("remote_cmd: setting set_defer to %d\n", set_defer); goto done; } + if (strstr(p, "extra_fbur") == p) { + COLON_CHECK("extra_fbur:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%d", p, co, extra_fbur); + goto qry; + } + p += strlen("extra_fbur:"); + extra_fbur = atoi(p); + rfbLog("remote_cmd: setting extra_fbur to %d\n", extra_fbur); + goto done; + } if (strstr(p, "wait_ui") == p) { double w; COLON_CHECK("wait_ui:") @@ -5169,6 +5566,11 @@ char *process_remote_cmd(char *cmd, int stringonly) { NONUL(guess_desktop())); goto qry; } + if (!strcmp(p, "guess_dbus")) { + snprintf(buf, bufn, "aro=%s:%s", p, + NONUL(dbus_session())); + goto qry; + } if (!strcmp(p, "http_url")) { if (!screen) { snprintf(buf, bufn, "aro=%s:", p); @@ -5448,6 +5850,38 @@ char *process_remote_cmd(char *cmd, int stringonly) { snprintf(buf, bufn, "aro=%s:%d", p, cursor_y); goto qry; } + if (!strcmp(p, "grab_state")) { + int ptr_grabbed, kbd_grabbed; + + grab_state(&ptr_grabbed, &kbd_grabbed); + snprintf(buf, bufn, "aro=%s:%d,%d", p, ptr_grabbed, kbd_grabbed); + rfbLog("remote_cmd: ptr,kbd: %s\n", buf); + goto qry; + } + + if (!strcmp(p, "pointer_pos")) { + int px = -1, py = -1; + int wx, wy; + unsigned int m; + Window r, c; + + + snprintf(buf, bufn, "aro=%s:%d,%d", p, px, py); + if (!dpy) { + goto qry; + } +#if NO_X11 + goto qry; +#else + X_LOCK; + XQueryPointer_wr(dpy, rootwin, &r, &c, &px, &py, &wx, &wy, &m); + X_UNLOCK; +#endif + + snprintf(buf, bufn, "aro=%s:%d,%d", p, px, py); + rfbLog("remote_cmd: pointer_pos: %s\n", buf); + goto qry; + } if (!strcmp(p, "bpp")) { snprintf(buf, bufn, "aro=%s:%d", p, bpp); goto qry; |