~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/x11vnc.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * x11vnc: a VNC server for X displays.
 
3
 *
 
4
 * Copyright (c) 2002-2007 Karl J. Runge <runge@karlrunge.com>
 
5
 * All rights reserved.
 
6
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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,
 
19
 *  USA.
 
20
 *
 
21
 *
 
22
 * This program is based on the following programs:
 
23
 *
 
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)
 
27
 *
 
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.
 
36
 *
 
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.
 
40
 *
 
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
 
43
 * of options!
 
44
 *
 
45
 * To build:
 
46
 *
 
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.
 
50
 *
 
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).
 
56
 *
 
57
 * Known shortcomings:
 
58
 *
 
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.
 
67
 *
 
68
 * General audio at the remote display is lost unless one separately
 
69
 * sets up some audio side-channel such as esd.
 
70
 *
 
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)
 
76
 * 
 
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)
 
82
 *
 
83
 * Under XFIXES mode for showing the cursor shape, the cursor may be
 
84
 * poorly approximated if it has transparency (alpha channel).
 
85
 *
 
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.
 
93
 *
 
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.
 
98
 *
 
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.
 
104
 *
 
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.
 
108
 *
 
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).
 
112
 *
 
113
 */
 
114
 
 
115
 
 
116
/* -- x11vnc.c -- */
 
117
 
 
118
#include "x11vnc.h"
 
119
#include "xwrappers.h"
 
120
#include "xdamage.h"
 
121
#include "xrecord.h"
 
122
#include "xevents.h"
 
123
#include "xinerama.h"
 
124
#include "xrandr.h"
 
125
#include "xkb_bell.h"
 
126
#include "win_utils.h"
 
127
#include "remote.h"
 
128
#include "scan.h"
 
129
#include "gui.h"
 
130
#include "help.h"
 
131
#include "user.h"
 
132
#include "cleanup.h"
 
133
#include "keyboard.h"
 
134
#include "pointer.h"
 
135
#include "cursor.h"
 
136
#include "userinput.h"
 
137
#include "screen.h"
 
138
#include "connections.h"
 
139
#include "rates.h"
 
140
#include "unixpw.h"
 
141
#include "inet.h"
 
142
#include "sslcmds.h"
 
143
#include "sslhelper.h"
 
144
#include "selection.h"
 
145
#include "pm.h"
 
146
#include "solid.h"
 
147
 
 
148
/*
 
149
 * main routine for the x11vnc program
 
150
 */
 
151
 
 
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);
 
161
 
 
162
 
 
163
static void check_cursor_changes(void) {
 
164
        static double last_push = 0.0;
 
165
 
 
166
        if (unixpw_in_progress) return;
 
167
 
 
168
        cursor_changes += check_x11_pointer();
 
169
 
 
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;
 
173
 
 
174
                if (! all_clients_initialized()) {
 
175
                        /* play it safe */
 
176
                        return;
 
177
                }
 
178
 
 
179
                if (0) cursor_shape = cursor_shape_updates_clients(screen);
 
180
        
 
181
                dtime0(&tm);
 
182
                link = link_rate(&latency, &netrate);
 
183
                if (link == LR_DIALUP) {
 
184
                        max_push = 0.2;
 
185
                        wait = 0.05;
 
186
                } else if (link == LR_BROADBAND) {
 
187
                        max_push = 0.075;
 
188
                        wait = 0.05;
 
189
                } else if (link == LR_LAN) {
 
190
                        max_push = 0.01;
 
191
                } else if (latency < 5 && netrate > 200) {
 
192
                        max_push = 0.01;
 
193
                }
 
194
                
 
195
                if (tm > last_push + max_push) {
 
196
                        dopush = 1;
 
197
                } else if (cursor_changes > 1 && tm > last_push + multi_push) {
 
198
                        dopush = 1;
 
199
                }
 
200
 
 
201
                if (dopush) { 
 
202
                        mark_rect_as_modified(0, 0, 1, 1, 1);
 
203
                        fb_push_wait(wait, FB_MOD);
 
204
                        last_push = tm;
 
205
                } else {
 
206
                        rfbPE(0);
 
207
                }
 
208
        }
 
209
        cursor_changes = 0;
 
210
}
 
211
 
 
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);
 
216
        int rbs = -1;
 
217
        rfbClientIteratorPtr iter;
 
218
        rfbClientPtr cl;
 
219
 
 
220
        if (last_fb_bytes_sent == 0) {
 
221
                last_fb_bytes_sent = now;
 
222
                last_call = now;
 
223
        }
 
224
 
 
225
        if (now <= last_call + 1) {
 
226
                /* check every second or so */
 
227
                return;
 
228
        }
 
229
 
 
230
        if (unixpw_in_progress) return;
 
231
 
 
232
        last_call = now;
 
233
 
 
234
        if (! screen) {
 
235
                return;
 
236
        }
 
237
 
 
238
        iter = rfbGetClientIterator(screen);
 
239
        while( (cl = rfbClientIteratorNext(iter)) ) {
 
240
#if 0
 
241
                rbs += cl->rawBytesEquivalent;
 
242
#else
 
243
                rbs += rfbStatGetSentBytesIfRaw(cl);
 
244
#endif
 
245
        }
 
246
        rfbReleaseClientIterator(iter);
 
247
 
 
248
        if (rbs != rbs0) {
 
249
                rbs0 = rbs;
 
250
                if (debug_tiles > 1) {
 
251
                        printf("record_last_fb_update: %d %d\n",
 
252
                            (int) now, (int) last_fb_bytes_sent);
 
253
                }
 
254
                last_fb_bytes_sent = now;
 
255
        }
 
256
}
 
257
 
 
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;
 
266
        double fac = 1.0;
 
267
        int db = 0;
 
268
        static double dts[8];
 
269
 
 
270
        if (waitms == 0) {
 
271
                return waitms;
 
272
        }
 
273
        if (nofb) {
 
274
                return waitms;
 
275
        }
 
276
 
 
277
        if (first) {
 
278
                for(i=0; i<ndt; i++) {
 
279
                        dts[i] = 0.0;
 
280
                }
 
281
                first = 0;
 
282
        }
 
283
 
 
284
        now = dnow();
 
285
 
 
286
        /*
 
287
         * first check for bogdown, e.g. lots of activity, scrolling text
 
288
         * from command output, etc.
 
289
         */
 
290
        if (nap_ok) {
 
291
                dt = 0.0;
 
292
        }
 
293
        if (! wait_bog) {
 
294
                bogdown = 0;
 
295
 
 
296
        } else if (button_mask || now < last_keyboard_time + 2*bogdown_time) {
 
297
                /*
 
298
                 * let scrolls & keyboard input through the normal way
 
299
                 * otherwise, it will likely just annoy them.
 
300
                 */
 
301
                bogdown = 0;
 
302
 
 
303
        } else if (dt > 0.0) {
 
304
                /*
 
305
                 * inspect recent dt's:
 
306
                 * 0 1 2 3 4 5 6 7 dt
 
307
                 *             ^ ^ ^
 
308
                 */
 
309
                for (i = ndt - (nave - 1); i < ndt; i++) {
 
310
                        bave += dts[i];
 
311
                        bcnt++;
 
312
                        if (dts[i] < bogdown_time) {
 
313
                                bogdown = 0;
 
314
                                break;
 
315
                        }
 
316
                }
 
317
                bave += dt;
 
318
                bcnt++;
 
319
                bave = bave / bcnt;
 
320
                if (dt < bogdown_time) {
 
321
                        bogdown = 0;
 
322
                }
 
323
        } else {
 
324
                bogdown = 0;
 
325
        }
 
326
        /* shift for next time */
 
327
        for (i = 0; i < ndt-1; i++) {
 
328
                dts[i] = dts[i+1];
 
329
        }
 
330
        dts[ndt-1] = dt;
 
331
 
 
332
if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnowx());
 
333
        if (bogdown) {
 
334
                if (use_xdamage) {
 
335
                        /* DAMAGE can queue ~1000 rectangles for a scroll */
 
336
                        clear_xdamage_mark_region(NULL, 0);
 
337
                }
 
338
                msec = (int) (1000 * 1.75 * bave);
 
339
                if (dts[ndt - nave - 1] > 0.75 * bave) {
 
340
                        msec = 1.5 * msec;
 
341
                        set_xdamage_mark(0, 0, dpy_x, dpy_y);
 
342
                }
 
343
                if (msec > 1500) {
 
344
                        msec = 1500;
 
345
                }
 
346
                if (msec < waitms) {
 
347
                        msec = waitms;
 
348
                }
 
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]);
 
352
                return msec;
 
353
        }
 
354
 
 
355
        /* next check for pointer motion, keystrokes, to speed up */
 
356
        t2 = dnow();
 
357
        x2 = cursor_x;
 
358
        y2 = cursor_y;
 
359
 
 
360
        dx0 = nabs(x1 - x0);
 
361
        dy0 = nabs(y1 - y0);
 
362
        dx1 = nabs(x2 - x1);
 
363
        dy1 = nabs(y2 - y1);
 
364
        if (dx1 > dy1) {
 
365
                dm = dx1;
 
366
        } else {
 
367
                dm = dy1;
 
368
        }
 
369
 
 
370
        if ((dx0 || dy0) && (dx1 || dy1)) {
 
371
                if (t2 < t0 + cut1 || t2 < t1 + cut2 || dm > 20) {
 
372
                        fac = wait_ui * 1.25;
 
373
                }
 
374
        } else if ((dx1 || dy1) && dm > 40) {
 
375
                fac = wait_ui;
 
376
        }
 
377
 
 
378
        if (fac == 1 && t2 < last_keyboard_time + cut3) {
 
379
                fac = wait_ui;
 
380
        }
 
381
        msec = (int) ((double) waitms / fac);
 
382
        if (msec == 0) {
 
383
                msec = 1;
 
384
        }
 
385
 
 
386
        x0 = x1;
 
387
        y0 = y1;
 
388
        t0 = t1;
 
389
 
 
390
        x1 = x2;
 
391
        y1 = y2;
 
392
        t1 = t2;
 
393
 
 
394
        return msec;
 
395
}
 
396
 
 
397
static int tsdo_timeout_flag;
 
398
 
 
399
static void tsdo_timeout (int sig) {
 
400
        tsdo_timeout_flag = 1;
 
401
        if (sig) {};
 
402
}
 
403
 
 
404
#define TASKMAX 32
 
405
static pid_t ts_tasks[TASKMAX];
 
406
static int ts_taskn = -1;
 
407
 
 
408
int tsdo(int port, int lsock, int *conn) {
 
409
        int csock, rsock, i, db = 1;
 
410
        pid_t pid;
 
411
        struct sockaddr_in addr;
 
412
#ifdef __hpux
 
413
        int addrlen = sizeof(addr);
 
414
#else
 
415
        socklen_t addrlen = sizeof(addr);
 
416
#endif
 
417
 
 
418
        if (*conn < 0) {
 
419
                signal(SIGALRM, tsdo_timeout);
 
420
                tsdo_timeout_flag = 0;
 
421
 
 
422
                alarm(10);
 
423
                csock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
 
424
                alarm(0);
 
425
 
 
426
                if (db) rfbLog("tsdo: accept: lsock: %d, csock: %d, port: %d\n", lsock, csock, port);
 
427
 
 
428
                if (tsdo_timeout_flag > 0 || csock < 0) {
 
429
                        close(csock);
 
430
                        *conn = -1;
 
431
                        return 1;
 
432
                }
 
433
                *conn = csock;
 
434
        } else {
 
435
                csock = *conn;
 
436
                if (db) rfbLog("tsdo: using exiting csock: %d, port: %d\n", csock, port);
 
437
        }
 
438
 
 
439
        rsock = rfbConnectToTcpAddr("127.0.0.1", port);
 
440
        if (rsock < 0) {
 
441
                if (db) rfbLog("tsdo: rfbConnectToTcpAddr(port=%d) failed.\n", port);
 
442
                return 2;
 
443
        }
 
444
 
 
445
        pid = fork();
 
446
        if (pid < 0) {
 
447
                close(rsock);
 
448
                return 3;
 
449
        }
 
450
        if (pid > 0) {
 
451
                ts_taskn = (ts_taskn+1) % TASKMAX;
 
452
                ts_tasks[ts_taskn] = pid;
 
453
                close(csock);
 
454
                *conn = -1;
 
455
                close(rsock);
 
456
                return 0;
 
457
        }
 
458
        if (pid == 0) {
 
459
                for (i=0; i<255; i++) {
 
460
                        if (i != csock && i != rsock && i != 2) {
 
461
                                close(i);
 
462
                        }
 
463
                }
 
464
#if LIBVNCSERVER_HAVE_SETSID
 
465
                if (setsid() == -1) {
 
466
                        perror("setsid");
 
467
                        exit(1);
 
468
                }
 
469
#else
 
470
                if (setpgrp() == -1) {
 
471
                        perror("setpgrp");
 
472
                        exit(1);
 
473
                }
 
474
#endif  /* SETSID */
 
475
                raw_xfer(rsock, csock, csock);
 
476
                exit(0);
 
477
        }
 
478
        return 0;
 
479
}
 
480
 
 
481
void set_redir_properties(void);
 
482
 
 
483
#define TSMAX 32
 
484
#define TSSTK 16
 
485
void terminal_services(char *list) {
 
486
        int i, j, n = 0, db = 1;
 
487
        char *p, *q, *r, *str = strdup(list);
 
488
#if !NO_X11
 
489
        char *tag[TSMAX];
 
490
        int listen[TSMAX], redir[TSMAX][TSSTK], socks[TSMAX], tstk[TSSTK];
 
491
        Atom at, atom[TSMAX];
 
492
        fd_set rd;
 
493
        Window rwin;
 
494
        XErrorHandler   old_handler1;
 
495
        XIOErrorHandler old_handler2;
 
496
        char num[32];
 
497
        time_t last_clean = time(NULL);
 
498
 
 
499
        if (! dpy) {
 
500
                return;
 
501
        }
 
502
        rwin = RootWindow(dpy, DefaultScreen(dpy));
 
503
 
 
504
        at = XInternAtom(dpy, "TS_REDIR_LIST", False);
 
505
        if (at != None) {
 
506
                XChangeProperty(dpy, rwin, at, XA_STRING, 8,
 
507
                    PropModeReplace, (unsigned char *)list, strlen(list));
 
508
                XSync(dpy, False);
 
509
        }
 
510
        for (i=0; i<TASKMAX; i++) {
 
511
                ts_tasks[i] = 0;
 
512
        }
 
513
        for (i=0; i<TSMAX; i++) {
 
514
                for (j=0; j<TSSTK; j++) {
 
515
                        redir[i][j] = 0;
 
516
                }
 
517
        }
 
518
 
 
519
        p = strtok(str, ",");
 
520
        while (p) {
 
521
                int m1, m2;
 
522
                if (db) fprintf(stderr, "item: %s\n", p);
 
523
                q = strrchr(p, ':');
 
524
                if (!q) {
 
525
                        p = strtok(NULL, ",");
 
526
                        continue;
 
527
                }
 
528
                r = strchr(p, ':');
 
529
                if (!r || r == q) {
 
530
                        p = strtok(NULL, ",");
 
531
                        continue;
 
532
                }
 
533
 
 
534
                m1 = atoi(q+1);
 
535
                *q = '\0';
 
536
                m2 = atoi(r+1);
 
537
                *r = '\0';
 
538
 
 
539
                if (m1 <= 0 || m2 <= 0 || m1 >= 0xffff || m2 >= 0xffff) {
 
540
                        p = strtok(NULL, ",");
 
541
                        continue;
 
542
                }
 
543
 
 
544
                redir[n][0] = m1;
 
545
                listen[n] = m2;
 
546
                tag[n] = strdup(p);
 
547
 
 
548
                if (db) fprintf(stderr, "     %d %d %s\n", redir[n][0], listen[n], tag[n]);
 
549
 
 
550
                *r = ':';
 
551
                *q = ':';
 
552
 
 
553
                n++;
 
554
                if (n >= TSMAX) {
 
555
                        break;
 
556
                }
 
557
                p = strtok(NULL, ",");
 
558
        }
 
559
        free(str);
 
560
 
 
561
        if (n==0) {
 
562
                return;
 
563
        }
 
564
 
 
565
        at = XInternAtom(dpy, "TS_REDIR_PID", False);
 
566
        if (at != None) {
 
567
                sprintf(num, "%d", getpid());
 
568
                XChangeProperty(dpy, rwin, at, XA_STRING, 8,
 
569
                    PropModeReplace, (unsigned char *)num, strlen(num));
 
570
                XSync(dpy, False);
 
571
        }
 
572
 
 
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) {
 
577
                        continue;
 
578
                }
 
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));
 
583
                XSync(dpy, False);
 
584
 
 
585
                socks[i] = rfbListenOnTCPPort(listen[i], htonl(INADDR_LOOPBACK));
 
586
        }
 
587
 
 
588
        if (getenv("TSD_RESTART")) {
 
589
                if (!strcmp(getenv("TSD_RESTART"), "1")) {
 
590
                        set_redir_properties();
 
591
                }
 
592
        }
 
593
 
 
594
        while (1) {
 
595
                struct timeval tv;
 
596
                int nfd;
 
597
                int fmax = -1;
 
598
 
 
599
                tv.tv_sec  = 3;
 
600
                tv.tv_usec = 0;
 
601
 
 
602
                FD_ZERO(&rd);
 
603
                for (i=0; i<n; i++) {
 
604
                        if (socks[i] >= 0) {
 
605
                                FD_SET(socks[i], &rd);
 
606
                                if (socks[i] > fmax) {
 
607
                                        fmax = socks[i];
 
608
                                }
 
609
                        }
 
610
                }
 
611
 
 
612
                nfd = select(fmax+1, &rd, NULL, NULL, &tv);
 
613
 
 
614
                if (db && 0) fprintf(stderr, "nfd=%d\n", nfd);
 
615
                if (nfd < 0 && errno == EINTR) {
 
616
                        XSync(dpy, True);
 
617
                        continue;
 
618
                }
 
619
                if (nfd > 0) {
 
620
                        for(i=0; i<n; i++) {
 
621
                                int k = 0;
 
622
                                for (j = 0; j < TSSTK; j++) {
 
623
                                        tstk[j] = 0;
 
624
                                }
 
625
                                for (j = 0; j < TSSTK; j++) {
 
626
                                        if (redir[i][j] != 0) {
 
627
                                                tstk[k++] = redir[i][j];
 
628
                                        }
 
629
                                }
 
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]);
 
633
                                }
 
634
                        }
 
635
                        for(i=0; i<n; i++) {
 
636
                                int s = socks[i];
 
637
                                if (s < 0) {
 
638
                                        continue;
 
639
                                }
 
640
                                if (FD_ISSET(s, &rd)) {
 
641
                                        int p0, p, found = -1, jzero = -1;
 
642
                                        int conn = -1;
 
643
 
 
644
                                        get_prop(num, 32, atom[i]);
 
645
                                        p0 = atoi(num);
 
646
 
 
647
                                        for (j = TSSTK-1; j >= 0; j--) {
 
648
                                                if (redir[i][j] == 0) {
 
649
                                                        jzero = j;
 
650
                                                        continue;
 
651
                                                }
 
652
                                                if (p0 > 0 && p0 < 0xffff) {
 
653
                                                        if (redir[i][j] == p0) {
 
654
                                                                found = j;
 
655
                                                                break;
 
656
                                                        }
 
657
                                                }
 
658
                                        }
 
659
                                        if (jzero < 0) {
 
660
                                                jzero = TSSTK-1;
 
661
                                        }
 
662
                                        if (found < 0) {
 
663
                                                if (p0 > 0 && p0 < 0xffff) {
 
664
                                                        redir[i][jzero] = p0;
 
665
                                                }
 
666
                                        }
 
667
                                        for (j = TSSTK-1; j >= 0; j--) {
 
668
                                                int rc;
 
669
                                                p = redir[i][j];
 
670
                                                if (p <= 0 || p >= 0xffff) {
 
671
                                                        redir[i][j] = 0;
 
672
                                                        continue;
 
673
                                                }
 
674
                                                rc = tsdo(p, s, &conn);
 
675
                                                if (rc == 0) {
 
676
                                                        /* AOK */
 
677
                                                        if (db) fprintf(stderr, "tsdo[%d] OK: %d\n", i, p);
 
678
                                                        if (p != p0) {
 
679
                                                                sprintf(num, "%d", p);
 
680
                                                                XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
 
681
                                                                    PropModeReplace, (unsigned char *)num, strlen(num));
 
682
                                                                XSync(dpy, False);
 
683
                                                        }
 
684
                                                        break;
 
685
                                                } else if (rc == 1) {
 
686
                                                        /* accept failed */
 
687
                                                        if (db) fprintf(stderr, "tsdo[%d] accept failed: %d\n", i, p);
 
688
                                                        break;
 
689
                                                } else if (rc == 2) {
 
690
                                                        /* connect failed */
 
691
                                                        if (db) fprintf(stderr, "tsdo[%d] connect failed: %d\n", i, p);
 
692
                                                        redir[i][j] = 0;
 
693
                                                        continue;
 
694
                                                } else if (rc == 3) {
 
695
                                                        /* fork failed */
 
696
                                                        usleep(250*1000);
 
697
                                                        break;
 
698
                                                }
 
699
                                        }
 
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]);
 
702
                                        }
 
703
                                }
 
704
                        }
 
705
                }
 
706
                for (i=0; i<TASKMAX; i++) {
 
707
                        pid_t p = ts_tasks[i];
 
708
                        if (p > 0) {
 
709
                                int status;
 
710
                                pid_t p2 = waitpid(p, &status, WNOHANG); 
 
711
                                if (p2 == p) {
 
712
                                        ts_tasks[i] = 0;
 
713
                                }
 
714
                        }
 
715
                }
 
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);
 
