2
* x11vnc: a VNC server for X displays.
4
* Copyright (c) 2002-2007 Karl J. Runge <runge@karlrunge.com>
7
* This is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; version 2 of the License.
11
* This software is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this software; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22
* This program is based on the following programs:
24
* the originial x11vnc.c in libvncserver (Johannes E. Schindelin)
25
* x0rfbserver, the original native X vnc server (Jens Wagner)
26
* krfb, the KDE desktopsharing project (Tim Jansen)
28
* The primary goal of this program is to create a portable and simple
29
* command-line server utility that allows a VNC viewer to connect
30
* to an actual X display (as the above do). The only non-standard
31
* dependency of this program is the static library libvncserver.a.
32
* Although in some environments libjpeg.so or libz.so may not be
33
* readily available and needs to be installed, they may be found
34
* at ftp://ftp.uu.net/graphics/jpeg/ and http://www.gzip.org/zlib/,
35
* respectively. To increase portability it is written in plain C.
37
* Another goal is to improve performance and interactive response.
38
* The algorithm of x0rfbserver was used as a base. Many additional
39
* heuristics are also applied.
41
* Another goal is to add many features that enable and incourage creative
42
* usage and application of the tool. Apologies for the large number
47
* Obtain the libvncserver package (http://libvncserver.sourceforge.net).
48
* As of 12/2002 this version of x11vnc.c is contained in the libvncserver
49
* CVS tree and released in version 0.5.
51
* gcc should be used on all platforms. To build a threaded version put
52
* "-D_REENTRANT -DX11VNC_THREADED" in the environment variable CFLAGS
53
* or CPPFLAGS (e.g. before running the libvncserver configure). The
54
* threaded mode is a bit more responsive, but can be unstable (e.g.
55
* if more than one client the same tight or zrle encoding).
59
* The screen updates are good, but of course not perfect since the X
60
* display must be continuously polled and read for changes and this is
61
* slow for most hardware. This can be contrasted with receiving a change
62
* callback from the X server, if that were generally possible... (UPDATE:
63
* this is handled now with the X DAMAGE extension, but unfortunately
64
* that doesn't seem to address the slow read from the video h/w). So,
65
* e.g., opaque moves and similar window activity can be very painful;
66
* one has to modify one's behavior a bit.
68
* General audio at the remote display is lost unless one separately
69
* sets up some audio side-channel such as esd.
71
* It does not appear possible to query the X server for the current
72
* cursor shape. We can use XTest to compare cursor to current window's
73
* cursor, but we cannot extract what the cursor is... (UPDATE: we now
74
* use XFIXES extension for this. Also on Solaris and IRIX Overlay
75
* extensions exists that allow drawing the mouse into the framebuffer)
77
* The current *position* of the remote X mouse pointer is shown with
78
* the -cursor option. Further, if -cursor X is used, a trick
79
* is done to at least show the root window cursor vs non-root cursor.
80
* (perhaps some heuristic can be done to further distinguish cases...,
81
* currently "-cursor some" is a first hack at this)
83
* Under XFIXES mode for showing the cursor shape, the cursor may be
84
* poorly approximated if it has transparency (alpha channel).
86
* Windows using visuals other than the default X visual may have
87
* their colors messed up. When using 8bpp indexed color, the colormap
88
* is attempted to be followed, but may become out of date. Use the
89
* -flashcmap option to have colormap flashing as the pointer moves
90
* windows with private colormaps (slow). Displays with mixed depth 8 and
91
* 24 visuals will incorrectly display windows using the non-default one.
92
* On Sun and Sgi hardware we can to work around this with -overlay.
94
* Feature -id <windowid> can be picky: it can crash for things like
95
* the window not sufficiently mapped into server memory, etc (UPDATE:
96
* we now use the -xrandr mechanisms to trap errors more robustly for
97
* this mode). SaveUnders menus, popups, etc will not be seen.
99
* Under some situations the keysym unmapping is not correct, especially
100
* if the two keyboards correspond to different languages. The -modtweak
101
* option is the default and corrects most problems. One can use the
102
* -xkb option to try to use the XKEYBOARD extension to clear up any
103
* remaining problems.
105
* Occasionally, a few tile updates can be missed leaving a patch of
106
* color that needs to be refreshed. This may only be when threaded,
107
* which is no longer the default.
109
* There seems to be a serious bug with simultaneous clients when
110
* threaded, currently the only workaround in this case is -nothreads
111
* (which is now the default).
119
#include "xwrappers.h"
123
#include "xinerama.h"
125
#include "xkb_bell.h"
126
#include "win_utils.h"
133
#include "keyboard.h"
136
#include "userinput.h"
138
#include "connections.h"
143
#include "sslhelper.h"
144
#include "selection.h"
149
* main routine for the x11vnc program
152
static void check_cursor_changes(void);
153
static void record_last_fb_update(void);
154
static int choose_delay(double dt);
155
static void watch_loop(void);
156
static int limit_shm(void);
157
static void check_rcfile(int argc, char **argv);
158
static void immediate_switch_user(int argc, char* argv[]);
159
static void print_settings(int try_http, int bg, char *gui_str);
160
static void check_loop_mode(int argc, char* argv[], int force);
163
static void check_cursor_changes(void) {
164
static double last_push = 0.0;
166
if (unixpw_in_progress) return;
168
cursor_changes += check_x11_pointer();
170
if (cursor_changes) {
171
double tm, max_push = 0.125, multi_push = 0.01, wait = 0.02;
172
int cursor_shape, dopush = 0, link, latency, netrate;
174
if (! all_clients_initialized()) {
179
if (0) cursor_shape = cursor_shape_updates_clients(screen);
182
link = link_rate(&latency, &netrate);
183
if (link == LR_DIALUP) {
186
} else if (link == LR_BROADBAND) {
189
} else if (link == LR_LAN) {
191
} else if (latency < 5 && netrate > 200) {
195
if (tm > last_push + max_push) {
197
} else if (cursor_changes > 1 && tm > last_push + multi_push) {
202
mark_rect_as_modified(0, 0, 1, 1, 1);
203
fb_push_wait(wait, FB_MOD);
212
static void record_last_fb_update(void) {
213
static int rbs0 = -1;
214
static time_t last_call = 0;
215
time_t now = time(NULL);
217
rfbClientIteratorPtr iter;
220
if (last_fb_bytes_sent == 0) {
221
last_fb_bytes_sent = now;
225
if (now <= last_call + 1) {
226
/* check every second or so */
230
if (unixpw_in_progress) return;
238
iter = rfbGetClientIterator(screen);
239
while( (cl = rfbClientIteratorNext(iter)) ) {
241
rbs += cl->rawBytesEquivalent;
243
rbs += rfbStatGetSentBytesIfRaw(cl);
246
rfbReleaseClientIterator(iter);
250
if (debug_tiles > 1) {
251
printf("record_last_fb_update: %d %d\n",
252
(int) now, (int) last_fb_bytes_sent);
254
last_fb_bytes_sent = now;
258
static int choose_delay(double dt) {
259
static double t0 = 0.0, t1 = 0.0, t2 = 0.0, now;
260
static int x0, y0, x1, y1, x2, y2, first = 1;
261
int dx0, dy0, dx1, dy1, dm, i, msec = waitms;
262
double cut1 = 0.15, cut2 = 0.075, cut3 = 0.25;
263
double bogdown_time = 0.25, bave = 0.0;
264
int bogdown = 1, bcnt = 0;
265
int ndt = 8, nave = 3;
268
static double dts[8];
278
for(i=0; i<ndt; i++) {
287
* first check for bogdown, e.g. lots of activity, scrolling text
288
* from command output, etc.
296
} else if (button_mask || now < last_keyboard_time + 2*bogdown_time) {
298
* let scrolls & keyboard input through the normal way
299
* otherwise, it will likely just annoy them.
303
} else if (dt > 0.0) {
305
* inspect recent dt's:
309
for (i = ndt - (nave - 1); i < ndt; i++) {
312
if (dts[i] < bogdown_time) {
320
if (dt < bogdown_time) {
326
/* shift for next time */
327
for (i = 0; i < ndt-1; i++) {
332
if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnowx());
335
/* DAMAGE can queue ~1000 rectangles for a scroll */
336
clear_xdamage_mark_region(NULL, 0);
338
msec = (int) (1000 * 1.75 * bave);
339
if (dts[ndt - nave - 1] > 0.75 * bave) {
341
set_xdamage_mark(0, 0, dpy_x, dpy_y);
349
db = (db || debug_tiles);
350
if (db) fprintf(stderr, "bogg[%d] %.3f %.3f %.3f %.3f\n",
351
msec, dts[ndt-4], dts[ndt-3], dts[ndt-2], dts[ndt-1]);
355
/* next check for pointer motion, keystrokes, to speed up */
370
if ((dx0 || dy0) && (dx1 || dy1)) {
371
if (t2 < t0 + cut1 || t2 < t1 + cut2 || dm > 20) {
372
fac = wait_ui * 1.25;
374
} else if ((dx1 || dy1) && dm > 40) {
378
if (fac == 1 && t2 < last_keyboard_time + cut3) {
381
msec = (int) ((double) waitms / fac);
397
static int tsdo_timeout_flag;
399
static void tsdo_timeout (int sig) {
400
tsdo_timeout_flag = 1;
405
static pid_t ts_tasks[TASKMAX];
406
static int ts_taskn = -1;
408
int tsdo(int port, int lsock, int *conn) {
409
int csock, rsock, i, db = 1;
411
struct sockaddr_in addr;
413
int addrlen = sizeof(addr);
415
socklen_t addrlen = sizeof(addr);
419
signal(SIGALRM, tsdo_timeout);
420
tsdo_timeout_flag = 0;
423
csock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
426
if (db) rfbLog("tsdo: accept: lsock: %d, csock: %d, port: %d\n", lsock, csock, port);
428
if (tsdo_timeout_flag > 0 || csock < 0) {
436
if (db) rfbLog("tsdo: using exiting csock: %d, port: %d\n", csock, port);
439
rsock = rfbConnectToTcpAddr("127.0.0.1", port);
441
if (db) rfbLog("tsdo: rfbConnectToTcpAddr(port=%d) failed.\n", port);
451
ts_taskn = (ts_taskn+1) % TASKMAX;
452
ts_tasks[ts_taskn] = pid;
459
for (i=0; i<255; i++) {
460
if (i != csock && i != rsock && i != 2) {
464
#if LIBVNCSERVER_HAVE_SETSID
465
if (setsid() == -1) {
470
if (setpgrp() == -1) {
475
raw_xfer(rsock, csock, csock);
481
void set_redir_properties(void);
485
void terminal_services(char *list) {
486
int i, j, n = 0, db = 1;
487
char *p, *q, *r, *str = strdup(list);
490
int listen[TSMAX], redir[TSMAX][TSSTK], socks[TSMAX], tstk[TSSTK];
491
Atom at, atom[TSMAX];
494
XErrorHandler old_handler1;
495
XIOErrorHandler old_handler2;
497
time_t last_clean = time(NULL);
502
rwin = RootWindow(dpy, DefaultScreen(dpy));
504
at = XInternAtom(dpy, "TS_REDIR_LIST", False);
506
XChangeProperty(dpy, rwin, at, XA_STRING, 8,
507
PropModeReplace, (unsigned char *)list, strlen(list));
510
for (i=0; i<TASKMAX; i++) {
513
for (i=0; i<TSMAX; i++) {
514
for (j=0; j<TSSTK; j++) {
519
p = strtok(str, ",");
522
if (db) fprintf(stderr, "item: %s\n", p);
525
p = strtok(NULL, ",");
530
p = strtok(NULL, ",");
539
if (m1 <= 0 || m2 <= 0 || m1 >= 0xffff || m2 >= 0xffff) {
540
p = strtok(NULL, ",");
548
if (db) fprintf(stderr, " %d %d %s\n", redir[n][0], listen[n], tag[n]);
557
p = strtok(NULL, ",");
565
at = XInternAtom(dpy, "TS_REDIR_PID", False);
567
sprintf(num, "%d", getpid());
568
XChangeProperty(dpy, rwin, at, XA_STRING, 8,
569
PropModeReplace, (unsigned char *)num, strlen(num));
573
for (i=0; i<n; i++) {
574
atom[i] = XInternAtom(dpy, tag[i], False);
575
if (db) fprintf(stderr, "tag: %s atom: %d\n", tag[i], (int) atom[i]);
576
if (atom[i] == None) {
579
sprintf(num, "%d", redir[i][0]);
580
if (db) fprintf(stderr, " listen: %d redir: %s\n", listen[i], num);
581
XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
582
PropModeReplace, (unsigned char *)num, strlen(num));
585
socks[i] = rfbListenOnTCPPort(listen[i], htonl(INADDR_LOOPBACK));
588
if (getenv("TSD_RESTART")) {
589
if (!strcmp(getenv("TSD_RESTART"), "1")) {
590
set_redir_properties();
603
for (i=0; i<n; i++) {
605
FD_SET(socks[i], &rd);
606
if (socks[i] > fmax) {
612
nfd = select(fmax+1, &rd, NULL, NULL, &tv);
614
if (db && 0) fprintf(stderr, "nfd=%d\n", nfd);
615
if (nfd < 0 && errno == EINTR) {
622
for (j = 0; j < TSSTK; j++) {
625
for (j = 0; j < TSSTK; j++) {
626
if (redir[i][j] != 0) {
627
tstk[k++] = redir[i][j];
630
for (j = 0; j < TSSTK; j++) {
631
redir[i][j] = tstk[j];
632
if (tstk[j] != 0) fprintf(stderr, "B redir[%d][%d] = %d %s\n", i, j, tstk[j], tag[i]);
640
if (FD_ISSET(s, &rd)) {
641
int p0, p, found = -1, jzero = -1;
644
get_prop(num, 32, atom[i]);
647
for (j = TSSTK-1; j >= 0; j--) {
648
if (redir[i][j] == 0) {
652
if (p0 > 0 && p0 < 0xffff) {
653
if (redir[i][j] == p0) {
663
if (p0 > 0 && p0 < 0xffff) {
664
redir[i][jzero] = p0;
667
for (j = TSSTK-1; j >= 0; j--) {
670
if (p <= 0 || p >= 0xffff) {
674
rc = tsdo(p, s, &conn);
677
if (db) fprintf(stderr, "tsdo[%d] OK: %d\n", i, p);
679
sprintf(num, "%d", p);
680
XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
681
PropModeReplace, (unsigned char *)num, strlen(num));
685
} else if (rc == 1) {
687
if (db) fprintf(stderr, "tsdo[%d] accept failed: %d\n", i, p);
689
} else if (rc == 2) {
691
if (db) fprintf(stderr, "tsdo[%d] connect failed: %d\n", i, p);
694
} else if (rc == 3) {
700
for (j = 0; j < TSSTK; j++) {
701
if (redir[i][j] != 0) fprintf(stderr, "A redir[%d][%d] = %d %s\n", i, j, redir[i][j], tag[i]);
706
for (i=0; i<TASKMAX; i++) {
707
pid_t p = ts_tasks[i];
710
pid_t p2 = waitpid(p, &status, WNOHANG);
716
/* this is to drop events and exit when X server is gone. */
717
old_handler1 = XSetErrorHandler(trap_xerror);
718
old_handler2 = XSetIOErrorHandler(trap_xioerror);
720
trapped_xioerror = 0;
724
sprintf(num, "%d", (int) time(NULL));
725
at = XInternAtom(dpy, "TS_REDIR", False);
727
XChangeProperty(dpy, rwin, at, XA_STRING, 8,
728
PropModeReplace, (unsigned char *)num, strlen(num));
731
if (time(NULL) > last_clean + 20 * 60) {
735
for (j = TSSTK-1; j >= 0; j--) {
736
int s, p = redir[i][j];
737
if (p <= 0 || p >= 0xffff) {
741
s = rfbConnectToTcpAddr("127.0.0.1", p);
744
if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p);
748
sprintf(num, "%d", p);
749
XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
750
PropModeReplace, (unsigned char *)num, strlen(num));
758
last_clean = time(NULL);
760
if (trapped_xerror || trapped_xioerror) {
761
if (db) fprintf(stderr, "Xerror: %d/%d\n", trapped_xerror, trapped_xioerror);
764
XSetErrorHandler(old_handler1);
765
XSetIOErrorHandler(old_handler2);
770
char *ts_services[][2] = {
771
{"FD_CUPS", "TS_CUPS_REDIR"},
772
{"FD_SMB", "TS_SMB_REDIR"},
773
{"FD_ESD", "TS_ESD_REDIR"},
774
{"FD_NAS", "TS_NAS_REDIR"},
785
char *disp = DisplayString(dpy);
788
a = XInternAtom(dpy, "TS_REDIR_LIST", False);
790
get_prop(prop, 512, a);
793
if (prop[0] == '\0') {
797
if (! program_name) {
798
program_name = "x11vnc";
800
sz += strlen(program_name) + 1;
801
sz += strlen("-display") + 1;
802
sz += strlen(disp) + 1;
803
sz += strlen("-tsd") + 1;
804
sz += 1 + strlen(prop) + 1 + 1;
805
sz += strlen("-env TSD_RESTART=1") + 1;
806
sz += strlen("</dev/null 1>/dev/null 2>&1") + 1;
807
sz += strlen(" &") + 1;
809
cmd = (char *) malloc(sz);
811
if (getenv("XAUTHORITY")) {
812
char *xauth = getenv("XAUTHORITY");
813
if (!strcmp(xauth, "") || access(xauth, R_OK) != 0) {
814
*(xauth-2) = '_'; /* yow */
817
sprintf(cmd, "%s -display %s -tsd '%s' -env TSD_RESTART=1 </dev/null 1>/dev/null 2>&1 &", program_name, disp, prop);
818
rfbLog("running: %s\n", cmd);
820
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
821
/* fork into the background now */
822
if ((pid = fork()) > 0) {
827
while (dnow() < s + 1.5) {
828
pidw = waitpid(pid, &status, WNOHANG);
836
} else if (pid == -1) {
840
/* adjust our stdio */
841
n = open("/dev/null", O_RDONLY);
858
void set_redir_properties(void) {
870
while (ts_services[i][0] != NULL) {
871
f = ts_services[i][0];
872
t = ts_services[i][1];
874
if (!e || strstr(e, "DAEMON-") != e) {
878
p = atoi(e + strlen("DAEMON-"));
883
sprintf(num, "%d", p);
884
a = XInternAtom(dpy, t, False);
886
Window rwin = RootWindow(dpy, DefaultScreen(dpy));
887
fprintf(stderr, "Set: %s %s %s -> %s\n", f, t, e, num);
888
XChangeProperty(dpy, rwin, a, XA_STRING, 8,
889
PropModeReplace, (unsigned char *) num, strlen(num));
897
void check_redir_services(void) {
909
a = XInternAtom(dpy, "TS_REDIR_PID", False);
912
get_prop(prop, 512, a);
913
if (prop[0] != '\0') {
914
pid = (pid_t) atoi(prop);
918
if (getenv("FD_TAG")) {
919
a = XInternAtom(dpy, "FD_TAG", False);
921
Window rwin = RootWindow(dpy, DefaultScreen(dpy));
922
char *tag = getenv("FD_TAG");
923
XChangeProperty(dpy, rwin, a, XA_STRING, 8,
924
PropModeReplace, (unsigned char *)tag, strlen(tag));
930
a = XInternAtom(dpy, "TS_REDIR", False);
932
get_prop(prop, 512, a);
934
if (prop[0] == '\0') {
935
rfbLog("TS_REDIR is empty, restarting...\n");
938
tsd_last = (time_t) atoi(prop);
939
if (time(NULL) > tsd_last + 30) {
940
rfbLog("TS_REDIR seems dead for: %d sec, restarting...\n",
941
time(NULL) - tsd_last);
943
} else if (pid > 0 && time(NULL) > tsd_last + 6) {
944
if (kill(pid, 0) != 0) {
945
rfbLog("TS_REDIR seems dead via kill(%d, 0), restarting...\n",
954
rfbLog("killing TS_REDIR_PID: %d\n", pid);
963
set_redir_properties();
967
void ssh_remote_tunnel(char *instr, int lport) {
968
char *p, *q, *cmd, *ssh;
969
char *s = strdup(instr);
970
int sleep = 300, disp = 0, sport = 0;
973
/* user@host:port:disp+secs */
1005
len += strlen(ssh) + strlen(s) + 500;
1006
cmd = (char *) malloc(len);
1008
if (disp >= 0 && disp <= 200) {
1009
rport = disp + 5900;
1010
} else if (disp < 0) {
1017
sprintf(cmd, "%s -f -p %d -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, sport, rport, lport, s, sleep);
1019
sprintf(cmd, "%s -f -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, rport, lport, s, sleep);
1022
if (no_external_cmds || !cmd_ok("ssh")) {
1024
rfbLog("cannot run external commands in -nocmds mode:\n");
1025
rfbLog(" \"%s\"\n", cmd);
1026
rfbLog(" exiting.\n");
1031
fprintf(stderr, "\n");
1032
rfbLog("running: %s\n", cmd);
1038
rfbLog("ssh remote listen failed.\n");
1044
int mypid = (int) getpid();
1048
char *psef = "ps -ef";
1049
char *psww = "ps wwwwwwaux";
1051
/* not portable... but it is really good to terminate the ssh when done. */
1052
/* ps -ef | egrep 'ssh2.*-R.*5907:localhost:5900.*runge@celias.lbl.gov.*sleep 300' | grep -v grep | awk '{print $2}' */
1053
if (strstr(UT.sysname, "Linux")) {
1055
} else if (strstr(UT.sysname, "BSD")) {
1057
} else if (strstr(UT.sysname, "Darwin")) {
1060
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);
1061
pipe = popen(cmd, "r");
1063
while (fgets(line, 1024, pipe) != NULL) {
1070
score = p - mypid + 32768;
1075
if (best < 0 || score < best) {
1084
if (bestpid != -1) {
1085
ssh_pid = (pid_t) bestpid;
1086
rfbLog("guessed ssh pid=%d, will terminate it on exit.\n", bestpid);
1095
void check_filexfer(void) {
1096
static time_t last_check = 0;
1097
rfbClientIteratorPtr iter;
1099
int transferring = 0;
1101
if (time(NULL) <= last_check) {
1106
if (getenv("NOFT")) {
1111
iter = rfbGetClientIterator(screen);
1112
while( (cl = rfbClientIteratorNext(iter)) ) {
1113
if (cl->fileTransfer.receiving) {
1117
if (cl->fileTransfer.sending) {
1122
rfbReleaseClientIterator(iter);
1125
double start = dnow();
1126
while (dnow() < start + 0.5) {
1132
last_check = time(NULL);
1137
* main x11vnc loop: polls, checks for events, iterate libvncserver, etc.
1139
static void watch_loop(void) {
1140
int cnt = 0, tile_diffs = 0, skip_pe = 0;
1141
double tm, dtr, dt = 0.0;
1142
time_t start = time(NULL);
1145
rfbRunEventLoop(screen, -1, TRUE);
1149
char msg[] = "new client: %s taking unixpw client off hold.\n";
1152
got_pointer_input = 0;
1153
got_local_pointer_input = 0;
1154
got_pointer_calls = 0;
1155
got_keyboard_input = 0;
1156
got_keyboard_calls = 0;
1159
x11vnc_current = dnow();
1161
if (! use_threads) {
1164
if (unixpw_in_progress) {
1165
rfbClientPtr cl = unixpw_client;
1166
if (cl && cl->onHold) {
1167
rfbLog(msg, cl->host);
1168
unixpw_client->onHold = FALSE;
1171
measure_send_rates(1);
1174
unixpw_in_rfbPE = 1;
1177
* do a few more since a key press may
1178
* have induced a small change we want to
1179
* see quickly (just 1 rfbPE will likely
1180
* only process the subsequent "up" event)
1182
if (tm < last_keyboard_time + 0.16) {
1192
unixpw_in_rfbPE = 0;
1194
if (unixpw_in_progress) {
1195
/* rfbPE loop until logged in. */
1197
check_new_clients();
1200
measure_send_rates(0);
1201
fb_update_sent(NULL);
1204
if (unixpw_in_progress) {
1206
check_new_clients();
1212
if (! cursor_shape_updates) {
1213
/* undo any cursor shape requests */
1214
disable_cursor_shape_updates(screen);
1216
if (screen && screen->clientHead) {
1217
int ret = check_user_input(dt, dtr,
1219
/* true: loop back for more input */
1224
if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
1228
/* watch for viewonly input piling up: */
1229
if ((got_pointer_calls > got_pointer_input) ||
1230
(got_keyboard_calls > got_keyboard_input)) {
1231
eat_viewonly_input(10, 3);
1234
/* -threads here. */
1235
if (wireframe && button_mask) {
1245
if (unixpw_in_progress) {
1246
check_new_clients();
1250
if (! urgent_update) {
1251
if (do_copy_screen) {
1256
check_new_clients();
1262
check_keycode_state();
1263
check_connect_inputs();
1268
record_last_fb_update();
1271
check_xdamage_state();
1272
check_xrecord_reset(0);
1273
check_add_keysyms();
1274
check_new_passwds(0);
1275
if (started_as_root) {
1276
check_switched_user();
1279
if (first_conn_timeout < 0) {
1281
first_conn_timeout = -first_conn_timeout;
1285
/* if (rawfb_vnc_reflect) {
1286
static time_t lastone = 0;
1287
if (time(NULL) > lastone + 10) {
1288
lastone = time(NULL);
1289
vnc_reflect_process_client();
1293
if (! screen || ! screen->clientHead) {
1294
/* waiting for a client */
1295
if (first_conn_timeout) {
1296
if (time(NULL) - start > first_conn_timeout) {
1297
rfbLog("No client after %d secs.\n",
1298
first_conn_timeout);
1306
if (first_conn_timeout && all_clients_initialized()) {
1307
first_conn_timeout = 0;
1311
/* no framebuffer polling needed */
1312
if (cursor_pos_updates) {
1313
check_x11_pointer();
1316
else check_x11_pointer();
1321
if (button_mask && (!show_dragging || pointer_mode == 0)) {
1323
* if any button is pressed in this mode do
1324
* not update rfb screen, but do flush the
1332
static double last_dt = 0.0;
1333
double xdamage_thrash = 0.4;
1335
check_cursor_changes();
1337
/* for timing the scan to try to detect thrashing */
1339
if (use_xdamage && last_dt > xdamage_thrash) {
1340
clear_xdamage_mark_region(NULL, 0);
1343
if (unixpw_in_progress) continue;
1345
/* if (rawfb_vnc_reflect) {
1346
vnc_reflect_process_client();
1351
if (xrandr_present && !xrandr && xrandr_maybe) {
1353
/* there may be xrandr right after xsession start */
1354
if (tm < x11vnc_start + delay || tm < last_client + delay) {
1356
if (auth_file != NULL) {
1360
if (tm < x11vnc_start + tw || tm < last_client + tw) {
1367
check_xrandr_event("before-scan");
1373
for (t=0; t < tries; t++) {
1374
tile_diffs = scan_for_updates(0);
1377
tile_diffs = scan_for_updates(0);
1384
if ((debug_tiles || debug_scroll > 1 || debug_wireframe > 1)
1385
&& (tile_diffs > 4 || debug_tiles > 1)) {
1386
double rate = (tile_x * tile_y * bpp/8 * tile_diffs) / dt;
1387
fprintf(stderr, "============================= TILES: %d dt: %.4f"
1388
" t: %.4f %.2f MB/s nap_ok: %d\n", tile_diffs, dt,
1389
tm - x11vnc_start, rate/1000000.0, nap_ok);
1394
/* sleep a bit to lessen load */
1395
if (! urgent_update) {
1396
int wait = choose_delay(dt);
1397
if (wait > 2*waitms) {
1398
/* bog case, break it up */
1399
nap_sleep(wait, 10);
1401
usleep(wait * 1000);
1409
* check blacklist for OSs with tight shm limits.
1411
static int limit_shm(void) {
1414
if (UT.sysname == NULL) {
1417
if (!strcmp(UT.sysname, "SunOS")) {
1418
char *r = UT.release;
1419
if (*r == '5' && *(r+1) == '.') {
1420
if (strchr("2345678", *(r+2)) != NULL) {
1424
} else if (!strcmp(UT.sysname, "Darwin")) {
1427
if (limit && ! quiet) {
1428
fprintf(stderr, "reducing shm usage on %s %s (adding "
1429
"-onetile)\n", UT.sysname, UT.release);
1436
* quick-n-dirty ~/.x11vncrc: each line (except # comments) is a cmdline option.
1438
static int argc2 = 0;
1439
static char **argv2;
1441
static void check_rcfile(int argc, char **argv) {
1442
int i, j, pwlast, norc = 0, argmax = 1024;
1443
char *infile = NULL;
1447
for (i=1; i < argc; i++) {
1448
if (!strcmp(argv[i], "-printgui")) {
1449
fprintf(stdout, "%s", get_gui_code());
1453
if (!strcmp(argv[i], "-norc")) {
1457
if (!strcmp(argv[i], "-QD")) {
1460
if (!strcmp(argv[i], "-rc")) {
1462
fprintf(stderr, "-rc option requires a "
1471
rc_rcfile = strdup("");
1474
} else if (infile != NULL) {
1475
rc = fopen(infile, "r");
1476
rc_rcfile = strdup(infile);
1478
fprintf(stderr, "could not open rcfile: %s\n", infile);
1483
char *home = get_home_dir();
1487
strncpy(rcfile, home, 500);
1490
strcat(rcfile, "/.x11vncrc");
1492
rc = fopen(rcfile, "r");
1496
rc_rcfile = strdup(rcfile);
1497
rc_rcfile_default = 1;
1502
argv2 = (char **) malloc(argmax * sizeof(char *));
1503
argv2[argc2++] = strdup(argv[0]);
1506
char line[4096], parm[400], tmp[401];
1511
if (fstat(fileno(rc), &sbuf) != 0) {
1512
fprintf(stderr, "problem with %s\n", infile);
1516
sz = sbuf.st_size+1; /* allocate whole file size */
1521
buf = (char *) malloc(sz);
1524
while (fgets(line, 4096, rc) != NULL) {
1552
while (isspace((unsigned char) (*q))) {
1564
if (q != p && !cont) {
1568
while (isspace((unsigned char) (*q))) {
1579
strncat(buf, p, sz - strlen(buf) - 1);
1583
if (buf[0] == '\0') {
1591
if (*q == '\n' || isspace((unsigned char) (*q))) {
1598
fprintf(stderr, "invalid rcfile line: %s/%s\n",
1603
if (sscanf(buf, "%s", parm) != 1) {
1604
fprintf(stderr, "invalid rcfile line: %s\n", p);
1607
if (parm[0] == '-') {
1608
strncpy(tmp, parm, 400);
1611
strncpy(tmp+1, parm, 400);
1614
if (strstr(tmp, "-loop") == tmp) {
1615
if (! getenv("X11VNC_LOOP_MODE")) {
1616
check_loop_mode(argc, argv, 1);
1621
argv2[argc2++] = strdup(tmp);
1622
if (argc2 >= argmax) {
1623
fprintf(stderr, "too many rcfile options\n");
1636
tbuf = (char *) calloc(strlen(p) + 1, 1);
1640
if (*p == '\\' && *(p+1) == '#') {
1648
argv2[argc2++] = strdup(tbuf);
1650
if (argc2 >= argmax) {
1651
fprintf(stderr, "too many rcfile options\n");
1660
for (i=1; i < argc; i++) {
1661
argv2[argc2++] = strdup(argv[i]);
1663
if (pwlast || !strcmp("-passwd", argv[i])
1664
|| !strcmp("-viewpasswd", argv[i])) {
1673
if (argc2 >= argmax) {
1674
fprintf(stderr, "too many rcfile options\n");
1680
static void immediate_switch_user(int argc, char* argv[]) {
1682
for (i=1; i < argc; i++) {
1683
if (strcmp(argv[i], "-inetd")) {
1686
if (strcmp(argv[i], "-quiet")) {
1689
if (strcmp(argv[i], "-q")) {
1693
for (i=1; i < argc; i++) {
1696
if (strcmp(argv[i], "-users")) {
1699
if (i == argc - 1) {
1700
fprintf(stderr, "not enough arguments for: -users\n");
1703
if (*(argv[i+1]) != '=') {
1707
/* wants an immediate switch: =bob */
1708
u = strdup(argv[i+1]);
1712
user2group = (char **) malloc(2*sizeof(char *));
1713
user2group[0] = strdup(u+1);
1714
user2group[1] = NULL;
1717
if (strstr(u, "+guess") == u) {
1718
fprintf(stderr, "invalid user: %s\n", u+1);
1721
if (!switch_user(u, 0)) {
1722
fprintf(stderr, "Could not switch to user: %s\n", u+1);
1726
fprintf(stderr, "Switched to user: %s\n", u+1);
1728
started_as_root = 2;
1735
static void quick_pw(char *str) {
1740
if (db) fprintf(stderr, "quick_pw: %s\n", str);
1742
if (! str || str[0] == '\0') {
1745
if (str[0] != '%') {
1749
* "%-" or "%stdin" means read one line from stdin.
1751
* "%env" means it is in $UNIXPW env var.
1753
* starting "%/" or "%." means read the first line from that file.
1755
* "%%" or "%" means prompt user.
1757
* otherwise: %user:pass
1759
if (!strcmp(str, "%-") || !strcmp(str, "%stdin")) {
1760
if(fgets(tmp, 1024, stdin) == NULL) {
1764
} else if (!strcmp(str, "%env")) {
1765
if (getenv("UNIXPW") == NULL) {
1768
q = strdup(getenv("UNIXPW"));
1769
} else if (!strcmp(str, "%%") || !strcmp(str, "%")) {
1771
fprintf(stdout, "username: ");
1772
if(fgets(tmp, 128, stdin) == NULL) {
1776
t = strchr(inp, '\n');
1783
fprintf(stdout, "password: ");
1784
/* test mode: no_external_cmds does not apply */
1785
system("stty -echo");
1786
if(fgets(tmp, 128, stdin) == NULL) {
1787
fprintf(stdout, "\n");
1788
system("stty echo");
1791
system("stty echo");
1792
fprintf(stdout, "\n");
1795
} else if (str[1] == '/' || str[1] == '.') {
1796
FILE *in = fopen(str+1, "r");
1800
if(fgets(tmp, 1024, in) == NULL) {
1807
p = (char *) malloc(strlen(q) + 10);
1809
if (strchr(p, '\n') == NULL) {
1813
if ((q = strchr(p, ':')) == NULL) {
1817
if (db) fprintf(stderr, "'%s' '%s'\n", p, q+1);
1819
if (cmd_verify(p, q+1)) {
1820
fprintf(stdout, "Y %s\n", p);
1823
fprintf(stdout, "N %s\n", p);
1826
} else if (unixpw_nis) {
1827
if (crypt_verify(p, q+1)) {
1828
fprintf(stdout, "Y %s\n", p);
1831
fprintf(stdout, "N %s\n", p);
1835
if (su_verify(p, q+1, NULL, NULL, NULL, 1)) {
1836
fprintf(stdout, "Y %s\n", p);
1839
fprintf(stdout, "N %s\n", p);
1847
static void print_settings(int try_http, int bg, char *gui_str) {
1849
fprintf(stderr, "\n");
1850
fprintf(stderr, "Settings:\n");
1851
fprintf(stderr, " display: %s\n", use_dpy ? use_dpy
1853
#if SMALL_FOOTPRINT < 2
1854
fprintf(stderr, " authfile: %s\n", auth_file ? auth_file
1856
fprintf(stderr, " subwin: 0x%lx\n", subwin);
1857
fprintf(stderr, " -sid mode: %d\n", rootshift);
1858
fprintf(stderr, " clip: %s\n", clip_str ? clip_str
1860
fprintf(stderr, " flashcmap: %d\n", flash_cmap);
1861
fprintf(stderr, " shiftcmap: %d\n", shift_cmap);
1862
fprintf(stderr, " force_idx: %d\n", force_indexed_color);
1863
fprintf(stderr, " cmap8to24: %d\n", cmap8to24);
1864
fprintf(stderr, " 8to24_opts: %s\n", cmap8to24_str ? cmap8to24_str
1866
fprintf(stderr, " 24to32: %d\n", xform24to32);
1867
fprintf(stderr, " visual: %s\n", visual_str ? visual_str
1869
fprintf(stderr, " overlay: %d\n", overlay);
1870
fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor);
1871
fprintf(stderr, " scaling: %d %.4f\n", scaling, scale_fac);
1872
fprintf(stderr, " viewonly: %d\n", view_only);
1873
fprintf(stderr, " shared: %d\n", shared);
1874
fprintf(stderr, " conn_once: %d\n", connect_once);
1875
fprintf(stderr, " timeout: %d\n", first_conn_timeout);
1876
fprintf(stderr, " ping: %d\n", ping_interval);
1877
fprintf(stderr, " inetd: %d\n", inetd);
1878
fprintf(stderr, " tightfilexfer: %d\n", tightfilexfer);
1879
fprintf(stderr, " http: %d\n", try_http);
1880
fprintf(stderr, " connect: %s\n", client_connect
1881
? client_connect : "null");
1882
fprintf(stderr, " connectfile %s\n", client_connect_file
1883
? client_connect_file : "null");
1884
fprintf(stderr, " vnc_conn: %d\n", vnc_connect);
1885
fprintf(stderr, " allow: %s\n", allow_list ? allow_list
1887
fprintf(stderr, " input: %s\n", allowed_input_str
1888
? allowed_input_str : "null");
1889
fprintf(stderr, " passfile: %s\n", passwdfile ? passwdfile
1891
fprintf(stderr, " unixpw: %d\n", unixpw);
1892
fprintf(stderr, " unixpw_lst: %s\n", unixpw_list ? unixpw_list:"null");
1893
fprintf(stderr, " ssl: %s\n", openssl_pem ? openssl_pem:"null");
1894
fprintf(stderr, " ssldir: %s\n", ssl_certs_dir ? ssl_certs_dir:"null");
1895
fprintf(stderr, " ssltimeout %d\n", ssl_timeout_secs);
1896
fprintf(stderr, " sslverify: %s\n", ssl_verify ? ssl_verify:"null");
1897
fprintf(stderr, " stunnel: %d\n", use_stunnel);
1898
fprintf(stderr, " accept: %s\n", accept_cmd ? accept_cmd
1900
fprintf(stderr, " accept: %s\n", afteraccept_cmd ? afteraccept_cmd
1902
fprintf(stderr, " gone: %s\n", gone_cmd ? gone_cmd
1904
fprintf(stderr, " users: %s\n", users_list ? users_list
1906
fprintf(stderr, " using_shm: %d\n", using_shm);
1907
fprintf(stderr, " flipbytes: %d\n", flip_byte_order);
1908
fprintf(stderr, " onetile: %d\n", single_copytile);
1909
fprintf(stderr, " solid: %s\n", solid_str
1910
? solid_str : "null");
1911
fprintf(stderr, " blackout: %s\n", blackout_str
1912
? blackout_str : "null");
1913
fprintf(stderr, " xinerama: %d\n", xinerama);
1914
fprintf(stderr, " xtrap: %d\n", xtrap_input);
1915
fprintf(stderr, " xrandr: %d\n", xrandr);
1916
fprintf(stderr, " xrandrmode: %s\n", xrandr_mode ? xrandr_mode
1918
fprintf(stderr, " padgeom: %s\n", pad_geometry
1919
? pad_geometry : "null");
1920
fprintf(stderr, " logfile: %s\n", logfile ? logfile
1922
fprintf(stderr, " logappend: %d\n", logfile_append);
1923
fprintf(stderr, " flag: %s\n", flagfile ? flagfile
1925
fprintf(stderr, " rc_file: \"%s\"\n", rc_rcfile ? rc_rcfile
1927
fprintf(stderr, " norc: %d\n", rc_norc);
1928
fprintf(stderr, " dbg: %d\n", crash_debug);
1929
fprintf(stderr, " bg: %d\n", bg);
1930
fprintf(stderr, " mod_tweak: %d\n", use_modifier_tweak);
1931
fprintf(stderr, " isolevel3: %d\n", use_iso_level3);
1932
fprintf(stderr, " xkb: %d\n", use_xkb_modtweak);
1933
fprintf(stderr, " skipkeys: %s\n",
1934
skip_keycodes ? skip_keycodes : "null");
1935
fprintf(stderr, " sloppykeys: %d\n", sloppy_keys);
1936
fprintf(stderr, " skip_dups: %d\n", skip_duplicate_key_events);
1937
fprintf(stderr, " addkeysyms: %d\n", add_keysyms);
1938
fprintf(stderr, " xkbcompat: %d\n", xkbcompat);
1939
fprintf(stderr, " clearmods: %d\n", clear_mods);
1940
fprintf(stderr, " remap: %s\n", remap_file ? remap_file
1942
fprintf(stderr, " norepeat: %d\n", no_autorepeat);
1943
fprintf(stderr, " norepeatcnt:%d\n", no_repeat_countdown);
1944
fprintf(stderr, " nofb: %d\n", nofb);
1945
fprintf(stderr, " watchbell: %d\n", watch_bell);
1946
fprintf(stderr, " watchsel: %d\n", watch_selection);
1947
fprintf(stderr, " watchprim: %d\n", watch_primary);
1948
fprintf(stderr, " seldir: %s\n", sel_direction ?
1949
sel_direction : "null");
1950
fprintf(stderr, " cursor: %d\n", show_cursor);
1951
fprintf(stderr, " multicurs: %d\n", show_multiple_cursors);
1952
fprintf(stderr, " curs_mode: %s\n", multiple_cursors_mode
1953
? multiple_cursors_mode : "null");
1954
fprintf(stderr, " arrow: %d\n", alt_arrow);
1955
fprintf(stderr, " xfixes: %d\n", use_xfixes);
1956
fprintf(stderr, " alphacut: %d\n", alpha_threshold);
1957
fprintf(stderr, " alphafrac: %.2f\n", alpha_frac);
1958
fprintf(stderr, " alpharemove:%d\n", alpha_remove);
1959
fprintf(stderr, " alphablend: %d\n", alpha_blend);
1960
fprintf(stderr, " cursorshape:%d\n", cursor_shape_updates);
1961
fprintf(stderr, " cursorpos: %d\n", cursor_pos_updates);
1962
fprintf(stderr, " xwarpptr: %d\n", use_xwarppointer);
1963
fprintf(stderr, " buttonmap: %s\n", pointer_remap
1964
? pointer_remap : "null");
1965
fprintf(stderr, " dragging: %d\n", show_dragging);
1966
fprintf(stderr, " ncache: %d\n", ncache);
1967
fprintf(stderr, " wireframe: %s\n", wireframe_str ?
1968
wireframe_str : WIREFRAME_PARMS);
1969
fprintf(stderr, " wirecopy: %s\n", wireframe_copyrect ?
1970
wireframe_copyrect : wireframe_copyrect_default);
1971
fprintf(stderr, " scrollcopy: %s\n", scroll_copyrect ?
1972
scroll_copyrect : scroll_copyrect_default);
1973
fprintf(stderr, " scr_area: %d\n", scrollcopyrect_min_area);
1974
fprintf(stderr, " scr_skip: %s\n", scroll_skip_str ?
1975
scroll_skip_str : scroll_skip_str0);
1976
fprintf(stderr, " scr_inc: %s\n", scroll_good_str ?
1977
scroll_good_str : scroll_good_str0);
1978
fprintf(stderr, " scr_keys: %s\n", scroll_key_list_str ?
1979
scroll_key_list_str : "null");
1980
fprintf(stderr, " scr_term: %s\n", scroll_term_str ?
1981
scroll_term_str : "null");
1982
fprintf(stderr, " scr_keyrep: %s\n", max_keyrepeat_str ?
1983
max_keyrepeat_str : "null");
1984
fprintf(stderr, " scr_parms: %s\n", scroll_copyrect_str ?
1985
scroll_copyrect_str : SCROLL_COPYRECT_PARMS);
1986
fprintf(stderr, " fixscreen: %s\n", screen_fixup_str ?
1987
screen_fixup_str : "null");
1988
fprintf(stderr, " noxrecord: %d\n", noxrecord);
1989
fprintf(stderr, " grabbuster: %d\n", grab_buster);
1990
fprintf(stderr, " ptr_mode: %d\n", pointer_mode);
1991
fprintf(stderr, " inputskip: %d\n", ui_skip);
1992
fprintf(stderr, " speeds: %s\n", speeds_str
1993
? speeds_str : "null");
1994
fprintf(stderr, " wmdt: %s\n", wmdt_str
1995
? wmdt_str : "null");
1996
fprintf(stderr, " debug_ptr: %d\n", debug_pointer);
1997
fprintf(stderr, " debug_key: %d\n", debug_keyboard);
1998
fprintf(stderr, " defer: %d\n", defer_update);
1999
fprintf(stderr, " waitms: %d\n", waitms);
2000
fprintf(stderr, " wait_ui: %.2f\n", wait_ui);
2001
fprintf(stderr, " nowait_bog: %d\n", !wait_bog);
2002
fprintf(stderr, " slow_fb: %.2f\n", slow_fb);
2003
fprintf(stderr, " xrefresh: %.2f\n", xrefresh);
2004
fprintf(stderr, " readtimeout: %d\n", rfbMaxClientWait/1000);
2005
fprintf(stderr, " take_naps: %d\n", take_naps);
2006
fprintf(stderr, " sb: %d\n", screen_blank);
2007
fprintf(stderr, " fbpm: %d\n", !watch_fbpm);
2008
fprintf(stderr, " dpms: %d\n", !watch_dpms);
2009
fprintf(stderr, " xdamage: %d\n", use_xdamage);
2010
fprintf(stderr, " xd_area: %d\n", xdamage_max_area);
2011
fprintf(stderr, " xd_mem: %.3f\n", xdamage_memory);
2012
fprintf(stderr, " sigpipe: %s\n", sigpipe
2013
? sigpipe : "null");
2014
fprintf(stderr, " threads: %d\n", use_threads);
2015
fprintf(stderr, " fs_frac: %.2f\n", fs_frac);
2016
fprintf(stderr, " gaps_fill: %d\n", gaps_fill);
2017
fprintf(stderr, " grow_fill: %d\n", grow_fill);
2018
fprintf(stderr, " tile_fuzz: %d\n", tile_fuzz);
2019
fprintf(stderr, " snapfb: %d\n", use_snapfb);
2020
fprintf(stderr, " rawfb: %s\n", raw_fb_str
2021
? raw_fb_str : "null");
2022
fprintf(stderr, " pipeinput: %s\n", pipeinput_str
2023
? pipeinput_str : "null");
2024
fprintf(stderr, " gui: %d\n", launch_gui);
2025
fprintf(stderr, " gui_mode: %s\n", gui_str
2026
? gui_str : "null");
2027
fprintf(stderr, " noremote: %d\n", !accept_remote_cmds);
2028
fprintf(stderr, " unsafe: %d\n", !safe_remote_only);
2029
fprintf(stderr, " privremote: %d\n", priv_remote);
2030
fprintf(stderr, " safer: %d\n", more_safe);
2031
fprintf(stderr, " nocmds: %d\n", no_external_cmds);
2032
fprintf(stderr, " deny_all: %d\n", deny_all);
2033
fprintf(stderr, " pid: %d\n", getpid());
2034
fprintf(stderr, "\n");
2039
static void check_loop_mode(int argc, char* argv[], int force) {
2041
int loop_mode = 0, loop_sleep = 2000, loop_max = 0;
2046
for (i=1; i < argc; i++) {
2048
if (strstr(p, "--") == p) {
2051
if (strstr(p, "-loop") == p) {
2054
if ((q = strchr(p, ',')) != NULL) {
2055
loop_max = atoi(q+1);
2058
if (strstr(p, "-loopbg") == p) {
2059
set_env("X11VNC_LOOP_MODE_BG", "1");
2063
q = strpbrk(p, "0123456789");
2065
loop_sleep = atoi(q);
2066
if (loop_sleep <= 0) {
2072
if (loop_mode && getenv("X11VNC_LOOP_MODE") == NULL) {
2073
#if LIBVNCSERVER_HAVE_FORK
2077
set_env("X11VNC_LOOP_MODE", "1");
2078
argv2 = (char **) malloc((argc+1)*sizeof(char *));
2080
for (k=0; k < argc+1; k++) {
2089
fprintf(stderr, "\n --- x11vnc loop: %d ---\n\n", i++);
2092
if ((p = fork()) > 0) {
2093
fprintf(stderr, " --- x11vnc loop: waiting "
2096
} else if (p == -1) {
2097
fprintf(stderr, "could not fork\n");
2101
/* loop mode: no_external_cmds does not apply */
2102
execvp(argv[0], argv2);
2106
if (loop_max > 0 && i > loop_max) {
2107
fprintf(stderr, "\n --- x11vnc loop: did %d"
2108
" done. ---\n\n", loop_max);
2112
fprintf(stderr, "\n --- x11vnc loop: sleeping %d ms "
2113
"---\n\n", loop_sleep);
2114
usleep(loop_sleep * 1000);
2118
fprintf(stderr, "fork unavailable, cannot do -loop mode\n");
2123
static void store_homedir_passwd(char *file) {
2124
char str1[32], str2[32], *p, *h, *f;
2131
if (no_external_cmds || !cmd_ok("storepasswd")) {
2132
fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
2136
fprintf(stderr, "Enter VNC password: ");
2137
system("stty -echo");
2138
if (fgets(str1, 32, stdin) == NULL) {
2139
system("stty echo");
2142
fprintf(stderr, "\n");
2144
fprintf(stderr, "Verify password: ");
2145
if (fgets(str2, 32, stdin) == NULL) {
2146
system("stty echo");
2149
fprintf(stderr, "\n");
2150
system("stty echo");
2152
if ((p = strchr(str1, '\n')) != NULL) {
2155
if ((p = strchr(str2, '\n')) != NULL) {
2158
if (strcmp(str1, str2)) {
2159
fprintf(stderr, "** passwords differ.\n");
2162
if (str1[0] == '\0') {
2163
fprintf(stderr, "** no password supplied.\n");
2173
fprintf(stderr, "** $HOME not set.\n");
2177
f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1);
2178
sprintf(f, "%s/.vnc", h);
2180
if (stat(f, &sbuf) != 0) {
2181
if (mkdir(f, 0755) != 0) {
2182
fprintf(stderr, "** could not create directory %s\n", f);
2186
} else if (! S_ISDIR(sbuf.st_mode)) {
2187
fprintf(stderr, "** not a directory %s\n", f);
2191
sprintf(f, "%s/.vnc/passwd", h);
2193
fprintf(stderr, "Write password to %s? [y]/n ", f);
2195
if (fgets(str2, 32, stdin) == NULL) {
2198
if (str2[0] == 'n' || str2[0] == 'N') {
2199
fprintf(stderr, "not creating password.\n");
2203
if (rfbEncryptAndStorePasswd(str1, f) != 0) {
2204
fprintf(stderr, "** error creating password.\n");
2205
perror("storepasswd");
2208
fprintf(stderr, "Password written to: %s\n", f);
2209
if (stat(f, &sbuf) != 0) {
2215
void ncache_beta_tester_message(void) {
2219
"******************************************************************************\n"
2221
"Hello! Exciting News!!\n"
2223
"You have been selected at random to beta-test the x11vnc '-ncache' VNC\n"
2224
"client-side pixel caching feature!\n"
2226
"This scheme stores pixel data offscreen on the VNC viewer side for faster\n"
2227
"retrieval. It should work with any VNC viewer.\n"
2229
"This method requires much testing and so we hope you will try it out and\n"
2230
"perhaps even report back your observations. However, if you do not want\n"
2231
"to test or use the feature, run x11vnc like this:\n"
2233
" x11vnc -noncache ...\n"
2235
"Your current setting is: -ncache %d\n"
2237
"The feature needs additional testing because we want to have x11vnc\n"
2238
"performance enhancements on by default. Otherwise, only a relative few\n"
2239
"would notice and use the -ncache option (e.g. the wireframe and scroll\n"
2240
"detection features are on by default). A couple things to note:\n"
2242
" 1) It uses a large amount of RAM (on both viewer and server sides)\n"
2244
" 2) You can actually see the cached pixel data if you scroll down\n"
2245
" to it in your viewer; adjust your viewer's size to hide it.\n"
2247
"More info: http://www.karlrunge.com/x11vnc/#faq-client-caching\n"
2249
"waiting for connections:\n"
2254
"******************************************************************************\n"
2255
"Have you tried the x11vnc '-ncache' VNC client-side pixel caching feature yet?\n"
2257
"The scheme stores pixel data offscreen on the VNC viewer side for faster\n"
2258
"retrieval. It should work with any VNC viewer. Try it by running:\n"
2260
" x11vnc -ncache 10 ...\n"
2262
"more info: http://www.karlrunge.com/x11vnc/#faq-client-caching\n"
2266
if (raw_fb_str && !macosx_console) {
2280
fprintf(stderr, msg2);
2281
ncache0 = ncache = 0;
2283
fprintf(stderr, msg, ncache);
2287
#define SHOW_NO_PASSWORD_WARNING \
2288
(!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
2289
&& !query_cmd && !remote_cmd && !unixpw && !got_gui_pw \
2290
&& ! ssl_verify && !inetd && !terminal_services_daemon)
2292
extern int dragum(void);
2294
int main(int argc, char* argv[]) {
2297
int ev, er, maj, min;
2299
int remote_sync = 0;
2300
char *remote_cmd = NULL;
2301
char *query_cmd = NULL;
2302
char *gui_str = NULL;
2304
int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW;
2305
int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0;
2308
int got_rfbwait = 0;
2309
int got_httpdir = 0, try_http = 0;
2310
int orig_use_xdamage = use_xdamage;
2314
/* used to pass args we do not know about to rfbGetScreen(): */
2315
int argc_vnc_max = 1024;
2316
int argc_vnc = 1; char *argv_vnc[2048];
2319
/* check for -loop mode: */
2320
check_loop_mode(argc, argv, 0);
2322
dtime0(&x11vnc_start);
2324
if (!getuid() || !geteuid()) {
2325
started_as_root = 1;
2327
/* check for '-users =bob' */
2328
immediate_switch_user(argc, argv);
2331
for (i=0; i < 2048; i++) {
2335
argv_vnc[0] = strdup(argv[0]);
2336
program_name = strdup(argv[0]);
2337
program_pid = (int) getpid();
2339
solid_default = strdup(solid_default); /* for freeing with -R */
2342
for (i=1; i < argc; i++) {
2343
len += strlen(argv[i]) + 4 + 1;
2345
program_cmdline = (char *) malloc(len+1);
2346
program_cmdline[0] = '\0';
2347
for (i=1; i < argc; i++) {
2349
if (program_cmdline[0]) {
2350
strcat(program_cmdline, " ");
2353
strcat(program_cmdline, s);
2355
strcat(program_cmdline, "{{");
2356
strcat(program_cmdline, s);
2357
strcat(program_cmdline, "}}");
2361
for (i=0; i<ICON_MODE_SOCKS; i++) {
2362
icon_mode_socks[i] = -1;
2365
check_rcfile(argc, argv);
2366
/* kludge for the new array argv2 set in check_rcfile() */
2370
# define CHECK_ARGC if (i >= argc-1) { \
2371
fprintf(stderr, "not enough arguments for: %s\n", arg); \
2376
* do a quick check for parameters that apply to "utility"
2377
* commands, i.e. ones that do not run the server.
2379
for (i=1; i < argc; i++) {
2381
if (strstr(arg, "--") == arg) {
2384
if (!strcmp(arg, "-ssldir")) {
2386
ssl_certs_dir = strdup(argv[++i]);
2391
* do a quick check for -env parameters
2393
for (i=1; i < argc; i++) {
2396
if (strstr(arg, "--") == arg) {
2399
if (!strcmp(arg, "-env")) {
2401
p = strdup(argv[++i]);
2404
fprintf(stderr, "no -env '=' found: %s\n", p);
2414
for (i=1; i < argc; i++) {
2415
/* quick-n-dirty --option handling. */
2417
if (strstr(arg, "--") == arg) {
2421
if (!strcmp(arg, "-display")) {
2423
use_dpy = strdup(argv[++i]);
2424
if (strstr(use_dpy, "WAIT")) {
2425
extern char find_display[];
2426
extern char create_display[];
2427
if (strstr(use_dpy, "cmd=FINDDISPLAY-print")) {
2428
fprintf(stdout, "%s", find_display);
2431
if (strstr(use_dpy, "cmd=FINDCREATEDISPLAY-print")) {
2432
fprintf(stdout, "%s", create_display);
2436
} else if (!strcmp(arg, "-find")) {
2437
use_dpy = strdup("WAIT:cmd=FINDDISPLAY");
2438
} else if (!strcmp(arg, "-finddpy") || strstr(arg, "-listdpy") == arg) {
2440
use_dpy = strdup("WAIT:cmd=FINDDISPLAY-run");
2442
set_env("X11VNC_USER", argv[i+1]);
2443
fprintf(stdout, "X11VNC_USER=%s\n", getenv("X11VNC_USER"));
2445
if (strstr(arg, "-listdpy") == arg) {
2446
set_env("FIND_DISPLAY_ALL", "1");
2448
wait_for_client(&ic, NULL, 0);
2450
} else if (!strcmp(arg, "-create")) {
2451
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb");
2452
} else if (!strcmp(arg, "-xdummy")) {
2453
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy");
2454
} else if (!strcmp(arg, "-xvnc")) {
2455
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc");
2456
} else if (!strcmp(arg, "-xvnc_redirect")) {
2457
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc.redirect");
2458
} else if (!strcmp(arg, "-redirect")) {
2459
char *q, *t, *t0 = "WAIT:cmd=FINDDISPLAY-vnc_redirect";
2461
t = (char *) malloc(strlen(t0) + strlen(argv[++i]) + 2);
2462
q = strrchr(argv[i], ':');
2464
sprintf(t, "%s=%s", t0, argv[i]);
2466
} else if (!strcmp(arg, "-auth") || !strcmp(arg, "-xauth")) {
2468
auth_file = strdup(argv[++i]);
2469
} else if (!strcmp(arg, "-N")) {
2471
} else if (!strcmp(arg, "-autoport")) {
2473
auto_port = atoi(argv[++i]);
2474
} else if (!strcmp(arg, "-reflect")) {
2476
raw_fb_str = (char *) malloc(4 + strlen(argv[i]) + 1);
2477
sprintf(raw_fb_str, "vnc:%s", argv[++i]);
2479
} else if (!strcmp(arg, "-tsd")) {
2481
terminal_services_daemon = strdup(argv[++i]);
2482
} else if (!strcmp(arg, "-id") || !strcmp(arg, "-sid")) {
2484
if (!strcmp(arg, "-sid")) {
2490
if (!strcmp("pick", argv[i])) {
2491
if (started_as_root) {
2492
fprintf(stderr, "unsafe: %s pick\n",
2495
} else if (! pick_windowid(&subwin)) {
2496
fprintf(stderr, "invalid %s pick\n",
2500
} else if (! scan_hexdec(argv[i], &subwin)) {
2501
fprintf(stderr, "invalid %s arg: %s\n", arg,
2505
} else if (!strcmp(arg, "-waitmapped")) {
2506
subwin_wait_mapped = 1;
2507
} else if (!strcmp(arg, "-clip")) {
2509
clip_str = strdup(argv[++i]);
2510
} else if (!strcmp(arg, "-flashcmap")) {
2512
} else if (!strcmp(arg, "-shiftcmap")) {
2514
shift_cmap = atoi(argv[++i]);
2515
} else if (!strcmp(arg, "-notruecolor")) {
2516
force_indexed_color = 1;
2517
} else if (!strcmp(arg, "-overlay")) {
2519
} else if (!strcmp(arg, "-overlay_nocursor")) {
2522
} else if (!strcmp(arg, "-overlay_yescursor")) {
2526
} else if (!strcmp(arg, "-8to24")) {
2529
char *s = argv[i+1];
2531
cmap8to24_str = strdup(s);
2536
} else if (!strcmp(arg, "-24to32")) {
2538
} else if (!strcmp(arg, "-visual")) {
2540
visual_str = strdup(argv[++i]);
2541
} else if (!strcmp(arg, "-scale")) {
2543
scale_str = strdup(argv[++i]);
2544
} else if (!strcmp(arg, "-scale_cursor")) {
2546
scale_cursor_str = strdup(argv[++i]);
2547
} else if (!strcmp(arg, "-viewonly")) {
2549
} else if (!strcmp(arg, "-noviewonly")) {
2552
} else if (!strcmp(arg, "-shared")) {
2554
} else if (!strcmp(arg, "-noshared")) {
2556
} else if (!strcmp(arg, "-once")) {
2558
got_connect_once = 1;
2559
} else if (!strcmp(arg, "-many") || !strcmp(arg, "-forever")) {
2561
} else if (strstr(arg, "-loop") == arg) {
2562
; /* handled above */
2563
} else if (!strcmp(arg, "-timeout")) {
2565
first_conn_timeout = atoi(argv[++i]);
2566
} else if (!strcmp(arg, "-sleepin")) {
2569
n = atoi(argv[++i]);
2571
usleep(1000*1000*n);
2573
} else if (!strcmp(arg, "-users")) {
2575
users_list = strdup(argv[++i]);
2576
} else if (!strcmp(arg, "-inetd")) {
2578
} else if (!strcmp(arg, "-notightfilexfer")) {
2580
} else if (!strcmp(arg, "-tightfilexfer")) {
2582
} else if (!strcmp(arg, "-http")) {
2584
} else if (!strcmp(arg, "-http_ssl")) {
2587
} else if (!strcmp(arg, "-avahi") || !strcmp(arg, "-mdns")) {
2589
} else if (!strcmp(arg, "-connect") ||
2590
!strcmp(arg, "-connect_or_exit")) {
2592
if (strchr(argv[++i], '/')) {
2593
client_connect_file = strdup(argv[i]);
2595
client_connect = strdup(argv[i]);
2597
if (!strcmp(arg, "-connect_or_exit")) {
2598
connect_or_exit = 1;
2600
} else if (!strcmp(arg, "-proxy")) {
2602
connect_proxy = strdup(argv[++i]);
2603
} else if (!strcmp(arg, "-vncconnect")) {
2605
} else if (!strcmp(arg, "-novncconnect")) {
2607
} else if (!strcmp(arg, "-allow")) {
2609
allow_list = strdup(argv[++i]);
2610
} else if (!strcmp(arg, "-localhost")) {
2611
allow_list = strdup("127.0.0.1");
2613
} else if (!strcmp(arg, "-nolookup")) {
2615
} else if (!strcmp(arg, "-input")) {
2617
allowed_input_str = strdup(argv[++i]);
2618
} else if (!strcmp(arg, "-grabkbd")) {
2620
} else if (!strcmp(arg, "-grabptr")) {
2622
} else if (!strcmp(arg, "-grabalways")) {
2626
} else if (!strcmp(arg, "-viewpasswd")) {
2629
viewonly_passwd = strdup(argv[++i]);
2631
} else if (!strcmp(arg, "-passwdfile")) {
2633
passwdfile = strdup(argv[++i]);
2635
} else if (!strcmp(arg, "-svc") || !strcmp(arg, "-service")) {
2636
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb");
2638
users_list = strdup("unixpw=");
2640
openssl_pem = strdup("SAVE");
2641
} else if (!strcmp(arg, "-svc_xdummy")) {
2642
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy");
2644
users_list = strdup("unixpw=");
2646
openssl_pem = strdup("SAVE");
2647
set_env("FD_XDUMMY_NOROOT", "1");
2648
} else if (!strcmp(arg, "-svc_xvnc")) {
2649
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc");
2651
users_list = strdup("unixpw=");
2653
openssl_pem = strdup("SAVE");
2654
} else if (!strcmp(arg, "-xdmsvc") || !strcmp(arg, "-xdm_service")) {
2655
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp");
2657
users_list = strdup("unixpw=");
2659
openssl_pem = strdup("SAVE");
2660
} else if (!strcmp(arg, "-sshxdmsvc")) {
2661
use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp");
2662
allow_list = strdup("127.0.0.1");
2664
#ifndef NO_SSL_OR_UNIXPW
2665
} else if (!strcmp(arg, "-unixpw_cmd")
2666
|| !strcmp(arg, "-unixpw_cmd_unsafe")) {
2668
unixpw_cmd = strdup(argv[++i]);
2670
if (strstr(arg, "_unsafe")) {
2671
/* hidden option for testing. */
2672
set_env("UNIXPW_DISABLE_SSL", "1");
2673
set_env("UNIXPW_DISABLE_LOCALHOST", "1");
2675
} else if (strstr(arg, "-unixpw") == arg) {
2677
if (strstr(arg, "-unixpw_nis")) {
2681
char *s = argv[i+1];
2683
unixpw_list = strdup(s);
2692
if (strstr(arg, "_unsafe")) {
2693
/* hidden option for testing. */
2694
set_env("UNIXPW_DISABLE_SSL", "1");
2695
set_env("UNIXPW_DISABLE_LOCALHOST", "1");
2697
} else if (!strcmp(arg, "-nossl")) {
2700
} else if (!strcmp(arg, "-ssl")) {
2703
char *s = argv[i+1];
2705
openssl_pem = strdup(s);
2709
} else if (!strcmp(arg, "-ssltimeout")) {
2711
ssl_timeout_secs = atoi(argv[++i]);
2712
} else if (!strcmp(arg, "-sslnofail")) {
2714
} else if (!strcmp(arg, "-ssldir")) {
2716
ssl_certs_dir = strdup(argv[++i]);
2718
} else if (!strcmp(arg, "-sslverify")) {
2720
ssl_verify = strdup(argv[++i]);
2722
} else if (!strcmp(arg, "-sslGenCA")) {
2725
char *s = argv[i+1];
2733
} else if (!strcmp(arg, "-sslGenCert")) {
2734
char *ty, *nm = NULL;
2736
fprintf(stderr, "Must be:\n");
2737
fprintf(stderr, " x11vnc -sslGenCert server ...\n");
2738
fprintf(stderr, "or x11vnc -sslGenCert client ...\n");
2742
if (strcmp(ty, "server") && strcmp(ty, "client")) {
2743
fprintf(stderr, "Must be:\n");
2744
fprintf(stderr, " x11vnc -sslGenCert server ...\n");
2745
fprintf(stderr, "or x11vnc -sslGenCert client ...\n");
2753
} else if (!strcmp(arg, "-sslEncKey")) {
2755
char *s = argv[i+1];
2759
} else if (!strcmp(arg, "-sslCertInfo")) {
2761
char *s = argv[i+1];
2765
} else if (!strcmp(arg, "-sslDelCert")) {
2767
char *s = argv[i+1];
2772
} else if (!strcmp(arg, "-stunnel")) {
2775
char *s = argv[i+1];
2777
stunnel_pem = strdup(s);
2781
} else if (!strcmp(arg, "-stunnel3")) {
2784
char *s = argv[i+1];
2786
stunnel_pem = strdup(s);
2790
} else if (!strcmp(arg, "-https")) {
2794
char *s = argv[i+1];
2796
https_port_num = atoi(s);
2800
} else if (!strcmp(arg, "-httpsredir")) {
2801
https_port_redir = -1;
2803
char *s = argv[i+1];
2805
https_port_redir = atoi(s);
2810
} else if (!strcmp(arg, "-nopw")) {
2812
} else if (!strcmp(arg, "-ssh")) {
2814
ssh_str = strdup(argv[++i]);
2815
} else if (!strcmp(arg, "-usepw")) {
2817
} else if (!strcmp(arg, "-storepasswd")) {
2819
store_homedir_passwd(NULL);
2823
store_homedir_passwd(argv[i+1]);
2826
if (argc >= i+4 || rfbEncryptAndStorePasswd(argv[i+1],
2828
fprintf(stderr, "-storepasswd failed\n");
2831
fprintf(stderr, "stored passwd in file %s\n",
2835
} else if (!strcmp(arg, "-accept")) {
2837
accept_cmd = strdup(argv[++i]);
2838
} else if (!strcmp(arg, "-afteraccept")) {
2840
afteraccept_cmd = strdup(argv[++i]);
2841
} else if (!strcmp(arg, "-gone")) {
2843
gone_cmd = strdup(argv[++i]);
2844
} else if (!strcmp(arg, "-noshm")) {
2846
} else if (!strcmp(arg, "-flipbyteorder")) {
2847
flip_byte_order = 1;
2848
} else if (!strcmp(arg, "-onetile")) {
2849
single_copytile = 1;
2850
} else if (!strcmp(arg, "-solid")) {
2853
char *s = argv[i+1];
2855
solid_str = strdup(s);
2860
solid_str = strdup(solid_default);
2862
} else if (!strcmp(arg, "-blackout")) {
2864
blackout_str = strdup(argv[++i]);
2865
} else if (!strcmp(arg, "-xinerama")) {
2867
} else if (!strcmp(arg, "-noxinerama")) {
2869
} else if (!strcmp(arg, "-xtrap")) {
2871
} else if (!strcmp(arg, "-xrandr")) {
2874
char *s = argv[i+1];
2875
if (known_xrandr_mode(s)) {
2876
xrandr_mode = strdup(s);
2880
} else if (!strcmp(arg, "-noxrandr")) {
2883
} else if (!strcmp(arg, "-rotate")) {
2885
rotating_str = strdup(argv[++i]);
2886
} else if (!strcmp(arg, "-padgeom")
2887
|| !strcmp(arg, "-padgeometry")) {
2889
pad_geometry = strdup(argv[++i]);
2890
} else if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) {
2893
logfile = strdup(argv[++i]);
2894
} else if (!strcmp(arg, "-oa") || !strcmp(arg, "-logappend")) {
2897
logfile = strdup(argv[++i]);
2898
} else if (!strcmp(arg, "-flag")) {
2900
flagfile = strdup(argv[++i]);
2901
} else if (!strcmp(arg, "-rc")) {
2902
i++; /* done above */
2903
} else if (!strcmp(arg, "-norc")) {
2905
} else if (!strcmp(arg, "-env")) {
2906
i++; /* done above */
2907
} else if (!strcmp(arg, "-prog")) {
2912
program_name = strdup(argv[++i]);
2913
} else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) {
2915
} else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) {
2917
} else if (!strcmp(arg, "-V") || !strcmp(arg, "-version")) {
2918
fprintf(stdout, "x11vnc: %s\n", lastmod);
2920
} else if (!strcmp(arg, "-license") ||
2921
!strcmp(arg, "-copying") || !strcmp(arg, "-warranty")) {
2923
} else if (!strcmp(arg, "-dbg")) {
2925
} else if (!strcmp(arg, "-nodbg")) {
2927
} else if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) {
2929
} else if (!strcmp(arg, "-v") || !strcmp(arg, "-verbose")) {
2931
} else if (!strcmp(arg, "-bg") || !strcmp(arg, "-background")) {
2932
#if LIBVNCSERVER_HAVE_SETSID
2936
fprintf(stderr, "warning: -bg mode not supported.\n");
2938
} else if (!strcmp(arg, "-modtweak")) {
2939
use_modifier_tweak = 1;
2940
} else if (!strcmp(arg, "-nomodtweak")) {
2941
use_modifier_tweak = 0;
2943
} else if (!strcmp(arg, "-isolevel3")) {
2945
} else if (!strcmp(arg, "-xkb")) {
2946
use_modifier_tweak = 1;
2947
use_xkb_modtweak = 1;
2948
} else if (!strcmp(arg, "-noxkb")) {
2949
use_xkb_modtweak = 0;
2951
} else if (!strcmp(arg, "-capslock")) {
2953
} else if (!strcmp(arg, "-skip_lockkeys")) {
2955
} else if (!strcmp(arg, "-xkbcompat")) {
2957
} else if (!strcmp(arg, "-skip_keycodes")) {
2959
skip_keycodes = strdup(argv[++i]);
2960
} else if (!strcmp(arg, "-sloppy_keys")) {
2962
} else if (!strcmp(arg, "-skip_dups")) {
2963
skip_duplicate_key_events = 1;
2964
} else if (!strcmp(arg, "-noskip_dups")) {
2965
skip_duplicate_key_events = 0;
2966
} else if (!strcmp(arg, "-add_keysyms")) {
2968
} else if (!strcmp(arg, "-noadd_keysyms")) {
2970
} else if (!strcmp(arg, "-clear_mods")) {
2972
} else if (!strcmp(arg, "-clear_keys")) {
2974
} else if (!strcmp(arg, "-clear_all")) {
2976
} else if (!strcmp(arg, "-remap")) {
2978
remap_file = strdup(argv[++i]);
2979
} else if (!strcmp(arg, "-norepeat")) {
2982
char *s = argv[i+1];
2986
if (isdigit((unsigned char) (*s))) {
2987
no_repeat_countdown = atoi(argv[++i]);
2990
} else if (!strcmp(arg, "-repeat")) {
2992
} else if (!strcmp(arg, "-nofb")) {
2994
} else if (!strcmp(arg, "-nobell")) {
2997
} else if (!strcmp(arg, "-nosel")) {
2998
watch_selection = 0;
3000
watch_clipboard = 0;
3001
} else if (!strcmp(arg, "-noprimary")) {
3003
} else if (!strcmp(arg, "-nosetprimary")) {
3005
} else if (!strcmp(arg, "-noclipboard")) {
3006
watch_clipboard = 0;
3007
} else if (!strcmp(arg, "-nosetclipboard")) {
3009
} else if (!strcmp(arg, "-seldir")) {
3011
sel_direction = strdup(argv[++i]);
3012
} else if (!strcmp(arg, "-cursor")) {
3015
char *s = argv[i+1];
3016
if (known_cursors_mode(s)) {
3017
multiple_cursors_mode = strdup(s);
3019
if (!strcmp(s, "none")) {
3024
} else if (!strcmp(arg, "-nocursor")) {
3025
multiple_cursors_mode = strdup("none");
3027
} else if (!strcmp(arg, "-cursor_drag")) {
3028
cursor_drag_changes = 1;
3029
} else if (!strcmp(arg, "-nocursor_drag")) {
3030
cursor_drag_changes = 0;
3031
} else if (!strcmp(arg, "-arrow")) {
3033
alt_arrow = atoi(argv[++i]);
3034
} else if (!strcmp(arg, "-xfixes")) {
3036
} else if (!strcmp(arg, "-noxfixes")) {
3038
} else if (!strcmp(arg, "-alphacut")) {
3040
alpha_threshold = atoi(argv[++i]);
3041
} else if (!strcmp(arg, "-alphafrac")) {
3043
alpha_frac = atof(argv[++i]);
3044
} else if (!strcmp(arg, "-alpharemove")) {
3046
} else if (!strcmp(arg, "-noalphablend")) {
3048
} else if (!strcmp(arg, "-nocursorshape")) {
3049
cursor_shape_updates = 0;
3050
} else if (!strcmp(arg, "-cursorpos")) {
3051
cursor_pos_updates = 1;
3053
} else if (!strcmp(arg, "-nocursorpos")) {
3054
cursor_pos_updates = 0;
3055
} else if (!strcmp(arg, "-xwarppointer")) {
3056
use_xwarppointer = 1;
3057
} else if (!strcmp(arg, "-noxwarppointer")) {
3058
use_xwarppointer = 0;
3059
got_noxwarppointer = 1;
3060
} else if (!strcmp(arg, "-buttonmap")) {
3062
pointer_remap = strdup(argv[++i]);
3063
} else if (!strcmp(arg, "-nodragging")) {
3066
} else if (!strcmp(arg, "-ncache") || !strcmp(arg, "-nc")) {
3068
char *s = argv[i+1];
3073
ncache = ncache_default;
3076
ncache = ncache_default;
3078
if (ncache % 2 != 0) {
3081
} else if (!strcmp(arg, "-noncache") || !strcmp(arg, "-nonc")) {
3083
} else if (!strcmp(arg, "-ncache_cr") || !strcmp(arg, "-nc_cr")) {
3084
ncache_copyrect = 1;
3085
} else if (!strcmp(arg, "-ncache_no_moveraise") || !strcmp(arg, "-nc_no_moveraise")) {
3086
ncache_wf_raises = 1;
3087
} else if (!strcmp(arg, "-ncache_no_dtchange") || !strcmp(arg, "-nc_no_dtchange")) {
3088
ncache_dt_change = 0;
3089
} else if (!strcmp(arg, "-ncache_no_rootpixmap") || !strcmp(arg, "-nc_no_rootpixmap")) {
3090
ncache_xrootpmap = 0;
3091
} else if (!strcmp(arg, "-ncache_keep_anims") || !strcmp(arg, "-nc_keep_anims")) {
3092
ncache_keep_anims = 1;
3093
} else if (!strcmp(arg, "-ncache_old_wm") || !strcmp(arg, "-nc_old_wm")) {
3095
} else if (!strcmp(arg, "-ncache_pad") || !strcmp(arg, "-nc_pad")) {
3097
ncache_pad = atoi(argv[++i]);
3098
} else if (!strcmp(arg, "-debug_ncache")) {
3101
} else if (!strcmp(arg, "-wireframe")
3102
|| !strcmp(arg, "-wf")) {
3105
char *s = argv[i+1];
3107
wireframe_str = strdup(argv[++i]);
3110
} else if (!strcmp(arg, "-nowireframe")
3111
|| !strcmp(arg, "-nowf")) {
3113
} else if (!strcmp(arg, "-nowireframelocal")
3114
|| !strcmp(arg, "-nowfl")) {
3115
wireframe_local = 0;
3116
} else if (!strcmp(arg, "-wirecopyrect")
3117
|| !strcmp(arg, "-wcr")) {
3119
set_wirecopyrect_mode(argv[++i]);
3120
got_wirecopyrect = 1;
3121
} else if (!strcmp(arg, "-nowirecopyrect")
3122
|| !strcmp(arg, "-nowcr")) {
3123
set_wirecopyrect_mode("never");
3124
} else if (!strcmp(arg, "-debug_wireframe")
3125
|| !strcmp(arg, "-dwf")) {
3127
} else if (!strcmp(arg, "-scrollcopyrect")
3128
|| !strcmp(arg, "-scr")) {
3130
set_scrollcopyrect_mode(argv[++i]);
3131
got_scrollcopyrect = 1;
3132
} else if (!strcmp(arg, "-noscrollcopyrect")
3133
|| !strcmp(arg, "-noscr")) {
3134
set_scrollcopyrect_mode("never");
3135
} else if (!strcmp(arg, "-scr_area")) {
3138
tn = atoi(argv[++i]);
3140
scrollcopyrect_min_area = tn;
3142
} else if (!strcmp(arg, "-scr_skip")) {
3144
scroll_skip_str = strdup(argv[++i]);
3145
} else if (!strcmp(arg, "-scr_inc")) {
3147
scroll_good_str = strdup(argv[++i]);
3148
} else if (!strcmp(arg, "-scr_keys")) {
3150
scroll_key_list_str = strdup(argv[++i]);
3151
} else if (!strcmp(arg, "-scr_term")) {
3153
scroll_term_str = strdup(argv[++i]);
3154
} else if (!strcmp(arg, "-scr_keyrepeat")) {
3156
max_keyrepeat_str = strdup(argv[++i]);
3157
} else if (!strcmp(arg, "-scr_parms")) {
3159
scroll_copyrect_str = strdup(argv[++i]);
3160
} else if (!strcmp(arg, "-fixscreen")) {
3162
screen_fixup_str = strdup(argv[++i]);
3163
} else if (!strcmp(arg, "-debug_scroll")
3164
|| !strcmp(arg, "-ds")) {
3166
} else if (!strcmp(arg, "-noxrecord")) {
3168
} else if (!strcmp(arg, "-pointer_mode")
3169
|| !strcmp(arg, "-pm")) {
3173
if ((p = strchr(s, ':')) != NULL) {
3174
ui_skip = atoi(p+1);
3175
if (! ui_skip) ui_skip = 1;
3178
if (atoi(s) < 1 || atoi(s) > pointer_mode_max) {
3179
rfbLog("pointer_mode out of range 1-%d: %d\n",
3180
pointer_mode_max, atoi(s));
3182
pointer_mode = atoi(s);
3183
got_pointer_mode = pointer_mode;
3185
} else if (!strcmp(arg, "-input_skip")) {
3187
ui_skip = atoi(argv[++i]);
3188
if (! ui_skip) ui_skip = 1;
3189
} else if (!strcmp(arg, "-allinput")) {
3191
} else if (!strcmp(arg, "-noallinput")) {
3193
} else if (!strcmp(arg, "-speeds")) {
3195
speeds_str = strdup(argv[++i]);
3196
} else if (!strcmp(arg, "-wmdt")) {
3198
wmdt_str = strdup(argv[++i]);
3199
} else if (!strcmp(arg, "-debug_pointer")
3200
|| !strcmp(arg, "-dp")) {
3202
} else if (!strcmp(arg, "-debug_keyboard")
3203
|| !strcmp(arg, "-dk")) {
3205
} else if (!strcmp(arg, "-debug_xdamage")) {
3207
} else if (!strcmp(arg, "-defer")) {
3209
defer_update = atoi(argv[++i]);
3211
} else if (!strcmp(arg, "-wait")) {
3213
waitms = atoi(argv[++i]);
3214
} else if (!strcmp(arg, "-wait_ui")) {
3216
wait_ui = atof(argv[++i]);
3217
} else if (!strcmp(arg, "-nowait_bog")) {
3219
} else if (!strcmp(arg, "-slow_fb")) {
3221
slow_fb = atof(argv[++i]);
3222
} else if (!strcmp(arg, "-xrefresh")) {
3224
xrefresh = atof(argv[++i]);
3225
} else if (!strcmp(arg, "-readtimeout")) {
3227
rfbMaxClientWait = atoi(argv[++i]) * 1000;
3228
} else if (!strcmp(arg, "-ping")) {
3230
ping_interval = atoi(argv[++i]);
3231
} else if (!strcmp(arg, "-nap")) {
3233
} else if (!strcmp(arg, "-nonap")) {
3235
} else if (!strcmp(arg, "-sb")) {
3237
screen_blank = atoi(argv[++i]);
3238
} else if (!strcmp(arg, "-nofbpm")) {
3240
} else if (!strcmp(arg, "-fbpm")) {
3242
} else if (!strcmp(arg, "-nodpms")) {
3244
} else if (!strcmp(arg, "-dpms")) {
3246
} else if (!strcmp(arg, "-forcedpms")) {
3248
} else if (!strcmp(arg, "-clientdpms")) {
3250
} else if (!strcmp(arg, "-noserverdpms")) {
3252
} else if (!strcmp(arg, "-noultraext")) {
3254
} else if (!strcmp(arg, "-xdamage")) {
3256
} else if (!strcmp(arg, "-noxdamage")) {
3258
} else if (!strcmp(arg, "-xd_area")) {
3261
tn = atoi(argv[++i]);
3263
xdamage_max_area = tn;
3265
} else if (!strcmp(arg, "-xd_mem")) {
3268
f = atof(argv[++i]);
3272
} else if (!strcmp(arg, "-sigpipe") || !strcmp(arg, "-sig")) {
3274
if (known_sigpipe_mode(argv[++i])) {
3275
sigpipe = strdup(argv[i]);
3277
fprintf(stderr, "invalid -sigpipe arg: %s, must"
3278
" be \"ignore\" or \"exit\"\n", argv[i]);
3281
#if LIBVNCSERVER_HAVE_LIBPTHREAD
3282
} else if (!strcmp(arg, "-threads")) {
3284
} else if (!strcmp(arg, "-nothreads")) {
3287
} else if (!strcmp(arg, "-fs")) {
3289
fs_frac = atof(argv[++i]);
3290
} else if (!strcmp(arg, "-gaps")) {
3292
gaps_fill = atoi(argv[++i]);
3293
} else if (!strcmp(arg, "-grow")) {
3295
grow_fill = atoi(argv[++i]);
3296
} else if (!strcmp(arg, "-fuzz")) {
3298
tile_fuzz = atoi(argv[++i]);
3299
} else if (!strcmp(arg, "-debug_tiles")
3300
|| !strcmp(arg, "-dbt")) {
3302
} else if (!strcmp(arg, "-debug_grabs")) {
3304
} else if (!strcmp(arg, "-debug_sel")) {
3306
} else if (!strcmp(arg, "-grab_buster")) {
3308
} else if (!strcmp(arg, "-nograb_buster")) {
3310
} else if (!strcmp(arg, "-snapfb")) {
3312
} else if (!strcmp(arg, "-rawfb")) {
3314
raw_fb_str = strdup(argv[++i]);
3315
if (strstr(raw_fb_str, "vnc:") == raw_fb_str) {
3318
} else if (!strcmp(arg, "-freqtab")) {
3320
freqtab = strdup(argv[++i]);
3321
} else if (!strcmp(arg, "-pipeinput")) {
3323
pipeinput_str = strdup(argv[++i]);
3324
} else if (!strcmp(arg, "-macnodim")) {
3325
macosx_nodimming = 1;
3326
} else if (!strcmp(arg, "-macnosleep")) {
3328
} else if (!strcmp(arg, "-macnosaver")) {
3329
macosx_noscreensaver = 1;
3330
} else if (!strcmp(arg, "-macnowait")) {
3331
macosx_wait_for_switch = 0;
3332
} else if (!strcmp(arg, "-macwheel")) {
3334
macosx_mouse_wheel_speed = atoi(argv[++i]);
3335
} else if (!strcmp(arg, "-macnoswap")) {
3337
} else if (!strcmp(arg, "-macnoresize")) {
3339
} else if (!strcmp(arg, "-maciconanim")) {
3341
macosx_icon_anim_time = atoi(argv[++i]);
3342
} else if (!strcmp(arg, "-macmenu")) {
3343
macosx_ncache_macmenu = 1;
3344
} else if (!strcmp(arg, "-gui")) {
3347
char *s = argv[i+1];
3349
gui_str = strdup(s);
3350
if (strstr(gui_str, "setp")) {
3356
} else if (!strcmp(arg, "-remote") || !strcmp(arg, "-R")
3357
|| !strcmp(arg, "-r") || !strcmp(arg, "-remote-control")) {
3363
/* accidental leading '-' */
3366
if (!strcmp(str, "ping")) {
3367
query_cmd = strdup(str);
3369
remote_cmd = strdup(str);
3371
if (remote_cmd && strchr(remote_cmd, ':') == NULL) {
3372
/* interpret -R -scale 3/4 at least */
3373
if (i < argc-1 && *(argv[i+1]) != '-') {
3376
/* it must be the parameter value */
3378
n = strlen(remote_cmd) + strlen(argv[i]) + 2;
3380
str = (char *) malloc(n);
3381
sprintf(str, "%s:%s", remote_cmd, argv[i]);
3388
} else if (!strcmp(arg, "-query") || !strcmp(arg, "-Q")) {
3390
query_cmd = strdup(argv[++i]);
3393
} else if (!strcmp(arg, "-QD")) {
3395
query_cmd = strdup(argv[++i]);
3397
} else if (!strcmp(arg, "-sync")) {
3399
} else if (!strcmp(arg, "-nosync")) {
3401
} else if (!strcmp(arg, "-noremote")) {
3402
accept_remote_cmds = 0;
3403
} else if (!strcmp(arg, "-yesremote")) {
3404
accept_remote_cmds = 1;
3405
} else if (!strcmp(arg, "-unsafe")) {
3406
safe_remote_only = 0;
3407
} else if (!strcmp(arg, "-privremote")) {
3409
} else if (!strcmp(arg, "-safer")) {
3411
} else if (!strcmp(arg, "-nocmds")) {
3412
no_external_cmds = 1;
3413
} else if (!strcmp(arg, "-allowedcmds")) {
3415
allowed_external_cmds = strdup(argv[++i]);
3416
} else if (!strcmp(arg, "-deny_all")) {
3418
} else if (!strcmp(arg, "-httpdir")) {
3420
http_dir = strdup(argv[++i]);
3423
if (!strcmp(arg, "-desktop") && i < argc-1) {
3425
rfb_desktop_name = strdup(argv[i+1]);
3427
if (!strcmp(arg, "-passwd")) {
3431
if (!strcmp(arg, "-rfbauth")) {
3434
if (!strcmp(arg, "-rfbwait")) {
3437
if (!strcmp(arg, "-deferupdate")) {
3438
got_deferupdate = 1;
3440
if (!strcmp(arg, "-rfbport") && i < argc-1) {
3442
got_rfbport_val = atoi(argv[i+1]);
3444
if (!strcmp(arg, "-alwaysshared ")) {
3445
got_alwaysshared = 1;
3447
if (!strcmp(arg, "-nevershared")) {
3448
got_nevershared = 1;
3450
if (!strcmp(arg, "-listen") && i < argc-1) {
3451
listen_str = strdup(argv[i+1]);
3453
/* otherwise copy it for libvncserver use below. */
3454
if (!strcmp(arg, "-ultrafilexfer")) {
3455
if (argc_vnc + 2 < argc_vnc_max) {
3456
argv_vnc[argc_vnc++] = strdup("-rfbversion");
3457
argv_vnc[argc_vnc++] = strdup("3.6");
3458
argv_vnc[argc_vnc++] = strdup("-permitfiletransfer");
3460
} else if (argc_vnc < argc_vnc_max) {
3461
argv_vnc[argc_vnc++] = strdup(arg);
3463
rfbLog("too many arguments.\n");
3469
orig_use_xdamage = use_xdamage;
3471
if (!auto_port && getenv("AUTO_PORT")) {
3472
auto_port = atoi(getenv("AUTO_PORT"));
3475
if (getenv("X11VNC_LOOP_MODE")) {
3476
if (bg && !getenv("X11VNC_LOOP_MODE_BG")) {
3478
fprintf(stderr, "disabling -bg in -loop "
3485
fprintf(stderr, "disabling -inetd in -loop "
3492
if (launch_gui && (query_cmd || remote_cmd)) {
3502
/* we need this for gui since no X properties */
3503
if (!client_connect_file && !client_connect) {
3504
char *user = get_user_name();
3505
char *str = (char *) malloc(strlen(user) + strlen("/tmp/x11vnc-macosx-remote.") + 1);
3507
sprintf(str, "/tmp/x11vnc-macosx-remote.%s", user);
3508
if (!remote_cmd && !query_cmd) {
3510
if (stat(str, &sb) != 0) {
3511
int fd = open(str, O_WRONLY|O_EXCL|O_CREAT, 0600);
3514
client_connect_file = str;
3518
client_connect_file = str;
3520
if (client_connect_file) {
3521
rfbLog("MacOS X: set -connect file to %s\n", client_connect_file);
3528
if (SHOW_NO_PASSWORD_WARNING && !nopw) {
3531
do_gui(gui_str, sleep);
3535
if (logfile_append) {
3536
n = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666);
3538
n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
3541
fprintf(stderr, "error opening logfile: %s\n", logfile);
3545
if (dup2(n, 2) < 0) {
3546
fprintf(stderr, "dup2 failed\n");
3554
if (inetd && quiet && !logfile) {
3557
* Redir stderr to /dev/null under -inetd and -quiet
3558
* but no -o logfile. Typical problem:
3559
* Xlib: extension "RECORD" missing on display ":1.0".
3560
* If they want this info, they should use -o logfile,
3561
* or no -q and 2>logfile.
3563
n = open("/dev/null", O_WRONLY);
3565
if (dup2(n, 2) >= 0) {
3572
if (! quiet && ! inetd) {
3574
for (i=1; i < argc_vnc; i++) {
3575
rfbLog("passing arg to libvncserver: %s\n", argv_vnc[i]);
3576
if (!strcmp(argv_vnc[i], "-passwd")) {
3582
if (remote_cmd || query_cmd) {
3584
* no need to open DISPLAY, just write it to the file now
3585
* similar for query_default.
3587
if (client_connect_file || query_default) {
3588
int rc = do_remote_query(remote_cmd, query_cmd,
3589
remote_sync, query_default);
3596
if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile && !unixpw) {
3597
char *f, *h = getenv("HOME");
3599
int found = 0, set_rfbauth = 0;
3602
rfbLog("HOME unset in -usepw mode.\n");
3605
f = (char *) malloc(strlen(h)+strlen("/.vnc/passwdfile") + 1);
3607
sprintf(f, "%s/.vnc/passwd", h);
3608
if (stat(f, &sbuf) == 0) {
3611
rfbLog("-usepw: found %s\n", f);
3617
sprintf(f, "%s/.vnc/passwdfile", h);
3618
if (! found && stat(f, &sbuf) == 0) {
3621
rfbLog("-usepw: found %s\n", f);
3624
passwdfile = strdup(f);
3627
#if LIBVNCSERVER_HAVE_FORK
3628
#if LIBVNCSERVER_HAVE_SYS_WAIT_H
3629
#if LIBVNCSERVER_HAVE_WAITPID
3634
} else if (pid == 0) {
3635
execlp(argv[0], argv[0], "-storepasswd",
3640
waitpid(pid, &s, 0);
3641
if (WIFEXITED(s) && WEXITSTATUS(s) == 0) {
3653
sprintf(f, "%s/.vnc/passwd", h);
3654
if (argc_vnc < 100) {
3655
argv_vnc[argc_vnc++] = strdup("-rfbauth");
3659
if (argc_vnc < 100) {
3660
argv_vnc[argc_vnc++] = strdup(f);
3666
fprintf(stderr, "x11vnc -usepw: could not find"
3667
" a password to use.\n");
3673
if (got_rfbauth && (got_passwd || got_viewpasswd || got_passwdfile)) {
3674
fprintf(stderr, "option -rfbauth is incompatible with:\n");
3675
fprintf(stderr, " -passwd, -viewpasswd, and -passwdfile\n");
3678
if (got_passwdfile && (got_passwd || got_viewpasswd)) {
3679
fprintf(stderr, "option -passwdfile is incompatible with:\n");
3680
fprintf(stderr, " -passwd and -viewpasswd\n");
3685
* If -passwd was used, clear it out of argv. This does not
3686
* work on all UNIX, have to use execvp() in general...
3690
for (i=pw_loc; i <= pw_loc+1; i++) {
3696
} else if (passwdfile) {
3697
/* read passwd(s) from file */
3698
if (strstr(passwdfile, "cmd:") == passwdfile ||
3699
strstr(passwdfile, "custom:") == passwdfile) {
3701
sprintf(tstr, "%f", dnow());
3702
if ((q = strrchr(tstr, '.')) == NULL) {
3707
/* never used under cmd:, used to force auth */
3708
argv_vnc[argc_vnc++] = strdup("-passwd");
3709
argv_vnc[argc_vnc++] = strdup(q);
3710
} else if (read_passwds(passwdfile)) {
3711
argv_vnc[argc_vnc++] = strdup("-passwd");
3712
argv_vnc[argc_vnc++] = strdup(passwd_list[0]);
3715
pw_loc = 100; /* just for pw_loc check below */
3719
for (i=vpw_loc; i <= vpw_loc+1; i++) {
3726
#ifdef HARDWIRE_PASSWD
3727
if (!got_rfbauth && !got_passwd) {
3728
argv_vnc[argc_vnc++] = strdup("-passwd");
3729
argv_vnc[argc_vnc++] = strdup(HARDWIRE_PASSWD);
3734
#ifdef HARDWIRE_VIEWPASSWD
3735
if (!got_rfbauth && got_passwd && !viewonly_passwd && !passwd_list) {
3736
viewonly_passwd = strdup(HARDWIRE_VIEWPASSWD);
3739
if (viewonly_passwd && pw_loc < 0) {
3740
rfbLog("-passwd must be supplied when using -viewpasswd\n");
3744
if (SHOW_NO_PASSWORD_WARNING) {
3745
char message[] = "-rfbauth, -passwdfile, -passwd password, "
3746
"or -unixpw required.";
3748
nopassword_warning_msg(got_localhost);
3751
rfbLog("%s\n", message);
3754
#if PASSWD_UNLESS_NOPW
3756
rfbLog("%s\n", message);
3760
message[0] = '\0'; /* avoid compiler warning */
3765
rfbLog("-safer mode:\n");
3766
rfbLog(" vnc_connect=0\n");
3767
rfbLog(" accept_remote_cmds=0\n");
3768
rfbLog(" safe_remote_only=1\n");
3769
rfbLog(" launch_gui=0\n");
3772
accept_remote_cmds = 0;
3773
safe_remote_only = 1;
3777
if (users_list && strchr(users_list, '.')) {
3778
char *p, *q, *tmp = (char *) malloc(strlen(users_list)+1);
3779
char *str = strdup(users_list);
3784
n = strlen(users_list) + 1;
3785
user2group = (char **) malloc(n * sizeof(char *));
3786
for (i=0; i<n; i++) {
3787
user2group[i] = NULL;
3791
p = strtok(str, ",");
3792
if (db) fprintf(stderr, "users_list: %s\n", users_list);
3794
if (tmp[0] != '\0') {
3799
char *s = strchr(p, '=');
3805
if (s[0] == '+') s++;
3806
user2group[i++] = strdup(s);
3807
if (db) fprintf(stderr, "u2g: %s\n", s);
3811
p = strtok(NULL, ",");
3815
if (db) fprintf(stderr, "users_list: %s\n", users_list);
3822
if (! use_stunnel && ! use_openssl) {
3823
if (getenv("UNIXPW_DISABLE_LOCALHOST")) {
3824
rfbLog("Skipping -ssl/-stunnel requirement"
3826
rfbLog("UNIXPW_DISABLE_LOCALHOST setting.\n");
3827
} else if (have_ssh_env()) {
3828
char *s = getenv("SSH_CONNECTION");
3829
if (! s) s = getenv("SSH_CLIENT");
3830
if (! s) s = "SSH_CONNECTION";
3831
fprintf(stderr, "\n");
3832
rfbLog("Skipping -ssl/-stunnel constraint in"
3834
rfbLog("mode, assuming your SSH encryption"
3836
rfbLog("Setting -localhost in SSH + -unixpw"
3838
fprintf(stderr, "\n");
3839
allow_list = strdup("127.0.0.1");
3845
if (openssl_present()) {
3846
rfbLog("set -ssl in -unixpw mode.\n");
3849
rfbLog("could not set -ssl in -inetd"
3850
" + -unixpw mode.\n");
3853
rfbLog("set -stunnel in -unixpw mode.\n");
3860
rfbLog("disabling -threads under -unixpw\n");
3865
if (use_stunnel && ! got_localhost) {
3866
if (! getenv("STUNNEL_DISABLE_LOCALHOST") &&
3867
! getenv("UNIXPW_DISABLE_LOCALHOST")) {
3869
rfbLog("Setting -localhost in -stunnel mode.\n");
3871
allow_list = strdup("127.0.0.1");
3875
if (ssl_verify && ! use_stunnel && ! use_openssl) {
3876
rfbLog("-sslverify must be used with -ssl or -stunnel\n");
3879
if (https_port_num >= 0 && ! use_openssl) {
3880
rfbLog("-https must be used with -ssl\n");
3884
/* fixup settings that do not make sense */
3886
if (use_threads && nofb && cursor_pos_updates) {
3888
rfbLog("disabling -threads under -nofb -cursorpos\n");
3892
if (tile_fuzz < 1) {
3899
if (alpha_threshold < 0) {
3900
alpha_threshold = 0;
3902
if (alpha_threshold > 256) {
3903
alpha_threshold = 256;
3905
if (alpha_frac < 0.0) {
3908
if (alpha_frac > 1.0) {
3915
if (cmap8to24 && overlay) {
3917
rfbLog("disabling -overlay in -8to24 mode.\n");
3922
if (tightfilexfer && view_only) {
3924
rfbLog("setting -notightfilexfer in -viewonly mode.\n");
3926
/* how to undo via -R? */
3939
if (flip_byte_order && using_shm && ! quiet) {
3940
rfbLog("warning: -flipbyte order only works with -noshm\n");
3943
if (! wireframe_copyrect) {
3944
set_wirecopyrect_mode(NULL);
3946
if (! scroll_copyrect) {
3947
set_scrollcopyrect_mode(NULL);
3949
if (screen_fixup_str) {
3952
initialize_scroll_matches();
3953
initialize_scroll_term();
3954
initialize_max_keyrepeat();
3956
/* increase rfbwait if threaded */
3957
if (use_threads && ! got_rfbwait) {
3958
rfbMaxClientWait = 604800000;
3961
/* no framebuffer (Win2VNC) mode */
3964
/* disable things that do not make sense with no fb */
3967
if (! got_deferupdate && ! got_defer) {
3968
/* reduce defer time under -nofb */
3969
defer_update = defer_update_nofb;
3971
if (got_pointer_mode < 0) {
3972
pointer_mode = POINTER_MODE_NOFB;
3977
ncache_beta_tester = 1;
3983
if (try_http || got_httpdir) {
3984
/* JVM usually not set to handle all the memory */
3995
set_raw_fb_params(0);
3997
if (! got_deferupdate) {
3999
sprintf(tmp, "%d", defer_update);
4000
argv_vnc[argc_vnc++] = strdup("-deferupdate");
4001
argv_vnc[argc_vnc++] = strdup(tmp);
4004
if (debug_pointer || debug_keyboard) {
4006
rfbLog("disabling -bg/-q under -debug_pointer"
4007
"/-debug_keyboard\n");
4013
/* initialize added_keysyms[] array to zeros */
4014
add_keysym(NoSymbol);
4016
/* tie together cases of -localhost vs. -listen localhost */
4018
if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
4019
listen_str = strdup("localhost");
4020
argv_vnc[argc_vnc++] = strdup("-listen");
4021
argv_vnc[argc_vnc++] = strdup(listen_str);
4023
} else if (!strcmp(listen_str, "localhost") ||
4024
!strcmp(listen_str, "127.0.0.1")) {
4025
allow_list = strdup("127.0.0.1");
4028
/* set OS struct UT */
4031
initialize_crash_handler();
4035
print_settings(try_http, bg, gui_str);
4037
rfbLog("x11vnc version: %s\n", lastmod);
4045
/* open the X display: */
4047
set_env("XAUTHORITY", auth_file);
4048
if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY"));
4050
#if LIBVNCSERVER_HAVE_XKEYBOARD
4052
* Disable XKEYBOARD before calling XOpenDisplay()
4053
* this should be used if there is ambiguity in the keymapping.
4056
Bool rc = XkbIgnoreExtension(True);
4058
rfbLog("Disabling xkb XKEYBOARD extension. rc=%d\n",
4063
if (! quiet) rfbLog("Disabling bell.\n");
4068
use_xkb_modtweak = 0;
4071
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
4072
if (tightfilexfer) {
4073
rfbLog("rfbRegisterTightVNCFileTransferExtension: 6\n");
4074
rfbRegisterTightVNCFileTransferExtension();
4076
if (0) rfbLog("rfbUnregisterTightVNCFileTransferExtension: 3\n");
4077
rfbUnregisterTightVNCFileTransferExtension();
4081
initialize_allowed_input();
4083
if (display_N && !got_rfbport) {
4086
ud = getenv("DISPLAY");
4088
if (ud && strstr(ud, "cmd=") == NULL) {
4091
p = strrchr(ud, ':');
4094
char *q = strchr(p, '.');
4099
if (argc_vnc+1 < argc_vnc_max) {
4101
sprintf(Nstr, "%d", (5900 + N) % 65536);
4102
argv_vnc[argc_vnc++] = strdup("-rfbport");
4103
argv_vnc[argc_vnc++] = strdup(Nstr);
4111
if (users_list && strstr(users_list, "lurk=")) {
4113
rfbLog("warning: -display does not make sense in "
4114
"\"lurk=\" mode...\n");
4116
lurk_loop(users_list);
4118
} else if (use_dpy && strstr(use_dpy, "WAIT:") == use_dpy) {
4119
char *mcm = multiple_cursors_mode;
4121
waited_for_client = wait_for_client(&argc_vnc, argv_vnc,
4122
try_http && ! got_httpdir);
4124
if (!mcm && multiple_cursors_mode) {
4125
free(multiple_cursors_mode);
4126
multiple_cursors_mode = NULL;
4131
if (use_dpy && !strcmp(use_dpy, "console")) {
4136
dpy = XOpenDisplay_wr(use_dpy);
4138
} else if (!subwin && getenv("DISPLAY")
4139
&& strstr(getenv("DISPLAY"), "/tmp/") ) {
4140
/* e.g. /tmp/launch-XlspvM/:0 on leopard */
4141
rfbLog("MacOSX: Ignoring $DISPLAY '%s'\n", getenv("DISPLAY"));
4142
rfbLog("MacOSX: Use -display $DISPLAY to force it.\n");
4144
} else if ( (use_dpy = getenv("DISPLAY")) ) {
4145
dpy = XOpenDisplay_wr(use_dpy);
4147
dpy = XOpenDisplay_wr("");
4150
if (terminal_services_daemon != NULL) {
4151
terminal_services(terminal_services_daemon);
4156
if (! dpy && ! raw_fb_str) {
4157
raw_fb_str = strdup("console");
4161
if (! dpy && raw_fb_str) {
4162
rfbLog("continuing without X display in -rawfb mode, "
4163
"hold on tight..\n");
4164
goto raw_fb_pass_go_and_collect_200_dollars;
4167
if (! dpy && ! use_dpy && ! getenv("DISPLAY")) {
4171
rfbLog("*** XOpenDisplay failed. No -display or DISPLAY.\n");
4172
rfbLog("*** Trying \":0\" in %d seconds. Press Ctrl-C to"
4175
for (i=1; i<=s; i++) {
4176
fprintf(stderr, "%d ", i);
4179
fprintf(stderr, "\n");
4181
dpy = XOpenDisplay_wr(use_dpy);
4183
rfbLog("*** XOpenDisplay of \":0\" successful.\n");
4186
if (quiet) rfbLogEnable(0);
4191
if (!d) d = getenv("DISPLAY");
4194
fprintf(stderr, "\n");
4195
rfbLog("***************************************\n", d);
4196
rfbLog("*** XOpenDisplay failed (%s)\n", d);
4197
xopen_display_fail_message(d);
4199
} else if (use_dpy) {
4200
if (! quiet) rfbLog("Using X display %s\n", use_dpy);
4202
if (! quiet) rfbLog("Using default X display.\n");
4206
scr = DefaultScreen(dpy);
4207
rootwin = RootWindow(dpy, scr);
4209
if (ncache_beta_tester) {
4210
int h = DisplayHeight(dpy, scr);
4211
int w = DisplayWidth(dpy, scr);
4212
int mem = (w * h * 4) / (1000 * 1000), MEM = 96;
4213
if (mem < 1) mem = 1;
4215
/* limit poor, unsuspecting beta tester's viewer to 96 MB */
4216
if ( (ncache+2) * mem > MEM ) {
4217
int n = (MEM/mem) - 2;
4227
Window save = window;
4233
if (! quiet && ! raw_fb_str) {
4235
rfbLog("------------------ USEFUL INFORMATION ------------------\n");
4238
if (remote_cmd || query_cmd) {
4239
int rc = do_remote_query(remote_cmd, query_cmd, remote_sync,
4244
usleep(30 * 1000); /* still needed? */
4245
XCloseDisplay_wr(dpy);
4250
if (! remote_control_access_ok()) {
4251
rfbLog("** Disabling remote commands in -privremote mode.\n");
4252
accept_remote_cmds = 0;
4256
sync_tod_with_servertime();
4258
spawn_grab_buster();
4261
#if LIBVNCSERVER_HAVE_LIBXFIXES
4262
if (! XFixesQueryExtension(dpy, &xfixes_base_event_type, &er)) {
4263
if (! quiet && ! raw_fb_str) {
4264
rfbLog("Disabling XFIXES mode: display does not support it.\n");
4266
xfixes_base_event_type = 0;
4272
if (! xfixes_present) {
4276
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
4277
if (! XDamageQueryExtension(dpy, &xdamage_base_event_type, &er)) {
4278
if (! quiet && ! raw_fb_str) {
4279
rfbLog("Disabling X DAMAGE mode: display does not support it.\n");
4281
xdamage_base_event_type = 0;
4282
xdamage_present = 0;
4284
xdamage_present = 1;
4287
if (! xdamage_present) {
4290
if (! quiet && xdamage_present && use_xdamage && ! raw_fb_str) {
4291
rfbLog("X DAMAGE available on display, using it for polling hints.\n");
4292
rfbLog(" To disable this behavior use: '-noxdamage'\n");
4295
if (! quiet && wireframe && ! raw_fb_str) {
4297
rfbLog("Wireframing: -wireframe mode is in effect for window moves.\n");
4298
rfbLog(" If this yields undesired behavior (poor response, painting\n");
4299
rfbLog(" errors, etc) it may be disabled:\n");
4300
rfbLog(" - use '-nowf' to disable wireframing completely.\n");
4301
rfbLog(" - use '-nowcr' to disable the Copy Rectangle after the\n");
4302
rfbLog(" moved window is released in the new position.\n");
4303
rfbLog(" Also see the -help entry for tuning parameters.\n");
4304
rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
4305
rfbLog(" repaint the screen, also see the -fixscreen option for\n");
4306
rfbLog(" periodic repaints.\n");
4307
if (scale_str && !strstr(scale_str, "nocr")) {
4308
rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
4312
overlay_present = 0;
4313
#if defined(SOLARIS_OVERLAY) && !NO_X11
4314
if (! XQueryExtension(dpy, "SUN_OVL", &maj, &ev, &er)) {
4315
if (! quiet && overlay && ! raw_fb_str) {
4316
rfbLog("Disabling -overlay: SUN_OVL extension not available.\n");
4319
overlay_present = 1;
4322
#if defined(IRIX_OVERLAY) && !NO_X11
4323
if (! XReadDisplayQueryExtension(dpy, &ev, &er)) {
4324
if (! quiet && overlay && ! raw_fb_str) {
4325
rfbLog("Disabling -overlay: IRIX ReadDisplay extension not available.\n");
4328
overlay_present = 1;
4331
if (overlay && !overlay_present) {
4336
/* cursor shapes setup */
4337
if (! multiple_cursors_mode) {
4338
multiple_cursors_mode = strdup("default");
4341
if(!strcmp(multiple_cursors_mode, "default")
4342
&& xfixes_present && use_xfixes) {
4343
free(multiple_cursors_mode);
4344
multiple_cursors_mode = strdup("most");
4346
if (! quiet && ! raw_fb_str) {
4348
rfbLog("XFIXES available on display, resetting cursor mode\n");
4349
rfbLog(" to: '-cursor most'.\n");
4350
rfbLog(" to disable this behavior use: '-cursor arrow'\n");
4351
rfbLog(" or '-noxfixes'.\n");
4354
if(!strcmp(multiple_cursors_mode, "most")) {
4355
if (xfixes_present && use_xfixes &&
4356
overlay_cursor == 1) {
4357
if (! quiet && ! raw_fb_str) {
4358
rfbLog("using XFIXES for cursor drawing.\n");
4367
if (flash_cmap && ! quiet && ! raw_fb_str) {
4368
rfbLog("warning: -flashcmap may be incompatible with -overlay\n");
4370
if (show_cursor && overlay_cursor) {
4371
char *s = multiple_cursors_mode;
4372
if (*s == 'X' || !strcmp(s, "some") ||
4373
!strcmp(s, "arrow")) {
4375
* user wants these modes, so disable fb cursor
4380
* "default" and "most", we turn off
4381
* show_cursor since it will automatically
4382
* be in the framebuffer.
4389
initialize_cursors_mode();
4391
/* check for XTEST */
4392
if (! XTestQueryExtension_wr(dpy, &ev, &er, &maj, &min)) {
4393
if (! quiet && ! raw_fb_str) {
4395
rfbLog("WARNING: XTEST extension not available (either missing from\n");
4396
rfbLog(" display or client library libXtst missing at build time).\n");
4397
rfbLog(" MOST user input (pointer and keyboard) will be DISCARDED.\n");
4398
rfbLog(" If display does have XTEST, be sure to build x11vnc with\n");
4399
rfbLog(" a working libXtst build environment (e.g. libxtst-dev,\n");
4400
rfbLog(" or other packages).\n");
4401
rfbLog("No XTEST extension, switching to -xwarppointer mode for\n");
4402
rfbLog(" pointer motion input.\n");
4405
use_xwarppointer = 1;
4408
xtest_base_event_type = ev;
4409
if (maj <= 1 || (maj == 2 && min <= 2)) {
4410
/* no events defined as of 2.2 */
4411
xtest_base_event_type = 0;
4415
if (! XETrapQueryExtension_wr(dpy, &ev, &er, &maj)) {
4419
xtrap_base_event_type = ev;
4423
* Window managers will often grab the display during resize,
4424
* etc, using XGrabServer(). To avoid deadlock (our user resize
4425
* input is not processed) we tell the server to process our
4426
* requests during all grabs:
4428
disable_grabserver(dpy, 0);
4430
/* check for RECORD */
4431
if (! XRecordQueryVersion_wr(dpy, &maj, &min)) {
4432
xrecord_present = 0;
4435
rfbLog("The RECORD X extension was not found on the display.\n");
4436
rfbLog("If your system has disabled it by default, you can\n");
4437
rfbLog("enable it to get a nice x11vnc performance speedup\n");
4438
rfbLog("for scrolling by putting this into the \"Module\" section\n");
4439
rfbLog("of /etc/X11/xorg.conf or /etc/X11/XF86Config:\n");
4441
rfbLog(" Section \"Module\"\n");
4443
rfbLog(" Load \"record\"\n");
4445
rfbLog(" EndSection\n");
4449
xrecord_present = 1;
4452
initialize_xrecord();
4455
if (scroll_copyrect) {
4456
if (strstr(scroll_copyrect, "never")) {
4459
} else if (scroll_copyrect_default) {
4460
if (strstr(scroll_copyrect_default, "never")) {
4464
if (! xrecord_present) {
4467
#if !LIBVNCSERVER_HAVE_RECORD
4470
if (! quiet && tmpi && ! raw_fb_str) {
4472
rfbLog("Scroll Detection: -scrollcopyrect mode is in effect to\n");
4473
rfbLog(" use RECORD extension to try to detect scrolling windows\n");
4474
rfbLog(" (induced by either user keystroke or mouse input).\n");
4475
rfbLog(" If this yields undesired behavior (poor response, painting\n");
4476
rfbLog(" errors, etc) it may be disabled via: '-noscr'\n");
4477
rfbLog(" Also see the -help entry for tuning parameters.\n");
4478
rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
4479
rfbLog(" repaint the screen, also see the -fixscreen option for\n");
4480
rfbLog(" periodic repaints.\n");
4481
if (scale_str && !strstr(scale_str, "nocr")) {
4482
rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
4486
if (! quiet && ncache && ! raw_fb_str) {
4488
rfbLog("Client Side Caching: -ncache mode is in effect to provide\n");
4489
rfbLog(" client-side pixel data caching. This speeds up\n");
4490
rfbLog(" iconifying/deiconifying windows, moving and raising\n");
4491
rfbLog(" windows, and reposting menus. In the simple CopyRect\n");
4492
rfbLog(" encoding scheme used (no compression) a huge amount\n");
4493
rfbLog(" of extra memory (20-100MB) is used on both the server and\n");
4494
rfbLog(" client sides. This mode works with any VNC viewer.\n");
4495
rfbLog(" However, in most you can actually see the cached pixel\n");
4496
rfbLog(" data by scrolling down, so you need to re-adjust its size.\n");
4497
rfbLog(" See http://www.karlrunge.com/x11vnc/#faq-client-caching.\n");
4498
rfbLog(" If this mode yields undesired behavior (poor response,\n");
4499
rfbLog(" painting errors, etc) it may be disabled via: '-ncache 0'\n");
4500
rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
4501
rfbLog(" repaint the screen, also see the -fixscreen option for\n");
4502
rfbLog(" periodic repaints.\n");
4504
rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
4507
if (ncache && getenv("NCACHE_DEBUG")) {
4511
/* check for OS with small shm limits */
4512
if (using_shm && ! single_copytile) {
4514
single_copytile = 1;
4518
single_copytile_orig = single_copytile;
4520
/* check for MIT-SHM */
4521
if (! XShmQueryExtension_wr(dpy)) {
4524
if (! quiet && ! raw_fb_str) {
4525
rfbLog("info: display does not support XShm.\n");
4528
if (! quiet && ! raw_fb_str) {
4530
rfbLog("warning: XShm extension is not available.\n");
4531
rfbLog("For best performance the X Display should be local. (i.e.\n");
4532
rfbLog("the x11vnc and X server processes should be running on\n");
4533
rfbLog("the same machine.)\n");
4534
#if LIBVNCSERVER_HAVE_XSHM
4535
rfbLog("Restart with -noshm to override this.\n");
4539
rfbLog("Switching to -noshm mode.\n");
4546
#if LIBVNCSERVER_HAVE_XKEYBOARD
4547
/* check for XKEYBOARD */
4549
initialize_watch_bell();
4550
if (!xkb_present && use_xkb_modtweak) {
4551
if (! quiet && ! raw_fb_str) {
4552
rfbLog("warning: disabling xkb modtweak. XKEYBOARD ext. not present.\n");
4554
use_xkb_modtweak = 0;
4558
if (xkb_present && !use_xkb_modtweak && !got_noxkb) {
4559
if (use_modifier_tweak) {
4560
switch_to_xkb_if_better();
4564
#if LIBVNCSERVER_HAVE_LIBXRANDR
4565
if (! XRRQueryExtension(dpy, &xrandr_base_event_type, &er)) {
4566
if (xrandr && ! quiet && ! raw_fb_str) {
4567
rfbLog("Disabling -xrandr mode: display does not support X RANDR.\n");
4569
xrandr_base_event_type = 0;
4580
if (! quiet && ! raw_fb_str) {
4581
rfbLog("--------------------------------------------------------\n");
4585
raw_fb_pass_go_and_collect_200_dollars:
4587
if (! dpy || raw_fb_str) {
4589
/* XXX this needs improvement (esp. for remote control) */
4590
if (! raw_fb_str || strstr(raw_fb_str, "console") == raw_fb_str) {
4595
if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
4599
if (! multiple_cursors_mode) {
4600
multiple_cursors_mode = strdup("most");
4602
initialize_cursors_mode();
4603
use_xdamage = orig_use_xdamage;
4605
xdamage_present = 1;
4606
initialize_xdamage();
4612
static char str[] = "-desktop";
4613
argv_vnc[argc_vnc++] = str;
4614
argv_vnc[argc_vnc++] = choose_title(use_dpy);
4615
rfb_desktop_name = strdup(argv_vnc[argc_vnc-1]);
4619
* Create the XImage corresponding to the display framebuffer.
4622
fb0 = initialize_xdisplay_fb();
4625
* In some cases (UINPUT touchscreens) we need the dpy_x dpy_y
4626
* to initialize pipeinput. So we do it after fb is created.
4628
initialize_pipeinput();
4631
* n.b. we do not have to X_LOCK any X11 calls until watch_loop()
4632
* is called since we are single-threaded until then.
4635
initialize_screen(&argc_vnc, argv_vnc, fb0);
4637
if (waited_for_client) {
4642
if (use_solid_bg && client_count) {
4645
if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) {
4646
rfbClientIteratorPtr iter;
4647
rfbClientPtr cl, cl0 = NULL;
4649
iter = rfbGetClientIterator(screen);
4650
while( (cl = rfbClientIteratorNext(iter)) ) {
4653
rfbLog("WAIT popup: too many clients\n");
4658
rfbReleaseClientIterator(iter);
4659
if (i != 1 || cl0 == NULL) {
4660
rfbLog("WAIT popup: no clients.\n");
4663
if (! accept_client(cl0)) {
4664
rfbLog("WAIT popup: denied.\n");
4667
rfbLog("waited_for_client: popup accepted.\n");
4668
cl0->onHold = FALSE;
4670
if (macosx_console) {
4673
if (dpy && xdmcp_insert != NULL) {
4676
int n = strlen(xdmcp_insert);
4680
for (i = 0; i < n; i++) {
4681
c = xdmcp_insert[i];
4683
if (sym < ' ' || sym > 0x7f) {
4687
k = XKeysymToKeycode(dpy, sym);
4688
if (k == NoSymbol) {
4695
usleep(2*1000*1000);
4697
rfbLog("sending XDM '%s'\n", xdmcp_insert);
4699
for (i = 0; i < n; i++) {
4700
c = xdmcp_insert[i];
4702
k = XKeysymToKeycode(dpy, sym);
4704
k2 = XKeysymToKeycode(dpy, XK_Shift_L);
4705
XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
4709
if (0) fprintf(stderr, "C/k %c/%x\n", c, k);
4710
XTestFakeKeyEvent_wr(dpy, k, True, CurrentTime);
4713
XTestFakeKeyEvent_wr(dpy, k, False, CurrentTime);
4717
k2 = XKeysymToKeycode(dpy, XK_Shift_L);
4718
XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
4723
k2 = XKeysymToKeycode(dpy, XK_Tab);
4724
XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
4727
XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
4734
check_redir_services();
4738
if (! waited_for_client) {
4739
if (try_http && ! got_httpdir && check_httpdir()) {
4740
http_connections(1);
4742
if (ssh_str != NULL) {
4743
ssh_remote_tunnel(ssh_str, screen->port);
4749
/* rectangular blackout regions */
4750
initialize_blackouts_and_xinerama();
4752
/* created shm or XImages when using_shm = 0 */
4753
initialize_polling_images();
4755
initialize_signals();
4757
initialize_speeds();
4759
initialize_keyboard_and_pointer();
4761
if (inetd && use_openssl) {
4762
if (! waited_for_client) {
4763
accept_openssl(OPENSSL_INETD, -1);
4766
if (! inetd && ! use_openssl) {
4767
if (! screen->port || screen->listenSock < 0) {
4768
if (got_rfbport && got_rfbport_val == 0) {
4772
rfbLog("Error: could not obtain listening port.\n");
4778
rfbLog("screen setup finished.\n");
4779
if (SHOW_NO_PASSWORD_WARNING && !nopw) {
4781
rfbLog("WARNING: You are running x11vnc WITHOUT"
4782
" a password. See\n");
4783
rfbLog("WARNING: the warning message printed above"
4784
" for more info.\n");
4787
set_vnc_desktop_name();
4789
if (ncache_beta_tester && (ncache != 0 || ncache_msg)) {
4790
ncache_beta_tester_message();
4793
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
4796
if (getenv("X11VNC_LOOP_MODE_BG")) {
4797
if (screen && screen->listenSock >= 0) {
4798
close(screen->listenSock);
4799
FD_CLR(screen->listenSock,&screen->allFds);
4800
screen->listenSock = -1;
4802
if (screen && screen->httpListenSock >= 0) {
4803
close(screen->httpListenSock);
4804
FD_CLR(screen->httpListenSock,&screen->allFds);
4805
screen->httpListenSock = -1;
4807
if (openssl_sock >= 0) {
4808
close(openssl_sock);
4811
if (https_sock >= 0) {
4816
/* fork into the background now */
4817
if ((p = fork()) > 0) {
4819
} else if (p == -1) {
4821
fprintf(stderr, "could not fork\n");
4825
if (setsid() == -1) {
4827
fprintf(stderr, "setsid failed\n");
4831
/* adjust our stdio */
4832
n = open("/dev/null", O_RDONLY);