/ica/x11/x11vnc/x11vnc.c
C | 5955 lines | 5355 code | 328 blank | 272 comment | 1733 complexity | 3972ec586c7c1d83fbd30cbee6dd99a3 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * x11vnc: a VNC server for X displays.
- *
- * Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
- * All rights reserved.
- *
- * This file is part of x11vnc.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License, or (at
- * your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA or see <http://www.gnu.org/licenses/>.
- *
- * In addition, as a special exception, Karl J. Runge
- * gives permission to link the code of its release of x11vnc with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify this file, you may extend this exception to your version of the
- * file, but you are not obligated to do so. If you do not wish to do
- * so, delete this exception statement from your version.
- */
- /*
- * This program is based on some ideas from the following programs:
- *
- * the initial x11vnc.c in libvncserver (Johannes E. Schindelin)
- * x0rfbserver, the original native X vnc server (Jens Wagner)
- * krfb, the KDE desktopsharing project (Tim Jansen)
- *
- * Please see http://www.karlrunge.com/x11vnc for the most up-to-date
- * information about x11vnc. Some of the following text may be out
- * of date.
- *
- * The primary goal of this program is to create a portable and simple
- * command-line server utility that allows a VNC viewer to connect
- * to an actual X display (as the above do). The only non-standard
- * dependency of this program is the static library libvncserver.a.
- * Although in some environments libjpeg.so or libz.so may not be
- * readily available and needs to be installed, they may be found
- * at ftp://ftp.uu.net/graphics/jpeg/ and http://www.gzip.org/zlib/,
- * respectively. To increase portability it is written in plain C.
- *
- * Another goal is to improve performance and interactive response.
- * The algorithm of x0rfbserver was used as a base. Many additional
- * heuristics are also applied.
- *
- * Another goal is to add many features that enable and incourage creative
- * usage and application of the tool. Apologies for the large number
- * of options!
- *
- * To build:
- *
- * Obtain the libvncserver package (http://libvncserver.sourceforge.net).
- * As of 12/2002 this version of x11vnc.c is contained in the libvncserver
- * CVS tree and released in version 0.5.
- *
- * gcc should be used on all platforms. To build a threaded version put
- * "-D_REENTRANT -DX11VNC_THREADED" in the environment variable CFLAGS
- * or CPPFLAGS (e.g. before running the libvncserver configure). The
- * threaded mode is a bit more responsive, but can be unstable (e.g.
- * if more than one client the same tight or zrle encoding).
- *
- * Known shortcomings:
- *
- * The screen updates are good, but of course not perfect since the X
- * display must be continuously polled and read for changes and this is
- * slow for most hardware. This can be contrasted with receiving a change
- * callback from the X server, if that were generally possible... (UPDATE:
- * this is handled now with the X DAMAGE extension, but unfortunately
- * that doesn't seem to address the slow read from the video h/w). So,
- * e.g., opaque moves and similar window activity can be very painful;
- * one has to modify one's behavior a bit.
- *
- * General audio at the remote display is lost unless one separately
- * sets up some audio side-channel such as esd.
- *
- * It does not appear possible to query the X server for the current
- * cursor shape. We can use XTest to compare cursor to current window's
- * cursor, but we cannot extract what the cursor is... (UPDATE: we now
- * use XFIXES extension for this. Also on Solaris and IRIX Overlay
- * extensions exists that allow drawing the mouse into the framebuffer)
- *
- * The current *position* of the remote X mouse pointer is shown with
- * the -cursor option. Further, if -cursor X is used, a trick
- * is done to at least show the root window cursor vs non-root cursor.
- * (perhaps some heuristic can be done to further distinguish cases...,
- * currently "-cursor some" is a first hack at this)
- *
- * Under XFIXES mode for showing the cursor shape, the cursor may be
- * poorly approximated if it has transparency (alpha channel).
- *
- * Windows using visuals other than the default X visual may have
- * their colors messed up. When using 8bpp indexed color, the colormap
- * is attempted to be followed, but may become out of date. Use the
- * -flashcmap option to have colormap flashing as the pointer moves
- * windows with private colormaps (slow). Displays with mixed depth 8 and
- * 24 visuals will incorrectly display windows using the non-default one.
- * On Sun and Sgi hardware we can to work around this with -overlay.
- *
- * Feature -id <windowid> can be picky: it can crash for things like
- * the window not sufficiently mapped into server memory, etc (UPDATE:
- * we now use the -xrandr mechanisms to trap errors more robustly for
- * this mode). SaveUnders menus, popups, etc will not be seen.
- *
- * Under some situations the keysym unmapping is not correct, especially
- * if the two keyboards correspond to different languages. The -modtweak
- * option is the default and corrects most problems. One can use the
- * -xkb option to try to use the XKEYBOARD extension to clear up any
- * remaining problems.
- *
- * Occasionally, a few tile updates can be missed leaving a patch of
- * color that needs to be refreshed. This may only be when threaded,
- * which is no longer the default.
- *
- * There seems to be a serious bug with simultaneous clients when
- * threaded, currently the only workaround in this case is -nothreads
- * (which is now the default).
- */
- /* -- x11vnc.c -- */
- #include "x11vnc.h"
- #include "xwrappers.h"
- #include "xdamage.h"
- #include "xrecord.h"
- #include "xevents.h"
- #include "xinerama.h"
- #include "xrandr.h"
- #include "xkb_bell.h"
- #include "win_utils.h"
- #include "remote.h"
- #include "scan.h"
- #include "gui.h"
- #include "help.h"
- #include "user.h"
- #include "cleanup.h"
- #include "keyboard.h"
- #include "pointer.h"
- #include "cursor.h"
- #include "userinput.h"
- #include "screen.h"
- #include "connections.h"
- #include "rates.h"
- #include "unixpw.h"
- #include "inet.h"
- #include "sslcmds.h"
- #include "sslhelper.h"
- #include "selection.h"
- #include "pm.h"
- #include "solid.h"
- /*
- * main routine for the x11vnc program
- */
- void watch_loop(void);
- static int limit_shm(void);
- static void check_rcfile(int argc, char **argv);
- static void immediate_switch_user(int argc, char* argv[]);
- static void print_settings(int try_http, int bg, char *gui_str);
- static void check_loop_mode(int argc, char* argv[], int force);
- static void check_appshare_mode(int argc, char* argv[]);
- static int tsdo_timeout_flag;
- static void tsdo_timeout (int sig) {
- tsdo_timeout_flag = 1;
- if (sig) {};
- }
- #define TASKMAX 32
- static pid_t ts_tasks[TASKMAX];
- static int ts_taskn = -1;
- int tsdo(int port, int lsock, int *conn) {
- int csock, rsock, i, db = 1;
- pid_t pid;
- struct sockaddr_in addr;
- #ifdef __hpux
- int addrlen = sizeof(addr);
- #else
- socklen_t addrlen = sizeof(addr);
- #endif
- if (*conn < 0) {
- signal(SIGALRM, tsdo_timeout);
- tsdo_timeout_flag = 0;
- alarm(10);
- csock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
- alarm(0);
- if (db) rfbLog("tsdo: accept: lsock: %d, csock: %d, port: %d\n", lsock, csock, port);
- if (tsdo_timeout_flag > 0 || csock < 0) {
- close(csock);
- *conn = -1;
- return 1;
- }
- *conn = csock;
- } else {
- csock = *conn;
- if (db) rfbLog("tsdo: using existing csock: %d, port: %d\n", csock, port);
- }
- rsock = connect_tcp("127.0.0.1", port);
- if (rsock < 0) {
- if (db) rfbLog("tsdo: connect_tcp(port=%d) failed.\n", port);
- close(csock);
- return 2;
- }
- pid = fork();
- if (pid < 0) {
- close(csock);
- close(rsock);
- return 3;
- }
- if (pid > 0) {
- ts_taskn = (ts_taskn+1) % TASKMAX;
- ts_tasks[ts_taskn] = pid;
- close(csock);
- close(rsock);
- *conn = -1;
- return 0;
- }
- if (pid == 0) {
- for (i=0; i<255; i++) {
- if (i != csock && i != rsock && i != 2) {
- close(i);
- }
- }
- #if LIBVNCSERVER_HAVE_SETSID
- if (setsid() == -1) {
- perror("setsid");
- close(csock);
- close(rsock);
- exit(1);
- }
- #else
- if (setpgrp() == -1) {
- perror("setpgrp");
- close(csock);
- close(rsock);
- exit(1);
- }
- #endif /* SETSID */
- raw_xfer(rsock, csock, csock);
- close(csock);
- close(rsock);
- exit(0);
- }
- return 0;
- }
- void set_redir_properties(void);
- #define TSMAX 32
- #define TSSTK 16
- void terminal_services(char *list) {
- int i, j, n, db = 1;
- char *p, *q, *r, *str;
- #if !NO_X11
- char *tag[TSMAX];
- int listen[TSMAX], redir[TSMAX][TSSTK], socks[TSMAX], tstk[TSSTK];
- double rate_start;
- int rate_count;
- Atom at, atom[TSMAX];
- fd_set rd;
- Window rwin;
- XErrorHandler old_handler1;
- XIOErrorHandler old_handler2;
- char num[32];
- time_t last_clean = time(NULL);
- if (getenv("TS_REDIR_DEBUG")) {
- db = 2;
- }
- if (! dpy) {
- return;
- }
- rwin = RootWindow(dpy, DefaultScreen(dpy));
- at = XInternAtom(dpy, "TS_REDIR_LIST", False);
- if (at != None) {
- XChangeProperty(dpy, rwin, at, XA_STRING, 8,
- PropModeReplace, (unsigned char *)list, strlen(list));
- XSync(dpy, False);
- }
- if (db) fprintf(stderr, "TS_REDIR_LIST Atom: %d.\n", (int) at);
- oh_restart_it_all:
- for (i=0; i<TASKMAX; i++) {
- ts_tasks[i] = 0;
- }
- for (i=0; i<TSMAX; i++) {
- socks[i] = -1;
- listen[i] = -1;
- for (j=0; j<TSSTK; j++) {
- redir[i][j] = 0;
- }
- }
- rate_start = 0.0;
- rate_count = 0;
- n = 0;
- str = strdup(list);
- p = strtok(str, ",");
- while (p) {
- int m1, m2;
- if (db) fprintf(stderr, "item: %s\n", p);
- q = strrchr(p, ':');
- if (!q) {
- p = strtok(NULL, ",");
- continue;
- }
- r = strchr(p, ':');
- if (!r || r == q) {
- p = strtok(NULL, ",");
- continue;
- }
- m1 = atoi(q+1);
- *q = '\0';
- m2 = atoi(r+1);
- *r = '\0';
- if (m1 <= 0 || m2 <= 0 || m1 >= 0xffff || m2 >= 0xffff) {
- p = strtok(NULL, ",");
- continue;
- }
- redir[n][0] = m1;
- listen[n] = m2;
- tag[n] = strdup(p);
- if (db) fprintf(stderr, " %d %d %s\n", redir[n][0], listen[n], tag[n]);
- *r = ':';
- *q = ':';
- n++;
- if (n >= TSMAX) {
- break;
- }
- p = strtok(NULL, ",");
- }
- free(str);
- if (n==0) {
- return;
- }
- at = XInternAtom(dpy, "TS_REDIR_PID", False);
- if (at != None) {
- sprintf(num, "%d", getpid());
- XChangeProperty(dpy, rwin, at, XA_STRING, 8,
- PropModeReplace, (unsigned char *)num, strlen(num));
- XSync(dpy, False);
- }
- for (i=0; i<n; i++) {
- int k;
- atom[i] = XInternAtom(dpy, tag[i], False);
- if (db) fprintf(stderr, "tag: %s atom: %d\n", tag[i], (int) atom[i]);
- if (atom[i] == None) {
- continue;
- }
- sprintf(num, "%d", redir[i][0]);
- if (db) fprintf(stderr, " listen: %d redir: %s\n", listen[i], num);
- XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
- PropModeReplace, (unsigned char *)num, strlen(num));
- XSync(dpy, False);
- for (k=1; k <= 5; k++) {
- /* XXX ::1 fallback? */
- socks[i] = listen_tcp(listen[i], htonl(INADDR_LOOPBACK), 1);
- if (socks[i] >= 0) {
- if (db) fprintf(stderr, " listen succeeded: %d\n", listen[i]);
- break;
- }
- if (db) fprintf(stderr, " listen failed***: %d\n", listen[i]);
- usleep(k * 2000*1000);
- }
- }
- if (getenv("TSD_RESTART")) {
- if (!strcmp(getenv("TSD_RESTART"), "1")) {
- set_redir_properties();
- }
- }
- while (1) {
- struct timeval tv;
- int nfd;
- int fmax = -1;
- tv.tv_sec = 3;
- tv.tv_usec = 0;
- FD_ZERO(&rd);
- for (i=0; i<n; i++) {
- if (socks[i] >= 0) {
- FD_SET(socks[i], &rd);
- if (socks[i] > fmax) {
- fmax = socks[i];
- }
- }
- }
- nfd = select(fmax+1, &rd, NULL, NULL, &tv);
- if (db && 0) fprintf(stderr, "nfd=%d\n", nfd);
- if (nfd < 0 && errno == EINTR) {
- XSync(dpy, True);
- continue;
- }
- if (nfd > 0) {
- int did_ts = 0;
- for(i=0; i<n; i++) {
- int k = 0;
- for (j = 0; j < TSSTK; j++) {
- tstk[j] = 0;
- }
- for (j = 0; j < TSSTK; j++) {
- if (redir[i][j] != 0) {
- tstk[k++] = redir[i][j];
- }
- }
- for (j = 0; j < TSSTK; j++) {
- redir[i][j] = tstk[j];
- if (tstk[j] != 0) fprintf(stderr, "B redir[%d][%d] = %d %s\n", i, j, tstk[j], tag[i]);
- }
- }
- for(i=0; i<n; i++) {
- int s = socks[i];
- if (s < 0) {
- continue;
- }
- if (FD_ISSET(s, &rd)) {
- int p0, p, found = -1, jzero = -1;
- int conn = -1;
- get_prop(num, 32, atom[i], None);
- p0 = atoi(num);
- for (j = TSSTK-1; j >= 0; j--) {
- if (redir[i][j] == 0) {
- jzero = j;
- continue;
- }
- if (p0 > 0 && p0 < 0xffff) {
- if (redir[i][j] == p0) {
- found = j;
- break;
- }
- }
- }
- if (jzero < 0) {
- jzero = TSSTK-1;
- }
- if (found < 0) {
- if (p0 > 0 && p0 < 0xffff) {
- redir[i][jzero] = p0;
- }
- }
- for (j = TSSTK-1; j >= 0; j--) {
- int rc;
- p = redir[i][j];
- if (p <= 0 || p >= 0xffff) {
- redir[i][j] = 0;
- continue;
- }
- if (dnow() > rate_start + 10.0) {
- rate_start = dnow();
- rate_count = 0;
- }
- rate_count++;
- rc = tsdo(p, s, &conn);
- did_ts++;
- if (rc == 0) {
- /* AOK */
- if (db) fprintf(stderr, "tsdo[%d] OK: %d\n", i, p);
- if (p != p0) {
- sprintf(num, "%d", p);
- XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
- PropModeReplace, (unsigned char *)num, strlen(num));
- XSync(dpy, False);
- }
- break;
- } else if (rc == 1) {
- /* accept failed */
- if (db) fprintf(stderr, "tsdo[%d] accept failed: %d, sleep 50ms\n", i, p);
- usleep(50*1000);
- break;
- } else if (rc == 2) {
- /* connect failed */
- if (db) fprintf(stderr, "tsdo[%d] connect failed: %d, sleep 50ms rate: %d/10s\n", i, p, rate_count);
- redir[i][j] = 0;
- usleep(50*1000);
- continue;
- } else if (rc == 3) {
- /* fork failed */
- usleep(500*1000);
- break;
- }
- }
- for (j = 0; j < TSSTK; j++) {
- if (redir[i][j] != 0) fprintf(stderr, "A redir[%d][%d] = %d %s\n", i, j, redir[i][j], tag[i]);
- }
- }
- }
- if (did_ts && rate_count > 100) {
- int db_netstat = 1;
- char dcmd[100];
- if (no_external_cmds) {
- db_netstat = 0;
- }
- rfbLog("terminal_services: throttling high connect rate %d/10s\n", rate_count);
- usleep(2*1000*1000);
- rfbLog("terminal_services: stopping ts services.\n");
- for(i=0; i<n; i++) {
- int s = socks[i];
- if (s < 0) {
- continue;
- }
- rfbLog("terminal_services: closing listen=%d sock=%d.\n", listen[i], socks[i]);
- if (listen[i] >= 0 && db_netstat) {
- sprintf(dcmd, "netstat -an | grep -w '%d'", listen[i]);
- fprintf(stderr, "#1 %s\n", dcmd);
- system(dcmd);
- }
- close(s);
- socks[i] = -1;
- usleep(2*1000*1000);
- if (listen[i] >= 0 && db_netstat) {
- fprintf(stderr, "#2 %s\n", dcmd);
- system(dcmd);
- }
- }
- usleep(10*1000*1000);
- rfbLog("terminal_services: restarting ts services\n");
- goto oh_restart_it_all;
- }
- }
- for (i=0; i<TASKMAX; i++) {
- pid_t p = ts_tasks[i];
- if (p > 0) {
- int status;
- pid_t p2 = waitpid(p, &status, WNOHANG);
- if (p2 == p) {
- ts_tasks[i] = 0;
- }
- }
- }
- /* this is to drop events and exit when X server is gone. */
- old_handler1 = XSetErrorHandler(trap_xerror);
- old_handler2 = XSetIOErrorHandler(trap_xioerror);
- trapped_xerror = 0;
- trapped_xioerror = 0;
- XSync(dpy, True);
- sprintf(num, "%d", (int) time(NULL));
- at = XInternAtom(dpy, "TS_REDIR", False);
- if (at != None) {
- XChangeProperty(dpy, rwin, at, XA_STRING, 8,
- PropModeReplace, (unsigned char *)num, strlen(num));
- XSync(dpy, False);
- }
- if (time(NULL) > last_clean + 20 * 60) {
- int i, j;
- for(i=0; i<n; i++) {
- int first = 1;
- for (j = TSSTK-1; j >= 0; j--) {
- int s, p = redir[i][j];
- if (p <= 0 || p >= 0xffff) {
- redir[i][j] = 0;
- continue;
- }
- s = connect_tcp("127.0.0.1", p);
- if (s < 0) {
- redir[i][j] = 0;
- if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p);
- } else {
- close(s);
- if (first) {
- sprintf(num, "%d", p);
- XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
- PropModeReplace, (unsigned char *)num, strlen(num));
- XSync(dpy, False);
- }
- first = 0;
- }
- usleep(500*1000);
- }
- }
- last_clean = time(NULL);
- }
- if (trapped_xerror || trapped_xioerror) {
- if (db) fprintf(stderr, "Xerror: %d/%d\n", trapped_xerror, trapped_xioerror);
- exit(0);
- }
- XSetErrorHandler(old_handler1);
- XSetIOErrorHandler(old_handler2);
- }
- #endif
- }
- char *ts_services[][2] = {
- {"FD_CUPS", "TS_CUPS_REDIR"},
- {"FD_SMB", "TS_SMB_REDIR"},
- {"FD_ESD", "TS_ESD_REDIR"},
- {"FD_NAS", "TS_NAS_REDIR"},
- {NULL, NULL}
- };
- void do_tsd(void) {
- #if !NO_X11
- Atom a;
- char prop[513];
- pid_t pid;
- char *cmd;
- int n, sz = 0;
- char *disp = DisplayString(dpy);
- char *logfile = getenv("TS_REDIR_LOGFILE");
- int db = 0;
- if (getenv("TS_REDIR_DEBUG")) {
- db = 1;
- }
- if (db) fprintf(stderr, "do_tsd() in.\n");
- prop[0] = '\0';
- a = XInternAtom(dpy, "TS_REDIR_LIST", False);
- if (a != None) {
- get_prop(prop, 512, a, None);
- }
- if (db) fprintf(stderr, "TS_REDIR_LIST Atom: %d = '%s'\n", (int) a, prop);
- if (prop[0] == '\0') {
- return;
- }
- if (! program_name) {
- program_name = "x11vnc";
- }
- sz += strlen(program_name) + 1;
- sz += strlen("-display") + 1;
- sz += strlen(disp) + 1;
- sz += strlen("-tsd") + 1;
- sz += 1 + strlen(prop) + 1 + 1;
- sz += strlen("-env TSD_RESTART=1") + 1;
- sz += strlen("</dev/null 1>/dev/null 2>&1") + 1;
- sz += strlen(" &") + 1;
- if (logfile) {
- sz += strlen(logfile);
- }
- if (ipv6_listen) {
- sz += strlen("-6") + 1;
- }
- cmd = (char *) malloc(sz);
- if (getenv("XAUTHORITY")) {
- char *xauth = getenv("XAUTHORITY");
- if (!strcmp(xauth, "") || access(xauth, R_OK) != 0) {
- *(xauth-2) = '_'; /* yow */
- }
- }
- sprintf(cmd, "%s -display %s -tsd '%s' -env TSD_RESTART=1 %s </dev/null 1>%s 2>&1 &",
- program_name, disp, prop, ipv6_listen ? "-6" : "",
- logfile ? logfile : "/dev/null" );
- rfbLog("running: %s\n", cmd);
- #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
- /* fork into the background now */
- if ((pid = fork()) > 0) {
- pid_t pidw;
- int status;
- double s = dnow();
- while (dnow() < s + 1.5) {
- pidw = waitpid(pid, &status, WNOHANG);
- if (pidw == pid) {
- break;
- }
- usleep(100*1000);
- }
- return;
- } else if (pid == -1) {
- system(cmd);
- } else {
- setsid();
- /* adjust our stdio */
- n = open("/dev/null", O_RDONLY);
- dup2(n, 0);
- dup2(n, 1);
- dup2(n, 2);
- if (n > 2) {
- close(n);
- }
- system(cmd);
- exit(0);
- }
- #else
- system(cmd);
- #endif
- #endif
- }
- void set_redir_properties(void) {
- #if !NO_X11
- char *e, *f, *t;
- Atom a;
- char num[32];
- int i, p;
- if (! dpy) {
- return;
- }
- i = 0;
- while (ts_services[i][0] != NULL) {
- f = ts_services[i][0];
- t = ts_services[i][1];
- e = getenv(f);
- if (!e || strstr(e, "DAEMON-") != e) {
- i++;
- continue;
- }
- p = atoi(e + strlen("DAEMON-"));
- if (p <= 0) {
- i++;
- continue;
- }
- sprintf(num, "%d", p);
- a = XInternAtom(dpy, t, False);
- if (a != None) {
- Window rwin = RootWindow(dpy, DefaultScreen(dpy));
- fprintf(stderr, "Set: %s %s %s -> %s\n", f, t, e, num);
- XChangeProperty(dpy, rwin, a, XA_STRING, 8,
- PropModeReplace, (unsigned char *) num, strlen(num));
- XSync(dpy, False);
- }
- i++;
- }
- #endif
- }
- static void check_redir_services(void) {
- #if !NO_X11
- Atom a;
- char prop[513];
- time_t tsd_last;
- int restart = 0;
- pid_t pid = 0;
- int db = 0;
- db = 0;
- if (getenv("TS_REDIR_DEBUG")) {
- db = 1;
- }
- if (db) fprintf(stderr, "check_redir_services in.\n");
- if (! dpy) {
- return;
- }
- a = XInternAtom(dpy, "TS_REDIR_PID", False);
- if (a != None) {
- prop[0] = '\0';
- get_prop(prop, 512, a, None);
- if (prop[0] != '\0') {
- pid = (pid_t) atoi(prop);
- }
- }
- if (db) fprintf(stderr, "TS_REDIR_PID Atom: %d = '%s'\n", (int) a, prop);
- if (getenv("FD_TAG") && strcmp(getenv("FD_TAG"), "")) {
- a = XInternAtom(dpy, "FD_TAG", False);
- if (a != None) {
- Window rwin = RootWindow(dpy, DefaultScreen(dpy));
- char *tag = getenv("FD_TAG");
- XChangeProperty(dpy, rwin, a, XA_STRING, 8,
- PropModeReplace, (unsigned char *)tag, strlen(tag));
- XSync(dpy, False);
- }
- if (db) fprintf(stderr, "FD_TAG Atom: %d = '%s'\n", (int) a, prop);
- }
- prop[0] = '\0';
- a = XInternAtom(dpy, "TS_REDIR", False);
- if (a != None) {
- get_prop(prop, 512, a, None);
- }
- if (db) fprintf(stderr, "TS_REDIR Atom: %d = '%s'\n", (int) a, prop);
- if (prop[0] == '\0') {
- rfbLog("TS_REDIR is empty, restarting...\n");
- restart = 1;
- } else {
- tsd_last = (time_t) atoi(prop);
- if (time(NULL) > tsd_last + 30) {
- rfbLog("TS_REDIR seems dead for: %d sec, restarting...\n",
- time(NULL) - tsd_last);
- restart = 1;
- } else if (pid > 0 && time(NULL) > tsd_last + 6) {
- if (kill(pid, 0) != 0) {
- rfbLog("TS_REDIR seems dead via kill(%d, 0), restarting...\n",
- pid);
- restart = 1;
- }
- }
- }
- if (restart) {
- if (pid > 1) {
- rfbLog("killing TS_REDIR_PID: %d\n", pid);
- kill(pid, SIGTERM);
- usleep(500*1000);
- kill(pid, SIGKILL);
- }
- do_tsd();
- if (db) fprintf(stderr, "check_redir_services restarted.\n");
- return;
- }
- if (db) fprintf(stderr, "check_redir_services, no restart, calling set_redir_properties.\n");
- set_redir_properties();
- #endif
- }
- void ssh_remote_tunnel(char *instr, int lport) {
- #ifndef WIN32
- char *q, *cmd, *ssh;
- char *s = strdup(instr);
- int sleep = 300, disp = 0, sport = 0;
- int rc, len, rport;
- /* user@host:port:disp+secs */
- /* +sleep */
- q = strrchr(s, '+');
- if (q) {
- sleep = atoi(q+1);
- if (sleep <= 0) {
- sleep = 1;
- }
- *q = '\0';
- }
- /* :disp */
- q = strrchr(s, ':');
- if (q) {
- disp = atoi(q+1);
- *q = '\0';
- }
-
- /* :sshport */
- q = strrchr(s, ':');
- if (q) {
- sport = atoi(q+1);
- *q = '\0';
- }
- if (getenv("SSH")) {
- ssh = getenv("SSH");
- } else {
- ssh = "ssh";
- }
- len = 0;
- len += strlen(ssh) + strlen(s) + 500;
- cmd = (char *) malloc(len);
- if (disp >= 0 && disp <= 200) {
- rport = disp + 5900;
- } else if (disp < 0) {
- rport = -disp;
- } else {
- rport = disp;
- }
- if (sport > 0) {
- sprintf(cmd, "%s -f -p %d -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, sport, rport, lport, s, sleep);
- } else {
- sprintf(cmd, "%s -f -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, rport, lport, s, sleep);
- }
- if (no_external_cmds || !cmd_ok("ssh")) {
- rfbLogEnable(1);
- rfbLog("cannot run external commands in -nocmds mode:\n");
- rfbLog(" \"%s\"\n", cmd);
- rfbLog(" exiting.\n");
- clean_up_exit(1);
- }
- close_exec_fds();
- fprintf(stderr, "\n");
- rfbLog("running: %s\n", cmd);
- rc = system(cmd);
- if (rc != 0) {
- free(cmd);
- free(s);
- rfbLog("ssh remote listen failed.\n");
- clean_up_exit(1);
- }
- if (1) {
- FILE *pipe;
- int mypid = (int) getpid();
- int bestpid = -1;
- int best = -1;
- char line[1024];
- char *psef = "ps -ef";
- char *psww = "ps wwwwwwaux";
- char *ps = psef;
- /* not portable... but it is really good to terminate the ssh when done. */
- /* ps -ef | egrep 'ssh2.*-R.*5907:localhost:5900.*runge@celias.lbl.gov.*sleep 300' | grep -v grep | awk '{print $2}' */
- if (strstr(UT.sysname, "Linux")) {
- ps = psww;
- } else if (strstr(UT.sysname, "BSD")) {
- ps = psww;
- } else if (strstr(UT.sysname, "Darwin")) {
- ps = psww;
- }
- sprintf(cmd, "env COLUMNS=256 %s | egrep '%s.*-R *%d:localhost:%d.*%s.*sleep *%d' | grep -v grep | awk '{print $2}'", ps, ssh, rport, lport, s, sleep);
- pipe = popen(cmd, "r");
- if (pipe) {
- while (fgets(line, 1024, pipe) != NULL) {
- int p = atoi(line);
- if (p > 0) {
- int score;
- if (p > mypid) {
- score = p - mypid;
- } else {
- score = p - mypid + 32768;
- if (score < 0) {
- score = 32768;
- }
- }
- if (best < 0 || score < best) {
- best = score;
- bestpid = p;
- }
- }
- }
- pclose(pipe);
- }
- if (bestpid != -1) {
- ssh_pid = (pid_t) bestpid;
- rfbLog("guessed ssh pid=%d, will terminate it on exit.\n", bestpid);
- }
- }
- free(cmd);
- free(s);
- #endif
- }
- /*
- * check blacklist for OSs with tight shm limits.
- */
- static int limit_shm(void) {
- int limit = 0;
- #ifndef WIN32
- if (UT.sysname == NULL) {
- return 0;
- }
- if (getenv("X11VNC_NO_LIMIT_SHM")) {
- return 0;
- }
- if (!strcmp(UT.sysname, "SunOS")) {
- char *r = UT.release;
- if (*r == '5' && *(r+1) == '.') {
- if (strchr("2345678", *(r+2)) != NULL) {
- limit = 1;
- }
- }
- } else if (!strcmp(UT.sysname, "Darwin")) {
- limit = 1;
- }
- if (limit && ! quiet) {
- fprintf(stderr, "reducing shm usage on %s %s (adding "
- "-onetile)\n", UT.sysname, UT.release);
- }
- #endif
- return limit;
- }
- /*
- * quick-n-dirty ~/.x11vncrc: each line (except # comments) is a cmdline option.
- */
- static int argc2 = 0;
- static char **argv2;
- static void check_rcfile(int argc, char **argv) {
- int i, j, pwlast, enclast, norc = 0, argmax = 1024;
- char *infile = NULL;
- char rcfile[1024];
- FILE *rc = NULL;
- for (i=1; i < argc; i++) {
- if (!strcmp(argv[i], "-printgui")) {
- fprintf(stdout, "%s", get_gui_code());
- fflush(stdout);
- exit(0);
- }
- if (!strcmp(argv[i], "-norc")) {
- norc = 1;
- got_norc = 1;
- }
- if (!strcmp(argv[i], "-QD")) {
- norc = 1;
- }
- if (!strcmp(argv[i], "-rc")) {
- if (i+1 >= argc) {
- fprintf(stderr, "-rc option requires a "
- "filename\n");
- exit(1);
- } else {
- infile = argv[i+1];
- }
- }
- }
- rc_norc = norc;
- rc_rcfile = strdup("");
- if (norc) {
- ;
- } else if (infile != NULL) {
- rc = fopen(infile, "r");
- rc_rcfile = strdup(infile);
- if (rc == NULL) {
- fprintf(stderr, "could not open rcfile: %s\n", infile);
- perror("fopen");
- exit(1);
- }
- } else {
- char *home = get_home_dir();
- if (! home) {
- norc = 1;
- } else {
- memset(rcfile, 0, sizeof(rcfile));
- strncpy(rcfile, home, 500);
- free(home);
- strcat(rcfile, "/.x11vncrc");
- infile = rcfile;
- rc = fopen(rcfile, "r");
- if (rc == NULL) {
- norc = 1;
- } else {
- rc_rcfile = strdup(rcfile);
- rc_rcfile_default = 1;
- }
- }
- }
- argv2 = (char **) malloc(argmax * sizeof(char *));
- argv2[argc2++] = strdup(argv[0]);
- if (! norc) {
- char line[4096], parm[400], tmp[401];
- char *buf, *tbuf;
- struct stat sbuf;
- int sz;
- if (fstat(fileno(rc), &sbuf) != 0) {
- fprintf(stderr, "problem with %s\n", infile);
- perror("fstat");
- exit(1);
- }
- sz = sbuf.st_size+1; /* allocate whole file size */
- if (sz < 1024) {
- sz = 1024;
- }
- buf = (char *) malloc(sz);
- buf[0] = '\0';
- while (fgets(line, 4096, rc) != NULL) {
- char *q, *p = line;
- char c;
- int cont = 0;
- q = p;
- c = '\0';
- while (*q) {
- if (*q == '#') {
- if (c != '\\') {
- *q = '\0';
- break;
- }
- }
- c = *q;
- q++;
- }
- q = p;
- c = '\0';
- while (*q) {
- if (*q == '\n') {
- if (c == '\\') {
- cont = 1;
- *q = '\0';
- *(q-1) = ' ';
- break;
- }
- while (isspace((unsigned char) (*q))) {
- *q = '\0';
- if (q == p) {
- break;
- }
- q--;
- }
- break;
- }
- c = *q;
- q++;
- }
- if (q != p && !cont) {
- if (*q == '\0') {
- q--;
- }
- while (isspace((unsigned char) (*q))) {
- *q = '\0';
- if (q == p) {
- break;
- }
- q--;
- }
- }
- p = lblanks(p);
- strncat(buf, p, sz - strlen(buf) - 1);
- if (cont) {
- continue;
- }
- if (buf[0] == '\0') {
- continue;
- }
- i = 0;
- q = buf;
- while (*q) {
- i++;
- if (*q == '\n' || isspace((unsigned char) (*q))) {
- break;
- }
- q++;
- }
- if (i >= 400) {
- fprintf(stderr, "invalid rcfile line: %s/%s\n",
- p, buf);
- exit(1);
- }
- if (sscanf(buf, "%s", parm) != 1) {
- fprintf(stderr, "invalid rcfile line: %s\n", p);
- exit(1);
- }
- if (parm[0] == '-') {
- strncpy(tmp, parm, 400);
- } else {
- tmp[0] = '-';
- strncpy(tmp+1, parm, 400);
- }
- if (strstr(tmp, "-loop") == tmp) {
- if (! getenv("X11VNC_LOOP_MODE")) {
- check_loop_mode(argc, argv, 1);
- exit(0);
- }
- }
- argv2[argc2++] = strdup(tmp);
- if (argc2 >= argmax) {
- fprintf(stderr, "too many rcfile options\n");
- exit(1);
- }
-
- p = buf;
- p += strlen(parm);
- p = lblanks(p);
- if (*p == '\0') {
- buf[0] = '\0';
- continue;
- }
- tbuf = (char *) calloc(strlen(p) + 1, 1);
- j = 0;
- while (*p) {
- if (*p == '\\' && *(p+1) == '#') {
- ;
- } else {
- tbuf[j++] = *p;
- }
- p++;
- }
- argv2[argc2++] = strdup(tbuf);
- free(tbuf);
- if (argc2 >= argmax) {
- fprintf(stderr, "too many rcfile options\n");
- exit(1);
- }
- buf[0] = '\0';
- }
- fclose(rc);
- free(buf);
- }
- pwlast = 0;
- enclast = 0;
- for (i=1; i < argc; i++) {
- argv2[argc2++] = strdup(argv[i]);
- if (pwlast || !strcmp("-passwd", argv[i])
- || !strcmp("-viewpasswd", argv[i])) {
- char *p = argv[i];
- if (pwlast) {
- pwlast = 0;
- } else {
- pwlast = 1;
- }
- strzero(p);
- }
- if (enclast || !strcmp("-enc", argv[i])) {
- char *q, *p = argv[i];
- if (enclast) {
- enclast = 0;
- } else {
- enclast = 1;
- }
- q = strstr(p, "pw=");
- if (q) {
- strzero(q);
- }
- }
- if (argc2 >= argmax) {
- fprintf(stderr, "too many rcfile options\n");
- exit(1);
- }
- }
- }
- static void immediate_switch_user(int argc, char* argv[]) {
- int i, bequiet = 0;
- for (i=1; i < argc; i++) {
- if (strcmp(argv[i], "-inetd")) {
- bequiet = 1;
- }
- if (strcmp(argv[i], "-quiet")) {
- bequiet = 1;
- }
- if (strcmp(argv[i], "-q")) {
- bequiet = 1;
- }
- }
- for (i=1; i < argc; i++) {
- char *u, *q;
- if (strcmp(argv[i], "-users")) {
- continue;
- }
- if (i == argc - 1) {
- fprintf(stderr, "not enough arguments for: -users\n");
- exit(1);
- }
- if (*(argv[i+1]) != '=') {
- break;
- }
- /* wants an immediate switch: =bob */
- u = strdup(argv[i+1]);
- *u = '+';
- q = strchr(u, '.');
- if (q) {
- user2group = (char **) malloc(2*sizeof(char *));
- user2group[0] = strdup(u+1);
- user2group[1] = NULL;
- *q = '\0';
- }
- if (strstr(u, "+guess") == u) {
- fprintf(stderr, "invalid user: %s\n", u+1);
- exit(1);
- }
- if (!switch_user(u, 0)) {
- fprintf(stderr, "Could not switch to user: %s\n", u+1);
- exit(1);
- } else {
- if (!bequiet) {
- fprintf(stderr, "Switched to user: %s\n", u+1);
- }
- started_as_root = 2;
- }
- free(u);
- break;
- }
- }
- static void quick_pw(char *str) {
- char *p, *q;
- char tmp[1024];
- int db = 0;
- if (db) fprintf(stderr, "quick_pw: %s\n", str);
- if (! str || str[0] == '\0') {
- exit(2);
- }
- if (str[0] != '%') {
- exit(2);
- }
- /*
- * "%-" or "%stdin" means read one line from stdin.
- *
- * "%env" means it is in $UNIXPW env var.
- *
- * starting "%/" or "%." means read the first line from that file.
- *
- * "%%" or "%" means prompt user.
- *
- * otherwise: %user:pass
- */
- if (!strcmp(str, "%-") || !strcmp(str, "%stdin")) {
- if(fgets(tmp, 1024, stdin) == NULL) {
- exit(2);
- }
- q = strdup(tmp);
- } else if (!strcmp(str, "%env")) {
- if (getenv("UNIXPW") == NULL) {
- exit(2);
- }
- q = strdup(getenv("UNIXPW"));
- } else if (!strcmp(str, "%%") || !strcmp(str, "%")) {
- char *t, inp[1024];
- fprintf(stdout, "username: ");
- if(fgets(tmp, 128, stdin) == NULL) {
- exit(2);
- }
- strcpy(inp, tmp);
- t = strchr(inp, '\n');
- if (t) {
- *t = ':';
- } else {
- strcat(inp, ":");
-
- }
- fprintf(stdout, "password: ");
- /* test mode: no_external_cmds does not apply */
- system("stty -echo");
- if(fgets(tmp, 128, stdin) == NULL) {
- fprintf(stdout, "\n");
- system("stty echo");
- exit(2);
- }
- system("stty echo");
- fprintf(stdout, "\n");
- strcat(inp, tmp);
- q = strdup(inp);
- } else if (str[1] == '/' || str[1] == '.') {
- FILE *in = fopen(str+1, "r");
- if (in == NULL) {
- exit(2);
- }
- if(fgets(tmp, 1024, in) == NULL) {
- exit(2);
- }
- fclose(in);
- q = strdup(tmp);
- } else {
- q = strdup(str+1);
- }
- p = (char *) malloc(strlen(q) + 10);
- strcpy(p, q);
- if (strchr(p, '\n') == NULL) {
- strcat(p, "\n");
- }
- if ((q = strchr(p, ':')) == NULL) {
- exit(2);
- }
- *q = '\0';
- if (db) fprintf(stderr, "'%s' '%s'\n", p, q+1);
- if (unixpw_cmd) {
- if (cmd_verify(p, q+1)) {
- fprintf(stdout, "Y %s\n", p);
- exit(0);
- } else {
- fprintf(stdout, "N %s\n", p);
- exit(1);
- }
- } else if (unixpw_nis) {
- if (crypt_verify(p, q+1)) {
- fprintf(stdout, "Y %s\n", p);
- exit(0);
- } else {
- fprintf(stdout, "N %s\n", p);
- exit(1);
- }
- } else {
- char *ucmd = getenv("UNIXPW_CMD");
- if (su_verify(p, q+1, ucmd, NULL, NULL, 1)) {
- fprintf(stdout, "Y %s\n", p);
- exit(0);
- } else {
- fprintf(stdout, "N %s\n", p);
- exit(1);
- }
- }
- /* NOTREACHED */
- exit(2);
- }
- static void print_settings(int try_http, int bg, char *gui_str) {
- fprintf(stderr, "\n");
- fprintf(stderr, "Settings:\n");
- fprintf(stderr, " display: %s\n", use_dpy ? use_dpy
- : "null");
- #if SMALL_FOOTPRINT < 2
- fprintf(stderr, " authfile: %s\n", auth_file ? auth_file
- : "null");
- fprintf(stderr, " subwin: 0x%lx\n", subwin);
- fprintf(stderr, " -sid mode: %d\n", rootshift);
- fprintf(stderr, " clip: %s\n", clip_str ? clip_str
- : "null");
- fprintf(stderr, " flashcmap: %d\n", flash_cmap);
- fprintf(stderr, " shiftcmap: %d\n", shift_cmap);
- fprintf(stderr, " force_idx: %d\n", force_indexed_color);
- fprintf(stderr, " cmap8to24: %d\n", cmap8to24);
- fprintf(stderr, " 8to24_opts: %s\n", cmap8to24_str ? cmap8to24_str
- : "null");
- fprintf(stderr, " 24to32: %d\n", xform24to32);
- fprintf(stderr, " visual: %s\n", visual_str ? visual_str
- : "null");
- fprintf(stderr, " overlay: %d\n", overlay);
- fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor);
- fprintf(stderr, " scaling: %d %.4f %.4f\n", scaling, scale_fac_x, scale_fac_y);
- fprintf(stderr, " viewonly: %d\n", view_only);
- fprintf(stderr, " shared: %d\n", shared);
- fprintf(stderr, " conn_once: %d\n", connect_once);
- fprintf(stderr, " timeout: %d\n", first_conn_timeout);
- fprintf(stderr, " ping: %d\n", ping_interval);
- fprintf(stderr, " inetd: %d\n", inetd);
- fprintf(stderr, " tightfilexfer: %d\n", tightfilexfer);
- fprintf(stderr, " http: %d\n", try_http);
- fprintf(stderr, " connect: %s\n", client_connect
- ? client_connect : "null");
- fprintf(stderr, " connectfile %s\n", client_connect_file
- ? client_connect_file : "null");
- fprintf(stderr, " vnc_conn: %d\n", vnc_connect);
- fprintf(stderr, " allow: %s\n", allow_list ? allow_list
- : "null");
- fprintf(stderr, " input: %s\n", allowed_input_str
- ? allowed_input_str : "null");
- fprintf(stderr, " passfile: %s\n", passwdfile ? passwdfile
- : "null");
- fprintf(stderr, " unixpw: %d\n", unixpw);
- fprintf(stderr, " unixpw_lst: %s\n", unixpw_list ? unixpw_list:"null");
- fprintf(stderr, " ssl: %s\n", openssl_pem ? openssl_pem:"null");
- fprintf(stderr, " ssldir: %s\n", ssl_certs_dir ? ssl_certs_dir:"null");
- fprintf(stderr, " ssltimeout %d\n", ssl_timeout_secs);
- fprintf(stderr, " sslverify: %s\n", ssl_verify ? ssl_verify:"null");
- fprintf(stderr, " stunnel: %d\n", use_stunnel);
- fprintf(stderr, " accept: %s\n", accept_cmd ? accept_cmd
- : "null");
- fprintf(stderr, " accept: %s\n", afteraccept_cmd ? afteraccept_cmd
- : "null");
- fprintf(stderr, " gone: %s\n", gone_cmd ? gone_cmd
- : "null");
- fprintf(stderr, " users: %s\n", users_list ? users_list
- : "null");
- fprintf(stderr, " using_shm: %d\n", using_shm);
- fprintf(stderr, " flipbytes: %d\n", flip_byte_order);
- fprintf(stderr, " onetile: %d\n", single_copytile);
- fprintf(stderr, " solid: %s\n", solid_str
- ? solid_str : "null");
- fprintf(stderr, " blackout: %s\n", blackout_str
- ? blackout_str : "null");
- fprintf(stderr, " xinerama: %d\n", xinerama);
- fprintf(stderr, " xtrap: %d\n", xtrap_input);
- fprintf(stderr, " xrandr: %d\n", xrandr);
- fprintf(stderr, " xrandrmode: %s\n", xrandr_mode ? xrandr_mode
- : "null");
- fprintf(stderr, " padgeom: %s\n", pad_geometry
- ? pad_geometry : "null");
- fprintf(stderr, " logfile: %s\n", logfile ? logfile
- : "null");
- fprintf(stderr, " logappend: %d\n", logfile_append);
- fprintf(stderr, " flag: %s\n", flagfile ? flagfile
- : "null");
- fprintf(stderr, " rm_flag: %s\n", rm_flagfile ? rm_flagfile
- : "null");
- fprintf(stderr, " rc_file: \"%s\"\n", rc_rcfile ? rc_rcfile
- : "null");
- fprintf(stderr, " norc: %d\n", rc_norc);
- fprintf(stderr, " dbg: %d\n", crash_debug);
- fprintf(stderr, " bg: %d\n", bg);
- fprintf(stderr, " mod_tweak: %d\n", use_modifier_tweak);
- fprintf(stderr, " isolevel3: %d\n", use_iso_level3);
- fprintf(stderr, " xkb: %d\n", use_xkb_modtweak);
- fprintf(stderr, " skipkeys: %s\n",
- skip_keycodes ? skip_keycodes : "null");
- fprintf(stderr, " sloppykeys: %d\n", sloppy_keys);
- fprintf(stderr, " skip_dups: %d\n", skip_duplicate_key_events);
- fprintf(stderr, " addkeysyms: %d\n", add_keysyms);
- fprintf(stderr, " xkbcompat: %d\n", xkbcompat);
- fprintf(stderr, " clearmods: %d\n", clear_mods);
- fprintf(stderr, " remap: %s\n", remap_file ? remap_file
- : "null");
- fprintf(stderr, " norepeat: %d\n", no_autorepeat);
- fprintf(stderr, " norepeatcnt:%d\n", no_repeat_countdown);
- fprintf(stderr, " nofb: %d\n", nofb);
- fprintf(stderr, " watchbell: %d\n", watch_bell);
- fprintf(stderr, " watchsel: %d\n", watch_selection);
- fprintf(stderr, " watchprim: %d\n", watch_primary);
- fprintf(stderr, " seldir: %s\n", sel_direction ?
- sel_direction : "null");
- fprintf(stderr, " cursor: %d\n", show_cursor);
- fprintf(stderr, " multicurs: %d\n", show_multiple_cursors);
- fprintf(stderr, " curs_mode: %s\n", multiple_cursors_mode
- ? multiple_cursors_mode : "null");
- fprintf(stderr, " arrow: %d\n", alt_arrow);
- fprintf(stderr, " xfixes: %d\n", use_xfixes);
- fprintf(stderr, " alphacut: %d\n", alpha_threshold);
- fprintf(stderr, " alphafrac: %.2f\n", alpha_frac);
- fprintf(stderr, " alpharemove:%d\n", alpha_remove);
- fprintf(stderr, " alphablend: %d\n", alpha_blend);
- fprintf(stderr, " cursorshape:%d\n", cursor_shape_updates);
- fprintf(stderr, " cursorpos: %d\n", cursor_pos_updates);
- fprintf(stderr, " xwarpptr: %d\n", use_xwarppointer);
- fprintf(stderr, " alwaysinj: %d\n", always_inject);
- fprintf(stderr, " buttonmap: %s\n", pointer_remap
- ? pointer_remap : "null");
- fprintf(stderr, " dragging: %d\n", show_dragging);
- fprintf(stderr, " ncache: %d\n", ncache);
- fprintf(stderr, " wireframe: %s\n", wireframe_str ?
- wireframe_str : WIREFRAME_PARMS);
- fprintf(stderr, " wirecopy: %s\n", wireframe_copyrect ?
- wireframe_copyrect : wireframe_copyrect_default);
- fprintf(stderr, " scrollcopy: %s\n", scroll_copyrect ?
- scroll_copyrect : scroll_copyrect_default);
- fprintf(stderr, " scr_area: %d\n", scrollcopyrect_min_area);
- fprintf(stderr, " scr_skip: %s\n", scroll_skip_str ?
- scroll_skip_str : scroll_skip_str0);
- fprintf(stderr, " scr_inc: %s\n", scroll_good_str ?
- scroll_good_str : scroll_good_str0);
- fprintf(stderr, " scr_keys: %s\n", scroll_key_list_str ?
- scroll_key_list_str : "null");
- fprintf(stderr, " scr_term: %s\n", scroll_term_str ?
- scroll_term_str : "null");
- fprintf(stderr, " scr_keyrep: %s\n", max_keyrepeat_str ?
- max_keyrepeat_str : "null");
- fprintf(stderr, " scr_parms: %s\n", scroll_copyrect_str ?
- scroll_copyrect_str : SCROLL_COPYRECT_PARMS);
- fprintf(stderr, " fixscreen: %s\n", screen_fixup_str ?
- screen_fixup_str : "null");
- fprintf(stderr, " noxrecord: %d\n", noxrecord);
- fprintf(stderr, " grabbuster: %d\n", grab_buster);
- fprintf(stderr, " ptr_mode: %d\n", pointer_mode);
- fprintf(stderr, " inputskip: %d\n", ui_skip);
- fprintf(stderr, " speeds: %s\n", speeds_str
- ? speeds_str : "null");
- fprintf(stderr, " wmdt: %s\n", wmdt_str
- ? wmdt_str : "null");
- fprintf(stderr, " debug_ptr: %d\n", debug_pointer);
- fprintf(stderr, " debug_key: %d\n", debug_keyboard);
- fprintf(stderr, " defer: %d\n", defer_update);
- fprintf(stderr, " waitms: %d\n", waitms);
- fprintf(stderr, " wait_ui: %.2f\n", wait_ui);
- fprintf(stderr, " nowait_bog: %d\n", !wait_bog);
- fprintf(stderr, " slow_fb: %.2f\n", slow_fb);
- fprintf(stderr, " xrefresh: %.2f\n", xrefresh);
- fprintf(stderr, " readtimeout: %d\n", rfbMaxClientWait/1000);
- fprintf(stderr, " take_naps: %d\n", take_naps);
- fprintf(stderr, " sb: %d\n", screen_blank);
- fprintf(stderr, " fbpm: %d\n", !watch_fbpm);
- fprintf(stderr, " dpms: %d\n", !watch_dpms);
- fprintf(stderr, " xdamage: %d\n", use_xdamage);
- fprintf(stderr, " xd_area: %d\n", xdamage_max_area);
- fprintf(stderr, " xd_mem: %.3f\n", xdamage_memory);
- fprintf(stderr, " sigpipe: %s\n", sigpipe
- ? sigpipe : "null");
- fprintf(stderr, " threads: %d\n", use_threads);
- fprintf(stderr, " fs_frac: %.2f\n", fs_frac);
- fprintf(stderr, " gaps_fill: %d\n", gaps_fill);
- fprintf(stderr, " grow_fill: %d\n", grow_fill);
- fprintf(stderr, " tile_fuzz: %d\n", tile_fuzz);
- fprintf(stderr, " snapfb: %d\n", use_snapfb);
- fprintf(stderr, " rawfb: %s\n", raw_fb_str
- ? raw_fb_str : "null");
- fprintf(stderr, " pipeinput: %s\n", pipeinput_str
- ? pipeinput_str : "null");
- fprintf(stderr, " gui: %d\n", launch_gui);
- fprintf(stderr, " gui_mode: %s\n", gui_str
- ? gui_str : "null");
- fprintf(stderr, " noremote: %d\n", !accept_remote_cmds);
- fprintf(stderr, " unsafe: %d\n", !safe_remote_only);
- fprintf(stderr, " privremote: %d\n", priv_remote);
- fprintf(stderr, " safer: %d\n", more_safe);
- fprintf(stderr, " nocmds: %d\n", no_external_cmds);
- fprintf(stderr, " deny_all: %d\n", deny_all);
- fprintf(stderr, " pid: %d\n", getpid());
- fprintf(stderr, "\n");
- #endif
- }
- static void check_loop_mode(int argc, char* argv[], int force) {
- int i;
- int loop_mode = 0, loop_sleep = 2000, loop_max = 0;
- if (force) {
- loop_mode = 1;
- }
- for (i=1; i < argc; i++) {
- char *p = argv[i];
- if (strstr(p, "--") == p) {
- p++;
- }
- if (strstr(p, "-loop") == p) {
- char *q;
- loop_mode = 1;
- if ((q = strchr(p, ',')) != NULL) {
- loop_max = atoi(q+1);
- *q = '\0';
- }
- if (strstr(p, "-loopbg") == p) {
- set_env("X11VNC_LOOP_MODE_BG", "1");
- loop_sleep = 500;
- }
-
- q = strpbrk(p, "0123456789");
- if (q) {
- loop_sleep = atoi(q);
- if (loop_sleep <= 0) {
- loop_sleep = 20;
- }
- }
- }
- }
- if (loop_mode && getenv("X11VNC_LOOP_MODE") == NULL) {
- #if LIBVNCSERVER_HAVE_FORK
- char **argv2;
- int k, i = 1;
- set_env("X11VNC_LOOP_MODE", "1");
- argv2 = (char **) malloc((argc+1)*sizeof(char *));
- for (k=0; k < argc+1; k++) {
- argv2[k] = NULL;
- if (k < argc) {
- argv2[k] = argv[k];
- }
- }
- while (1) {
- int status;
- pid_t p;
- fprintf(stderr, "\n --- x11vnc loop: %d ---\n\n", i++);
- fflush(stderr);
- usleep(500 * 1000);
- if ((p = fork()) > 0) {
- fprintf(stderr, " --- x11vnc loop: waiting "
- "for: %d\n\n", p);
- wait(&status);
- } else if (p == -1) {
- fprintf(stderr, "could not fork\n");
- perror("fork");
- exit(1);
- } else {
- /* loop mode: no_external_cmds does not apply */
- execvp(argv[0], argv2);
- exit(1);
- }
- if (loop_max > 0 && i > loop_max) {
- fprintf(stderr, "\n --- x11vnc loop: did %d"
- " done. ---\n\n", loop_max);
- break;
- }
-
- fprintf(stderr, "\n --- x11vnc loop: sleeping %d ms "
- "---\n\n", loop_sleep);
- usleep(loop_sleep * 1000);
- }
- exit(0);
- #else
- fprintf(stderr, "fork unavailable, cannot do -loop mode\n");
- exit(1);
- #endif
- }
- }
- extern int appshare_main(int argc, char* argv[]);
- static void check_appshare_mode(int argc, char* argv[]) {
- #ifndef WIN32
- int i;
- for (i=1; i < argc; i++) {
- char *p = argv[i];
- if (strstr(p, "--") == p) {
- p++;
- }
- if (strstr(p, "-appshare") == p) {
- appshare_main(argc, argv);
- exit(0);
- }
- }
- #endif
- }
- static void store_homedir_passwd(char *file) {
- #ifndef WIN32
- char str1[32], str2[32], *p, *h, *f;
- struct stat sbuf;
- str1[0] = '\0';
- str2[0] = '\0';
- /* storepasswd */
- if (no_external_cmds || !cmd_ok("storepasswd")) {
- fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
- exit(1);
- }
- fprintf(stderr, "Enter VNC password: ");
- system("stty -echo");
- if (fgets(str1, 32, stdin) == NULL) {
- perror("fgets");
- system("stty echo");
- exit(1);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "Verify password: ");
- if (fgets(str2, 32, stdin) == NULL) {
- perror("fgets");
- system("stty echo");
- exit(1);
- }
- fprintf(stderr, "\n");
- system("stty echo");
- if ((p = strchr(str1, '\n')) != NULL) {
- *p = '\0';
- }
- if ((p = strchr(str2, '\n')) != NULL) {
- *p = '\0';
- }
- if (strcmp(str1, str2)) {
- fprintf(stderr, "** passwords differ.\n");
- exit(1);
- }
- if (str1[0] == '\0') {
- fprintf(stderr, "** no password supplied.\n");
- exit(1);
- }
- if (file != NULL) {
- f = file;
- } else {
-
- h = getenv("HOME");
- if (! h) {
- fprintf(stderr, "** $HOME not set.\n");
- exit(1);
- }
- f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1);
- sprintf(f, "%s/.vnc", h);
- if (stat(f, &sbuf) != 0) {
- if (mkdir(f, 0755) != 0) {
- fprintf(stderr, "** could not create directory %s\n", f);
- perror("mkdir");
- exit(1);
- }
- } else if (! S_ISDIR(sbuf.st_mode)) {
- fprintf(stderr, "** not a directory %s\n", f);
- exit(1);
- }
- sprintf(f, "%s/.vnc/passwd", h);
- }
- fprintf(stderr, "Write password to %s? [y]/n ", f);
- if (fgets(str2, 32, stdin) == NULL) {
- perror("fgets");
- exit(1);
- }
- if (str2[0] == 'n' || str2[0] == 'N') {
- fprintf(stderr, "not creating password.\n");
- exit(1);
- }
- if (rfbEncryptAndStorePasswd(str1, f) != 0) {
- fprintf(stderr, "** error creating password: %s\n", f);
- perror("storepasswd");
- exit(1);
- }
- if (stat(f, &sbuf) != 0) {
- fprintf(stderr, "** error creating password: %s\n", f);
- perror("stat");
- exit(1);
- }
- fprintf(stdout, "Password written to: %s\n", f);
- exit(0);
- #endif
- }
- void ncache_beta_tester_message(void) {
- char msg[] =
- "\n"
- "******************************************************************************\n"
- "\n"
- "Hello! Exciting News!!\n"
- "\n"
- "You have been selected at random to beta-test the x11vnc '-ncache' VNC\n"
- "client-side pixel caching feature!\n"
- "\n"
- "This scheme stores pixel data offscreen on the VNC viewer side for faster\n"
- "retrieval. It should work with any VNC viewer.\n"
- "\n"
- "This method requires much testing and so we hope you will try it out and\n"
- "perhaps even report back your observations. However, if you do not want\n"
- "to test or use the feature, run x11vnc like this:\n"
- "\n"
- " x11vnc -noncache ...\n"
- "\n"
- "Your current setting is: -ncache %d\n"
- "\n"
- "The feature needs additional testing because we want to have x11vnc\n"
- "performance enhancements on by default. Otherwise, only a relative few\n"
- "would notice and use the -ncache option (e.g. the wireframe and scroll\n"
- "detection features are on by default). A couple things to note:\n"
- "\n"
- " 1) It uses a large amount of RAM (on both viewer and server sides)\n"
- "\n"
- " 2) You can actually see the cached pixel data if you scroll down\n"
- " to it in your viewer; adjust your viewer's size to hide it.\n"
- "\n"
- "More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching\n"
- "\n"
- "waiting for connections:\n"
- ;
- char msg2[] =
- "\n"
- "******************************************************************************\n"
- "Have you tried the x11vnc '-ncache' VNC client-side pixel caching feature yet?\n"
- "\n"
- "The scheme stores pixel data offscreen on the VNC viewer side for faster\n"
- "retrieval. It should work with any VNC viewer. Try it by running:\n"
- "\n"
- " x11vnc -ncache 10 ...\n"
- "\n"
- "One can also add -ncache_cr for smooth 'copyrect' window motion.\n"
- "More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching\n"
- "\n"
- ;
- if (raw_fb_str && !macosx_console) {
- return;
- }
- if (quiet) {
- return;
- }
- if (remote_direct) {
- return;
- }
- if (nofb) {
- return;
- }
- #ifdef NO_NCACHE
- return;
- #endif
- if (ncache == 0) {
- fprintf(stderr, "%s", msg2);
- ncache0 = ncache = 0;
- } else {
- fprintf(stderr, msg, ncache);
- }
- }
- #define SHOW_NO_PASSWORD_WARNING \
- (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
- && !query_cmd && !remote_cmd && !unixpw && !got_gui_pw \
- && ! ssl_verify && !inetd && !terminal_services_daemon)
- static void do_sleepin(char *sleep) {
- int n1, n2, nt;
- double f1, f2, ft;
- if (strchr(sleep, '-')) {
- double s = atof(strchr(sleep, '-')+1);
- if (sscanf(sleep, "%d-%d", &n1, &n2) == 2) {
- if (n1 > n2) {
- nt = n1;
- n1 = n2;
- n2 = nt;
- }
- s = n1 + rfac() * (n2 - n1);
- } else if (sscanf(sleep, "%lf-%lf", &f1, &f2) == 2) {
- if (f1 > f2) {
- ft = f1;
- f1 = f2;
- f2 = ft;
- }
- s = f1 + rfac() * (f2 - f1);
- }
- if (getenv("DEBUG_SLEEPIN")) fprintf(stderr, "sleepin: %f secs\n", s);
- usleep( (int) (1000*1000*s) );
- } else {
- n1 = atoi(sleep);
- if (getenv("DEBUG_SLEEPIN")) fprintf(stderr, "sleepin: %d secs\n", n1);
- if (n1 > 0) {
- usleep(1000*1000*n1);
- }
- }
- }
- static void check_guess_auth_file(void) {
- if (!strcasecmp(auth_file, "guess")) {
- char line[4096], *cmd, *q, *disp = use_dpy ? use_dpy: "";
- FILE *p;
- int n;
- if (!program_name) {
- rfbLog("-auth guess: no program_name found.\n");
- clean_up_exit(1);
- …
Large files files are truncated, but you can click here to view the full file