719
                trapped_xerror = 0;
 
720
                trapped_xioerror = 0;
 
721
 
 
722
                XSync(dpy, True);
 
723
 
 
724
                sprintf(num, "%d", (int) time(NULL));
 
725
                at = XInternAtom(dpy, "TS_REDIR", False);
 
726
                if (at != None) {
 
727
                        XChangeProperty(dpy, rwin, at, XA_STRING, 8,
 
728
                            PropModeReplace, (unsigned char *)num, strlen(num));
 
729
                        XSync(dpy, False);
 
730
                }
 
731
                if (time(NULL) > last_clean + 20 * 60) {
 
732
                        int i, j;
 
733
                        for(i=0; i<n; i++) {
 
734
                                int first = 1;
 
735
                                for (j = TSSTK-1; j >= 0; j--) {
 
736
                                        int s, p = redir[i][j];
 
737
                                        if (p <= 0 || p >= 0xffff) {
 
738
                                                redir[i][j] = 0;
 
739
                                                continue;
 
740
                                        }
 
741
                                        s = rfbConnectToTcpAddr("127.0.0.1", p);
 
742
                                        if (s < 0) {
 
743
                                                redir[i][j] = 0;
 
744
                                                if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p);
 
745
                                        } else {
 
746
                                                close(s);
 
747
                                                if (first) {
 
748
                                                        sprintf(num, "%d", p);
 
749
                                                        XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
 
750
                                                            PropModeReplace, (unsigned char *)num, strlen(num));
 
751
                                                        XSync(dpy, False);
 
752
                                                }
 
753
                                                first = 0;
 
754
                                        }
 
755
                                        usleep(500*1000);
 
756
                                }
 
757
                        }
 
758
                        last_clean = time(NULL);
 
759
                }
 
760
                if (trapped_xerror || trapped_xioerror) {
 
761
                        if (db) fprintf(stderr, "Xerror: %d/%d\n", trapped_xerror, trapped_xioerror);
 
762
                        exit(0);
 
763
                }
 
764
                XSetErrorHandler(old_handler1);
 
765
                XSetIOErrorHandler(old_handler2);
 
766
        }
 
767
#endif
 
768
}
 
769
 
 
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"},
 
775
        {NULL, NULL}
 
776
};
 
777
 
 
778
void do_tsd(void) {
 
779
#if !NO_X11
 
780
        Atom a;
 
781
        char prop[513];
 
782
        pid_t pid;
 
783
        char *cmd;
 
784
        int n, sz = 0;
 
785
        char *disp = DisplayString(dpy);
 
786
 
 
787
        prop[0] = '\0';
 
788
        a = XInternAtom(dpy, "TS_REDIR_LIST", False);
 
789
        if (a != None) {
 
790
                get_prop(prop, 512, a);
 
791
        }
 
792
 
 
793
        if (prop[0] == '\0') {
 
794
                return;
 
795
        }
 
796
 
 
797
        if (! program_name) {
 
798
                program_name = "x11vnc";
 
799
        }
 
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;
 
808
 
 
809
        cmd = (char *) malloc(sz);
 
810
 
 
811
        if (getenv("XAUTHORITY")) {
 
812
                char *xauth = getenv("XAUTHORITY");
 
813
                if (!strcmp(xauth, "") || access(xauth, R_OK) != 0) {
 
814
                        *(xauth-2) = '_';       /* yow */
 
815
                }
 
816
        }
 
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);
 
819
 
 
820
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
 
821
        /* fork into the background now */
 
822
        if ((pid = fork()) > 0)  {
 
823
                pid_t pidw;
 
824
                int status;
 
825
                double s = dnow();
 
826
 
 
827
                while (dnow() < s + 1.5) {
 
828
                        pidw = waitpid(pid, &status, WNOHANG);
 
829
                        if (pidw == pid) {
 
830
                                break;
 
831
                        }
 
832
                        usleep(100*1000);
 
833
                }
 
834
                return;
 
835
 
 
836
        } else if (pid == -1) {
 
837
                system(cmd);
 
838
        } else {
 
839
                setsid();
 
840
                /* adjust our stdio */
 
841
                n = open("/dev/null", O_RDONLY);
 
842
                dup2(n, 0);
 
843
                dup2(n, 1);
 
844
                dup2(n, 2);
 
845
                if (n > 2) {
 
846
                        close(n);
 
847
                }
 
848
                system(cmd);
 
849
                exit(0);
 
850
        }
 
851
#else
 
852
        system(cmd);
 
853
#endif
 
854
 
 
855
#endif
 
856
}
 
857
 
 
858
void set_redir_properties(void) {
 
859
#if !NO_X11
 
860
        char *e, *f, *t;
 
861
        Atom a;
 
862
        char num[32];
 
863
        int i, p;
 
864
 
 
865
        if (! dpy) {
 
866
                return;
 
867
        }
 
868
 
 
869
        i = 0;
 
870
        while (ts_services[i][0] != NULL) {
 
871
                f = ts_services[i][0]; 
 
872
                t = ts_services[i][1]; 
 
873
                e = getenv(f);
 
874
                if (!e || strstr(e, "DAEMON-") != e) {
 
875
                        i++;
 
876
                        continue;
 
877
                }
 
878
                p = atoi(e + strlen("DAEMON-"));
 
879
                if (p <= 0) {
 
880
                        i++;
 
881
                        continue;
 
882
                }
 
883
                sprintf(num, "%d", p);
 
884
                a = XInternAtom(dpy, t, False);
 
885
                if (a != None) {
 
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));
 
890
                        XSync(dpy, False);
 
891
                }
 
892
                i++;
 
893
        }
 
894
#endif
 
895
}
 
896
 
 
897
void check_redir_services(void) {
 
898
#if !NO_X11
 
899
        Atom a;
 
900
        char prop[513];
 
901
        time_t tsd_last;
 
902
        int restart = 0;
 
903
        pid_t pid = 0;
 
904
 
 
905
        if (! dpy) {
 
906
                return;
 
907
        }
 
908
 
 
909
        a = XInternAtom(dpy, "TS_REDIR_PID", False);
 
910
        if (a != None) {
 
911
                prop[0] = '\0';
 
912
                get_prop(prop, 512, a);
 
913
                if (prop[0] != '\0') {
 
914
                        pid = (pid_t) atoi(prop);
 
915
                }
 
916
        }
 
917
 
 
918
        if (getenv("FD_TAG")) {
 
919
                a = XInternAtom(dpy, "FD_TAG", False);
 
920
                if (a != None) {
 
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));
 
925
                        XSync(dpy, False);
 
926
                }
 
927
        }
 
928
 
 
929
        prop[0] = '\0';
 
930
        a = XInternAtom(dpy, "TS_REDIR", False);
 
931
        if (a != None) {
 
932
                get_prop(prop, 512, a);
 
933
        }
 
934
        if (prop[0] == '\0') {
 
935
                rfbLog("TS_REDIR is empty, restarting...\n");
 
936
                restart = 1;
 
937
        } else {
 
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);
 
942
                        restart = 1;
 
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",
 
946
                                    pid);
 
947
                                restart = 1;
 
948
                        }
 
949
                }
 
950
        }
 
951
        if (restart) {
 
952
 
 
953
                if (pid > 1) {
 
954
                        rfbLog("killing TS_REDIR_PID: %d\n", pid);
 
955
                        kill(pid, SIGTERM);
 
956
                        usleep(500*1000);
 
957
                        kill(pid, SIGKILL);
 
958
                }
 
959
                do_tsd();
 
960
                return;
 
961
        }
 
962
 
 
963
        set_redir_properties();
 
964
#endif
 
965
}
 
966
 
 
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;
 
971
        int rc, len, rport;
 
972
 
 
973
        /* user@host:port:disp+secs */
 
974
 
 
975
        /* +sleep */
 
976
        q = strrchr(s, '+');
 
977
        if (q) {
 
978
                sleep = atoi(q+1);
 
979
                if (sleep <= 0) {
 
980
                        sleep = 1;
 
981
                }
 
982
                *q = '\0';
 
983
        }
 
984
        /* :disp */
 
985
        q = strrchr(s, ':');
 
986
        if (q) {
 
987
                disp = atoi(q+1);
 
988
                *q = '\0';
 
989
        }
 
990
        
 
991
        /* :sshport */
 
992
        q = strrchr(s, ':');
 
993
        if (q) {
 
994
                sport = atoi(q+1);
 
995
                *q = '\0';
 
996
        }
 
997
 
 
998
        if (getenv("SSH")) {
 
999
                ssh = getenv("SSH");
 
1000
        } else {
 
1001
                ssh = "ssh";
 
1002
        }
 
1003
 
 
1004
        len = 0;
 
1005
        len += strlen(ssh) + strlen(s) + 500;
 
1006
        cmd = (char *) malloc(len);
 
1007
 
 
1008
        if (disp >= 0 && disp <= 200) {
 
1009
                rport = disp + 5900;
 
1010
        } else if (disp < 0) {
 
1011
                rport = -disp;
 
1012
        } else {
 
1013
                rport = disp;
 
1014
        }
 
1015
 
 
1016
        if (sport > 0) {
 
1017
                sprintf(cmd, "%s -f -p %d -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, sport, rport, lport, s, sleep);
 
1018
        } else {
 
1019
                sprintf(cmd, "%s -f       -R '%d:localhost:%d' '%s' 'sleep %d'", ssh,        rport, lport, s, sleep);
 
1020
        }
 
1021
 
 
1022
        if (no_external_cmds || !cmd_ok("ssh")) {
 
1023
                rfbLogEnable(1);
 
1024
                rfbLog("cannot run external commands in -nocmds mode:\n");
 
1025
                rfbLog("   \"%s\"\n", cmd);
 
1026
                rfbLog("   exiting.\n");
 
1027
                clean_up_exit(1);
 
1028
        }
 
1029
 
 
1030
        close_exec_fds();
 
1031
        fprintf(stderr, "\n");
 
1032
        rfbLog("running: %s\n", cmd);
 
1033
        rc = system(cmd);
 
1034
 
 
1035
        if (rc != 0) {
 
1036
                free(cmd);
 
1037
                free(s);
 
1038
                rfbLog("ssh remote listen failed.\n");
 
1039
                clean_up_exit(1);
 
1040
        }
 
1041
 
 
1042
        if (1) {
 
1043
                FILE *pipe;
 
1044
                int mypid = (int) getpid();
 
1045
                int bestpid = -1;
 
1046
                int best = -1;
 
1047
                char line[1024];
 
1048
                char *psef = "ps -ef";
 
1049
                char *psww = "ps wwwwwwaux";
 
1050
                char *ps = psef;
 
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")) {
 
1054
                        ps = psww;
 
1055
                } else if (strstr(UT.sysname, "BSD")) {
 
1056
                        ps = psww;
 
1057
                } else if (strstr(UT.sysname, "Darwin")) {
 
1058
                        ps = psww;
 
1059
                }
 
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");
 
1062
                if (pipe) {
 
1063
                        while (fgets(line, 1024, pipe) != NULL) {
 
1064
                                int p = atoi(line);
 
1065
                                if (p > 0) {
 
1066
                                        int score;
 
1067
                                        if (p > mypid)  {
 
1068
                                                score = p - mypid;
 
1069
                                        } else {
 
1070
                                                score = p - mypid + 32768;
 
1071
                                                if (score < 0) {
 
1072
                                                        score = 32768;
 
1073
                                                }
 
1074
                                        }
 
1075
                                        if (best < 0 || score < best) {
 
1076
                                                best = score;
 
1077
                                                bestpid = p;
 
1078
                                        }
 
1079
                                }
 
1080
                        }
 
1081
                        pclose(pipe);
 
1082
                }
 
1083
 
 
1084
                if (bestpid != -1) {
 
1085
                        ssh_pid = (pid_t) bestpid;
 
1086
                        rfbLog("guessed ssh pid=%d, will terminate it on exit.\n", bestpid);
 
1087
                }
 
1088
        }
 
1089
 
 
1090
        free(cmd);
 
1091
        free(s);
 
1092
 
 
1093
}
 
1094
 
 
1095
void check_filexfer(void) {
 
1096
        static time_t last_check = 0;
 
1097
        rfbClientIteratorPtr iter;
 
1098
        rfbClientPtr cl;
 
1099
        int transferring = 0; 
 
1100
        
 
1101
        if (time(NULL) <= last_check) {
 
1102
                return;
 
1103
        }
 
1104
 
 
1105
#if 0
 
1106
        if (getenv("NOFT")) {
 
1107
                return;
 
1108
        }
 
1109
#endif
 
1110
 
 
1111
        iter = rfbGetClientIterator(screen);
 
1112
        while( (cl = rfbClientIteratorNext(iter)) ) {
 
1113
                if (cl->fileTransfer.receiving) {
 
1114
                        transferring = 1;
 
1115
                        break;
 
1116
                }
 
1117
                if (cl->fileTransfer.sending) {
 
1118
                        transferring = 1;
 
1119
                        break;
 
1120
                }
 
1121
        }
 
1122
        rfbReleaseClientIterator(iter);
 
1123
 
 
1124
        if (transferring) {
 
1125
                double start = dnow();
 
1126
                while (dnow() < start + 0.5) {
 
1127
                        rfbCFD(5000);
 
1128
                        rfbCFD(1000);
 
1129
                        rfbCFD(0);
 
1130
                }
 
1131
        } else {
 
1132
                last_check = time(NULL);
 
1133
        }
 
1134
}
 
1135
 
 
1136
/*
 
1137
 * main x11vnc loop: polls, checks for events, iterate libvncserver, etc.
 
1138
 */
 
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);
 
1143
 
 
1144
        if (use_threads) {
 
1145
                rfbRunEventLoop(screen, -1, TRUE);
 
1146
        }
 
1147
 
 
1148
        while (1) {
 
1149
                char msg[] = "new client: %s taking unixpw client off hold.\n";
 
1150
 
 
1151
                got_user_input = 0;
 
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;
 
1157
                urgent_update = 0;
 
1158
 
 
1159
                x11vnc_current = dnow();
 
1160
 
 
1161
                if (! use_threads) {
 
1162
                        dtime0(&tm);
 
1163
                        if (! skip_pe) {
 
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;
 
1169
                                        }
 
1170
                                } else {
 
1171
                                        measure_send_rates(1);
 
1172
                                }
 
1173
 
 
1174
                                unixpw_in_rfbPE = 1;
 
1175
 
 
1176
                                /*
 
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)
 
1181
                                 */
 
1182
                                if (tm < last_keyboard_time + 0.16) {
 
1183
                                        rfbPE(0);
 
1184
                                        rfbPE(0);
 
1185
                                        rfbPE(-1);
 
1186
                                        rfbPE(0);
 
1187
                                        rfbPE(0);
 
1188
                                } else {
 
1189
                                        rfbPE(-1);
 
1190
                                }
 
1191
 
 
1192
                                unixpw_in_rfbPE = 0;
 
1193
 
 
1194
                                if (unixpw_in_progress) {
 
1195
                                        /* rfbPE loop until logged in. */
 
1196
                                        skip_pe = 0;
 
1197
                                        check_new_clients();
 
1198
                                        continue;
 
1199
                                } else {
 
1200
                                        measure_send_rates(0);
 
1201
                                        fb_update_sent(NULL);
 
1202
                                }
 
1203
                        } else {
 
1204
                                if (unixpw_in_progress) {
 
1205
                                        skip_pe = 0;
 
1206
                                        check_new_clients();
 
1207
                                        continue;
 
1208
                                }
 
1209
                        }
 
1210
                        dtr = dtime(&tm);
 
1211
 
 
1212
                        if (! cursor_shape_updates) {
 
1213
                                /* undo any cursor shape requests */
 
1214
                                disable_cursor_shape_updates(screen);
 
1215
                        }
 
1216
                        if (screen && screen->clientHead) {
 
1217
                                int ret = check_user_input(dt, dtr,
 
1218
                                    tile_diffs, &cnt);
 
1219
                                /* true: loop back for more input */
 
1220
                                if (ret == 2) {
 
1221
                                        skip_pe = 1;
 
1222
                                }
 
1223
                                if (ret) {
 
1224
                                        if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret);
 
1225
                                        continue;
 
1226
                                }
 
1227
                        }
 
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);
 
1232
                        }
 
1233
                } else {
 
1234
                        /* -threads here. */
 
1235
                        if (wireframe && button_mask) {
 
1236
                                check_wireframe();
 
1237
                        }
 
1238
                }
 
1239
                skip_pe = 0;
 
1240
 
 
1241
                if (shut_down) {
 
1242
                        clean_up_exit(0);
 
1243
                }
 
1244
 
 
1245
                if (unixpw_in_progress) {
 
1246
                        check_new_clients();
 
1247
                        continue;
 
1248
                }
 
1249
 
 
1250
                if (! urgent_update) {
 
1251
                        if (do_copy_screen) {
 
1252
                                do_copy_screen = 0;
 
1253
                                copy_screen();
 
1254
                        }
 
1255
 
 
1256
                        check_new_clients();
 
1257
                        check_ncache(0, 0);
 
1258
                        check_xevents(0);
 
1259
                        check_autorepeat();
 
1260
                        check_pm();
 
1261
                        check_filexfer();
 
1262
                        check_keycode_state();
 
1263
                        check_connect_inputs();
 
1264
                        check_gui_inputs();
 
1265
                        check_stunnel();
 
1266
                        check_openssl();
 
1267
                        check_https();
 
1268
                        record_last_fb_update();
 
1269
                        check_padded_fb();
 
1270
                        check_fixscreen();
 
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();
 
1277
                        }
 
1278
 
 
1279
                        if (first_conn_timeout < 0) {
 
1280
                                start = time(NULL);
 
1281
                                first_conn_timeout = -first_conn_timeout;
 
1282
                        }
 
1283
                }
 
1284
 
 
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();
 
1290
                        }
 
1291
                }*/
 
1292
 
 
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);
 
1299
                                        shut_down = 1;
 
1300
                                }
 
1301
                        }
 
1302
                        usleep(200 * 1000);
 
1303
                        continue;
 
1304
                }
 
1305
 
 
1306
                if (first_conn_timeout && all_clients_initialized()) {
 
1307
                        first_conn_timeout = 0;
 
1308
                }
 
1309
 
 
1310
                if (nofb) {
 
1311
                        /* no framebuffer polling needed */
 
1312
                        if (cursor_pos_updates) {
 
1313
                                check_x11_pointer();
 
1314
                        }
 
1315
#ifdef MACOSX
 
1316
                        else check_x11_pointer();
 
1317
#endif
 
1318
                        continue;
 
1319
                }
 
1320
 
 
1321
                if (button_mask && (!show_dragging || pointer_mode == 0)) {
 
1322
                        /*
 
1323
                         * if any button is pressed in this mode do
 
1324
                         * not update rfb screen, but do flush the
 
1325
                         * X11 display.
 
1326
                         */
 
1327
                        X_LOCK;
 
1328
                        XFlush_wr(dpy);
 
1329
                        X_UNLOCK;
 
1330
                        dt = 0.0;
 
1331
                } else {
 
1332
                        static double last_dt = 0.0;
 
1333
                        double xdamage_thrash = 0.4; 
 
1334
 
 
1335
                        check_cursor_changes();
 
1336
 
 
1337
                        /* for timing the scan to try to detect thrashing */
 
1338
 
 
1339
                        if (use_xdamage && last_dt > xdamage_thrash)  {
 
1340
                                clear_xdamage_mark_region(NULL, 0);
 
1341
                        }
 
1342
 
 
1343
                        if (unixpw_in_progress) continue;
 
1344
 
 
1345
/*                      if (rawfb_vnc_reflect) {
 
1346
                                vnc_reflect_process_client();
 
1347
                        }*/
 
1348
                        dtime0(&tm);
 
1349
 
 
1350
#if !NO_X11
 
1351
                        if (xrandr_present && !xrandr && xrandr_maybe) {
 
1352
                                int delay = 180;
 
1353
                                /*  there may be xrandr right after xsession start */
 
1354
                                if (tm < x11vnc_start + delay || tm < last_client + delay) {
 
1355
                                        int tw = 20;
 
1356
                                        if (auth_file != NULL) {
 
1357
                                                tw = 120;
 
1358
                                        }
 
1359
                                        X_LOCK;
 
1360
                                        if (tm < x11vnc_start + tw || tm < last_client + tw) {
 
1361
                                                XSync(dpy, False);
 
1362
                                        } else {
 
1363
                                                XFlush_wr(dpy);
 
1364
                                        }
 
1365
                                        X_UNLOCK;
 
1366
                                }
 
1367
                                check_xrandr_event("before-scan");
 
1368
                        }
 
1369
#endif
 
1370
                        if (use_snapfb) {
 
1371
                                int t, tries = 3;
 
1372
                                copy_snap();
 
1373
                                for (t=0; t < tries; t++) {
 
1374
                                        tile_diffs = scan_for_updates(0);
 
1375
                                }
 
1376
                        } else {
 
1377
                                tile_diffs = scan_for_updates(0);
 
1378
                        }
 
1379
                        dt = dtime(&tm);
 
1380
                        if (! nap_ok) {
 
1381
                                last_dt = dt;
 
1382
                        }
 
1383
 
 
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);
 
1390
 }
 
1391
 
 
1392
                }
 
1393
 
 
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);
 
1400
                        } else {
 
1401
                                usleep(wait * 1000);
 
1402
                        }
 
1403
                }
 
1404
                cnt++;
 
1405
        }
 
1406
}
 
1407
 
 
1408
/* 
 
1409
 * check blacklist for OSs with tight shm limits.
 
1410
 */
 
