diff options
Diffstat (limited to 'x11vnc/x11vnc.c')
-rw-r--r-- | x11vnc/x11vnc.c | 258 |
1 files changed, 227 insertions, 31 deletions
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 27148fc..f10b683 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -1,7 +1,7 @@ /* * x11vnc.c: a VNC server for X displays. * - * Copyright (c) 2002-2004 Karl J. Runge <runge@karlrunge.com> + * Copyright (c) 2002-2005 Karl J. Runge <runge@karlrunge.com> * All rights reserved. * * This is free software; you can redistribute it and/or modify @@ -27,17 +27,22 @@ * krfb, the KDE desktopsharing project (Tim Jansen) * * 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 may not be readily available and needs - * to be installed, it may be found at ftp://ftp.uu.net/graphics/jpeg/). - * To increase portability it is written in plain C. + * 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. * - * The next goal is to improve performance and interactive response. + * Another goal is to improve performance and interactive response. * The algorithm of x0rfbserver was used as a base. Additional heuristics * are also applied (currently there are a bit too many of these...) * + * Another goal is to add many features that enable and incourage creative + * Ausage and application of the tool. pologies for the large number + * Aof options! + * * To build: * * Obtain the libvncserver package (http://libvncserver.sourceforge.net). @@ -53,12 +58,13 @@ * Known shortcomings: * * The screen updates are good, but of course not perfect since the X - * display must be continuously polled and read for changes (as opposed to - * receiving a change callback from the X server, if that were generally - * possible... (Update: this seems to be 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. + * 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 seems to be 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. @@ -73,7 +79,10 @@ * the -cursor option. Further, if -cursorX or -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) + * 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. * * Windows using visuals other than the default X visual may have * their colors messed up. When using 8bpp indexed color, the colormap @@ -83,9 +92,16 @@ * 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. SaveUnders - * menus, popups, etc will not be seen. + * 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 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, @@ -113,15 +129,23 @@ /* * if you are inserting this file, x11vnc.c into an old CVS tree you - * may need to set OLD_TREE to 1. + * may need to set OLD_TREE to 1. See below for LibVNCServer 0.7 tips. */ + #define OLD_TREE 0 #if OLD_TREE /* - * if have a very old tree and get errors these may be needed as well: + * if you have a very old tree (LibVNCServer 0.6) and get errors these may + * be need to be uncommented. LibVNCServer <= 0.5 is no longer supported. + * note the maxRectsPerUpdate below is a hack that may break some usage. #define oldCursorX cursorX #define oldCursorY cursorY +#define thisHost rfbThisHost +#define framebufferUpdateMessagesSent rfbFramebufferUpdateMessagesSent +#define bytesSent rfbBytesSent +#define rawBytesEquivalent rfbRawBytesEquivalent +#define progressiveSliceHeight maxRectsPerUpdate */ /* @@ -189,8 +213,29 @@ #else #define RFBUNDRAWCURSOR(s) #endif +/* + * To get a clean build in a LibVNCServer 0.7 source tree no need for + * OLD_TREE, you just need to either download the forgotten tkx11vnc.h + * file or run: + * + * echo 'char gui_code[] = "";' > tkx11vnc.h + * + * (this disables the gui) and uncomment this line: +#define rfbSetCursor(a, b) rfbSetCursor((a), (b), FALSE) + */ + +/* + * To get a clean build on LibVNCServer 0.7.1 no need for OLD_TREE, + * just uncomment this line (note the maxRectsPerUpdate below is a hack + * that may break some usage): + * +#define listenInterface maxRectsPerUpdate + */ #if LIBVNCSERVER_HAVE_XSHM +# if defined(__hpux) && defined(__ia64) /* something weird on hp/itanic */ +# undef _INCLUDE_HPUX_SOURCE +# endif #include <sys/ipc.h> #include <sys/shm.h> #include <X11/extensions/XShm.h> @@ -290,7 +335,7 @@ static int xdamage_base_event_type; #endif /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.7.1 lastmod: 2005-02-23"; +char lastmod[] = "0.7.2pre lastmod: 2005-03-04"; /* X display info */ @@ -579,6 +624,7 @@ int safe_remote_only = 0; /* -safer, -unsafe */ int started_as_root = 0; char *users_list = NULL; /* -users */ char *allow_list = NULL; /* for -allow and -localhost */ +char *listen_str = NULL; char *allow_once = NULL; /* one time -allow */ char *accept_cmd = NULL; /* for -accept */ char *gone_cmd = NULL; /* for -gone */ @@ -1688,7 +1734,7 @@ typedef unsigned int in_addr_t; in_addr_t iaddr; iaddr = inet_addr(ip); - if (iaddr == INADDR_NONE) { + if (iaddr == htonl(INADDR_NONE)) { return strdup("unknown"); } @@ -7140,7 +7186,7 @@ void reset_httpport(int old, int new) { close(screen->httpListenSock); } rfbLog("reset_httpport: setting httpport %d -> %d.\n", - old, hp); + old == -1 ? hp : old, hp); rfbHttpInitSockets(screen); } } @@ -7171,7 +7217,7 @@ void reset_rfbport(int old, int new) { } rfbLog("reset_rfbport: setting rfbport %d -> %d.\n", - old, rp); + old == -1 ? rp : old, rp); rfbInitSockets(screen); maxfd = screen->maxFd; @@ -7731,7 +7777,9 @@ char *process_remote_cmd(char *cmd, int stringonly) { char *before, *old; if (query) { int state = 0; - if (allow_list && !strcmp(allow_list, "127.0.0.1")) { + char *s = allow_list; + if (s && (!strcmp(s, "127.0.0.1") || + !strcmp(s, "localhost"))) { state = 1; } snprintf(buf, bufn, "ans=%s:%d", p, state); @@ -7753,11 +7801,26 @@ char *process_remote_cmd(char *cmd, int stringonly) { } if (old) free(old); free(before); + + if (listen_str) { + free(listen_str); + } + listen_str = strdup("localhost"); + + screen->listenInterface = htonl(INADDR_LOOPBACK); + rfbLog("listening on loopback network only.\n"); + rfbLog("allow list is: '%s'\n", NONUL(allow_list)); + reset_rfbport(-1, screen->port); + if (screen->httpListenSock > -1) { + reset_httpport(-1, screen->httpPort); + } } else if (!strcmp(p, "nolocalhost")) { char *before, *old; if (query) { int state = 0; - if (allow_list && !strcmp(allow_list, "127.0.0.1")) { + char *s = allow_list; + if (s && (!strcmp(s, "127.0.0.1") || + !strcmp(s, "localhost"))) { state = 1; } snprintf(buf, bufn, "ans=%s:%d", p, !state); @@ -7780,6 +7843,106 @@ char *process_remote_cmd(char *cmd, int stringonly) { if (old) free(old); free(before); + if (listen_str) { + free(listen_str); + } + listen_str = NULL; + + screen->listenInterface = htonl(INADDR_ANY); + rfbLog("listening on ALL network interfaces.\n"); + rfbLog("allow list is: '%s'\n", NONUL(allow_list)); + reset_rfbport(-1, screen->port); + if (screen->httpListenSock > -1) { + reset_httpport(-1, screen->httpPort); + } + + } else if (strstr(p, "listen") == p) { + char *before; + int ok, mod = 0; + + COLON_CHECK("listen:") + if (query) { + snprintf(buf, bufn, "ans=%s%s%s", p, co, + NONUL(listen_str)); + goto qry; + } + if (listen_str) { + before = strdup(listen_str); + } else { + before = strdup(""); + } + p += strlen("listen:"); + + listen_str = strdup(p); + + if (strcmp(before, listen_str)) { + rfbLog("process_remote_cmd: modified listen_str:\n"); + rfbLog(" from: \"%s\"\n", before); + rfbLog(" to: \"%s\"\n", listen_str); + mod = 1; + } + + ok = 1; + if (listen_str == NULL || *listen_str == '\0' || + !strcmp(listen_str, "any")) { + screen->listenInterface = htonl(INADDR_ANY); + } else if (!strcmp(listen_str, "localhost")) { + screen->listenInterface = htonl(INADDR_LOOPBACK); + } else { + struct hostent *hp; + in_addr_t iface = inet_addr(listen_str); + if (iface == htonl(INADDR_NONE)) { + if (!(hp = gethostbyname(listen_str))) { + ok = 0; + } else { + iface = *(unsigned long *)hp->h_addr; + } + } + if (ok) { + screen->listenInterface = iface; + } + } + + if (ok && mod) { + int is_loopback = 0; + in_addr_t iface = screen->listenInterface; + + if (allow_list) { + if (!strcmp(allow_list, "127.0.0.1") || + !strcmp(allow_list, "localhost")) { + is_loopback = 1; + } + } + if (iface != htonl(INADDR_LOOPBACK)) { + if (is_loopback) { + rfbLog("re-setting -allow list to all " + "hosts for non-loopback listening.\n"); + free(allow_list); + allow_list = NULL; + } + } else { + if (!is_loopback) { + if (allow_list) { + free(allow_list); + } + rfbLog("setting -allow list to 127.0.0.1\n"); + allow_list = strdup("127.0.0.1"); + } + } + } + if (ok) { + rfbLog("allow list is: '%s'\n", NONUL(allow_list)); + reset_rfbport(-1, screen->port); + if (screen->httpListenSock > -1) { + reset_httpport(-1, screen->httpPort); + } + free(before); + } else { + rfbLog("bad listen string: %s\n", listen_str); + free(listen_str); + listen_str = before; + } + } else if (strstr(p, "accept") == p) { COLON_CHECK("accept:") if (query) { @@ -16079,7 +16242,7 @@ void initialize_speeds(void) { s = strdup("6,4,200"); } else if (!strcmp(speeds_str, "dsl")) { s = strdup("6,100,50"); - } else if (!strcmp(speeds_str, "modem")) { + } else if (!strcmp(speeds_str, "lan")) { s = strdup("6,5000,1"); } else { s = strdup(speeds_str); @@ -16556,7 +16719,19 @@ static void print_help(int mode) { " file containing addresses or prefixes that is re-read\n" " each time a new client connects. Lines can be commented\n" " out with the \"#\" character in the usual way.\n" -"-localhost Same as -allow 127.0.0.1\n" +"-localhost Same as \"-allow 127.0.0.1\".\n" +"\n" +" Note: if you want to restrict which network interface\n" +" x11vnc listens on, see the -listen option below.\n" +" E.g. \"-listen localhost\" or \"-listen 192.168.3.21\".\n" +" As a special case, the option \"-localhost\" implies\n" +" \"-listen localhost\".\n" +"\n" +" For non-localhost -listen usage, if you use the remote\n" +" control mechanism (-R) to change the -listen interface\n" +" you may need to manually adjust the -allow list (and\n" +" vice versa) to avoid situations where no connections\n" +" (or too many) are allowed.\n" "\n" "-input string Fine tuning of allowed user input. If \"string\" does\n" " not contain a comma \",\" the tuning applies only to\n" @@ -16708,7 +16883,7 @@ static void print_help(int mode) { " database as well. So it \"lurks\" waiting for anyone\n" " to log into an X session and then connects to it.\n" " Specify a list of users after the = to limit which\n" -" users will be tried. To enable a difference searching\n" +" users will be tried. To enable a different searching\n" " mode, if the first user in the list is something like\n" " \":0\" or \":0-2\" that indicates a range of DISPLAY\n" " numbers that will be tried (regardless of whether\n" @@ -17286,6 +17461,7 @@ static void print_help(int mode) { " use \"-host\" to delete a single host\n" " localhost enable -localhost mode\n" " nolocalhost disable -localhost mode\n" +" listen:str set -listen to str, empty to disable.\n" " input:str set -input to \"str\", empty to disable.\n" " client_input:str set the K, M, B -input on a per-client\n" " basis. select which client as for\n" @@ -17456,7 +17632,7 @@ static void print_help(int mode) { " overlay_nocursor visual scale viewonly noviewonly\n" " shared noshared forever noforever once timeout deny\n" " lock nodeny unlock connect allowonce allow localhost\n" -" nolocalhost accept gone shm noshm flipbyteorder\n" +" nolocalhost listen accept gone shm noshm flipbyteorder\n" " noflipbyteorder onetile noonetile solid_color solid\n" " nosolid blackout xinerama noxinerama xrandr noxrandr\n" " xrandr_mode padgeom quiet q noquiet modtweak nomodtweak\n" @@ -17606,6 +17782,11 @@ void set_vnc_desktop_name(void) { if (screen->port) { char *host = this_host(); int lport = screen->port; + char *iface = listen_str; + + if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) { + host = iface; + } if (host != NULL) { /* note that vncviewer special cases 5900-5999 */ if (inetd) { @@ -18159,7 +18340,7 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) { print_help(1); } else if (!strcmp(arg, "-V") || !strcmp(arg, "-version")) { - fprintf(stderr, "x11vnc: %s\n", lastmod); + fprintf(stdout, "x11vnc: %s\n", lastmod); exit(0); } else if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) { quiet = 1; @@ -18377,6 +18558,9 @@ int main(int argc, char* argv[]) { if (!strcmp(arg, "-nevershared")) { got_nevershared = 1; } + if (!strcmp(arg, "-listen") && i < argc-1) { + listen_str = strdup(argv[i+1]); + } /* otherwise copy it for libvncserver use below. */ if (argc_vnc < 100) { argv_vnc[argc_vnc++] = strdup(arg); @@ -18615,6 +18799,18 @@ int main(int argc, char* argv[]) { } } + /* tie together cases of -localhost vs. -listen localhost */ + if (! listen_str) { + if (allow_list && !strcmp(allow_list, "127.0.0.1")) { + listen_str = strdup("localhost"); + argv_vnc[argc_vnc++] = strdup("-listen"); + argv_vnc[argc_vnc++] = strdup(listen_str); + } + } else if (!strcmp(listen_str, "localhost") || + !strcmp(listen_str, "127.0.0.1")) { + allow_list = strdup("127.0.0.1"); + } + if (! quiet) { fprintf(stderr, "\n"); fprintf(stderr, "Settings:\n"); |