1411
static int limit_shm(void) {
 
1412
        int limit = 0;
 
1413
 
 
1414
        if (UT.sysname == NULL) {
 
1415
                return 0;
 
1416
        }
 
1417
        if (!strcmp(UT.sysname, "SunOS")) {
 
1418
                char *r = UT.release;
 
1419
                if (*r == '5' && *(r+1) == '.') {
 
1420
                        if (strchr("2345678", *(r+2)) != NULL) {
 
1421
                                limit = 1;
 
1422
                        }
 
1423
                }
 
1424
        } else if (!strcmp(UT.sysname, "Darwin")) {
 
1425
                limit = 1;
 
1426
        }
 
1427
        if (limit && ! quiet) {
 
1428
                fprintf(stderr, "reducing shm usage on %s %s (adding "
 
1429
                    "-onetile)\n", UT.sysname, UT.release);
 
1430
        }
 
1431
        return limit;
 
1432
}
 
1433
 
 
1434
 
 
1435
/*
 
1436
 * quick-n-dirty ~/.x11vncrc: each line (except # comments) is a cmdline option.
 
1437
 */
 
1438
static int argc2 = 0;
 
1439
static char **argv2;
 
1440
 
 
1441
static void check_rcfile(int argc, char **argv) {
 
1442
        int i, j, pwlast, norc = 0, argmax = 1024;
 
1443
        char *infile = NULL;
 
1444
        char rcfile[1024];
 
1445
        FILE *rc = NULL; 
 
1446
 
 
1447
        for (i=1; i < argc; i++) {
 
1448
                if (!strcmp(argv[i], "-printgui")) {
 
1449
                        fprintf(stdout, "%s", get_gui_code());
 
1450
                        fflush(stdout);
 
1451
                        exit(0);
 
1452
                }
 
1453
                if (!strcmp(argv[i], "-norc")) {
 
1454
                        norc = 1;
 
1455
                        got_norc = 1;
 
1456
                }
 
1457
                if (!strcmp(argv[i], "-QD")) {
 
1458
                        norc = 1;
 
1459
                }
 
1460
                if (!strcmp(argv[i], "-rc")) {
 
1461
                        if (i+1 >= argc) {
 
1462
                                fprintf(stderr, "-rc option requires a "
 
1463
                                    "filename\n");
 
1464
                                exit(1);
 
1465
                        } else {
 
1466
                                infile = argv[i+1];
 
1467
                        }
 
1468
                }
 
1469
        }
 
1470
        rc_norc = norc;
 
1471
        rc_rcfile = strdup("");
 
1472
        if (norc) {
 
1473
                ;
 
1474
        } else if (infile != NULL) {
 
1475
                rc = fopen(infile, "r");
 
1476
                rc_rcfile = strdup(infile);
 
1477
                if (rc == NULL) {
 
1478
                        fprintf(stderr, "could not open rcfile: %s\n", infile);
 
1479
                        perror("fopen");
 
1480
                        exit(1);
 
1481
                }
 
1482
        } else {
 
1483
                char *home = get_home_dir();
 
1484
                if (! home) {
 
1485
                        norc = 1;
 
1486
                } else {
 
1487
                        strncpy(rcfile, home, 500);
 
1488
                        free(home);
 
1489
 
 
1490
                        strcat(rcfile, "/.x11vncrc");
 
1491
                        infile = rcfile;
 
1492
                        rc = fopen(rcfile, "r");
 
1493
                        if (rc == NULL) {
 
1494
                                norc = 1;
 
1495
                        } else {
 
1496
                                rc_rcfile = strdup(rcfile);
 
1497
                                rc_rcfile_default = 1;
 
1498
                        }
 
1499
                }
 
1500
        }
 
1501
 
 
1502
        argv2 = (char **) malloc(argmax * sizeof(char *));
 
1503
        argv2[argc2++] = strdup(argv[0]);
 
1504
 
 
1505
        if (! norc) {
 
1506
                char line[4096], parm[400], tmp[401];
 
1507
                char *buf, *tbuf;
 
1508
                struct stat sbuf;
 
1509
                int sz;
 
1510
 
 
1511
                if (fstat(fileno(rc), &sbuf) != 0) {
 
1512
                        fprintf(stderr, "problem with %s\n", infile);
 
1513
                        perror("fstat");
 
1514
                        exit(1);
 
1515
                }
 
1516
                sz = sbuf.st_size+1;    /* allocate whole file size */
 
1517
                if (sz < 1024) {
 
1518
                        sz = 1024;
 
1519
                }
 
1520
 
 
1521
                buf = (char *) malloc(sz);
 
1522
                buf[0] = '\0';
 
1523
 
 
1524
                while (fgets(line, 4096, rc) != NULL) {
 
1525
                        char *q, *p = line;
 
1526
                        char c;
 
1527
                        int cont = 0;
 
1528
 
 
1529
                        q = p;
 
1530
                        c = '\0';
 
1531
                        while (*q) {
 
1532
                                if (*q == '#') {
 
1533
                                        if (c != '\\') {
 
1534
                                                *q = '\0';
 
1535
                                                break;
 
1536
                                        }
 
1537
                                }
 
1538
                                c = *q;
 
1539
                                q++;
 
1540
                        }
 
1541
 
 
1542
                        q = p;
 
1543
                        c = '\0';
 
1544
                        while (*q) {
 
1545
                                if (*q == '\n') {
 
1546
                                        if (c == '\\') {
 
1547
                                                cont = 1;
 
1548
                                                *q = '\0';
 
1549
                                                *(q-1) = ' ';
 
1550
                                                break;
 
1551
                                        }
 
1552
                                        while (isspace((unsigned char) (*q))) {
 
1553
                                                *q = '\0';
 
1554
                                                if (q == p) {
 
1555
                                                        break;
 
1556
                                                }
 
1557
                                                q--;
 
1558
                                        }
 
1559
                                        break;
 
1560
                                }
 
1561
                                c = *q;
 
1562
                                q++;
 
1563
                        }
 
1564
                        if (q != p && !cont) {
 
1565
                                if (*q == '\0') {
 
1566
                                        q--;
 
1567
                                }
 
1568
                                while (isspace((unsigned char) (*q))) {
 
1569
                                        *q = '\0';
 
1570
                                        if (q == p) {
 
1571
                                                break;
 
1572
                                        }
 
1573
                                        q--;
 
1574
                                }
 
1575
                        }
 
1576
 
 
1577
                        p = lblanks(p);
 
1578
 
 
1579
                        strncat(buf, p, sz - strlen(buf) - 1);
 
1580
                        if (cont) {
 
1581
                                continue;
 
1582
                        }
 
1583
                        if (buf[0] == '\0') {
 
1584
                                continue;
 
1585
                        }
 
1586
 
 
1587
                        i = 0;
 
1588
                        q = buf;
 
1589
                        while (*q) {
 
1590
                                i++;
 
1591
                                if (*q == '\n' || isspace((unsigned char) (*q))) {
 
1592
                                        break;
 
1593
                                }
 
1594
                                q++;
 
1595
                        }
 
1596
 
 
1597
                        if (i >= 400) {
 
1598
                                fprintf(stderr, "invalid rcfile line: %s/%s\n",
 
1599
                                    p, buf);
 
1600
                                exit(1);
 
1601
                        }
 
1602
 
 
1603
                        if (sscanf(buf, "%s", parm) != 1) {
 
1604
                                fprintf(stderr, "invalid rcfile line: %s\n", p);
 
1605
                                exit(1);
 
1606
                        }
 
1607
                        if (parm[0] == '-') {
 
1608
                                strncpy(tmp, parm, 400); 
 
1609
                        } else {
 
1610
                                tmp[0] = '-';
 
1611
                                strncpy(tmp+1, parm, 400); 
 
1612
                        }
 
1613
 
 
1614
                        if (strstr(tmp, "-loop") == tmp) {
 
1615
                                if (! getenv("X11VNC_LOOP_MODE")) {
 
1616
                                        check_loop_mode(argc, argv, 1);
 
1617
                                        exit(0);
 
1618
                                }
 
1619
                        }
 
1620
 
 
1621
                        argv2[argc2++] = strdup(tmp);
 
1622
                        if (argc2 >= argmax) {
 
1623
                                fprintf(stderr, "too many rcfile options\n");
 
1624
                                exit(1);
 
1625
                        }
 
1626
                        
 
1627
                        p = buf;
 
1628
                        p += strlen(parm);
 
1629
                        p = lblanks(p);
 
1630
 
 
1631
                        if (*p == '\0') {
 
1632
                                buf[0] = '\0';
 
1633
                                continue;
 
1634
                        }
 
1635
 
 
1636
                        tbuf = (char *) calloc(strlen(p) + 1, 1);
 
1637
 
 
1638
                        j = 0;
 
1639
                        while (*p) {
 
1640
                                if (*p == '\\' && *(p+1) == '#') {
 
1641
                                        ;
 
1642
                                } else {
 
1643
                                        tbuf[j++] = *p;
 
1644
                                }
 
1645
                                p++;
 
1646
                        }
 
1647
 
 
1648
                        argv2[argc2++] = strdup(tbuf);
 
1649
                        free(tbuf);
 
1650
                        if (argc2 >= argmax) {
 
1651
                                fprintf(stderr, "too many rcfile options\n");
 
1652
                                exit(1);
 
1653
                        }
 
1654
                        buf[0] = '\0';
 
1655
                }
 
1656
                fclose(rc);
 
1657
                free(buf);
 
1658
        }
 
1659
        pwlast = 0;
 
1660
        for (i=1; i < argc; i++) {
 
1661
                argv2[argc2++] = strdup(argv[i]);
 
1662
 
 
1663
                if (pwlast || !strcmp("-passwd", argv[i])
 
1664
                    || !strcmp("-viewpasswd", argv[i])) {
 
1665
                        char *p = argv[i];              
 
1666
                        if (pwlast) {
 
1667
                                pwlast = 0;
 
1668
                        } else {
 
1669
                                pwlast = 1;
 
1670
                        }
 
1671
                        strzero(p);
 
1672
                }
 
1673
                if (argc2 >= argmax) {
 
1674
                        fprintf(stderr, "too many rcfile options\n");
 
1675
                        exit(1);
 
1676
                }
 
1677
        }
 
1678
}
 
1679
 
 
1680
static void immediate_switch_user(int argc, char* argv[]) {
 
1681
        int i, bequiet = 0;
 
1682
        for (i=1; i < argc; i++) {
 
1683
                if (strcmp(argv[i], "-inetd")) {
 
1684
                        bequiet = 1;
 
1685
                }
 
1686
                if (strcmp(argv[i], "-quiet")) {
 
1687
                        bequiet = 1;
 
1688
                }
 
1689
                if (strcmp(argv[i], "-q")) {
 
1690
                        bequiet = 1;
 
1691
                }
 
1692
        }
 
1693
        for (i=1; i < argc; i++) {
 
1694
                char *u, *q;
 
1695
 
 
1696
                if (strcmp(argv[i], "-users")) {
 
1697
                        continue;
 
1698
                }
 
1699
                if (i == argc - 1) {
 
1700
                        fprintf(stderr, "not enough arguments for: -users\n");
 
1701
                        exit(1);
 
1702
                }
 
1703
                if (*(argv[i+1]) != '=') {
 
1704
                        break;
 
1705
                }
 
1706
 
 
1707
                /* wants an immediate switch: =bob */
 
1708
                u = strdup(argv[i+1]);
 
1709
                *u = '+';
 
1710
                q = strchr(u, '.');
 
1711
                if (q) {
 
1712
                        user2group = (char **) malloc(2*sizeof(char *));
 
1713
                        user2group[0] = strdup(u+1);
 
1714
                        user2group[1] = NULL;
 
1715
                        *q = '\0';
 
1716
                }
 
1717
                if (strstr(u, "+guess") == u) {
 
1718
                        fprintf(stderr, "invalid user: %s\n", u+1);
 
1719
                        exit(1);
 
1720
                }
 
1721
                if (!switch_user(u, 0)) {
 
1722
                        fprintf(stderr, "Could not switch to user: %s\n", u+1);
 
1723
                        exit(1);
 
1724
                } else {
 
1725
                        if (!bequiet) {
 
1726
                                fprintf(stderr, "Switched to user: %s\n", u+1);
 
1727
                        }
 
1728
                        started_as_root = 2;
 
1729
                }
 
1730
                free(u);
 
1731
                break;
 
1732
        }
 
1733
}
 
1734
 
 
1735
static void quick_pw(char *str) {
 
1736
        char *p, *q;
 
1737
        char tmp[1024];
 
1738
        int db = 0;
 
1739
 
 
1740
        if (db) fprintf(stderr, "quick_pw: %s\n", str);
 
1741
 
 
1742
        if (! str || str[0] == '\0') {
 
1743
                exit(1);
 
1744
        }
 
1745
        if (str[0] != '%') {
 
1746
                exit(1);
 
1747
        }
 
1748
        /*
 
1749
         * "%-" or "%stdin" means read one line from stdin.
 
1750
         *
 
1751
         * "%env" means it is in $UNIXPW env var.
 
1752
         *
 
1753
         * starting "%/" or "%." means read the first line from that file.
 
1754
         *
 
1755
         * "%%" or "%" means prompt user.
 
1756
         *
 
1757
         * otherwise: %user:pass
 
1758
         */
 
1759
        if (!strcmp(str, "%-") || !strcmp(str, "%stdin")) {
 
1760
                if(fgets(tmp, 1024, stdin) == NULL) {
 
1761
                        exit(1);
 
1762
                }
 
1763
                q = strdup(tmp);
 
1764
        } else if (!strcmp(str, "%env")) {
 
1765
                if (getenv("UNIXPW") == NULL) {
 
1766
                        exit(1);
 
1767
                }
 
1768
                q = strdup(getenv("UNIXPW"));
 
1769
        } else if (!strcmp(str, "%%") || !strcmp(str, "%")) {
 
1770
                char *t, inp[1024];
 
1771
                fprintf(stdout, "username: ");
 
1772
                if(fgets(tmp, 128, stdin) == NULL) {
 
1773
                        exit(1);
 
1774
                }
 
1775
                strcpy(inp, tmp);
 
1776
                t = strchr(inp, '\n');
 
1777
                if (t) {
 
1778
                        *t = ':'; 
 
1779
                } else {
 
1780
                        strcat(inp, ":");
 
1781
                        
 
1782
                }
 
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");
 
1789
                        exit(1);
 
1790
                }
 
1791
                system("stty echo");
 
1792
                fprintf(stdout, "\n");
 
1793
                strcat(inp, tmp);
 
1794
                q = strdup(inp);
 
1795
        } else if (str[1] == '/' || str[1] == '.') {
 
1796
                FILE *in = fopen(str+1, "r");
 
1797
                if (in == NULL) {
 
1798
                        exit(1);
 
1799
                }
 
1800
                if(fgets(tmp, 1024, in) == NULL) {
 
1801
                        exit(1);
 
1802
                }
 
1803
                q = strdup(tmp);
 
1804
        } else {
 
1805
                q = strdup(str+1);
 
1806
        }
 
1807
        p = (char *) malloc(strlen(q) + 10);
 
1808
        strcpy(p, q);
 
1809
        if (strchr(p, '\n') == NULL) {
 
1810
                strcat(p, "\n");
 
1811
        }
 
1812
 
 
1813
        if ((q = strchr(p, ':')) == NULL) {
 
1814
                exit(1);
 
1815
        }
 
1816
        *q = '\0';
 
1817
        if (db) fprintf(stderr, "'%s' '%s'\n", p, q+1);
 
1818
        if (unixpw_cmd) {
 
1819
                if (cmd_verify(p, q+1)) {
 
1820
                        fprintf(stdout, "Y %s\n", p);
 
1821
                        exit(0);
 
1822
                } else {
 
1823
                        fprintf(stdout, "N %s\n", p);
 
1824
                        exit(1);
 
1825
                }
 
1826
        } else if (unixpw_nis) {
 
1827
                if (crypt_verify(p, q+1)) {
 
1828
                        fprintf(stdout, "Y %s\n", p);
 
1829
                        exit(0);
 
1830
                } else {
 
1831
                        fprintf(stdout, "N %s\n", p);
 
1832
                        exit(1);
 
1833
                }
 
1834
        } else {
 
1835
                if (su_verify(p, q+1, NULL, NULL, NULL, 1)) {
 
1836
                        fprintf(stdout, "Y %s\n", p);
 
1837
                        exit(0);
 
1838
                } else {
 
1839
                        fprintf(stdout, "N %s\n", p);
 
1840
                        exit(1);
 
1841
                }
 
1842
        }
 
1843
        /* NOTREACHED */
 
1844
        exit(1);
 
1845
}
 
1846
 
 
1847
static void print_settings(int try_http, int bg, char *gui_str) {
 
1848
 
 
1849
        fprintf(stderr, "\n");
 
1850
        fprintf(stderr, "Settings:\n");
 
1851
        fprintf(stderr, " display:    %s\n", use_dpy ? use_dpy
 
1852
            : "null");
 
1853
#if SMALL_FOOTPRINT < 2
 
1854
        fprintf(stderr, " authfile:   %s\n", auth_file ? auth_file
 
1855
            : "null");
 
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
 
1859
            : "null");
 
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
 
1865
            : "null");
 
1866
        fprintf(stderr, " 24to32:     %d\n", xform24to32);
 
1867
        fprintf(stderr, " visual:     %s\n", visual_str ? visual_str
 
1868
            : "null");
 
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
 
1886
            : "null");
 
1887
        fprintf(stderr, " input:      %s\n", allowed_input_str
 
1888
            ? allowed_input_str : "null");
 
1889
        fprintf(stderr, " passfile:   %s\n", passwdfile ? passwdfile
 
1890
            : "null");
 
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
 
1899
            : "null");
 
1900
        fprintf(stderr, " accept:     %s\n", afteraccept_cmd ? afteraccept_cmd
 
1901
            : "null");
 
1902
        fprintf(stderr, " gone:       %s\n", gone_cmd ? gone_cmd
 
1903
            : "null");
 
1904
        fprintf(stderr, " users:      %s\n", users_list ? users_list
 
1905
            : "null");
 
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
 
1917
            : "null");
 
1918
        fprintf(stderr, " padgeom:    %s\n", pad_geometry
 
1919
            ? pad_geometry : "null");
 
1920
        fprintf(stderr, " logfile:    %s\n", logfile ? logfile
 
1921
            : "null");
 
1922
        fprintf(stderr, " logappend:  %d\n", logfile_append);
 
1923
        fprintf(stderr, " flag:       %s\n", flagfile ? flagfile
 
1924
            : "null");
 
1925
        fprintf(stderr, " rc_file:    \"%s\"\n", rc_rcfile ? rc_rcfile
 
1926
            : "null");
 
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
 
1941
            : "null");
 
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");
 
2035
#endif
 
2036
}
 
2037
 
 
2038
 
 
2039
static void check_loop_mode(int argc, char* argv[], int force) {
 
2040
        int i;
 
2041
        int loop_mode = 0, loop_sleep = 2000, loop_max = 0;
 
2042
 
 
2043
        if (force) {
 
2044
                loop_mode = 1;
 
2045
        }
 
2046
        for (i=1; i < argc; i++) {
 
2047
                char *p = argv[i];
 
2048
                if (strstr(p, "--") == p) {
 
2049
                        p++;
 
2050
                }
 
2051
                if (strstr(p, "-loop") == p) {
 
2052
                        char *q;
 
2053
                        loop_mode = 1;
 
2054
                        if ((q = strchr(p, ',')) != NULL) {
 
2055
                                loop_max = atoi(q+1);
 
2056
                                *q = '\0';
 
2057
                        }
 
2058
                        if (strstr(p, "-loopbg") == p) {
 
2059
                                set_env("X11VNC_LOOP_MODE_BG", "1");
 
2060
                                loop_sleep = 500;
 
2061
                        }
 
2062
                        
 
2063
                        q = strpbrk(p, "0123456789");
 
2064
                        if (q) {
 
2065
                                loop_sleep = atoi(q);
 
2066
                                if (loop_sleep <= 0) {
 
2067
                                        loop_sleep = 20;
 
2068
                                }
 
2069
                        }
 
2070
                }
 
2071
        }
 
2072
        if (loop_mode && getenv("X11VNC_LOOP_MODE") == NULL) {
 
2073
#if LIBVNCSERVER_HAVE_FORK
 
2074
                char **argv2;
 
2075
                int k, i = 1;
 
2076
 
 
2077
                set_env("X11VNC_LOOP_MODE", "1");
 
2078
                argv2 = (char **) malloc((argc+1)*sizeof(char *));
 
2079
 
 
2080
                for (k=0; k < argc+1; k++) {
 
2081
                        argv2[k] = NULL;
 
2082
                        if (k < argc) {
 
2083
                                argv2[k] = argv[k];
 
2084
                        }
 
2085
                }
 
2086
                while (1) {
 
2087
                        int status;
 
2088
                        pid_t p;
 
2089
                        fprintf(stderr, "\n --- x11vnc loop: %d ---\n\n", i++);
 
2090
                        fflush(stderr);
 
2091
                        usleep(500 * 1000);
 
2092
                        if ((p = fork()) > 0)  {
 
2093
                                fprintf(stderr, " --- x11vnc loop: waiting "
 
2094
                                    "for: %d\n\n", p);
 
2095
                                wait(&status);
 
2096
                        } else if (p == -1) {
 
2097
                                fprintf(stderr, "could not fork\n");
 
2098
                                perror("fork");
 
2099
                                exit(1);
 
2100
                        } else {
 
2101
                                /* loop mode: no_external_cmds does not apply */
 
2102
                                execvp(argv[0], argv2); 
 
2103
                                exit(1);
 
2104
                        }
 
2105
 
 
2106
                        if (loop_max > 0 && i > loop_max) {
 
2107
                                fprintf(stderr, "\n --- x11vnc loop: did %d"
 
2108
                                    " done. ---\n\n", loop_max);
 
2109
                                break;
 
2110
                        }
 
2111
                        
 
2112
                        fprintf(stderr, "\n --- x11vnc loop: sleeping %d ms "
 
2113
                            "---\n\n", loop_sleep);
 
2114
                        usleep(loop_sleep * 1000);
 
2115
                }
 
2116
                exit(0);
 
2117
#else
 
2118
                fprintf(stderr, "fork unavailable, cannot do -loop mode\n");
 
2119
                exit(1);
 
2120
#endif
 
2121
        }
 
2122
}
 
2123
static void store_homedir_passwd(char *file) {
 
2124
        char str1[32], str2[32], *p, *h, *f;
 
2125
        struct stat sbuf;
 
2126
 
 
2127
        str1[0] = '\0';
 
2128
        str2[0] = '\0';
 
2129
 
 
2130
        /* storepasswd */
 
2131
        if (no_external_cmds || !cmd_ok("storepasswd")) {
 
2132
                fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
 
2133
                exit(1);
 
2134
        }
 
2135
 
 
2136
        fprintf(stderr, "Enter VNC password: ");
 
2137
        system("stty -echo");
 
2138
        if (fgets(str1, 32, stdin) == NULL) {
 
2139
                system("stty echo");
 
2140
                exit(1);
 
2141
        }
 
2142
        fprintf(stderr, "\n");
 
2143
 
 
2144
        fprintf(stderr, "Verify password:    ");
 
2145
        if (fgets(str2, 32, stdin) == NULL) {
 
2146
                system("stty echo");
 
2147
                exit(1);
 
2148
        }
 
2149
        fprintf(stderr, "\n");
 
2150
        system("stty echo");
 
2151
 
 
2152
        if ((p = strchr(str1, '\n')) != NULL) {
 
2153
                *p = '\0';
 
2154
        }
 
2155
        if ((p = strchr(str2, '\n')) != NULL) {
 
2156
                *p = '\0';
 
2157
        }
 
2158
        if (strcmp(str1, str2)) {
 
2159
                fprintf(stderr, "** passwords differ.\n");
 
2160
                exit(1);
 
2161
        }
 
2162
        if (str1[0] == '\0') {
 
2163
                fprintf(stderr, "** no password supplied.\n");
 
2164
                exit(1);
 
2165
        }
 
2166
 
 
2167
        if (file != NULL) {
 
2168
                f = file;
 
2169
        } else {
 
2170
                
 
2171
                h = getenv("HOME");
 
2172
                if (! h) {
 
2173
                        fprintf(stderr, "** $HOME not set.\n");
 
2174
                        exit(1);
 
2175
                }
 
2176
 
 
2177
                f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1);
 
2178
                sprintf(f, "%s/.vnc", h);
 
2179
 
 
2180
                if (stat(f, &sbuf) != 0) {
 
2181
                        if (mkdir(f, 0755) != 0) {
 
2182
                                fprintf(stderr, "** could not create directory %s\n", f);
 
2183
                                perror("mkdir");
 
2184
                                exit(1);
 
2185
                        }
 
2186
                } else if (! S_ISDIR(sbuf.st_mode)) {
 
2187
                        fprintf(stderr, "** not a directory %s\n", f);
 
2188
                        exit(1);
 
2189
                }
 
2190
 
 
2191
                sprintf(f, "%s/.vnc/passwd", h);
 
2192
        }
 
2193
        fprintf(stderr, "Write password to %s?  [y]/n ", f);
 
2194
 
 
2195
        if (fgets(str2, 32, stdin) == NULL) {
 
2196
                exit(1);
 
2197
        }
 
2198
        if (str2[0] == 'n' || str2[0] == 'N') {
 
2199
                fprintf(stderr, "not creating password.\n");
 
2200
                exit(1);
 
2201
        }
 
2202
 
 
2203
        if (rfbEncryptAndStorePasswd(str1, f) != 0) {
 
2204
                fprintf(stderr, "** error creating password.\n");
 
2205
                perror("storepasswd");
 
2206
                exit(1);
 
2207
        }
 
2208
        fprintf(stderr, "Password written to: %s\n", f);
 
2209
        if (stat(f, &sbuf) != 0) {
 
2210
                exit(1);
 
2211
        }
 
2212
        exit(0);
 
2213
}
 
2214
 
 
2215
void ncache_beta_tester_message(void) {
 
2216
 
 
2217
char msg[] = 
 
2218
"\n"
 
2219
"******************************************************************************\n"
 
2220
"\n"
 
2221
"Hello!  Exciting News!!\n"
 
2222
"\n"
 
2223
"You have been selected at random to beta-test the x11vnc '-ncache' VNC\n"
 
2224
"client-side pixel caching feature!\n"
 
2225
"\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"
 
2228
"\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"
 
2232
"\n"
 
2233
"    x11vnc -noncache ...\n"
 
2234
"\n"
 
2235
"Your current setting is: -ncache %d\n"
 
2236
"\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"
 
2241
"\n"
 
2242
"    1) It uses a large amount of RAM (on both viewer and server sides)\n"
 
2243
"\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"
 
2246
"\n"
 
2247
"More info: http://www.karlrunge.com/x11vnc/#faq-client-caching\n"
 
2248
"\n"
 
2249
"waiting for connections:\n"
 
2250
;
 
2251
 
 
2252
char msg2[] = 
 
2253
"\n"
 
2254
"******************************************************************************\n"
 
2255
"Have you tried the x11vnc '-ncache' VNC client-side pixel caching feature yet?\n"
 
2256
"\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"
 
2259
"\n"
 
2260
"    x11vnc -ncache 10 ...\n"
 
2261
"\n"
 
2262
"more info: http://www.karlrunge.com/x11vnc/#faq-client-caching\n"
 
2263
"\n"
 
2264
;
 
2265
 
 
2266
        if (raw_fb_str && !macosx_console) {
 
2267
                return;
 
2268
        }
 
2269
        if (quiet) {
 
2270
                return;
 
2271
        }
 
2272
        if (nofb) {
 
2273
                return;
 
2274
        }
 
2275
#ifdef NO_NCACHE
 
2276
        return;
 
2277
#endif
 
2278
 
 
2279
        if (ncache == 0) {
 
2280
                fprintf(stderr, msg2);
 
2281
                ncache0 = ncache = 0;
 
2282
        } else {
 
2283
                fprintf(stderr, msg, ncache);
 
2284
        }
 
2285
}
 
2286
 
 
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)
 
2291
 
 
2292
extern int dragum(void);
 
2293
 
 
2294
int main(int argc, char* argv[]) {
 
2295
 
 
2296
        int i, len, tmpi;
 
2297
        int ev, er, maj, min;
 
2298
        char *arg;
 
2299
        int remote_sync = 0;
 
2300
        char *remote_cmd = NULL;
 
2301
        char *query_cmd  = NULL;
 
2302
        char *gui_str = NULL;
 
2303
        int got_gui_pw = 0;
 
2304
        int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW;
 
2305
        int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0;
 
2306
        int vpw_loc = -1;
 
2307
        int dt = 0, bg = 0;
 
2308
        int got_rfbwait = 0;
 
2309
        int got_httpdir = 0, try_http = 0;
 
2310
        int orig_use_xdamage = use_xdamage;
 
2311
        XImage *fb0 = NULL;
 
2312
        int ncache_msg = 0;
 
2313
 
 
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];
 
2317
 
 
2318
 
 
2319
        /* check for -loop mode: */
 
2320
        check_loop_mode(argc, argv, 0);
 
2321
 
 
2322
        dtime0(&x11vnc_start);
 
2323
 
 
2324
        if (!getuid() || !geteuid()) {
 
2325
                started_as_root = 1;
 
2326
 
 
2327
                /* check for '-users =bob' */
 
2328
                immediate_switch_user(argc, argv);
 
2329
        }
 
2330
 
 
2331
        for (i=0; i < 2048; i++) {
 
2332
                argv_vnc[i] = NULL;
 
2333
        }
 
2334
 
 
2335
        argv_vnc[0] = strdup(argv[0]);
 
2336
        program_name = strdup(argv[0]);
 
2337
        program_pid = (int) getpid();
 
2338
 
 
2339
        solid_default = strdup(solid_default);  /* for freeing with -R */
 
2340
 
 
2341
        len = 0;
 
2342
        for (i=1; i < argc; i++) {
 
2343
                len += strlen(argv[i]) + 4 + 1;
 
2344
        }
 
2345
        program_cmdline = (char *) malloc(len+1);
 
2346
        program_cmdline[0] = '\0';
 
2347
        for (i=1; i < argc; i++) {
 
2348
                char *s = argv[i];
 
2349
                if (program_cmdline[0]) {
 
2350
                        strcat(program_cmdline, " ");
 
2351
                }
 
2352
                if (*s == '-') {
 
2353
                        strcat(program_cmdline, s);
 
2354
                } else {
 
2355
                        strcat(program_cmdline, "{{");
 
2356
                        strcat(program_cmdline, s);
 
2357
                        strcat(program_cmdline, "}}");
 
2358
                }
 
2359
        }
 
2360
 
 
2361
        for (i=0; i<ICON_MODE_SOCKS; i++) {
 
2362
                icon_mode_socks[i] = -1;
 
2363
        }
 
2364
 
 
2365
        check_rcfile(argc, argv);
 
2366
        /* kludge for the new array argv2 set in check_rcfile() */
 
2367
#       define argc argc2
 
2368
#       define argv argv2
 
2369
 
 
2370
#       define CHECK_ARGC if (i >= argc-1) { \
 
2371
                fprintf(stderr, "not enough arguments for: %s\n", arg); \
 
2372
                exit(1); \
 
2373
        }
 
2374
 
 
2375
        /*
 
2376
         * do a quick check for parameters that apply to "utility"
 
2377
         * commands, i.e. ones that do not run the server.
 
2378
         */
 
2379
        for (i=1; i < argc; i++) {
 
2380
                arg = argv[i];
 
2381
                if (strstr(arg, "--") == arg) {
 
2382
                        arg++;
 
2383
                }
 
2384
                if (!strcmp(arg, "-ssldir")) {
 
2385
                        CHECK_ARGC
 
2386
                        ssl_certs_dir = strdup(argv[++i]);
 
2387
                }
 
2388
        }
 
2389
 
 
2390
        /*
 
2391
         * do a quick check for -env parameters
 
2392
         */
 
2393
        for (i=1; i < argc; i++) {
 
2394
                char *p, *q;
 
2395
                arg = argv[i];
 
2396
                if (strstr(arg, "--") == arg) {
 
2397
                        arg++;
 
2398
                }
 
2399
                if (!strcmp(arg, "-env")) {
 
2400
                        CHECK_ARGC
 
2401
                        p = strdup(argv[++i]);
 
2402
                        q = strchr(p, '=');
 
2403
                        if (! q) {
 
2404
                                fprintf(stderr, "no -env '=' found: %s\n", p);
 
2405
                                exit(1);
 
2406
                        } else {
 
2407
                                *q = '\0';
 
2408
                        }
 
2409
                        set_env(p, q+1);
 
2410
                        free(p);
 
2411
                }
 
2412
        }
 
2413
 
 
2414
        for (i=1; i < argc; i++) {
 
2415
                /* quick-n-dirty --option handling. */
 
2416
                arg = argv[i];
 
2417
                if (strstr(arg, "--") == arg) {
 
2418
                        arg++;
 
2419
                }
 
2420
 
 
2421
                if (!strcmp(arg, "-display")) {
 
2422
                        CHECK_ARGC
 
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);
 
2429
                                        exit(0);
 
2430
                                }
 
2431
                                if (strstr(use_dpy, "cmd=FINDCREATEDISPLAY-print")) {
 
2432
                                        fprintf(stdout, "%s", create_display);
 
2433
                                        exit(0);
 
2434
                                }
 
2435
                        }
 
2436
                } else if (!strcmp(arg, "-find")) {
 
2437
                        use_dpy = strdup("WAIT:cmd=FINDDISPLAY");
 
2438
                } else if (!strcmp(arg, "-finddpy") || strstr(arg, "-listdpy") == arg) {
 
2439
                        int ic = 0;
 
2440
                        use_dpy = strdup("WAIT:cmd=FINDDISPLAY-run");
 
2441
                        if (argc > i+1) {
 
2442
                                set_env("X11VNC_USER", argv[i+1]);
 
2443
                                fprintf(stdout, "X11VNC_USER=%s\n", getenv("X11VNC_USER"));
 
2444
                        }
 
2445
                        if (strstr(arg, "-listdpy") == arg) {
 
2446
                                set_env("FIND_DISPLAY_ALL", "1");
 
2447
                        }
 
2448
                        wait_for_client(&ic, NULL, 0);
 
2449
                        exit(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";
 
2460
                        CHECK_ARGC
 
2461
                        t = (char *) malloc(strlen(t0) + strlen(argv[++i]) + 2);
 
2462
                        q = strrchr(argv[i], ':');
 
2463
                        if (q) *q = ' ';
 
2464
                        sprintf(t, "%s=%s", t0, argv[i]);
 
2465
                        use_dpy = t;
 
2466
                } else if (!strcmp(arg, "-auth") || !strcmp(arg, "-xauth")) {
 
2467
                        CHECK_ARGC
 
2468
                        auth_file = strdup(argv[++i]);
 
2469
                } else if (!strcmp(arg, "-N")) {
 
2470
                        display_N = 1;
 
2471
                } else if (!strcmp(arg, "-autoport")) {
 
2472
                        CHECK_ARGC
 
2473
                        auto_port = atoi(argv[++i]);
 
2474
                } else if (!strcmp(arg, "-reflect")) {
 
2475
                        CHECK_ARGC
 
2476
                        raw_fb_str = (char *) malloc(4 + strlen(argv[i]) + 1);
 
2477
                        sprintf(raw_fb_str, "vnc:%s", argv[++i]);
 
2478
                        shared = 1;
 
2479
                } else if (!strcmp(arg, "-tsd")) {
 
2480
                        CHECK_ARGC
 
2481
                        terminal_services_daemon = strdup(argv[++i]);
 
2482
                } else if (!strcmp(arg, "-id") || !strcmp(arg, "-sid")) {
 
2483
                        CHECK_ARGC
 
2484
                        if (!strcmp(arg, "-sid")) {
 
2485
                                rootshift = 1;
 
2486
                        } else {
 
2487
                                rootshift = 0;
 
2488
                        }
 
2489
                        i++;
 
2490
                        if (!strcmp("pick", argv[i])) {
 
2491
                                if (started_as_root) {
 
2492
                                        fprintf(stderr, "unsafe: %s pick\n",
 
2493
                                            arg);
 
2494
                                        exit(1);
 
2495
                                } else if (! pick_windowid(&subwin)) {
 
2496
                                        fprintf(stderr, "invalid %s pick\n",
 
2497
                                            arg);
 
2498
                                        exit(1);
 
2499
                                }
 
2500
                        } else if (! scan_hexdec(argv[i], &subwin)) {
 
2501
                                fprintf(stderr, "invalid %s arg: %s\n", arg,
 
2502
                                    argv[i]);
 
2503
                                exit(1);
 
2504
                        }
 
2505
                } else if (!strcmp(arg, "-waitmapped")) {
 
2506
                        subwin_wait_mapped = 1;
 
2507
                } else if (!strcmp(arg, "-clip")) {
 
2508
                        CHECK_ARGC
 
2509
                        clip_str = strdup(argv[++i]);
 
2510
                } else if (!strcmp(arg, "-flashcmap")) {
 
2511
                        flash_cmap = 1;
 
2512
                } else if (!strcmp(arg, "-shiftcmap")) {
 
2513
                        CHECK_ARGC
 
2514
                        shift_cmap = atoi(argv[++i]);
 
2515
                } else if (!strcmp(arg, "-notruecolor")) {
 
2516
                        force_indexed_color = 1;
 
2517
                } else if (!strcmp(arg, "-overlay")) {
 
2518
                        overlay = 1;
 
2519
                } else if (!strcmp(arg, "-overlay_nocursor")) {
 
2520
                        overlay = 1;
 
2521
                        overlay_cursor = 0;
 
2522
                } else if (!strcmp(arg, "-overlay_yescursor")) {
 
2523
                        overlay = 1;
 
2524
                        overlay_cursor = 2;
 
2525
#if !SKIP_8TO24
 
2526
                } else if (!strcmp(arg, "-8to24")) {
 
2527
                        cmap8to24 = 1;
 
2528
                        if (i < argc-1) {
 
2529
                                char *s = argv[i+1];
 
2530
                                if (s[0] != '-') {
 
2531
                                        cmap8to24_str = strdup(s);
 
2532
                                        i++;
 
2533
                                }
 
2534
                        }
 
2535
#endif
 
2536
                } else if (!strcmp(arg, "-24to32")) {
 
2537
                        xform24to32 = 1;
 
2538
                } else if (!strcmp(arg, "-visual")) {
 
2539
                        CHECK_ARGC
 
2540
                        visual_str = strdup(argv[++i]);
 
2541
                } else if (!strcmp(arg, "-scale")) {
 
2542
                        CHECK_ARGC
 
2543
                        scale_str = strdup(argv[++i]);
 
2544
                } else if (!strcmp(arg, "-scale_cursor")) {
 
2545
                        CHECK_ARGC
 
2546
                        scale_cursor_str = strdup(argv[++i]);
 
2547
                } else if (!strcmp(arg, "-viewonly")) {
 
2548
                        view_only = 1;
 
2549
                } else if (!strcmp(arg, "-noviewonly")) {
 
2550
                        view_only = 0;
 
2551
                        got_noviewonly = 1;
 
2552
                } else if (!strcmp(arg, "-shared")) {
 
2553
                        shared = 1;
 
2554
                } else if (!strcmp(arg, "-noshared")) {
 
2555
                        shared = 0;
 
2556
                } else if (!strcmp(arg, "-once")) {
 
2557
                        connect_once = 1;
 
2558
                        got_connect_once = 1;
 
2559
                } else if (!strcmp(arg, "-many") || !strcmp(arg, "-forever")) {
 
2560
                        connect_once = 0;
 
2561
                } else if (strstr(arg, "-loop") == arg) {
 
2562
                        ;       /* handled above */
 
2563
                } else if (!strcmp(arg, "-timeout")) {
 
2564
                        CHECK_ARGC
 
2565
                        first_conn_timeout = atoi(argv[++i]);
 
2566
                } else if (!strcmp(arg, "-sleepin")) {
 
2567
                        int n;
 
2568
                        CHECK_ARGC
 
2569
                        n = atoi(argv[++i]);
 
2570
                        if (n > 0) {
 
2571
                                usleep(1000*1000*n);
 
2572
                        }
 
2573
                } else if (!strcmp(arg, "-users")) {
 
2574
                        CHECK_ARGC
 
2575
                        users_list = strdup(argv[++i]);
 
2576
                } else if (!strcmp(arg, "-inetd")) {
 
2577
                        inetd = 1;
 
2578
                } else if (!strcmp(arg, "-notightfilexfer")) {
 
2579
                        tightfilexfer = 0;
 
2580
                } else if (!strcmp(arg, "-tightfilexfer")) {
 
2581
                        tightfilexfer = 1;
 
2582
                } else if (!strcmp(arg, "-http")) {
 
2583
                        try_http = 1;
 
2584
                } else if (!strcmp(arg, "-http_ssl")) {
 
2585
                        try_http = 1;
 
2586
                        http_ssl = 1;
 
2587
                } else if (!strcmp(arg, "-avahi") || !strcmp(arg, "-mdns")) {
 
2588
                        avahi = 1;
 
2589
                } else if (!strcmp(arg, "-connect") ||
 
2590
                    !strcmp(arg, "-connect_or_exit")) {
 
2591
                        CHECK_ARGC
 
2592
                        if (strchr(argv[++i], '/')) {
 
2593
                                client_connect_file = strdup(argv[i]);
 
2594
                        } else {
 
2595
                                client_connect = strdup(argv[i]);
 
2596
                        }
 
2597
                        if (!strcmp(arg, "-connect_or_exit")) {
 
2598
                                connect_or_exit = 1;
 
2599
                        }
 
2600
                } else if (!strcmp(arg, "-proxy")) {
 
2601
                        CHECK_ARGC
 
2602
                        connect_proxy = strdup(argv[++i]);
 
2603
                } else if (!strcmp(arg, "-vncconnect")) {
 
2604
                        vnc_connect = 1;
 
2605
                } else if (!strcmp(arg, "-novncconnect")) {
 
2606
                        vnc_connect = 0;
 
2607
                } else if (!strcmp(arg, "-allow")) {
 
2608
                        CHECK_ARGC
 
2609
                        allow_list = strdup(argv[++i]);
 
2610
                } else if (!strcmp(arg, "-localhost")) {
 
2611
                        allow_list = strdup("127.0.0.1");
 
2612
                        got_localhost = 1;
 
2613
                } else if (!strcmp(arg, "-nolookup")) {
 
2614
                        host_lookup = 0;
 
2615
                } else if (!strcmp(arg, "-input")) {
 
2616
                        CHECK_ARGC
 
2617
                        allowed_input_str = strdup(argv[++i]);
 
2618
                } else if (!strcmp(arg, "-grabkbd")) {
 
2619
                        grab_kbd = 1;
 
2620
                } else if (!strcmp(arg, "-grabptr")) {
 
2621
                        grab_ptr = 1;
 
2622
                } else if (!strcmp(arg, "-grabalways")) {
 
2623
                        grab_kbd = 1;
 
2624
                        grab_ptr = 1;
 
2625
                        grab_always = 1;
 
2626
                } else if (!strcmp(arg, "-viewpasswd")) {
 
2627
                        vpw_loc = i;
 
2628
                        CHECK_ARGC
 
2629
                        viewonly_passwd = strdup(argv[++i]);
 
2630
                        got_viewpasswd = 1;
 
2631
                } else if (!strcmp(arg, "-passwdfile")) {
 
2632
                        CHECK_ARGC
 
2633
                        passwdfile = strdup(argv[++i]);
 
2634
                        got_passwdfile = 1;
 
2635
                } else if (!strcmp(arg, "-svc") || !strcmp(arg, "-service")) {
 
2636
                        use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb");
 
2637
                        unixpw = 1;
 
2638
                        users_list = strdup("unixpw=");
 
2639
                        use_openssl = 1;
 
2640
                        openssl_pem = strdup("SAVE");
 
2641
                } else if (!strcmp(arg, "-svc_xdummy")) {
 
2642
                        use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy");
 
2643
                        unixpw = 1;
 
2644
                        users_list = strdup("unixpw=");
 
2645
                        use_openssl = 1;
 
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");
 
2650
                        unixpw = 1;
 
2651
                        users_list = strdup("unixpw=");
 
2652
                        use_openssl = 1;
 
2653
                        openssl_pem = strdup("SAVE");
 
2654
                } else if (!strcmp(arg, "-xdmsvc") || !strcmp(arg, "-xdm_service")) {
 
2655
                        use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp");
 
2656
                        unixpw = 1;
 
2657
                        users_list = strdup("unixpw=");
 
2658
                        use_openssl = 1;
 
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");
 
2663
                        got_localhost = 1;
 
2664
#ifndef NO_SSL_OR_UNIXPW
 
2665
                } else if (!strcmp(arg, "-unixpw_cmd")
 
2666
                    || !strcmp(arg, "-unixpw_cmd_unsafe")) {
 
2667
                        CHECK_ARGC
 
2668
                        unixpw_cmd = strdup(argv[++i]);
 
2669
                        unixpw = 1;
 
2670
                        if (strstr(arg, "_unsafe")) {
 
2671
                                /* hidden option for testing. */
 
2672
                                set_env("UNIXPW_DISABLE_SSL", "1");
 
2673
                                set_env("UNIXPW_DISABLE_LOCALHOST", "1");
 
2674
                        }
 
2675
                } else if (strstr(arg, "-unixpw") == arg) {
 
2676
                        unixpw = 1;
 
2677
                        if (strstr(arg, "-unixpw_nis")) {
 
2678
                                unixpw_nis = 1;
 
2679
                        }
 
2680
                        if (i < argc-1) {
 
2681
                                char *s = argv[i+1];
 
2682
                                if (s[0] != '-') {
 
2683
                                        unixpw_list = strdup(s);
 
2684
                                        i++;
 
2685
                                }
 
2686
                                if (s[0] == '%') {
 
2687
                                        unixpw_list = NULL;
 
2688
                                        quick_pw(s);
 
2689
                                        exit(1);
 
2690
                                }
 
2691
                        }
 
2692
                        if (strstr(arg, "_unsafe")) {
 
2693
                                /* hidden option for testing. */
 
2694
                                set_env("UNIXPW_DISABLE_SSL", "1");
 
2695
                                set_env("UNIXPW_DISABLE_LOCALHOST", "1");
 
2696
                        }
 
2697
                } else if (!strcmp(arg, "-nossl")) {
 
2698
                        use_openssl = 0;
 
2699
                        openssl_pem = NULL;
 
2700
                } else if (!strcmp(arg, "-ssl")) {
 
2701
                        use_openssl = 1;
 
2702
                        if (i < argc-1) {
 
2703
                                char *s = argv[i+1];
 
2704
                                if (s[0] != '-') {
 
2705
                                        openssl_pem = strdup(s);
 
2706
                                        i++;
 
2707
                                }
 
2708
                        }
 
2709
                } else if (!strcmp(arg, "-ssltimeout")) {
 
2710
                        CHECK_ARGC
 
2711
                        ssl_timeout_secs = atoi(argv[++i]);
 
2712
                } else if (!strcmp(arg, "-sslnofail")) {
 
2713
                        ssl_no_fail = 1;
 
2714
                } else if (!strcmp(arg, "-ssldir")) {
 
2715
                        CHECK_ARGC
 
2716
                        ssl_certs_dir = strdup(argv[++i]);
 
2717
 
 
2718
                } else if (!strcmp(arg, "-sslverify")) {
 
2719
                        CHECK_ARGC
 
2720
                        ssl_verify = strdup(argv[++i]);
 
2721
 
 
2722
                } else if (!strcmp(arg, "-sslGenCA")) {
 
2723
                        char *cdir = NULL;
 
2724
                        if (i < argc-1) {
 
2725
                                char *s = argv[i+1];
 
2726
                                if (s[0] != '-') {
 
2727
                                        cdir = strdup(s);
 
2728
                                        i++;
 
2729
                                }
 
2730
                        }
 
2731
                        sslGenCA(cdir);
 
2732
                        exit(0);
 
2733
                } else if (!strcmp(arg, "-sslGenCert")) {
 
2734
                        char *ty, *nm = NULL;
 
2735
                        if (i >= argc-1) {
 
2736
                                fprintf(stderr, "Must be:\n");
 
2737
                                fprintf(stderr, "          x11vnc -sslGenCert server ...\n");
 
2738
                                fprintf(stderr, "or        x11vnc -sslGenCert client ...\n");
 
2739
                                exit(1);
 
2740
                        }
 
2741
                        ty = argv[i+1];
 
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");
 
2746
                                exit(1);
 
2747
                        }
 
2748
                        if (i < argc-2) {
 
2749
                                nm = argv[i+2];
 
2750
                        }
 
2751
                        sslGenCert(ty, nm);
 
2752
                        exit(0);
 
2753
                } else if (!strcmp(arg, "-sslEncKey")) {
 
2754
                        if (i < argc-1) {
 
2755
                                char *s = argv[i+1];
 
2756
                                sslEncKey(s, 0);
 
2757
                        }
 
2758
                        exit(0);
 
2759
                } else if (!strcmp(arg, "-sslCertInfo")) {
 
2760
                        if (i < argc-1) {
 
2761
                                char *s = argv[i+1];
 
2762
                                sslEncKey(s, 1);
 
2763
                        }
 
2764
                        exit(0);
 
2765
                } else if (!strcmp(arg, "-sslDelCert")) {
 
2766
                        if (i < argc-1) {
 
2767
                                char *s = argv[i+1];
 
2768
                                sslEncKey(s, 2);
 
2769
                        }
 
2770
                        exit(0);
 
2771
 
 
2772
                } else if (!strcmp(arg, "-stunnel")) {
 
2773
                        use_stunnel = 1;
 
2774
                        if (i < argc-1) {
 
2775
                                char *s = argv[i+1];
 
2776
                                if (s[0] != '-') {
 
2777
                                        stunnel_pem = strdup(s);
 
2778
                                        i++;
 
2779
                                }
 
2780
                        }
 
2781
                } else if (!strcmp(arg, "-stunnel3")) {
 
2782
                        use_stunnel = 3;
 
2783
                        if (i < argc-1) {
 
2784
                                char *s = argv[i+1];
 
2785
                                if (s[0] != '-') {
 
2786
                                        stunnel_pem = strdup(s);
 
2787
                                        i++;
 
2788
                                }
 
2789
                        }
 
2790
                } else if (!strcmp(arg, "-https")) {
 
2791
                        https_port_num = 0;
 
2792
                        try_http = 1;
 
2793
                        if (i < argc-1) {
 
2794
                                char *s = argv[i+1];
 
2795
                                if (s[0] != '-') {
 
2796
                                        https_port_num = atoi(s);
 
2797
                                        i++;
 
2798
                                }
 
2799
                        }
 
2800
                } else if (!strcmp(arg, "-httpsredir")) {
 
2801
                        https_port_redir = -1;
 
2802
                        if (i < argc-1) {
 
2803
                                char *s = argv[i+1];
 
2804
                                if (s[0] != '-') {
 
2805
                                        https_port_redir = atoi(s);
 
2806
                                        i++;
 
2807
                                }
 
2808
                        }
 
2809
#endif
 
2810
                } else if (!strcmp(arg, "-nopw")) {
 
2811
                        nopw = 1;
 
2812
                } else if (!strcmp(arg, "-ssh")) {
 
2813
                        CHECK_ARGC
 
2814
                        ssh_str = strdup(argv[++i]);
 
2815
                } else if (!strcmp(arg, "-usepw")) {
 
2816
                        usepw = 1;
 
2817
                } else if (!strcmp(arg, "-storepasswd")) {
 
2818
                        if (argc == i+1) {
 
2819
                                store_homedir_passwd(NULL);
 
2820
                                exit(0);
 
2821
                        }
 
2822
                        if (argc == i+2) {
 
2823
                                store_homedir_passwd(argv[i+1]);
 
2824
                                exit(0);
 
2825
                        }
 
2826
                        if (argc >= i+4 || rfbEncryptAndStorePasswd(argv[i+1],
 
2827
                            argv[i+2]) != 0) {
 
2828
                                fprintf(stderr, "-storepasswd failed\n");
 
2829
                                exit(1);
 
2830
                        } else {
 
2831
                                fprintf(stderr, "stored passwd in file %s\n",
 
2832
                                    argv[i+2]);
 
2833
                                exit(0);
 
2834
                        }
 
2835
                } else if (!strcmp(arg, "-accept")) {
 
2836
                        CHECK_ARGC
 
2837
                        accept_cmd = strdup(argv[++i]);
 
2838
                } else if (!strcmp(arg, "-afteraccept")) {
 
2839
                        CHECK_ARGC
 
2840
                        afteraccept_cmd = strdup(argv[++i]);
 
2841
                } else if (!strcmp(arg, "-gone")) {
 
2842
                        CHECK_ARGC
 
2843
                        gone_cmd = strdup(argv[++i]);
 
2844
                } else if (!strcmp(arg, "-noshm")) {
 
2845
                        using_shm = 0;
 
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")) {
 
2851
                        use_solid_bg = 1;
 
2852
                        if (i < argc-1) {
 
2853
                                char *s = argv[i+1];
 
2854
                                if (s[0] != '-') {
 
2855
                                        solid_str = strdup(s);
 
2856
                                        i++;
 
2857
                                }
 
2858
                        }
 
2859
                        if (! solid_str) {
 
2860
                                solid_str = strdup(solid_default);
 
2861
                        }
 
2862
                } else if (!strcmp(arg, "-blackout")) {
 
2863
                        CHECK_ARGC
 
2864
                        blackout_str = strdup(argv[++i]);
 
2865
                } else if (!strcmp(arg, "-xinerama")) {
 
2866
                        xinerama = 1;
 
2867
                } else if (!strcmp(arg, "-noxinerama")) {
 
2868
                        xinerama = 0;
 
2869
                } else if (!strcmp(arg, "-xtrap")) {
 
2870
                        xtrap_input = 1;
 
2871
                } else if (!strcmp(arg, "-xrandr")) {
 
2872
                        xrandr = 1;
 
2873
                        if (i < argc-1) {
 
2874
                                char *s = argv[i+1];
 
2875
                                if (known_xrandr_mode(s)) {
 
2876
                                        xrandr_mode = strdup(s);
 
2877
                                        i++;
 
2878
                                }
 
2879
                        }
 
2880
                } else if (!strcmp(arg, "-noxrandr")) {
 
2881
                        xrandr = 0;
 
2882
                        xrandr_maybe = 0;
 
2883
                } else if (!strcmp(arg, "-rotate")) {
 
2884
                        CHECK_ARGC
 
2885
                        rotating_str = strdup(argv[++i]);
 
2886
                } else if (!strcmp(arg, "-padgeom")
 
2887
                    || !strcmp(arg, "-padgeometry")) {
 
2888
                        CHECK_ARGC
 
2889
                        pad_geometry = strdup(argv[++i]);
 
2890
                } else if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) {
 
2891
                        CHECK_ARGC
 
2892
                        logfile_append = 0;
 
2893
                        logfile = strdup(argv[++i]);
 
2894
                } else if (!strcmp(arg, "-oa") || !strcmp(arg, "-logappend")) {
 
2895
                        CHECK_ARGC
 
2896
                        logfile_append = 1;
 
2897
                        logfile = strdup(argv[++i]);
 
2898
                } else if (!strcmp(arg, "-flag")) {
 
2899
                        CHECK_ARGC
 
2900
                        flagfile = strdup(argv[++i]);
 
2901
                } else if (!strcmp(arg, "-rc")) {
 
2902
                        i++;    /* done above */
 
2903
                } else if (!strcmp(arg, "-norc")) {
 
2904
                        ;       /* done above */
 
2905
                } else if (!strcmp(arg, "-env")) {
 
2906
                        i++;    /* done above */
 
2907
                } else if (!strcmp(arg, "-prog")) {
 
2908
                        CHECK_ARGC
 
2909
                        if (program_name) {
 
2910
                                free(program_name);
 
2911
                        }
 
2912
                        program_name = strdup(argv[++i]);
 
2913
                } else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) {
 
2914
                        print_help(0);
 
2915
                } else if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) {
 
2916
                        print_help(1);
 
2917
                } else if (!strcmp(arg, "-V") || !strcmp(arg, "-version")) {
 
2918
                        fprintf(stdout, "x11vnc: %s\n", lastmod);
 
2919
                        exit(0);
 
2920
                } else if (!strcmp(arg, "-license") ||
 
2921
                    !strcmp(arg, "-copying") || !strcmp(arg, "-warranty")) {
 
2922
                        print_license();
 
2923
                } else if (!strcmp(arg, "-dbg")) {
 
2924
                        crash_debug = 1;
 
2925
                } else if (!strcmp(arg, "-nodbg")) {
 
2926
                        crash_debug = 0;
 
2927
                } else if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) {
 
2928
                        quiet = 1;
 
2929
                } else if (!strcmp(arg, "-v") || !strcmp(arg, "-verbose")) {
 
2930
                        verbose = 1;
 
2931
                } else if (!strcmp(arg, "-bg") || !strcmp(arg, "-background")) {
 
2932
#if LIBVNCSERVER_HAVE_SETSID
 
2933
                        bg = 1;
 
2934
                        opts_bg = bg;
 
2935
#else
 
2936
                        fprintf(stderr, "warning: -bg mode not supported.\n");
 
2937
#endif
 
2938
                } else if (!strcmp(arg, "-modtweak")) {
 
2939
                        use_modifier_tweak = 1;
 
2940
                } else if (!strcmp(arg, "-nomodtweak")) {
 
2941
                        use_modifier_tweak = 0;
 
2942
                        got_nomodtweak = 1;
 
2943
                } else if (!strcmp(arg, "-isolevel3")) {
 
2944
                        use_iso_level3 = 1;
 
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;
 
2950
                        got_noxkb = 1;
 
2951
                } else if (!strcmp(arg, "-capslock")) {
 
2952
                        watch_capslock = 1;
 
2953
                } else if (!strcmp(arg, "-skip_lockkeys")) {
 
2954
                        skip_lockkeys = 1;
 
2955
                } else if (!strcmp(arg, "-xkbcompat")) {
 
2956
                        xkbcompat = 1;
 
2957
                } else if (!strcmp(arg, "-skip_keycodes")) {
 
2958
                        CHECK_ARGC
 
2959
                        skip_keycodes = strdup(argv[++i]);
 
2960
                } else if (!strcmp(arg, "-sloppy_keys")) {
 
2961
                        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")) {
 
2967
                        add_keysyms++;
 
2968
                } else if (!strcmp(arg, "-noadd_keysyms")) {
 
2969
                        add_keysyms = 0;
 
2970
                } else if (!strcmp(arg, "-clear_mods")) {
 
2971
                        clear_mods = 1;
 
2972
                } else if (!strcmp(arg, "-clear_keys")) {
 
2973
                        clear_mods = 2;
 
2974
                } else if (!strcmp(arg, "-clear_all")) {
 
2975
                        clear_mods = 3;
 
2976
                } else if (!strcmp(arg, "-remap")) {
 
2977
                        CHECK_ARGC
 
2978
                        remap_file = strdup(argv[++i]);
 
2979
                } else if (!strcmp(arg, "-norepeat")) {
 
2980
                        no_autorepeat = 1;
 
2981
                        if (i < argc-1) {
 
2982
                                char *s = argv[i+1];
 
2983
                                if (*s == '-') {
 
2984
                                        s++;
 
2985
                                }
 
2986
                                if (isdigit((unsigned char) (*s))) {
 
2987
                                        no_repeat_countdown = atoi(argv[++i]);
 
2988
                                }
 
2989
                        }
 
2990
                } else if (!strcmp(arg, "-repeat")) {
 
2991
                        no_autorepeat = 0;
 
2992
                } else if (!strcmp(arg, "-nofb")) {
 
2993
                        nofb = 1;
 
2994
                } else if (!strcmp(arg, "-nobell")) {
 
2995
                        watch_bell = 0;
 
2996
                        sound_bell = 0;
 
2997
                } else if (!strcmp(arg, "-nosel")) {
 
2998
                        watch_selection = 0;
 
2999
                        watch_primary = 0;
 
3000
                        watch_clipboard = 0;
 
3001
                } else if (!strcmp(arg, "-noprimary")) {
 
3002
                        watch_primary = 0;
 
3003
                } else if (!strcmp(arg, "-nosetprimary")) {
 
3004
                        set_primary = 0;
 
3005
                } else if (!strcmp(arg, "-noclipboard")) {
 
3006
                        watch_clipboard = 0;
 
3007
                } else if (!strcmp(arg, "-nosetclipboard")) {
 
3008
                        set_clipboard = 0;
 
3009
                } else if (!strcmp(arg, "-seldir")) {
 
3010
                        CHECK_ARGC
 
3011
                        sel_direction = strdup(argv[++i]);
 
3012
                } else if (!strcmp(arg, "-cursor")) {
 
3013
                        show_cursor = 1;
 
3014
                        if (i < argc-1) {
 
3015
                                char *s = argv[i+1];
 
3016
                                if (known_cursors_mode(s)) {
 
3017
                                        multiple_cursors_mode = strdup(s);
 
3018
                                        i++;
 
3019
                                        if (!strcmp(s, "none")) {
 
3020
                                                show_cursor = 0;
 
3021
                                        }
 
3022
                                } 
 
3023
                        }
 
3024
                } else if (!strcmp(arg, "-nocursor")) { 
 
3025
                        multiple_cursors_mode = strdup("none");
 
3026
                        show_cursor = 0;
 
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")) {
 
3032
                        CHECK_ARGC
 
3033
                        alt_arrow = atoi(argv[++i]);
 
3034
                } else if (!strcmp(arg, "-xfixes")) { 
 
3035
                        use_xfixes = 1;
 
3036
                } else if (!strcmp(arg, "-noxfixes")) { 
 
3037
                        use_xfixes = 0;
 
3038
                } else if (!strcmp(arg, "-alphacut")) {
 
3039
                        CHECK_ARGC
 
3040
                        alpha_threshold = atoi(argv[++i]);
 
3041
                } else if (!strcmp(arg, "-alphafrac")) {
 
3042
                        CHECK_ARGC
 
3043
                        alpha_frac = atof(argv[++i]);
 
3044
                } else if (!strcmp(arg, "-alpharemove")) {
 
3045
                        alpha_remove = 1;
 
3046
                } else if (!strcmp(arg, "-noalphablend")) {
 
3047
                        alpha_blend = 0;
 
3048
                } else if (!strcmp(arg, "-nocursorshape")) {
 
3049
                        cursor_shape_updates = 0;
 
3050
                } else if (!strcmp(arg, "-cursorpos")) {
 
3051
                        cursor_pos_updates = 1;
 
3052
                        got_cursorpos = 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")) {
 
3061
                        CHECK_ARGC
 
3062
                        pointer_remap = strdup(argv[++i]);
 
3063
                } else if (!strcmp(arg, "-nodragging")) {
 
3064
                        show_dragging = 0;
 
3065
#ifndef NO_NCACHE
 
3066
                } else if (!strcmp(arg, "-ncache") || !strcmp(arg, "-nc")) {
 
3067
                        if (i < argc-1) {
 
3068
                                char *s = argv[i+1];
 
3069
                                if (s[0] != '-') {
 
3070
                                        ncache = atoi(s);
 
3071
                                        i++;
 
3072
                                } else {
 
3073
                                        ncache = ncache_default;
 
3074
                                }
 
3075
                        } else {
 
3076
                                ncache = ncache_default;
 
3077
                        }
 
3078
                        if (ncache % 2 != 0) {
 
3079
                                ncache++;
 
3080
                        }
 
3081
                } else if (!strcmp(arg, "-noncache") || !strcmp(arg, "-nonc")) {
 
3082
                        ncache = 0;
 
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")) {
 
3094
                        ncache_old_wm = 1;
 
3095
                } else if (!strcmp(arg, "-ncache_pad") || !strcmp(arg, "-nc_pad")) {
 
3096
                        CHECK_ARGC
 
3097
                        ncache_pad = atoi(argv[++i]);
 
3098
                } else if (!strcmp(arg, "-debug_ncache")) {
 
3099
                        ncdb++;
 
3100
#endif
 
3101
                } else if (!strcmp(arg, "-wireframe")
 
3102
                    || !strcmp(arg, "-wf")) {
 
3103
                        wireframe = 1;
 
3104
                        if (i < argc-1) {
 
3105
                                char *s = argv[i+1];
 
3106
                                if (*s != '-') {
 
3107
                                        wireframe_str = strdup(argv[++i]);
 
3108
                                }
 
3109
                        }
 
3110
                } else if (!strcmp(arg, "-nowireframe")
 
3111
                    || !strcmp(arg, "-nowf")) {
 
3112
                        wireframe = 0;
 
3113
                } else if (!strcmp(arg, "-nowireframelocal")
 
3114
                    || !strcmp(arg, "-nowfl")) {
 
3115
                        wireframe_local = 0;
 
3116
                } else if (!strcmp(arg, "-wirecopyrect")
 
3117
                    || !strcmp(arg, "-wcr")) {
 
3118
                        CHECK_ARGC
 
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")) {
 
3126
                        debug_wireframe++;
 
3127
                } else if (!strcmp(arg, "-scrollcopyrect")
 
3128
                    || !strcmp(arg, "-scr")) {
 
3129
                        CHECK_ARGC
 
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")) {
 
3136
                        int tn;
 
3137
                        CHECK_ARGC
 
3138
                        tn = atoi(argv[++i]);
 
3139
                        if (tn >= 0) {
 
3140
                                scrollcopyrect_min_area = tn;
 
3141
                        }
 
3142
                } else if (!strcmp(arg, "-scr_skip")) {
 
3143
                        CHECK_ARGC
 
3144
                        scroll_skip_str = strdup(argv[++i]);
 
3145
                } else if (!strcmp(arg, "-scr_inc")) {
 
3146
                        CHECK_ARGC
 
3147
                        scroll_good_str = strdup(argv[++i]);
 
3148
                } else if (!strcmp(arg, "-scr_keys")) {
 
3149
                        CHECK_ARGC
 
3150
                        scroll_key_list_str = strdup(argv[++i]);
 
3151
                } else if (!strcmp(arg, "-scr_term")) {
 
3152
                        CHECK_ARGC
 
3153
                        scroll_term_str = strdup(argv[++i]);
 
3154
                } else if (!strcmp(arg, "-scr_keyrepeat")) {
 
3155
                        CHECK_ARGC
 
3156
                        max_keyrepeat_str = strdup(argv[++i]);
 
3157
                } else if (!strcmp(arg, "-scr_parms")) {
 
3158
                        CHECK_ARGC
 
3159
                        scroll_copyrect_str = strdup(argv[++i]);
 
3160
                } else if (!strcmp(arg, "-fixscreen")) {
 
3161
                        CHECK_ARGC
 
3162
                        screen_fixup_str = strdup(argv[++i]);
 
3163
                } else if (!strcmp(arg, "-debug_scroll")
 
3164
                    || !strcmp(arg, "-ds")) {
 
3165
                        debug_scroll++;
 
3166
                } else if (!strcmp(arg, "-noxrecord")) {
 
3167
                        noxrecord = 1;
 
3168
                } else if (!strcmp(arg, "-pointer_mode")
 
3169
                    || !strcmp(arg, "-pm")) {
 
3170
                        char *p, *s;
 
3171
                        CHECK_ARGC
 
3172
                        s = argv[++i];
 
3173
                        if ((p = strchr(s, ':')) != NULL) {
 
3174
                                ui_skip = atoi(p+1);
 
3175
                                if (! ui_skip) ui_skip = 1;
 
3176
                                *p = '\0';
 
3177
                        }
 
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));
 
3181
                        } else {
 
3182
                                pointer_mode = atoi(s);
 
3183
                                got_pointer_mode = pointer_mode;
 
3184
                        }
 
3185
                } else if (!strcmp(arg, "-input_skip")) {
 
3186
                        CHECK_ARGC
 
3187
                        ui_skip = atoi(argv[++i]);
 
3188
                        if (! ui_skip) ui_skip = 1;
 
3189
                } else if (!strcmp(arg, "-allinput")) {
 
3190
                        all_input = 1;
 
3191
                } else if (!strcmp(arg, "-noallinput")) {
 
3192
                        all_input = 0;
 
3193
                } else if (!strcmp(arg, "-speeds")) {
 
3194
                        CHECK_ARGC
 
3195
                        speeds_str = strdup(argv[++i]);
 
3196
                } else if (!strcmp(arg, "-wmdt")) {
 
3197
                        CHECK_ARGC
 
3198
                        wmdt_str = strdup(argv[++i]);
 
3199
                } else if (!strcmp(arg, "-debug_pointer")
 
3200
                    || !strcmp(arg, "-dp")) {
 
3201
                        debug_pointer++;
 
3202
                } else if (!strcmp(arg, "-debug_keyboard")
 
3203
                    || !strcmp(arg, "-dk")) {
 
3204
                        debug_keyboard++;
 
3205
                } else if (!strcmp(arg, "-debug_xdamage")) {
 
3206
                        debug_xdamage++;
 
3207
                } else if (!strcmp(arg, "-defer")) {
 
3208
                        CHECK_ARGC
 
3209
                        defer_update = atoi(argv[++i]);
 
3210
                        got_defer = 1;
 
3211
                } else if (!strcmp(arg, "-wait")) {
 
3212
                        CHECK_ARGC
 
3213
                        waitms = atoi(argv[++i]);
 
3214
                } else if (!strcmp(arg, "-wait_ui")) {
 
3215
                        CHECK_ARGC
 
3216
                        wait_ui = atof(argv[++i]);
 
3217
                } else if (!strcmp(arg, "-nowait_bog")) {
 
3218
                        wait_bog = 0;
 
3219
                } else if (!strcmp(arg, "-slow_fb")) {
 
3220
                        CHECK_ARGC
 
3221
                        slow_fb = atof(argv[++i]);
 
3222
                } else if (!strcmp(arg, "-xrefresh")) {
 
3223
                        CHECK_ARGC
 
3224
                        xrefresh = atof(argv[++i]);
 
3225
                } else if (!strcmp(arg, "-readtimeout")) {
 
3226
                        CHECK_ARGC
 
3227
                        rfbMaxClientWait = atoi(argv[++i]) * 1000;
 
3228
                } else if (!strcmp(arg, "-ping")) {
 
3229
                        CHECK_ARGC
 
3230
                        ping_interval = atoi(argv[++i]);
 
3231
                } else if (!strcmp(arg, "-nap")) {
 
3232
                        take_naps = 1;
 
3233
                } else if (!strcmp(arg, "-nonap")) {
 
3234
                        take_naps = 0;
 
3235
                } else if (!strcmp(arg, "-sb")) {
 
3236
                        CHECK_ARGC
 
3237
                        screen_blank = atoi(argv[++i]);
 
3238
                } else if (!strcmp(arg, "-nofbpm")) {
 
3239
                        watch_fbpm = 1;
 
3240
                } else if (!strcmp(arg, "-fbpm")) {
 
3241
                        watch_fbpm = 0;
 
3242
                } else if (!strcmp(arg, "-nodpms")) {
 
3243
                        watch_dpms = 1;
 
3244
                } else if (!strcmp(arg, "-dpms")) {
 
3245
                        watch_dpms = 0;
 
3246
                } else if (!strcmp(arg, "-forcedpms")) {
 
3247
                        force_dpms = 1;
 
3248
                } else if (!strcmp(arg, "-clientdpms")) {
 
3249
                        client_dpms = 1;
 
3250
                } else if (!strcmp(arg, "-noserverdpms")) {
 
3251
                        no_ultra_dpms = 1;
 
3252
                } else if (!strcmp(arg, "-noultraext")) {
 
3253
                        no_ultra_ext = 1;
 
3254
                } else if (!strcmp(arg, "-xdamage")) {
 
3255
                        use_xdamage++;
 
3256
                } else if (!strcmp(arg, "-noxdamage")) {
 
3257
                        use_xdamage = 0;
 
3258
                } else if (!strcmp(arg, "-xd_area")) {
 
3259
                        int tn;
 
3260
                        CHECK_ARGC
 
3261
                        tn = atoi(argv[++i]);
 
3262
                        if (tn >= 0) {
 
3263
                                xdamage_max_area = tn;
 
3264
                        }
 
3265
                } else if (!strcmp(arg, "-xd_mem")) {
 
3266
                        double f;
 
3267
                        CHECK_ARGC
 
3268
                        f = atof(argv[++i]);
 
3269
                        if (f >= 0.0) {
 
3270
                                xdamage_memory = f;
 
3271
                        }
 
3272
                } else if (!strcmp(arg, "-sigpipe") || !strcmp(arg, "-sig")) {
 
3273
                        CHECK_ARGC
 
3274
                        if (known_sigpipe_mode(argv[++i])) {
 
3275
                                sigpipe = strdup(argv[i]);
 
3276
                        } else {
 
3277
                                fprintf(stderr, "invalid -sigpipe arg: %s, must"
 
3278
                                    " be \"ignore\" or \"exit\"\n", argv[i]);
 
3279
                                exit(1);
 
3280
                        }
 
3281
#if LIBVNCSERVER_HAVE_LIBPTHREAD
 
3282
                } else if (!strcmp(arg, "-threads")) {
 
3283
                        use_threads = 1;
 
3284
                } else if (!strcmp(arg, "-nothreads")) {
 
3285
                        use_threads = 0;
 
3286
#endif
 
3287
                } else if (!strcmp(arg, "-fs")) {
 
3288
                        CHECK_ARGC
 
3289
                        fs_frac = atof(argv[++i]);
 
3290
                } else if (!strcmp(arg, "-gaps")) {
 
3291
                        CHECK_ARGC
 
3292
                        gaps_fill = atoi(argv[++i]);
 
3293
                } else if (!strcmp(arg, "-grow")) {
 
3294
                        CHECK_ARGC
 
3295
                        grow_fill = atoi(argv[++i]);
 
3296
                } else if (!strcmp(arg, "-fuzz")) {
 
3297
                        CHECK_ARGC
 
3298
                        tile_fuzz = atoi(argv[++i]);
 
3299
                } else if (!strcmp(arg, "-debug_tiles")
 
3300
                    || !strcmp(arg, "-dbt")) {
 
3301
                        debug_tiles++;
 
3302
                } else if (!strcmp(arg, "-debug_grabs")) {
 
3303
                        debug_grabs++;
 
3304
                } else if (!strcmp(arg, "-debug_sel")) {
 
3305
                        debug_sel++;
 
3306
                } else if (!strcmp(arg, "-grab_buster")) {
 
3307
                        grab_buster++;
 
3308
                } else if (!strcmp(arg, "-nograb_buster")) {
 
3309
                        grab_buster = 0;
 
3310
                } else if (!strcmp(arg, "-snapfb")) {
 
3311
                        use_snapfb = 1;
 
3312
                } else if (!strcmp(arg, "-rawfb")) {
 
3313
                        CHECK_ARGC
 
3314
                        raw_fb_str = strdup(argv[++i]);
 
3315
                        if (strstr(raw_fb_str, "vnc:") == raw_fb_str) {
 
3316
                                shared = 1;
 
3317
                        }
 
3318
                } else if (!strcmp(arg, "-freqtab")) {
 
3319
                        CHECK_ARGC
 
3320
                        freqtab = strdup(argv[++i]);
 
3321
                } else if (!strcmp(arg, "-pipeinput")) {
 
3322
                        CHECK_ARGC
 
3323
                        pipeinput_str = strdup(argv[++i]);
 
3324
                } else if (!strcmp(arg, "-macnodim")) {
 
3325
                        macosx_nodimming = 1;
 
3326
                } else if (!strcmp(arg, "-macnosleep")) {
 
3327
                        macosx_nosleep = 1;
 
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")) {
 
3333
                        CHECK_ARGC
 
3334
                        macosx_mouse_wheel_speed = atoi(argv[++i]);
 
3335
                } else if (!strcmp(arg, "-macnoswap")) {
 
3336
                        macosx_swap23 = 0;
 
3337
                } else if (!strcmp(arg, "-macnoresize")) {
 
3338
                        macosx_resize = 0;
 
3339
                } else if (!strcmp(arg, "-maciconanim")) {
 
3340
                        CHECK_ARGC
 
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")) {
 
3345
                        launch_gui = 1;
 
3346
                        if (i < argc-1) {
 
3347
                                char *s = argv[i+1];
 
3348
                                if (*s != '-') {
 
3349
                                        gui_str = strdup(s);
 
3350
                                        if (strstr(gui_str, "setp")) {
 
3351
                                                got_gui_pw = 1;
 
3352
                                        }
 
3353
                                        i++;
 
3354
                                } 
 
3355
                        }
 
3356
                } else if (!strcmp(arg, "-remote") || !strcmp(arg, "-R")
 
3357
                    || !strcmp(arg, "-r") || !strcmp(arg, "-remote-control")) {
 
3358
                        char *str;
 
3359
                        CHECK_ARGC
 
3360
                        i++;
 
3361
                        str = argv[i];
 
3362
                        if (*str == '-') {
 
3363
                                /* accidental leading '-' */
 
3364
                                str++;
 
3365
                        }
 
3366
                        if (!strcmp(str, "ping")) {
 
3367
                                query_cmd = strdup(str);
 
3368
                        } else {
 
3369
                                remote_cmd = strdup(str);
 
3370
                        }
 
3371
                        if (remote_cmd && strchr(remote_cmd, ':') == NULL) {
 
3372
                            /* interpret -R -scale 3/4 at least */
 
3373
                            if (i < argc-1 && *(argv[i+1]) != '-') {
 
3374
                                int n;
 
3375
 
 
3376
                                /* it must be the parameter value */
 
3377
                                i++;
 
3378
                                n = strlen(remote_cmd) + strlen(argv[i]) + 2;
 
3379
 
 
3380
                                str = (char *) malloc(n);
 
3381
                                sprintf(str, "%s:%s", remote_cmd, argv[i]);
 
3382
                                free(remote_cmd);
 
3383
                                remote_cmd = str;
 
3384
                            }
 
3385
                        }
 
3386
                        quiet = 1;
 
3387
                        xkbcompat = 0;
 
3388
                } else if (!strcmp(arg, "-query") || !strcmp(arg, "-Q")) {
 
3389
                        CHECK_ARGC
 
3390
                        query_cmd = strdup(argv[++i]);
 
3391
                        quiet = 1;
 
3392
                        xkbcompat = 0;
 
3393
                } else if (!strcmp(arg, "-QD")) {
 
3394
                        CHECK_ARGC
 
3395
                        query_cmd = strdup(argv[++i]);
 
3396
                        query_default = 1;
 
3397
                } else if (!strcmp(arg, "-sync")) {
 
3398
                        remote_sync = 1;
 
3399
                } else if (!strcmp(arg, "-nosync")) {
 
3400
                        remote_sync = 0;
 
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")) {
 
3408
                        priv_remote = 1;
 
3409
                } else if (!strcmp(arg, "-safer")) {
 
3410
                        more_safe = 1;
 
3411
                } else if (!strcmp(arg, "-nocmds")) {
 
3412
                        no_external_cmds = 1;
 
3413
                } else if (!strcmp(arg, "-allowedcmds")) {
 
3414
                        CHECK_ARGC
 
3415
                        allowed_external_cmds = strdup(argv[++i]);
 
3416
                } else if (!strcmp(arg, "-deny_all")) {
 
3417
                        deny_all = 1;
 
3418
                } else if (!strcmp(arg, "-httpdir")) {
 
3419
                        CHECK_ARGC
 
3420
                        http_dir = strdup(argv[++i]);
 
3421
                        got_httpdir = 1;
 
3422
                } else {
 
3423
                        if (!strcmp(arg, "-desktop") && i < argc-1) {
 
3424
                                dt = 1;
 
3425
                                rfb_desktop_name = strdup(argv[i+1]);
 
3426
                        }
 
3427
                        if (!strcmp(arg, "-passwd")) {
 
3428
                                pw_loc = i;
 
3429
                                got_passwd = 1;
 
3430
                        }
 
3431
                        if (!strcmp(arg, "-rfbauth")) {
 
3432
                                got_rfbauth = 1;
 
3433
                        }
 
3434
                        if (!strcmp(arg, "-rfbwait")) {
 
3435
                                got_rfbwait = 1;
 
3436
                        }
 
3437
                        if (!strcmp(arg, "-deferupdate")) {
 
3438
                                got_deferupdate = 1;
 
3439
                        }
 
3440
                        if (!strcmp(arg, "-rfbport") && i < argc-1) {
 
3441
                                got_rfbport = 1;
 
3442
                                got_rfbport_val = atoi(argv[i+1]);
 
3443
                        }
 
3444
                        if (!strcmp(arg, "-alwaysshared ")) {
 
3445
                                got_alwaysshared = 1;
 
3446
                        }
 
3447
                        if (!strcmp(arg, "-nevershared")) {
 
3448
                                got_nevershared = 1;
 
3449
                        }
 
3450
                        if (!strcmp(arg, "-listen") && i < argc-1) {
 
3451
                                listen_str = strdup(argv[i+1]);
 
3452
                        }
 
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");
 
3459
                                }
 
3460
                        } else if (argc_vnc < argc_vnc_max) {
 
3461
                                argv_vnc[argc_vnc++] = strdup(arg);
 
3462
                        } else {
 
3463
                                rfbLog("too many arguments.\n");
 
3464
                                exit(1);
 
3465
                        }
 
3466
                }
 
3467
        }
 
3468
 
 
3469
        orig_use_xdamage = use_xdamage;
 
3470
 
 
3471
        if (!auto_port && getenv("AUTO_PORT")) {
 
3472
                auto_port = atoi(getenv("AUTO_PORT"));
 
3473
        }
 
3474
 
 
3475
        if (getenv("X11VNC_LOOP_MODE")) {
 
3476
                if (bg && !getenv("X11VNC_LOOP_MODE_BG")) {
 
3477
                        if (! quiet) {
 
3478
                                fprintf(stderr, "disabling -bg in -loop "
 
3479
                                    "mode\n");
 
3480
                        }
 
3481
                        bg = 0;
 
3482
                }
 
3483
                if (inetd) {
 
3484
                        if (! quiet) {
 
3485
                                fprintf(stderr, "disabling -inetd in -loop "
 
3486
                                    "mode\n");
 
3487
                        }
 
3488
                        inetd = 0;
 
3489
                }
 
3490
        }
 
3491
 
 
3492
        if (launch_gui && (query_cmd || remote_cmd)) {
 
3493
                launch_gui = 0;
 
3494
                gui_str = NULL;
 
3495
        }
 
3496
        if (more_safe) {
 
3497
                launch_gui = 0;
 
3498
        }
 
3499
 
 
3500
#ifdef MACOSX
 
3501
        if (! use_dpy) {
 
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);
 
3506
                        struct stat sb;
 
3507
                        sprintf(str, "/tmp/x11vnc-macosx-remote.%s", user);
 
3508
                        if (!remote_cmd && !query_cmd) {
 
3509
                                unlink(str);
 
3510
                                if (stat(str, &sb) != 0) {
 
3511
                                        int fd = open(str, O_WRONLY|O_EXCL|O_CREAT, 0600);
 
3512
                                        if (fd >= 0) {
 
3513
                                                close(fd);
 
3514
                                                client_connect_file = str;
 
3515
                                        }
 
3516
                                }
 
3517
                        } else {
 
3518
                                client_connect_file = str;
 
3519
                        }
 
3520
                        if (client_connect_file) {
 
3521
                                rfbLog("MacOS X: set -connect file to %s\n", client_connect_file);
 
3522
                        }
 
3523
                }
 
3524
        }
 
3525
#endif
 
3526
        if (launch_gui) {
 
3527
                int sleep = 0;
 
3528
                if (SHOW_NO_PASSWORD_WARNING && !nopw) {
 
3529
                        sleep = 1;
 
3530
                }
 
3531
                do_gui(gui_str, sleep);
 
3532
        }
 
3533
        if (logfile) {
 
3534
                int n;
 
3535
                if (logfile_append) {
 
3536
                        n = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666);
 
3537
                } else {
 
3538
                        n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
 
3539
                }
 
3540
                if (n < 0) {
 
3541
                        fprintf(stderr, "error opening logfile: %s\n", logfile);
 
3542
                        perror("open");
 
3543
                        exit(1);
 
3544
                }
 
3545
                if (dup2(n, 2) < 0) {
 
3546
                        fprintf(stderr, "dup2 failed\n");
 
3547
                        perror("dup2");
 
3548
                        exit(1);
 
3549
                }
 
3550
                if (n > 2) {
 
3551
                        close(n);
 
3552
                }
 
3553
        }
 
3554
        if (inetd && quiet && !logfile) {
 
3555
                int n;
 
3556
                /*
 
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.
 
3562
                 */
 
3563
                n = open("/dev/null", O_WRONLY);
 
3564
                if (n >= 0) {
 
3565
                        if (dup2(n, 2) >= 0) {
 
3566
                                if (n > 2) {
 
3567
                                        close(n);
 
3568
                                }
 
3569
                        }
 
3570
                }
 
3571
        }
 
3572
        if (! quiet && ! inetd) {
 
3573
                int i;
 
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")) {
 
3577
                                i++;
 
3578
                        }
 
3579
                }
 
3580
        }
 
3581
 
 
3582
        if (remote_cmd || query_cmd) {
 
3583
                /*
 
3584
                 * no need to open DISPLAY, just write it to the file now
 
3585
                 * similar for query_default.
 
3586
                 */
 
3587
                if (client_connect_file || query_default) {
 
3588
                        int rc = do_remote_query(remote_cmd, query_cmd,
 
3589
                             remote_sync, query_default);
 
3590
                        fflush(stderr);
 
3591
                        fflush(stdout);
 
3592
                        exit(rc);
 
3593
                }
 
3594
        }
 
3595
 
 
3596
        if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile && !unixpw) {
 
3597
                char *f, *h = getenv("HOME");
 
3598
                struct stat sbuf;
 
3599
                int found = 0, set_rfbauth = 0;
 
3600
 
 
3601
                if (!h) {
 
3602
                        rfbLog("HOME unset in -usepw mode.\n");
 
3603
                        exit(1);
 
3604
                }
 
3605
                f = (char *) malloc(strlen(h)+strlen("/.vnc/passwdfile") + 1);
 
3606
 
 
3607
                sprintf(f, "%s/.vnc/passwd", h);
 
3608
                if (stat(f, &sbuf) == 0) {
 
3609
                        found = 1;
 
3610
                        if (! quiet) {
 
3611
                                rfbLog("-usepw: found %s\n", f);
 
3612
                        }
 
3613
                        got_rfbauth = 1;
 
3614
                        set_rfbauth = 1;
 
3615
                }
 
3616
 
 
3617
                sprintf(f, "%s/.vnc/passwdfile", h);
 
3618
                if (! found && stat(f, &sbuf) == 0) {
 
3619
                        found = 1;
 
3620
                        if (! quiet) {
 
3621
                                rfbLog("-usepw: found %s\n", f);
 
3622
                        }
 
3623
                        got_passwdfile = 1;
 
3624
                        passwdfile = strdup(f);
 
3625
                }
 
3626
 
 
3627
#if LIBVNCSERVER_HAVE_FORK
 
3628
#if LIBVNCSERVER_HAVE_SYS_WAIT_H
 
3629
#if LIBVNCSERVER_HAVE_WAITPID
 
3630
                if (! found) {
 
3631
                        pid_t pid = fork();
 
3632
                        if (pid < 0) {
 
3633
                                ;
 
3634
                        } else if (pid == 0) {
 
3635
                                execlp(argv[0], argv[0], "-storepasswd",
 
3636
                                    (char *) NULL);
 
3637
                                exit(1);
 
3638
                        } else {
 
3639
                                int s;
 
3640
                                waitpid(pid, &s, 0); 
 
3641
                                if (WIFEXITED(s) && WEXITSTATUS(s) == 0) {
 
3642
                                        got_rfbauth = 1;
 
3643
                                        set_rfbauth = 1;
 
3644
                                        found = 1;
 
3645
                                }
 
3646
                        }
 
3647
                }
 
3648
#endif
 
3649
#endif
 
3650
#endif
 
3651
 
 
3652
                if (set_rfbauth) {
 
3653
                        sprintf(f, "%s/.vnc/passwd", h);
 
3654
                        if (argc_vnc < 100) {
 
3655
                                argv_vnc[argc_vnc++] = strdup("-rfbauth");
 
3656
                        } else {
 
3657
                                exit(1);
 
3658
                        }
 
3659
                        if (argc_vnc < 100) {
 
3660
                                argv_vnc[argc_vnc++] = strdup(f);
 
3661
                        } else {
 
3662
                                exit(1);
 
3663
                        }
 
3664
                }
 
3665
                if (! found) {
 
3666
                        fprintf(stderr, "x11vnc -usepw: could not find"
 
3667
                            " a password to use.\n");
 
3668
                        exit(1);
 
3669
                }
 
3670
                free(f);
 
3671
        }
 
3672
 
 
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");
 
3676
                exit(1);
 
3677
        }
 
3678
        if (got_passwdfile && (got_passwd || got_viewpasswd)) {
 
3679
                fprintf(stderr, "option -passwdfile is incompatible with:\n");
 
3680
                fprintf(stderr, "            -passwd and -viewpasswd\n");
 
3681
                exit(1);
 
3682
        }
 
3683
 
 
3684
        /*
 
3685
         * If -passwd was used, clear it out of argv.  This does not
 
3686
         * work on all UNIX, have to use execvp() in general...
 
3687
         */
 
3688
        if (pw_loc > 0) {
 
3689
                int i;
 
3690
                for (i=pw_loc; i <= pw_loc+1; i++) {
 
3691
                        if (i < argc) {
 
3692
                                char *p = argv[i];              
 
3693
                                strzero(p);
 
3694
                        }
 
3695
                }
 
3696
        } else if (passwdfile) {
 
3697
                /* read passwd(s) from file */
 
3698
                if (strstr(passwdfile, "cmd:") == passwdfile ||
 
3699
                    strstr(passwdfile, "custom:") == passwdfile) {
 
3700
                        char tstr[100], *q;
 
3701
                        sprintf(tstr, "%f", dnow());
 
3702
                        if ((q = strrchr(tstr, '.')) == NULL) {
 
3703
                                q = tstr;
 
3704
                        } else {
 
3705
                                q++;
 
3706
                        }
 
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]);
 
3713
                }
 
3714
                got_passwd = 1;
 
3715
                pw_loc = 100;   /* just for pw_loc check below */
 
3716
        }
 
3717
        if (vpw_loc > 0) {
 
3718
                int i;
 
3719
                for (i=vpw_loc; i <= vpw_loc+1; i++) {
 
3720
                        if (i < argc) {
 
3721
                                char *p = argv[i];              
 
3722
                                strzero(p);
 
3723
                        }
 
3724
                }
 
3725
        } 
 
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);
 
3730
                got_passwd = 1;
 
3731
                pw_loc = 100;
 
3732
        }
 
3733
#endif
 
3734
#ifdef HARDWIRE_VIEWPASSWD
 
3735
        if (!got_rfbauth && got_passwd && !viewonly_passwd && !passwd_list) {
 
3736
                viewonly_passwd = strdup(HARDWIRE_VIEWPASSWD);
 
3737
        }
 
3738
#endif
 
3739
        if (viewonly_passwd && pw_loc < 0) {
 
3740
                rfbLog("-passwd must be supplied when using -viewpasswd\n");
 
3741
                exit(1);
 
3742
        }
 
3743
 
 
3744
        if (SHOW_NO_PASSWORD_WARNING) {
 
3745
                char message[] = "-rfbauth, -passwdfile, -passwd password, "
 
3746
                    "or -unixpw required.";
 
3747
                if (! nopw) {
 
3748
                        nopassword_warning_msg(got_localhost);
 
3749
                }
 
3750
#if PASSWD_REQUIRED
 
3751
                rfbLog("%s\n", message);
 
3752
                exit(1);
 
3753
#endif
 
3754
#if PASSWD_UNLESS_NOPW
 
3755
                if (! nopw) {
 
3756
                        rfbLog("%s\n", message);
 
3757
                        exit(1);
 
3758
                }
 
3759
#endif
 
3760
                message[0] = '\0';      /* avoid compiler warning */
 
3761
        }
 
3762
 
 
3763
        if (more_safe) {
 
3764
                if (! quiet) {
 
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");
 
3770
                }
 
3771
                vnc_connect = 0;
 
3772
                accept_remote_cmds = 0;
 
3773
                safe_remote_only = 1;
 
3774
                launch_gui = 0;
 
3775
        }
 
3776
 
 
3777
        if (users_list && strchr(users_list, '.')) {
 
3778
                char *p, *q, *tmp = (char *) malloc(strlen(users_list)+1);
 
3779
                char *str = strdup(users_list);
 
3780
                int i, n, db = 1;
 
3781
 
 
3782
                tmp[0] = '\0';
 
3783
 
 
3784
                n = strlen(users_list) + 1;
 
3785
                user2group = (char **) malloc(n * sizeof(char *));
 
3786
                for (i=0; i<n; i++) {
 
3787
                        user2group[i] = NULL;
 
3788
                }
 
3789
 
 
3790
                i = 0;
 
3791
                p = strtok(str, ",");
 
3792
                if (db) fprintf(stderr, "users_list: %s\n", users_list);
 
3793
                while (p) {
 
3794
                        if (tmp[0] != '\0') {
 
3795
                                strcat(tmp, ",");
 
3796
                        }
 
3797
                        q = strchr(p, '.');
 
3798
                        if (q) {
 
3799
                                char *s = strchr(p, '=');
 
3800
                                if (! s) {
 
3801
                                        s = p;
 
3802
                                } else {
 
3803
                                        s++;
 
3804
                                }
 
3805
                                if (s[0] == '+') s++;
 
3806
                                user2group[i++] = strdup(s);
 
3807
                                if (db) fprintf(stderr, "u2g: %s\n", s);
 
3808
                                *q = '\0';
 
3809
                        }
 
3810
                        strcat(tmp, p);
 
3811
                        p = strtok(NULL, ",");
 
3812
                }
 
3813
                free(str);
 
3814
                users_list = tmp;
 
3815
                if (db) fprintf(stderr, "users_list: %s\n", users_list);
 
3816
        }
 
3817
 
 
3818
        if (unixpw) {
 
3819
                if (inetd) {
 
3820
                        use_stunnel = 0;
 
3821
                }
 
3822
                if (! use_stunnel && ! use_openssl) {
 
3823
                        if (getenv("UNIXPW_DISABLE_LOCALHOST")) {
 
3824
                                rfbLog("Skipping -ssl/-stunnel requirement"
 
3825
                                    " due to\n");
 
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"
 
3833
                                    " -unixpw\n");
 
3834
                                rfbLog("mode, assuming your SSH encryption"
 
3835
                                    " is: %s\n", s);
 
3836
                                rfbLog("Setting -localhost in SSH + -unixpw"
 
3837
                                    " mode.\n");
 
3838
                                fprintf(stderr, "\n");
 
3839
                                allow_list = strdup("127.0.0.1");
 
3840
                                got_localhost = 1;
 
3841
                                if (! nopw) {
 
3842
                                        usleep(2000*1000);
 
3843
                                }
 
3844
                        } else {
 
3845
                                if (openssl_present()) {
 
3846
                                        rfbLog("set -ssl in -unixpw mode.\n");
 
3847
                                        use_openssl = 1;
 
3848
                                } else if (inetd) {
 
3849
                                        rfbLog("could not set -ssl in -inetd"
 
3850
                                            " + -unixpw mode.\n");
 
3851
                                        exit(1);
 
3852
                                } else {
 
3853
                                        rfbLog("set -stunnel in -unixpw mode.\n");
 
3854
                                        use_stunnel = 1;
 
3855
                                }
 
3856
                        }
 
3857
                }
 
3858
                if (use_threads) {
 
3859
                        if (! quiet) {
 
3860
                                rfbLog("disabling -threads under -unixpw\n");
 
3861
                        }
 
3862
                        use_threads = 0;
 
3863
                }
 
3864
        }
 
3865
        if (use_stunnel && ! got_localhost) {
 
3866
                if (! getenv("STUNNEL_DISABLE_LOCALHOST") &&
 
3867
                    ! getenv("UNIXPW_DISABLE_LOCALHOST")) {
 
3868
                        if (! quiet) {
 
3869
                                rfbLog("Setting -localhost in -stunnel mode.\n");
 
3870
                        }
 
3871
                        allow_list = strdup("127.0.0.1");
 
3872
                        got_localhost = 1;
 
3873
                }
 
3874
        }
 
3875
        if (ssl_verify && ! use_stunnel && ! use_openssl) {
 
3876
                rfbLog("-sslverify must be used with -ssl or -stunnel\n");
 
3877
                exit(1);
 
3878
        }
 
3879
        if (https_port_num >= 0 && ! use_openssl) {
 
3880
                rfbLog("-https must be used with -ssl\n");
 
3881
                exit(1);
 
3882
        }
 
3883
 
 
3884
        /* fixup settings that do not make sense */
 
3885
                
 
3886
        if (use_threads && nofb && cursor_pos_updates) {
 
3887
                if (! quiet) {
 
3888
                        rfbLog("disabling -threads under -nofb -cursorpos\n");
 
3889
                }
 
3890
                use_threads = 0;
 
3891
        }
 
3892
        if (tile_fuzz < 1) {
 
3893
                tile_fuzz = 1;
 
3894
        }
 
3895
        if (waitms < 0) {
 
3896
                waitms = 0;
 
3897
        }
 
3898
 
 
3899
        if (alpha_threshold < 0) {
 
3900
                alpha_threshold = 0;
 
3901
        }
 
3902
        if (alpha_threshold > 256) {
 
3903
                alpha_threshold = 256;
 
3904
        }
 
3905
        if (alpha_frac < 0.0) {
 
3906
                alpha_frac = 0.0;
 
3907
        }
 
3908
        if (alpha_frac > 1.0) {
 
3909
                alpha_frac = 1.0;
 
3910
        }
 
3911
        if (alpha_blend) {
 
3912
                alpha_remove = 0;
 
3913
        }
 
3914
 
 
3915
        if (cmap8to24 && overlay) {
 
3916
                if (! quiet) {
 
3917
                        rfbLog("disabling -overlay in -8to24 mode.\n");
 
3918
                }
 
3919
                overlay = 0;
 
3920
        }
 
3921
 
 
3922
        if (tightfilexfer && view_only) {
 
3923
                if (! quiet) {
 
3924
                        rfbLog("setting -notightfilexfer in -viewonly mode.\n");
 
3925
                }
 
3926
                /* how to undo via -R? */
 
3927
                tightfilexfer = 0;
 
3928
        }
 
3929
 
 
3930
        if (inetd) {
 
3931
                shared = 0;
 
3932
                connect_once = 1;
 
3933
                bg = 0;
 
3934
                if (use_stunnel) {
 
3935
                        exit(1);
 
3936
                }
 
3937
        }
 
3938
 
 
3939
        if (flip_byte_order && using_shm && ! quiet) {
 
3940
                rfbLog("warning: -flipbyte order only works with -noshm\n");
 
3941
        }
 
3942
 
 
3943
        if (! wireframe_copyrect) {
 
3944
                set_wirecopyrect_mode(NULL);
 
3945
        }
 
3946
        if (! scroll_copyrect) {
 
3947
                set_scrollcopyrect_mode(NULL);
 
3948
        }
 
3949
        if (screen_fixup_str) {
 
3950
                parse_fixscreen();
 
3951
        }
 
3952
        initialize_scroll_matches();
 
3953
        initialize_scroll_term();
 
3954
        initialize_max_keyrepeat();
 
3955
 
 
3956
        /* increase rfbwait if threaded */
 
3957
        if (use_threads && ! got_rfbwait) {
 
3958
                rfbMaxClientWait = 604800000;
 
3959
        }
 
3960
 
 
3961
        /* no framebuffer (Win2VNC) mode */
 
3962
 
 
3963
        if (nofb) {
 
3964
                /* disable things that do not make sense with no fb */
 
3965
                set_nofb_params(0);
 
3966
 
 
3967
                if (! got_deferupdate && ! got_defer) {
 
3968
                        /* reduce defer time under -nofb */
 
3969
                        defer_update = defer_update_nofb;
 
3970
                }
 
3971
                if (got_pointer_mode < 0) {
 
3972
                        pointer_mode = POINTER_MODE_NOFB;
 
3973
                }
 
3974
        }
 
3975
 
 
3976
        if (ncache < 0) {
 
3977
                ncache_beta_tester = 1;
 
3978
                ncache_msg = 1;
 
3979
                if (ncache == -1) {
 
3980
                        ncache = 0;
 
3981
                }
 
3982
                ncache = -ncache;
 
3983
                if (try_http || got_httpdir) {
 
3984
                        /* JVM usually not set to handle all the memory */
 
3985
                        ncache = 0;
 
3986
                        ncache_msg = 0;
 
3987
                }
 
3988
                if (subwin) {
 
3989
                        ncache = 0;
 
3990
                        ncache_msg = 0;
 
3991
                }
 
3992
        }
 
3993
 
 
3994
        if (raw_fb_str) {
 
3995
                set_raw_fb_params(0);
 
3996
        }
 
3997
        if (! got_deferupdate) {
 
3998
                char tmp[40];
 
3999
                sprintf(tmp, "%d", defer_update);
 
4000
                argv_vnc[argc_vnc++] = strdup("-deferupdate");
 
4001
                argv_vnc[argc_vnc++] = strdup(tmp);
 
4002
        }
 
4003
 
 
4004
        if (debug_pointer || debug_keyboard) {
 
4005
                if (bg || quiet) {
 
4006
                        rfbLog("disabling -bg/-q under -debug_pointer"
 
4007
                            "/-debug_keyboard\n");
 
4008
                        bg = 0;
 
4009
                        quiet = 0;
 
4010
                }
 
4011
        }
 
4012
 
 
4013
        /* initialize added_keysyms[] array to zeros */
 
4014
        add_keysym(NoSymbol);
 
4015
 
 
4016
        /* tie together cases of -localhost vs. -listen localhost */
 
4017
        if (! listen_str) {
 
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);
 
4022
                }
 
4023
        } else if (!strcmp(listen_str, "localhost") ||
 
4024
            !strcmp(listen_str, "127.0.0.1")) {
 
4025
                allow_list = strdup("127.0.0.1");
 
4026
        }
 
4027
 
 
4028
        /* set OS struct UT */
 
4029
        uname(&UT);
 
4030
 
 
4031
        initialize_crash_handler();
 
4032
 
 
4033
        if (! quiet) {
 
4034
                if (verbose) {
 
4035
                        print_settings(try_http, bg, gui_str);
 
4036
                }
 
4037
                rfbLog("x11vnc version: %s\n", lastmod);
 
4038
        } else {
 
4039
                rfbLogEnable(0);
 
4040
        }
 
4041
 
 
4042
        X_INIT;
 
4043
        SCR_INIT;
 
4044
        
 
4045
        /* open the X display: */
 
4046
        if (auth_file) {
 
4047
                set_env("XAUTHORITY", auth_file);
 
4048
if (0) fprintf(stderr, "XA: %s\n", getenv("XAUTHORITY"));
 
4049
        }
 
4050
#if LIBVNCSERVER_HAVE_XKEYBOARD
 
4051
        /*
 
4052
         * Disable XKEYBOARD before calling XOpenDisplay()
 
4053
         * this should be used if there is ambiguity in the keymapping. 
 
4054
         */
 
4055
        if (xkbcompat) {
 
4056
                Bool rc = XkbIgnoreExtension(True);
 
4057
                if (! quiet) {
 
4058
                        rfbLog("Disabling xkb XKEYBOARD extension. rc=%d\n",
 
4059
                            rc);
 
4060
                }
 
4061
                if (watch_bell) {
 
4062
                        watch_bell = 0;
 
4063
                        if (! quiet) rfbLog("Disabling bell.\n");
 
4064
                }
 
4065
        }
 
4066
#else
 
4067
        watch_bell = 0;
 
4068
        use_xkb_modtweak = 0;
 
4069
#endif
 
4070
 
 
4071
#ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
 
4072
        if (tightfilexfer) {
 
4073
                rfbLog("rfbRegisterTightVNCFileTransferExtension: 6\n");
 
4074
                rfbRegisterTightVNCFileTransferExtension();
 
4075
        } else {
 
4076
                if (0) rfbLog("rfbUnregisterTightVNCFileTransferExtension: 3\n");
 
4077
                rfbUnregisterTightVNCFileTransferExtension();
 
4078
        }
 
4079
#endif
 
4080
 
 
4081
        initialize_allowed_input();
 
4082
 
 
4083
        if (display_N && !got_rfbport) {
 
4084
                char *ud = use_dpy;
 
4085
                if (ud == NULL) {
 
4086
                        ud = getenv("DISPLAY");
 
4087
                }
 
4088
                if (ud && strstr(ud, "cmd=") == NULL) {
 
4089
                        char *p;
 
4090
                        ud = strdup(ud);
 
4091
                        p = strrchr(ud, ':');
 
4092
                        if (p) {
 
4093
                                int N;  
 
4094
                                char *q = strchr(p, '.');
 
4095
                                if (q) {
 
4096
                                        *q = '\0';
 
4097
                                }
 
4098
                                N = atoi(p+1);  
 
4099
                                if (argc_vnc+1 < argc_vnc_max) {
 
4100
                                        char Nstr[16];
 
4101
                                        sprintf(Nstr, "%d", (5900 + N) % 65536); 
 
4102
                                        argv_vnc[argc_vnc++] = strdup("-rfbport");
 
4103
                                        argv_vnc[argc_vnc++] = strdup(Nstr);
 
4104
                                        got_rfbport = 1;
 
4105
                                }
 
4106
                        }
 
4107
                        free(ud);
 
4108
                }
 
4109
        }
 
4110
 
 
4111
        if (users_list && strstr(users_list, "lurk=")) {
 
4112
                if (use_dpy) {
 
4113
                        rfbLog("warning: -display does not make sense in "
 
4114
                            "\"lurk=\" mode...\n");
 
4115
                }
 
4116
                lurk_loop(users_list);
 
4117
 
 
4118
        } else if (use_dpy && strstr(use_dpy, "WAIT:") == use_dpy) {
 
4119
                char *mcm = multiple_cursors_mode;
 
4120
 
 
4121
                waited_for_client = wait_for_client(&argc_vnc, argv_vnc,
 
4122
                    try_http && ! got_httpdir);
 
4123
 
 
4124
                if (!mcm && multiple_cursors_mode) {
 
4125
                        free(multiple_cursors_mode);
 
4126
                        multiple_cursors_mode = NULL;
 
4127
                }
 
4128
        }
 
4129
 
 
4130
#ifdef MACOSX
 
4131
        if (use_dpy && !strcmp(use_dpy, "console")) {
 
4132
                ;
 
4133
        } else
 
4134
#endif
 
4135
        if (use_dpy) {
 
4136
                dpy = XOpenDisplay_wr(use_dpy);
 
4137
#ifdef MACOSX
 
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");
 
4143
#endif
 
4144
        } else if ( (use_dpy = getenv("DISPLAY")) ) {
 
4145
                dpy = XOpenDisplay_wr(use_dpy);
 
4146
        } else {
 
4147
                dpy = XOpenDisplay_wr("");
 
4148
        }
 
4149
 
 
4150
        if (terminal_services_daemon != NULL) {
 
4151
                terminal_services(terminal_services_daemon);
 
4152
                exit(0);
 
4153
        }
 
4154
 
 
4155
#ifdef MACOSX
 
4156
        if (! dpy && ! raw_fb_str) {
 
4157
                raw_fb_str = strdup("console");
 
4158
        }
 
4159
#endif
 
4160
 
 
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;
 
4165
        }
 
4166
 
 
4167
        if (! dpy && ! use_dpy && ! getenv("DISPLAY")) {
 
4168
                int i, s = 4;
 
4169
                rfbLogEnable(1);
 
4170
                rfbLog("\a\n");
 
4171
                rfbLog("*** XOpenDisplay failed. No -display or DISPLAY.\n");
 
4172
                rfbLog("*** Trying \":0\" in %d seconds.  Press Ctrl-C to"
 
4173
                    " abort.\n", s);
 
4174
                rfbLog("*** ");
 
4175
                for (i=1; i<=s; i++)  {
 
4176
                        fprintf(stderr, "%d ", i);
 
4177
                        sleep(1);
 
4178
                }
 
4179
                fprintf(stderr, "\n");
 
4180
                use_dpy = ":0";
 
4181
                dpy = XOpenDisplay_wr(use_dpy);
 
4182
                if (dpy) {
 
4183
                        rfbLog("*** XOpenDisplay of \":0\" successful.\n");
 
4184
                }
 
4185
                rfbLog("\n");
 
4186
                if (quiet) rfbLogEnable(0);
 
4187
        }
 
4188
 
 
4189
        if (! dpy) {
 
4190
                char *d = use_dpy;
 
4191
                if (!d) d = getenv("DISPLAY");
 
4192
                if (!d) d = "null";
 
4193
                rfbLogEnable(1);
 
4194
                fprintf(stderr, "\n");
 
4195
                rfbLog("***************************************\n", d);
 
4196
                rfbLog("*** XOpenDisplay failed (%s)\n", d);
 
4197
                xopen_display_fail_message(d);
 
4198
                exit(1);
 
4199
        } else if (use_dpy) {
 
4200
                if (! quiet) rfbLog("Using X display %s\n", use_dpy);
 
4201
        } else {
 
4202
                if (! quiet) rfbLog("Using default X display.\n");
 
4203
        }
 
4204
 
 
4205
 
 
4206
        scr = DefaultScreen(dpy);
 
4207
        rootwin = RootWindow(dpy, scr);
 
4208
 
 
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;
 
4214
 
 
4215
                /* limit poor, unsuspecting beta tester's viewer to 96 MB */
 
4216
                if ( (ncache+2) * mem > MEM ) {
 
4217
                        int n = (MEM/mem) - 2;
 
4218
                        if (n < 0) n = 0;
 
4219
                        n = 2 * (n / 2);
 
4220
                        if (n < ncache) {
 
4221
                                ncache = n;
 
4222
                        }
 
4223
                }
 
4224
        }
 
4225
 
 
4226
        if (grab_always) {
 
4227
                Window save = window;
 
4228
                window = rootwin;
 
4229
                adjust_grabs(1, 0);
 
4230
                window = save;
 
4231
        }
 
4232
 
 
4233
        if (! quiet && ! raw_fb_str) {
 
4234
                rfbLog("\n");
 
4235
                rfbLog("------------------ USEFUL INFORMATION ------------------\n");
 
4236
        }
 
4237
 
 
4238
        if (remote_cmd || query_cmd) {
 
4239
                int rc = do_remote_query(remote_cmd, query_cmd, remote_sync,
 
4240
                    query_default);
 
4241
                XFlush_wr(dpy);
 
4242
                fflush(stderr);
 
4243
                fflush(stdout);
 
4244
                usleep(30 * 1000);      /* still needed? */
 
4245
                XCloseDisplay_wr(dpy);
 
4246
                exit(rc);
 
4247
        }
 
4248
 
 
4249
        if (priv_remote) {
 
4250
                if (! remote_control_access_ok()) {
 
4251
                        rfbLog("** Disabling remote commands in -privremote mode.\n");
 
4252
                        accept_remote_cmds = 0;
 
4253
                }
 
4254
        }
 
4255
 
 
4256
        sync_tod_with_servertime();
 
4257
        if (grab_buster) {
 
4258
                spawn_grab_buster();
 
4259
        }
 
4260
 
 
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");
 
4265
                }
 
4266
                xfixes_base_event_type = 0;
 
4267
                xfixes_present = 0;
 
4268
        } else {
 
4269
                xfixes_present = 1;
 
4270
        }
 
4271
#endif
 
4272
        if (! xfixes_present) {
 
4273
                use_xfixes = 0;
 
4274
        }
 
4275
 
 
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");
 
4280
                }
 
4281
                xdamage_base_event_type = 0;
 
4282
                xdamage_present = 0;
 
4283
        } else {
 
4284
                xdamage_present = 1;
 
4285
        }
 
4286
#endif
 
4287
        if (! xdamage_present) {
 
4288
                use_xdamage = 0;
 
4289
        }
 
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");
 
4293
        }
 
4294
 
 
4295
        if (! quiet && wireframe && ! raw_fb_str) {
 
4296
                rfbLog("\n");
 
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");
 
4309
                }
 
4310
        }
 
4311
 
 
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");
 
4317
                }
 
4318
        } else {
 
4319
                overlay_present = 1;
 
4320
        }
 
4321
#endif
 
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");
 
4326
                }
 
4327
        } else {
 
4328
                overlay_present = 1;
 
4329
        }
 
4330
#endif
 
4331
        if (overlay && !overlay_present) {
 
4332
                overlay = 0;
 
4333
                overlay_cursor = 0;
 
4334
        }
 
4335
 
 
4336
        /* cursor shapes setup */
 
4337
        if (! multiple_cursors_mode) {
 
4338
                multiple_cursors_mode = strdup("default");
 
4339
        }
 
4340
        if (show_cursor) {
 
4341
                if(!strcmp(multiple_cursors_mode, "default")
 
4342
                    && xfixes_present && use_xfixes) {
 
4343
                        free(multiple_cursors_mode);
 
4344
                        multiple_cursors_mode = strdup("most");
 
4345
 
 
4346
                        if (! quiet && ! raw_fb_str) {
 
4347
                                rfbLog("\n");
 
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");
 
4352
                        }
 
4353
                }
 
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");
 
4359
                                }
 
4360
                                overlay_cursor = 0;
 
4361
                        }
 
4362
                }
 
4363
        }
 
4364
 
 
4365
        if (overlay) {
 
4366
                using_shm = 0;
 
4367
                if (flash_cmap && ! quiet && ! raw_fb_str) {
 
4368
                        rfbLog("warning: -flashcmap may be incompatible with -overlay\n");
 
4369
                }
 
4370
                if (show_cursor && overlay_cursor) {
 
4371
                        char *s = multiple_cursors_mode;
 
4372
                        if (*s == 'X' || !strcmp(s, "some") ||
 
4373
                            !strcmp(s, "arrow")) {
 
4374
                                /*
 
4375
                                 * user wants these modes, so disable fb cursor
 
4376
                                 */
 
4377
                                overlay_cursor = 0;
 
4378
                        } else {
 
4379
                                /*
 
4380
                                 * "default" and "most", we turn off
 
4381
                                 * show_cursor since it will automatically
 
4382
                                 * be in the framebuffer.
 
4383
                                 */
 
4384
                                show_cursor = 0;
 
4385
                        }
 
4386
                }
 
4387
        }
 
4388
 
 
4389
        initialize_cursors_mode();
 
4390
 
 
4391
        /* check for XTEST */
 
4392
        if (! XTestQueryExtension_wr(dpy, &ev, &er, &maj, &min)) {
 
4393
                if (! quiet && ! raw_fb_str) {
 
4394
                        rfbLog("\n");
 
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");
 
4403
                }
 
4404
                xtest_present = 0;
 
4405
                use_xwarppointer = 1;
 
4406
        } else {
 
4407
                xtest_present = 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;
 
4412
                }
 
4413
        }
 
4414
 
 
4415
        if (! XETrapQueryExtension_wr(dpy, &ev, &er, &maj)) {
 
4416
                xtrap_present = 0;
 
4417
        } else {
 
4418
                xtrap_present = 1;
 
4419
                xtrap_base_event_type = ev;
 
4420
        }
 
4421
 
 
4422
        /*
 
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:
 
4427
         */
 
4428
        disable_grabserver(dpy, 0);
 
4429
 
 
4430
        /* check for RECORD */
 
4431
        if (! XRecordQueryVersion_wr(dpy, &maj, &min)) {
 
4432
                xrecord_present = 0;
 
4433
                if (! quiet) {
 
4434
                        rfbLog("\n");
 
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");
 
4440
                        rfbLog("\n");
 
4441
                        rfbLog("  Section \"Module\"\n");
 
4442
                        rfbLog("  ...\n");
 
4443
                        rfbLog("      Load    \"record\"\n");
 
4444
                        rfbLog("  ...\n");
 
4445
                        rfbLog("  EndSection\n");
 
4446
                        rfbLog("\n");
 
4447
                }
 
4448
        } else {
 
4449
                xrecord_present = 1;
 
4450
        }
 
4451
 
 
4452
        initialize_xrecord();
 
4453
 
 
4454
        tmpi = 1;
 
4455
        if (scroll_copyrect) {
 
4456
                if (strstr(scroll_copyrect, "never")) {
 
4457
                        tmpi = 0;
 
4458
                }
 
4459
        } else if (scroll_copyrect_default) {
 
4460
                if (strstr(scroll_copyrect_default, "never")) {
 
4461
                        tmpi = 0;
 
4462
                }
 
4463
        }
 
4464
        if (! xrecord_present) {
 
4465
                tmpi = 0;
 
4466
        }
 
4467
#if !LIBVNCSERVER_HAVE_RECORD
 
4468
        tmpi = 0;
 
4469
#endif
 
4470
        if (! quiet && tmpi && ! raw_fb_str) {
 
4471
                rfbLog("\n");
 
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");
 
4483
                }
 
4484
        }
 
4485
 
 
4486
        if (! quiet && ncache && ! raw_fb_str) {
 
4487
                rfbLog("\n");
 
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");
 
4503
                if (scale_str) {
 
4504
                        rfbLog("  Note: '-scale' is on and this can cause more problems.\n");
 
4505
                }
 
4506
        }
 
4507
        if (ncache && getenv("NCACHE_DEBUG")) {
 
4508
                ncdb = 1;
 
4509
        }
 
4510
 
 
4511
        /* check for OS with small shm limits */
 
4512
        if (using_shm && ! single_copytile) {
 
4513
                if (limit_shm()) {
 
4514
                        single_copytile = 1;
 
4515
                }
 
4516
        }
 
4517
 
 
4518
        single_copytile_orig = single_copytile;
 
4519
 
 
4520
        /* check for MIT-SHM */
 
4521
        if (! XShmQueryExtension_wr(dpy)) {
 
4522
                xshm_present = 0;
 
4523
                if (! using_shm) {
 
4524
                        if (! quiet && ! raw_fb_str) {
 
4525
                                rfbLog("info: display does not support XShm.\n");
 
4526
                        }
 
4527
                } else {
 
4528
                    if (! quiet && ! raw_fb_str) {
 
4529
                        rfbLog("\n");
 
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");
 
4536
                    }
 
4537
                    exit(1);
 
4538
#else
 
4539
                        rfbLog("Switching to -noshm mode.\n");
 
4540
                    }
 
4541
                    using_shm = 0;
 
4542
#endif
 
4543
                }
 
4544
        }
 
4545
 
 
4546
#if LIBVNCSERVER_HAVE_XKEYBOARD
 
4547
        /* check for XKEYBOARD */
 
4548
        initialize_xkb();
 
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");
 
4553
                }
 
4554
                use_xkb_modtweak = 0;
 
4555
        }
 
4556
#endif
 
4557
 
 
4558
        if (xkb_present && !use_xkb_modtweak && !got_noxkb) {
 
4559
                if (use_modifier_tweak) {
 
4560
                        switch_to_xkb_if_better();
 
4561
                }
 
4562
        }
 
4563
 
 
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");
 
4568
                }
 
4569
                xrandr_base_event_type = 0;
 
4570
                xrandr = 0;
 
4571
                xrandr_maybe = 0;
 
4572
                xrandr_present = 0;
 
4573
        } else {
 
4574
                xrandr_present = 1;
 
4575
        }
 
4576
#endif
 
4577
 
 
4578
        check_pm();
 
4579
 
 
4580
        if (! quiet && ! raw_fb_str) {
 
4581
                rfbLog("--------------------------------------------------------\n");
 
4582
                rfbLog("\n");
 
4583
        }
 
4584
 
 
4585
        raw_fb_pass_go_and_collect_200_dollars:
 
4586
 
 
4587
        if (! dpy || raw_fb_str) {
 
4588
                int doit = 0;
 
4589
                /* XXX this needs improvement (esp. for remote control) */
 
4590
                if (! raw_fb_str || strstr(raw_fb_str, "console") == raw_fb_str) {
 
4591
#ifdef MACOSX
 
4592
                        doit = 1;
 
4593
#endif
 
4594
                }
 
4595
                if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
 
4596
                        doit = 1;
 
4597
                }
 
4598
                if (doit) {
 
4599
                        if (! multiple_cursors_mode) {
 
4600
                                multiple_cursors_mode = strdup("most");
 
4601
                        }
 
4602
                        initialize_cursors_mode();
 
4603
                        use_xdamage = orig_use_xdamage;
 
4604
                        if (use_xdamage) {
 
4605
                                xdamage_present = 1;
 
4606
                                initialize_xdamage();
 
4607
                        }
 
4608
                }
 
4609
        }
 
4610
 
 
4611
        if (! dt) {
 
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]);
 
4616
        }
 
4617
        
 
4618
        /*
 
4619
         * Create the XImage corresponding to the display framebuffer.
 
4620
         */
 
4621
 
 
4622
        fb0 = initialize_xdisplay_fb();
 
4623
 
 
4624
        /*
 
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.
 
4627
         */
 
4628
        initialize_pipeinput();
 
4629
 
 
4630
        /*
 
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.
 
4633
         */
 
4634
 
 
4635
        initialize_screen(&argc_vnc, argv_vnc, fb0);
 
4636
 
 
4637
        if (waited_for_client) {
 
4638
                if (fake_fb) {
 
4639
                        free(fake_fb);
 
4640
                        fake_fb = NULL;
 
4641
                }
 
4642
                if (use_solid_bg && client_count) {
 
4643
                        solid_bg(0);
 
4644
                }
 
4645
                if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) {
 
4646
                        rfbClientIteratorPtr iter;
 
4647
                        rfbClientPtr cl, cl0 = NULL;
 
4648
                        int i = 0;
 
4649
                        iter = rfbGetClientIterator(screen);
 
4650
                        while( (cl = rfbClientIteratorNext(iter)) ) {
 
4651
                                i++;    
 
4652
                                if (i != 1) {
 
4653
                                        rfbLog("WAIT popup: too many clients\n");
 
4654
                                        clean_up_exit(1);
 
4655
                                }
 
4656
                                cl0 = cl;
 
4657
                        }
 
4658
                        rfbReleaseClientIterator(iter);
 
4659
                        if (i != 1 || cl0 == NULL) {
 
4660
                                rfbLog("WAIT popup: no clients.\n");
 
4661
                                clean_up_exit(1);
 
4662
                        }
 
4663
                        if (! accept_client(cl0)) {
 
4664
                                rfbLog("WAIT popup: denied.\n");
 
4665
                                clean_up_exit(1);
 
4666
                        }
 
4667
                        rfbLog("waited_for_client: popup accepted.\n");
 
4668
                        cl0->onHold = FALSE;
 
4669
                }
 
4670
                if (macosx_console) {
 
4671
                        refresh_screen(1);
 
4672
                }
 
4673
                if (dpy && xdmcp_insert != NULL) {
 
4674
#if !NO_X11
 
4675
                        char c;
 
4676
                        int n = strlen(xdmcp_insert);
 
4677
                        KeyCode k, k2;
 
4678
                        KeySym sym;
 
4679
                        int i, ok = 1;
 
4680
                        for (i = 0; i < n; i++) {
 
4681
                                c = xdmcp_insert[i];
 
4682
                                sym = (KeySym) c;
 
4683
                                if (sym < ' ' || sym > 0x7f) {
 
4684
                                        ok = 0;
 
4685
                                        break;
 
4686
                                }
 
4687
                                k = XKeysymToKeycode(dpy, sym);
 
4688
                                if (k == NoSymbol) {
 
4689
                                        ok = 0;
 
4690
                                        break;
 
4691
                                }
 
4692
                        }
 
4693
                        if (ok) {
 
4694
                                XFlush_wr(dpy);
 
4695
                                usleep(2*1000*1000);
 
4696
                                if (!quiet) {
 
4697
                                        rfbLog("sending XDM '%s'\n", xdmcp_insert);
 
4698
                                }
 
4699
                                for (i = 0; i < n; i++) {
 
4700
                                        c = xdmcp_insert[i];
 
4701
                                        sym = (KeySym) c;
 
4702
                                        k = XKeysymToKeycode(dpy, sym);
 
4703
                                        if (isupper(c)) {
 
4704
                                                k2 = XKeysymToKeycode(dpy, XK_Shift_L);
 
4705
                                                XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
 
4706
                                                XFlush_wr(dpy);
 
4707
                                                usleep(100*1000);
 
4708
                                        }
 
4709
                                        if (0) fprintf(stderr, "C/k %c/%x\n", c, k);
 
4710
                                        XTestFakeKeyEvent_wr(dpy, k, True, CurrentTime);
 
4711
                                        XFlush_wr(dpy);
 
4712
                                        usleep(100*1000);
 
4713
                                        XTestFakeKeyEvent_wr(dpy, k, False, CurrentTime);
 
4714
                                        XFlush_wr(dpy);
 
4715
                                        usleep(100*1000);
 
4716
                                        if (isupper(c)) {
 
4717
                                                k2 = XKeysymToKeycode(dpy, XK_Shift_L);
 
4718
                                                XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
 
4719
                                                XFlush_wr(dpy);
 
4720
                                                usleep(100*1000);
 
4721
                                        }
 
4722
                                }
 
4723
                                k2 = XKeysymToKeycode(dpy, XK_Tab);
 
4724
                                XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
 
4725
                                XFlush_wr(dpy);
 
4726
                                usleep(100*1000);
 
4727
                                XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
 
4728
                                XFlush_wr(dpy);
 
4729
                                usleep(100*1000);
 
4730
                        }
 
4731
                        free(xdmcp_insert);
 
4732
#endif
 
4733
                }
 
4734
                check_redir_services();
 
4735
 
 
4736
        }
 
4737
 
 
4738
        if (! waited_for_client) {
 
4739
                if (try_http && ! got_httpdir && check_httpdir()) {
 
4740
                        http_connections(1);
 
4741
                }
 
4742
                if (ssh_str != NULL) {
 
4743
                        ssh_remote_tunnel(ssh_str, screen->port);
 
4744
                }
 
4745
        }
 
4746
 
 
4747
        initialize_tiles();
 
4748
 
 
4749
        /* rectangular blackout regions */
 
4750
        initialize_blackouts_and_xinerama();
 
4751
 
 
4752
        /* created shm or XImages when using_shm = 0 */
 
4753
        initialize_polling_images();
 
4754
 
 
4755
        initialize_signals();
 
4756
 
 
4757
        initialize_speeds();
 
4758
 
 
4759
        initialize_keyboard_and_pointer();
 
4760
 
 
4761
        if (inetd && use_openssl) {
 
4762
                if (! waited_for_client) {
 
4763
                        accept_openssl(OPENSSL_INETD, -1);
 
4764
                }
 
4765
        }
 
4766
        if (! inetd && ! use_openssl) {
 
4767
                if (! screen->port || screen->listenSock < 0) {
 
4768
                        if (got_rfbport && got_rfbport_val == 0) {
 
4769
                                ;
 
4770
                        } else {
 
4771
                                rfbLogEnable(1);
 
4772
                                rfbLog("Error: could not obtain listening port.\n");
 
4773
                                clean_up_exit(1);
 
4774
                        }
 
4775
                }
 
4776
        }
 
4777
        if (! quiet) {
 
4778
                rfbLog("screen setup finished.\n");
 
4779
                if (SHOW_NO_PASSWORD_WARNING && !nopw) {
 
4780
                        rfbLog("\n");
 
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");
 
4785
                }
 
4786
        }
 
4787
        set_vnc_desktop_name();
 
4788
 
 
4789
        if (ncache_beta_tester && (ncache != 0 || ncache_msg)) {
 
4790
                ncache_beta_tester_message();
 
4791
        }
 
4792
 
 
4793
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
 
4794
        if (bg) {
 
4795
                int p, n;
 
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;
 
4801
                        }
 
4802
                        if (screen && screen->httpListenSock >= 0) {
 
4803
                                close(screen->httpListenSock);
 
4804
                                FD_CLR(screen->httpListenSock,&screen->allFds);
 
4805
                                screen->httpListenSock = -1;
 
4806
                        }
 
4807
                        if (openssl_sock >= 0) {
 
4808
                                close(openssl_sock);
 
4809
                                openssl_sock = -1;
 
4810
                        }
 
4811
                        if (https_sock >= 0) {
 
4812
                                close(https_sock);
 
4813
                                https_sock = -1;
 
4814
                        }
 
4815
                }
 
4816
                /* fork into the background now */
 
4817
                if ((p = fork()) > 0)  {
 
4818
                        exit(0);
 
4819
                } else if (p == -1) {
 
4820
                        rfbLogEnable(1);
 
4821
                        fprintf(stderr, "could not fork\n");
 
4822
                        perror("fork");
 
4823
                        clean_up_exit(1);
 
4824
                }
 
4825
                if (setsid() == -1) {
 
4826
                        rfbLogEnable(1);
 
4827
                        fprintf(stderr, "setsid failed\n");
 
4828
                        perror("setsid");
 
4829
                        clean_up_exit(1);
 
4830
                }
 
4831
                /* adjust our stdio */
 
4832
                n = open("/dev/null", O_RDONLY);
 
4833
                dup2(n, 0);
 
4834
                dup2(n, 1);
 
4835
                if (! logfile) {
 
4836
                        dup2(n, 2);
 
4837
                }
 
4838
                if (n > 2) {
 
4839
                        close(n);
 
4840
                }
 
4841
        }
 
4842
#endif
 
4843
 
 
4844
        watch_loop();
 
4845
 
 
4846
        return(0);
 
4847
 
 
4848
#undef argc
 
4849
#undef argv
 
4850
 
 
4851
}