PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/ica/x11/x11vnc/x11vnc.c

https://github.com/EmebedQtsoft/italc2
C | 5955 lines | 5355 code | 328 blank | 272 comment | 1733 complexity | 3972ec586c7c1d83fbd30cbee6dd99a3 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * x11vnc: a VNC server for X displays.
  3. *
  4. * Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
  5. * All rights reserved.
  6. *
  7. * This file is part of x11vnc.
  8. *
  9. * This is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; version 2 of the License, or (at
  12. * your option) any later version.
  13. *
  14. * This software is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this software; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  22. * USA or see <http://www.gnu.org/licenses/>.
  23. *
  24. * In addition, as a special exception, Karl J. Runge
  25. * gives permission to link the code of its release of x11vnc with the
  26. * OpenSSL project's "OpenSSL" library (or with modified versions of it
  27. * that use the same license as the "OpenSSL" library), and distribute
  28. * the linked executables. You must obey the GNU General Public License
  29. * in all respects for all of the code used other than "OpenSSL". If you
  30. * modify this file, you may extend this exception to your version of the
  31. * file, but you are not obligated to do so. If you do not wish to do
  32. * so, delete this exception statement from your version.
  33. */
  34. /*
  35. * This program is based on some ideas from the following programs:
  36. *
  37. * the initial x11vnc.c in libvncserver (Johannes E. Schindelin)
  38. * x0rfbserver, the original native X vnc server (Jens Wagner)
  39. * krfb, the KDE desktopsharing project (Tim Jansen)
  40. *
  41. * Please see http://www.karlrunge.com/x11vnc for the most up-to-date
  42. * information about x11vnc. Some of the following text may be out
  43. * of date.
  44. *
  45. * The primary goal of this program is to create a portable and simple
  46. * command-line server utility that allows a VNC viewer to connect
  47. * to an actual X display (as the above do). The only non-standard
  48. * dependency of this program is the static library libvncserver.a.
  49. * Although in some environments libjpeg.so or libz.so may not be
  50. * readily available and needs to be installed, they may be found
  51. * at ftp://ftp.uu.net/graphics/jpeg/ and http://www.gzip.org/zlib/,
  52. * respectively. To increase portability it is written in plain C.
  53. *
  54. * Another goal is to improve performance and interactive response.
  55. * The algorithm of x0rfbserver was used as a base. Many additional
  56. * heuristics are also applied.
  57. *
  58. * Another goal is to add many features that enable and incourage creative
  59. * usage and application of the tool. Apologies for the large number
  60. * of options!
  61. *
  62. * To build:
  63. *
  64. * Obtain the libvncserver package (http://libvncserver.sourceforge.net).
  65. * As of 12/2002 this version of x11vnc.c is contained in the libvncserver
  66. * CVS tree and released in version 0.5.
  67. *
  68. * gcc should be used on all platforms. To build a threaded version put
  69. * "-D_REENTRANT -DX11VNC_THREADED" in the environment variable CFLAGS
  70. * or CPPFLAGS (e.g. before running the libvncserver configure). The
  71. * threaded mode is a bit more responsive, but can be unstable (e.g.
  72. * if more than one client the same tight or zrle encoding).
  73. *
  74. * Known shortcomings:
  75. *
  76. * The screen updates are good, but of course not perfect since the X
  77. * display must be continuously polled and read for changes and this is
  78. * slow for most hardware. This can be contrasted with receiving a change
  79. * callback from the X server, if that were generally possible... (UPDATE:
  80. * this is handled now with the X DAMAGE extension, but unfortunately
  81. * that doesn't seem to address the slow read from the video h/w). So,
  82. * e.g., opaque moves and similar window activity can be very painful;
  83. * one has to modify one's behavior a bit.
  84. *
  85. * General audio at the remote display is lost unless one separately
  86. * sets up some audio side-channel such as esd.
  87. *
  88. * It does not appear possible to query the X server for the current
  89. * cursor shape. We can use XTest to compare cursor to current window's
  90. * cursor, but we cannot extract what the cursor is... (UPDATE: we now
  91. * use XFIXES extension for this. Also on Solaris and IRIX Overlay
  92. * extensions exists that allow drawing the mouse into the framebuffer)
  93. *
  94. * The current *position* of the remote X mouse pointer is shown with
  95. * the -cursor option. Further, if -cursor X is used, a trick
  96. * is done to at least show the root window cursor vs non-root cursor.
  97. * (perhaps some heuristic can be done to further distinguish cases...,
  98. * currently "-cursor some" is a first hack at this)
  99. *
  100. * Under XFIXES mode for showing the cursor shape, the cursor may be
  101. * poorly approximated if it has transparency (alpha channel).
  102. *
  103. * Windows using visuals other than the default X visual may have
  104. * their colors messed up. When using 8bpp indexed color, the colormap
  105. * is attempted to be followed, but may become out of date. Use the
  106. * -flashcmap option to have colormap flashing as the pointer moves
  107. * windows with private colormaps (slow). Displays with mixed depth 8 and
  108. * 24 visuals will incorrectly display windows using the non-default one.
  109. * On Sun and Sgi hardware we can to work around this with -overlay.
  110. *
  111. * Feature -id <windowid> can be picky: it can crash for things like
  112. * the window not sufficiently mapped into server memory, etc (UPDATE:
  113. * we now use the -xrandr mechanisms to trap errors more robustly for
  114. * this mode). SaveUnders menus, popups, etc will not be seen.
  115. *
  116. * Under some situations the keysym unmapping is not correct, especially
  117. * if the two keyboards correspond to different languages. The -modtweak
  118. * option is the default and corrects most problems. One can use the
  119. * -xkb option to try to use the XKEYBOARD extension to clear up any
  120. * remaining problems.
  121. *
  122. * Occasionally, a few tile updates can be missed leaving a patch of
  123. * color that needs to be refreshed. This may only be when threaded,
  124. * which is no longer the default.
  125. *
  126. * There seems to be a serious bug with simultaneous clients when
  127. * threaded, currently the only workaround in this case is -nothreads
  128. * (which is now the default).
  129. */
  130. /* -- x11vnc.c -- */
  131. #include "x11vnc.h"
  132. #include "xwrappers.h"
  133. #include "xdamage.h"
  134. #include "xrecord.h"
  135. #include "xevents.h"
  136. #include "xinerama.h"
  137. #include "xrandr.h"
  138. #include "xkb_bell.h"
  139. #include "win_utils.h"
  140. #include "remote.h"
  141. #include "scan.h"
  142. #include "gui.h"
  143. #include "help.h"
  144. #include "user.h"
  145. #include "cleanup.h"
  146. #include "keyboard.h"
  147. #include "pointer.h"
  148. #include "cursor.h"
  149. #include "userinput.h"
  150. #include "screen.h"
  151. #include "connections.h"
  152. #include "rates.h"
  153. #include "unixpw.h"
  154. #include "inet.h"
  155. #include "sslcmds.h"
  156. #include "sslhelper.h"
  157. #include "selection.h"
  158. #include "pm.h"
  159. #include "solid.h"
  160. /*
  161. * main routine for the x11vnc program
  162. */
  163. void watch_loop(void);
  164. static int limit_shm(void);
  165. static void check_rcfile(int argc, char **argv);
  166. static void immediate_switch_user(int argc, char* argv[]);
  167. static void print_settings(int try_http, int bg, char *gui_str);
  168. static void check_loop_mode(int argc, char* argv[], int force);
  169. static void check_appshare_mode(int argc, char* argv[]);
  170. static int tsdo_timeout_flag;
  171. static void tsdo_timeout (int sig) {
  172. tsdo_timeout_flag = 1;
  173. if (sig) {};
  174. }
  175. #define TASKMAX 32
  176. static pid_t ts_tasks[TASKMAX];
  177. static int ts_taskn = -1;
  178. int tsdo(int port, int lsock, int *conn) {
  179. int csock, rsock, i, db = 1;
  180. pid_t pid;
  181. struct sockaddr_in addr;
  182. #ifdef __hpux
  183. int addrlen = sizeof(addr);
  184. #else
  185. socklen_t addrlen = sizeof(addr);
  186. #endif
  187. if (*conn < 0) {
  188. signal(SIGALRM, tsdo_timeout);
  189. tsdo_timeout_flag = 0;
  190. alarm(10);
  191. csock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
  192. alarm(0);
  193. if (db) rfbLog("tsdo: accept: lsock: %d, csock: %d, port: %d\n", lsock, csock, port);
  194. if (tsdo_timeout_flag > 0 || csock < 0) {
  195. close(csock);
  196. *conn = -1;
  197. return 1;
  198. }
  199. *conn = csock;
  200. } else {
  201. csock = *conn;
  202. if (db) rfbLog("tsdo: using existing csock: %d, port: %d\n", csock, port);
  203. }
  204. rsock = connect_tcp("127.0.0.1", port);
  205. if (rsock < 0) {
  206. if (db) rfbLog("tsdo: connect_tcp(port=%d) failed.\n", port);
  207. close(csock);
  208. return 2;
  209. }
  210. pid = fork();
  211. if (pid < 0) {
  212. close(csock);
  213. close(rsock);
  214. return 3;
  215. }
  216. if (pid > 0) {
  217. ts_taskn = (ts_taskn+1) % TASKMAX;
  218. ts_tasks[ts_taskn] = pid;
  219. close(csock);
  220. close(rsock);
  221. *conn = -1;
  222. return 0;
  223. }
  224. if (pid == 0) {
  225. for (i=0; i<255; i++) {
  226. if (i != csock && i != rsock && i != 2) {
  227. close(i);
  228. }
  229. }
  230. #if LIBVNCSERVER_HAVE_SETSID
  231. if (setsid() == -1) {
  232. perror("setsid");
  233. close(csock);
  234. close(rsock);
  235. exit(1);
  236. }
  237. #else
  238. if (setpgrp() == -1) {
  239. perror("setpgrp");
  240. close(csock);
  241. close(rsock);
  242. exit(1);
  243. }
  244. #endif /* SETSID */
  245. raw_xfer(rsock, csock, csock);
  246. close(csock);
  247. close(rsock);
  248. exit(0);
  249. }
  250. return 0;
  251. }
  252. void set_redir_properties(void);
  253. #define TSMAX 32
  254. #define TSSTK 16
  255. void terminal_services(char *list) {
  256. int i, j, n, db = 1;
  257. char *p, *q, *r, *str;
  258. #if !NO_X11
  259. char *tag[TSMAX];
  260. int listen[TSMAX], redir[TSMAX][TSSTK], socks[TSMAX], tstk[TSSTK];
  261. double rate_start;
  262. int rate_count;
  263. Atom at, atom[TSMAX];
  264. fd_set rd;
  265. Window rwin;
  266. XErrorHandler old_handler1;
  267. XIOErrorHandler old_handler2;
  268. char num[32];
  269. time_t last_clean = time(NULL);
  270. if (getenv("TS_REDIR_DEBUG")) {
  271. db = 2;
  272. }
  273. if (! dpy) {
  274. return;
  275. }
  276. rwin = RootWindow(dpy, DefaultScreen(dpy));
  277. at = XInternAtom(dpy, "TS_REDIR_LIST", False);
  278. if (at != None) {
  279. XChangeProperty(dpy, rwin, at, XA_STRING, 8,
  280. PropModeReplace, (unsigned char *)list, strlen(list));
  281. XSync(dpy, False);
  282. }
  283. if (db) fprintf(stderr, "TS_REDIR_LIST Atom: %d.\n", (int) at);
  284. oh_restart_it_all:
  285. for (i=0; i<TASKMAX; i++) {
  286. ts_tasks[i] = 0;
  287. }
  288. for (i=0; i<TSMAX; i++) {
  289. socks[i] = -1;
  290. listen[i] = -1;
  291. for (j=0; j<TSSTK; j++) {
  292. redir[i][j] = 0;
  293. }
  294. }
  295. rate_start = 0.0;
  296. rate_count = 0;
  297. n = 0;
  298. str = strdup(list);
  299. p = strtok(str, ",");
  300. while (p) {
  301. int m1, m2;
  302. if (db) fprintf(stderr, "item: %s\n", p);
  303. q = strrchr(p, ':');
  304. if (!q) {
  305. p = strtok(NULL, ",");
  306. continue;
  307. }
  308. r = strchr(p, ':');
  309. if (!r || r == q) {
  310. p = strtok(NULL, ",");
  311. continue;
  312. }
  313. m1 = atoi(q+1);
  314. *q = '\0';
  315. m2 = atoi(r+1);
  316. *r = '\0';
  317. if (m1 <= 0 || m2 <= 0 || m1 >= 0xffff || m2 >= 0xffff) {
  318. p = strtok(NULL, ",");
  319. continue;
  320. }
  321. redir[n][0] = m1;
  322. listen[n] = m2;
  323. tag[n] = strdup(p);
  324. if (db) fprintf(stderr, " %d %d %s\n", redir[n][0], listen[n], tag[n]);
  325. *r = ':';
  326. *q = ':';
  327. n++;
  328. if (n >= TSMAX) {
  329. break;
  330. }
  331. p = strtok(NULL, ",");
  332. }
  333. free(str);
  334. if (n==0) {
  335. return;
  336. }
  337. at = XInternAtom(dpy, "TS_REDIR_PID", False);
  338. if (at != None) {
  339. sprintf(num, "%d", getpid());
  340. XChangeProperty(dpy, rwin, at, XA_STRING, 8,
  341. PropModeReplace, (unsigned char *)num, strlen(num));
  342. XSync(dpy, False);
  343. }
  344. for (i=0; i<n; i++) {
  345. int k;
  346. atom[i] = XInternAtom(dpy, tag[i], False);
  347. if (db) fprintf(stderr, "tag: %s atom: %d\n", tag[i], (int) atom[i]);
  348. if (atom[i] == None) {
  349. continue;
  350. }
  351. sprintf(num, "%d", redir[i][0]);
  352. if (db) fprintf(stderr, " listen: %d redir: %s\n", listen[i], num);
  353. XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
  354. PropModeReplace, (unsigned char *)num, strlen(num));
  355. XSync(dpy, False);
  356. for (k=1; k <= 5; k++) {
  357. /* XXX ::1 fallback? */
  358. socks[i] = listen_tcp(listen[i], htonl(INADDR_LOOPBACK), 1);
  359. if (socks[i] >= 0) {
  360. if (db) fprintf(stderr, " listen succeeded: %d\n", listen[i]);
  361. break;
  362. }
  363. if (db) fprintf(stderr, " listen failed***: %d\n", listen[i]);
  364. usleep(k * 2000*1000);
  365. }
  366. }
  367. if (getenv("TSD_RESTART")) {
  368. if (!strcmp(getenv("TSD_RESTART"), "1")) {
  369. set_redir_properties();
  370. }
  371. }
  372. while (1) {
  373. struct timeval tv;
  374. int nfd;
  375. int fmax = -1;
  376. tv.tv_sec = 3;
  377. tv.tv_usec = 0;
  378. FD_ZERO(&rd);
  379. for (i=0; i<n; i++) {
  380. if (socks[i] >= 0) {
  381. FD_SET(socks[i], &rd);
  382. if (socks[i] > fmax) {
  383. fmax = socks[i];
  384. }
  385. }
  386. }
  387. nfd = select(fmax+1, &rd, NULL, NULL, &tv);
  388. if (db && 0) fprintf(stderr, "nfd=%d\n", nfd);
  389. if (nfd < 0 && errno == EINTR) {
  390. XSync(dpy, True);
  391. continue;
  392. }
  393. if (nfd > 0) {
  394. int did_ts = 0;
  395. for(i=0; i<n; i++) {
  396. int k = 0;
  397. for (j = 0; j < TSSTK; j++) {
  398. tstk[j] = 0;
  399. }
  400. for (j = 0; j < TSSTK; j++) {
  401. if (redir[i][j] != 0) {
  402. tstk[k++] = redir[i][j];
  403. }
  404. }
  405. for (j = 0; j < TSSTK; j++) {
  406. redir[i][j] = tstk[j];
  407. if (tstk[j] != 0) fprintf(stderr, "B redir[%d][%d] = %d %s\n", i, j, tstk[j], tag[i]);
  408. }
  409. }
  410. for(i=0; i<n; i++) {
  411. int s = socks[i];
  412. if (s < 0) {
  413. continue;
  414. }
  415. if (FD_ISSET(s, &rd)) {
  416. int p0, p, found = -1, jzero = -1;
  417. int conn = -1;
  418. get_prop(num, 32, atom[i], None);
  419. p0 = atoi(num);
  420. for (j = TSSTK-1; j >= 0; j--) {
  421. if (redir[i][j] == 0) {
  422. jzero = j;
  423. continue;
  424. }
  425. if (p0 > 0 && p0 < 0xffff) {
  426. if (redir[i][j] == p0) {
  427. found = j;
  428. break;
  429. }
  430. }
  431. }
  432. if (jzero < 0) {
  433. jzero = TSSTK-1;
  434. }
  435. if (found < 0) {
  436. if (p0 > 0 && p0 < 0xffff) {
  437. redir[i][jzero] = p0;
  438. }
  439. }
  440. for (j = TSSTK-1; j >= 0; j--) {
  441. int rc;
  442. p = redir[i][j];
  443. if (p <= 0 || p >= 0xffff) {
  444. redir[i][j] = 0;
  445. continue;
  446. }
  447. if (dnow() > rate_start + 10.0) {
  448. rate_start = dnow();
  449. rate_count = 0;
  450. }
  451. rate_count++;
  452. rc = tsdo(p, s, &conn);
  453. did_ts++;
  454. if (rc == 0) {
  455. /* AOK */
  456. if (db) fprintf(stderr, "tsdo[%d] OK: %d\n", i, p);
  457. if (p != p0) {
  458. sprintf(num, "%d", p);
  459. XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
  460. PropModeReplace, (unsigned char *)num, strlen(num));
  461. XSync(dpy, False);
  462. }
  463. break;
  464. } else if (rc == 1) {
  465. /* accept failed */
  466. if (db) fprintf(stderr, "tsdo[%d] accept failed: %d, sleep 50ms\n", i, p);
  467. usleep(50*1000);
  468. break;
  469. } else if (rc == 2) {
  470. /* connect failed */
  471. if (db) fprintf(stderr, "tsdo[%d] connect failed: %d, sleep 50ms rate: %d/10s\n", i, p, rate_count);
  472. redir[i][j] = 0;
  473. usleep(50*1000);
  474. continue;
  475. } else if (rc == 3) {
  476. /* fork failed */
  477. usleep(500*1000);
  478. break;
  479. }
  480. }
  481. for (j = 0; j < TSSTK; j++) {
  482. if (redir[i][j] != 0) fprintf(stderr, "A redir[%d][%d] = %d %s\n", i, j, redir[i][j], tag[i]);
  483. }
  484. }
  485. }
  486. if (did_ts && rate_count > 100) {
  487. int db_netstat = 1;
  488. char dcmd[100];
  489. if (no_external_cmds) {
  490. db_netstat = 0;
  491. }
  492. rfbLog("terminal_services: throttling high connect rate %d/10s\n", rate_count);
  493. usleep(2*1000*1000);
  494. rfbLog("terminal_services: stopping ts services.\n");
  495. for(i=0; i<n; i++) {
  496. int s = socks[i];
  497. if (s < 0) {
  498. continue;
  499. }
  500. rfbLog("terminal_services: closing listen=%d sock=%d.\n", listen[i], socks[i]);
  501. if (listen[i] >= 0 && db_netstat) {
  502. sprintf(dcmd, "netstat -an | grep -w '%d'", listen[i]);
  503. fprintf(stderr, "#1 %s\n", dcmd);
  504. system(dcmd);
  505. }
  506. close(s);
  507. socks[i] = -1;
  508. usleep(2*1000*1000);
  509. if (listen[i] >= 0 && db_netstat) {
  510. fprintf(stderr, "#2 %s\n", dcmd);
  511. system(dcmd);
  512. }
  513. }
  514. usleep(10*1000*1000);
  515. rfbLog("terminal_services: restarting ts services\n");
  516. goto oh_restart_it_all;
  517. }
  518. }
  519. for (i=0; i<TASKMAX; i++) {
  520. pid_t p = ts_tasks[i];
  521. if (p > 0) {
  522. int status;
  523. pid_t p2 = waitpid(p, &status, WNOHANG);
  524. if (p2 == p) {
  525. ts_tasks[i] = 0;
  526. }
  527. }
  528. }
  529. /* this is to drop events and exit when X server is gone. */
  530. old_handler1 = XSetErrorHandler(trap_xerror);
  531. old_handler2 = XSetIOErrorHandler(trap_xioerror);
  532. trapped_xerror = 0;
  533. trapped_xioerror = 0;
  534. XSync(dpy, True);
  535. sprintf(num, "%d", (int) time(NULL));
  536. at = XInternAtom(dpy, "TS_REDIR", False);
  537. if (at != None) {
  538. XChangeProperty(dpy, rwin, at, XA_STRING, 8,
  539. PropModeReplace, (unsigned char *)num, strlen(num));
  540. XSync(dpy, False);
  541. }
  542. if (time(NULL) > last_clean + 20 * 60) {
  543. int i, j;
  544. for(i=0; i<n; i++) {
  545. int first = 1;
  546. for (j = TSSTK-1; j >= 0; j--) {
  547. int s, p = redir[i][j];
  548. if (p <= 0 || p >= 0xffff) {
  549. redir[i][j] = 0;
  550. continue;
  551. }
  552. s = connect_tcp("127.0.0.1", p);
  553. if (s < 0) {
  554. redir[i][j] = 0;
  555. if (db) fprintf(stderr, "tsdo[%d][%d] clean: connect failed: %d\n", i, j, p);
  556. } else {
  557. close(s);
  558. if (first) {
  559. sprintf(num, "%d", p);
  560. XChangeProperty(dpy, rwin, atom[i], XA_STRING, 8,
  561. PropModeReplace, (unsigned char *)num, strlen(num));
  562. XSync(dpy, False);
  563. }
  564. first = 0;
  565. }
  566. usleep(500*1000);
  567. }
  568. }
  569. last_clean = time(NULL);
  570. }
  571. if (trapped_xerror || trapped_xioerror) {
  572. if (db) fprintf(stderr, "Xerror: %d/%d\n", trapped_xerror, trapped_xioerror);
  573. exit(0);
  574. }
  575. XSetErrorHandler(old_handler1);
  576. XSetIOErrorHandler(old_handler2);
  577. }
  578. #endif
  579. }
  580. char *ts_services[][2] = {
  581. {"FD_CUPS", "TS_CUPS_REDIR"},
  582. {"FD_SMB", "TS_SMB_REDIR"},
  583. {"FD_ESD", "TS_ESD_REDIR"},
  584. {"FD_NAS", "TS_NAS_REDIR"},
  585. {NULL, NULL}
  586. };
  587. void do_tsd(void) {
  588. #if !NO_X11
  589. Atom a;
  590. char prop[513];
  591. pid_t pid;
  592. char *cmd;
  593. int n, sz = 0;
  594. char *disp = DisplayString(dpy);
  595. char *logfile = getenv("TS_REDIR_LOGFILE");
  596. int db = 0;
  597. if (getenv("TS_REDIR_DEBUG")) {
  598. db = 1;
  599. }
  600. if (db) fprintf(stderr, "do_tsd() in.\n");
  601. prop[0] = '\0';
  602. a = XInternAtom(dpy, "TS_REDIR_LIST", False);
  603. if (a != None) {
  604. get_prop(prop, 512, a, None);
  605. }
  606. if (db) fprintf(stderr, "TS_REDIR_LIST Atom: %d = '%s'\n", (int) a, prop);
  607. if (prop[0] == '\0') {
  608. return;
  609. }
  610. if (! program_name) {
  611. program_name = "x11vnc";
  612. }
  613. sz += strlen(program_name) + 1;
  614. sz += strlen("-display") + 1;
  615. sz += strlen(disp) + 1;
  616. sz += strlen("-tsd") + 1;
  617. sz += 1 + strlen(prop) + 1 + 1;
  618. sz += strlen("-env TSD_RESTART=1") + 1;
  619. sz += strlen("</dev/null 1>/dev/null 2>&1") + 1;
  620. sz += strlen(" &") + 1;
  621. if (logfile) {
  622. sz += strlen(logfile);
  623. }
  624. if (ipv6_listen) {
  625. sz += strlen("-6") + 1;
  626. }
  627. cmd = (char *) malloc(sz);
  628. if (getenv("XAUTHORITY")) {
  629. char *xauth = getenv("XAUTHORITY");
  630. if (!strcmp(xauth, "") || access(xauth, R_OK) != 0) {
  631. *(xauth-2) = '_'; /* yow */
  632. }
  633. }
  634. sprintf(cmd, "%s -display %s -tsd '%s' -env TSD_RESTART=1 %s </dev/null 1>%s 2>&1 &",
  635. program_name, disp, prop, ipv6_listen ? "-6" : "",
  636. logfile ? logfile : "/dev/null" );
  637. rfbLog("running: %s\n", cmd);
  638. #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
  639. /* fork into the background now */
  640. if ((pid = fork()) > 0) {
  641. pid_t pidw;
  642. int status;
  643. double s = dnow();
  644. while (dnow() < s + 1.5) {
  645. pidw = waitpid(pid, &status, WNOHANG);
  646. if (pidw == pid) {
  647. break;
  648. }
  649. usleep(100*1000);
  650. }
  651. return;
  652. } else if (pid == -1) {
  653. system(cmd);
  654. } else {
  655. setsid();
  656. /* adjust our stdio */
  657. n = open("/dev/null", O_RDONLY);
  658. dup2(n, 0);
  659. dup2(n, 1);
  660. dup2(n, 2);
  661. if (n > 2) {
  662. close(n);
  663. }
  664. system(cmd);
  665. exit(0);
  666. }
  667. #else
  668. system(cmd);
  669. #endif
  670. #endif
  671. }
  672. void set_redir_properties(void) {
  673. #if !NO_X11
  674. char *e, *f, *t;
  675. Atom a;
  676. char num[32];
  677. int i, p;
  678. if (! dpy) {
  679. return;
  680. }
  681. i = 0;
  682. while (ts_services[i][0] != NULL) {
  683. f = ts_services[i][0];
  684. t = ts_services[i][1];
  685. e = getenv(f);
  686. if (!e || strstr(e, "DAEMON-") != e) {
  687. i++;
  688. continue;
  689. }
  690. p = atoi(e + strlen("DAEMON-"));
  691. if (p <= 0) {
  692. i++;
  693. continue;
  694. }
  695. sprintf(num, "%d", p);
  696. a = XInternAtom(dpy, t, False);
  697. if (a != None) {
  698. Window rwin = RootWindow(dpy, DefaultScreen(dpy));
  699. fprintf(stderr, "Set: %s %s %s -> %s\n", f, t, e, num);
  700. XChangeProperty(dpy, rwin, a, XA_STRING, 8,
  701. PropModeReplace, (unsigned char *) num, strlen(num));
  702. XSync(dpy, False);
  703. }
  704. i++;
  705. }
  706. #endif
  707. }
  708. static void check_redir_services(void) {
  709. #if !NO_X11
  710. Atom a;
  711. char prop[513];
  712. time_t tsd_last;
  713. int restart = 0;
  714. pid_t pid = 0;
  715. int db = 0;
  716. db = 0;
  717. if (getenv("TS_REDIR_DEBUG")) {
  718. db = 1;
  719. }
  720. if (db) fprintf(stderr, "check_redir_services in.\n");
  721. if (! dpy) {
  722. return;
  723. }
  724. a = XInternAtom(dpy, "TS_REDIR_PID", False);
  725. if (a != None) {
  726. prop[0] = '\0';
  727. get_prop(prop, 512, a, None);
  728. if (prop[0] != '\0') {
  729. pid = (pid_t) atoi(prop);
  730. }
  731. }
  732. if (db) fprintf(stderr, "TS_REDIR_PID Atom: %d = '%s'\n", (int) a, prop);
  733. if (getenv("FD_TAG") && strcmp(getenv("FD_TAG"), "")) {
  734. a = XInternAtom(dpy, "FD_TAG", False);
  735. if (a != None) {
  736. Window rwin = RootWindow(dpy, DefaultScreen(dpy));
  737. char *tag = getenv("FD_TAG");
  738. XChangeProperty(dpy, rwin, a, XA_STRING, 8,
  739. PropModeReplace, (unsigned char *)tag, strlen(tag));
  740. XSync(dpy, False);
  741. }
  742. if (db) fprintf(stderr, "FD_TAG Atom: %d = '%s'\n", (int) a, prop);
  743. }
  744. prop[0] = '\0';
  745. a = XInternAtom(dpy, "TS_REDIR", False);
  746. if (a != None) {
  747. get_prop(prop, 512, a, None);
  748. }
  749. if (db) fprintf(stderr, "TS_REDIR Atom: %d = '%s'\n", (int) a, prop);
  750. if (prop[0] == '\0') {
  751. rfbLog("TS_REDIR is empty, restarting...\n");
  752. restart = 1;
  753. } else {
  754. tsd_last = (time_t) atoi(prop);
  755. if (time(NULL) > tsd_last + 30) {
  756. rfbLog("TS_REDIR seems dead for: %d sec, restarting...\n",
  757. time(NULL) - tsd_last);
  758. restart = 1;
  759. } else if (pid > 0 && time(NULL) > tsd_last + 6) {
  760. if (kill(pid, 0) != 0) {
  761. rfbLog("TS_REDIR seems dead via kill(%d, 0), restarting...\n",
  762. pid);
  763. restart = 1;
  764. }
  765. }
  766. }
  767. if (restart) {
  768. if (pid > 1) {
  769. rfbLog("killing TS_REDIR_PID: %d\n", pid);
  770. kill(pid, SIGTERM);
  771. usleep(500*1000);
  772. kill(pid, SIGKILL);
  773. }
  774. do_tsd();
  775. if (db) fprintf(stderr, "check_redir_services restarted.\n");
  776. return;
  777. }
  778. if (db) fprintf(stderr, "check_redir_services, no restart, calling set_redir_properties.\n");
  779. set_redir_properties();
  780. #endif
  781. }
  782. void ssh_remote_tunnel(char *instr, int lport) {
  783. #ifndef WIN32
  784. char *q, *cmd, *ssh;
  785. char *s = strdup(instr);
  786. int sleep = 300, disp = 0, sport = 0;
  787. int rc, len, rport;
  788. /* user@host:port:disp+secs */
  789. /* +sleep */
  790. q = strrchr(s, '+');
  791. if (q) {
  792. sleep = atoi(q+1);
  793. if (sleep <= 0) {
  794. sleep = 1;
  795. }
  796. *q = '\0';
  797. }
  798. /* :disp */
  799. q = strrchr(s, ':');
  800. if (q) {
  801. disp = atoi(q+1);
  802. *q = '\0';
  803. }
  804. /* :sshport */
  805. q = strrchr(s, ':');
  806. if (q) {
  807. sport = atoi(q+1);
  808. *q = '\0';
  809. }
  810. if (getenv("SSH")) {
  811. ssh = getenv("SSH");
  812. } else {
  813. ssh = "ssh";
  814. }
  815. len = 0;
  816. len += strlen(ssh) + strlen(s) + 500;
  817. cmd = (char *) malloc(len);
  818. if (disp >= 0 && disp <= 200) {
  819. rport = disp + 5900;
  820. } else if (disp < 0) {
  821. rport = -disp;
  822. } else {
  823. rport = disp;
  824. }
  825. if (sport > 0) {
  826. sprintf(cmd, "%s -f -p %d -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, sport, rport, lport, s, sleep);
  827. } else {
  828. sprintf(cmd, "%s -f -R '%d:localhost:%d' '%s' 'sleep %d'", ssh, rport, lport, s, sleep);
  829. }
  830. if (no_external_cmds || !cmd_ok("ssh")) {
  831. rfbLogEnable(1);
  832. rfbLog("cannot run external commands in -nocmds mode:\n");
  833. rfbLog(" \"%s\"\n", cmd);
  834. rfbLog(" exiting.\n");
  835. clean_up_exit(1);
  836. }
  837. close_exec_fds();
  838. fprintf(stderr, "\n");
  839. rfbLog("running: %s\n", cmd);
  840. rc = system(cmd);
  841. if (rc != 0) {
  842. free(cmd);
  843. free(s);
  844. rfbLog("ssh remote listen failed.\n");
  845. clean_up_exit(1);
  846. }
  847. if (1) {
  848. FILE *pipe;
  849. int mypid = (int) getpid();
  850. int bestpid = -1;
  851. int best = -1;
  852. char line[1024];
  853. char *psef = "ps -ef";
  854. char *psww = "ps wwwwwwaux";
  855. char *ps = psef;
  856. /* not portable... but it is really good to terminate the ssh when done. */
  857. /* ps -ef | egrep 'ssh2.*-R.*5907:localhost:5900.*runge@celias.lbl.gov.*sleep 300' | grep -v grep | awk '{print $2}' */
  858. if (strstr(UT.sysname, "Linux")) {
  859. ps = psww;
  860. } else if (strstr(UT.sysname, "BSD")) {
  861. ps = psww;
  862. } else if (strstr(UT.sysname, "Darwin")) {
  863. ps = psww;
  864. }
  865. 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);
  866. pipe = popen(cmd, "r");
  867. if (pipe) {
  868. while (fgets(line, 1024, pipe) != NULL) {
  869. int p = atoi(line);
  870. if (p > 0) {
  871. int score;
  872. if (p > mypid) {
  873. score = p - mypid;
  874. } else {
  875. score = p - mypid + 32768;
  876. if (score < 0) {
  877. score = 32768;
  878. }
  879. }
  880. if (best < 0 || score < best) {
  881. best = score;
  882. bestpid = p;
  883. }
  884. }
  885. }
  886. pclose(pipe);
  887. }
  888. if (bestpid != -1) {
  889. ssh_pid = (pid_t) bestpid;
  890. rfbLog("guessed ssh pid=%d, will terminate it on exit.\n", bestpid);
  891. }
  892. }
  893. free(cmd);
  894. free(s);
  895. #endif
  896. }
  897. /*
  898. * check blacklist for OSs with tight shm limits.
  899. */
  900. static int limit_shm(void) {
  901. int limit = 0;
  902. #ifndef WIN32
  903. if (UT.sysname == NULL) {
  904. return 0;
  905. }
  906. if (getenv("X11VNC_NO_LIMIT_SHM")) {
  907. return 0;
  908. }
  909. if (!strcmp(UT.sysname, "SunOS")) {
  910. char *r = UT.release;
  911. if (*r == '5' && *(r+1) == '.') {
  912. if (strchr("2345678", *(r+2)) != NULL) {
  913. limit = 1;
  914. }
  915. }
  916. } else if (!strcmp(UT.sysname, "Darwin")) {
  917. limit = 1;
  918. }
  919. if (limit && ! quiet) {
  920. fprintf(stderr, "reducing shm usage on %s %s (adding "
  921. "-onetile)\n", UT.sysname, UT.release);
  922. }
  923. #endif
  924. return limit;
  925. }
  926. /*
  927. * quick-n-dirty ~/.x11vncrc: each line (except # comments) is a cmdline option.
  928. */
  929. static int argc2 = 0;
  930. static char **argv2;
  931. static void check_rcfile(int argc, char **argv) {
  932. int i, j, pwlast, enclast, norc = 0, argmax = 1024;
  933. char *infile = NULL;
  934. char rcfile[1024];
  935. FILE *rc = NULL;
  936. for (i=1; i < argc; i++) {
  937. if (!strcmp(argv[i], "-printgui")) {
  938. fprintf(stdout, "%s", get_gui_code());
  939. fflush(stdout);
  940. exit(0);
  941. }
  942. if (!strcmp(argv[i], "-norc")) {
  943. norc = 1;
  944. got_norc = 1;
  945. }
  946. if (!strcmp(argv[i], "-QD")) {
  947. norc = 1;
  948. }
  949. if (!strcmp(argv[i], "-rc")) {
  950. if (i+1 >= argc) {
  951. fprintf(stderr, "-rc option requires a "
  952. "filename\n");
  953. exit(1);
  954. } else {
  955. infile = argv[i+1];
  956. }
  957. }
  958. }
  959. rc_norc = norc;
  960. rc_rcfile = strdup("");
  961. if (norc) {
  962. ;
  963. } else if (infile != NULL) {
  964. rc = fopen(infile, "r");
  965. rc_rcfile = strdup(infile);
  966. if (rc == NULL) {
  967. fprintf(stderr, "could not open rcfile: %s\n", infile);
  968. perror("fopen");
  969. exit(1);
  970. }
  971. } else {
  972. char *home = get_home_dir();
  973. if (! home) {
  974. norc = 1;
  975. } else {
  976. memset(rcfile, 0, sizeof(rcfile));
  977. strncpy(rcfile, home, 500);
  978. free(home);
  979. strcat(rcfile, "/.x11vncrc");
  980. infile = rcfile;
  981. rc = fopen(rcfile, "r");
  982. if (rc == NULL) {
  983. norc = 1;
  984. } else {
  985. rc_rcfile = strdup(rcfile);
  986. rc_rcfile_default = 1;
  987. }
  988. }
  989. }
  990. argv2 = (char **) malloc(argmax * sizeof(char *));
  991. argv2[argc2++] = strdup(argv[0]);
  992. if (! norc) {
  993. char line[4096], parm[400], tmp[401];
  994. char *buf, *tbuf;
  995. struct stat sbuf;
  996. int sz;
  997. if (fstat(fileno(rc), &sbuf) != 0) {
  998. fprintf(stderr, "problem with %s\n", infile);
  999. perror("fstat");
  1000. exit(1);
  1001. }
  1002. sz = sbuf.st_size+1; /* allocate whole file size */
  1003. if (sz < 1024) {
  1004. sz = 1024;
  1005. }
  1006. buf = (char *) malloc(sz);
  1007. buf[0] = '\0';
  1008. while (fgets(line, 4096, rc) != NULL) {
  1009. char *q, *p = line;
  1010. char c;
  1011. int cont = 0;
  1012. q = p;
  1013. c = '\0';
  1014. while (*q) {
  1015. if (*q == '#') {
  1016. if (c != '\\') {
  1017. *q = '\0';
  1018. break;
  1019. }
  1020. }
  1021. c = *q;
  1022. q++;
  1023. }
  1024. q = p;
  1025. c = '\0';
  1026. while (*q) {
  1027. if (*q == '\n') {
  1028. if (c == '\\') {
  1029. cont = 1;
  1030. *q = '\0';
  1031. *(q-1) = ' ';
  1032. break;
  1033. }
  1034. while (isspace((unsigned char) (*q))) {
  1035. *q = '\0';
  1036. if (q == p) {
  1037. break;
  1038. }
  1039. q--;
  1040. }
  1041. break;
  1042. }
  1043. c = *q;
  1044. q++;
  1045. }
  1046. if (q != p && !cont) {
  1047. if (*q == '\0') {
  1048. q--;
  1049. }
  1050. while (isspace((unsigned char) (*q))) {
  1051. *q = '\0';
  1052. if (q == p) {
  1053. break;
  1054. }
  1055. q--;
  1056. }
  1057. }
  1058. p = lblanks(p);
  1059. strncat(buf, p, sz - strlen(buf) - 1);
  1060. if (cont) {
  1061. continue;
  1062. }
  1063. if (buf[0] == '\0') {
  1064. continue;
  1065. }
  1066. i = 0;
  1067. q = buf;
  1068. while (*q) {
  1069. i++;
  1070. if (*q == '\n' || isspace((unsigned char) (*q))) {
  1071. break;
  1072. }
  1073. q++;
  1074. }
  1075. if (i >= 400) {
  1076. fprintf(stderr, "invalid rcfile line: %s/%s\n",
  1077. p, buf);
  1078. exit(1);
  1079. }
  1080. if (sscanf(buf, "%s", parm) != 1) {
  1081. fprintf(stderr, "invalid rcfile line: %s\n", p);
  1082. exit(1);
  1083. }
  1084. if (parm[0] == '-') {
  1085. strncpy(tmp, parm, 400);
  1086. } else {
  1087. tmp[0] = '-';
  1088. strncpy(tmp+1, parm, 400);
  1089. }
  1090. if (strstr(tmp, "-loop") == tmp) {
  1091. if (! getenv("X11VNC_LOOP_MODE")) {
  1092. check_loop_mode(argc, argv, 1);
  1093. exit(0);
  1094. }
  1095. }
  1096. argv2[argc2++] = strdup(tmp);
  1097. if (argc2 >= argmax) {
  1098. fprintf(stderr, "too many rcfile options\n");
  1099. exit(1);
  1100. }
  1101. p = buf;
  1102. p += strlen(parm);
  1103. p = lblanks(p);
  1104. if (*p == '\0') {
  1105. buf[0] = '\0';
  1106. continue;
  1107. }
  1108. tbuf = (char *) calloc(strlen(p) + 1, 1);
  1109. j = 0;
  1110. while (*p) {
  1111. if (*p == '\\' && *(p+1) == '#') {
  1112. ;
  1113. } else {
  1114. tbuf[j++] = *p;
  1115. }
  1116. p++;
  1117. }
  1118. argv2[argc2++] = strdup(tbuf);
  1119. free(tbuf);
  1120. if (argc2 >= argmax) {
  1121. fprintf(stderr, "too many rcfile options\n");
  1122. exit(1);
  1123. }
  1124. buf[0] = '\0';
  1125. }
  1126. fclose(rc);
  1127. free(buf);
  1128. }
  1129. pwlast = 0;
  1130. enclast = 0;
  1131. for (i=1; i < argc; i++) {
  1132. argv2[argc2++] = strdup(argv[i]);
  1133. if (pwlast || !strcmp("-passwd", argv[i])
  1134. || !strcmp("-viewpasswd", argv[i])) {
  1135. char *p = argv[i];
  1136. if (pwlast) {
  1137. pwlast = 0;
  1138. } else {
  1139. pwlast = 1;
  1140. }
  1141. strzero(p);
  1142. }
  1143. if (enclast || !strcmp("-enc", argv[i])) {
  1144. char *q, *p = argv[i];
  1145. if (enclast) {
  1146. enclast = 0;
  1147. } else {
  1148. enclast = 1;
  1149. }
  1150. q = strstr(p, "pw=");
  1151. if (q) {
  1152. strzero(q);
  1153. }
  1154. }
  1155. if (argc2 >= argmax) {
  1156. fprintf(stderr, "too many rcfile options\n");
  1157. exit(1);
  1158. }
  1159. }
  1160. }
  1161. static void immediate_switch_user(int argc, char* argv[]) {
  1162. int i, bequiet = 0;
  1163. for (i=1; i < argc; i++) {
  1164. if (strcmp(argv[i], "-inetd")) {
  1165. bequiet = 1;
  1166. }
  1167. if (strcmp(argv[i], "-quiet")) {
  1168. bequiet = 1;
  1169. }
  1170. if (strcmp(argv[i], "-q")) {
  1171. bequiet = 1;
  1172. }
  1173. }
  1174. for (i=1; i < argc; i++) {
  1175. char *u, *q;
  1176. if (strcmp(argv[i], "-users")) {
  1177. continue;
  1178. }
  1179. if (i == argc - 1) {
  1180. fprintf(stderr, "not enough arguments for: -users\n");
  1181. exit(1);
  1182. }
  1183. if (*(argv[i+1]) != '=') {
  1184. break;
  1185. }
  1186. /* wants an immediate switch: =bob */
  1187. u = strdup(argv[i+1]);
  1188. *u = '+';
  1189. q = strchr(u, '.');
  1190. if (q) {
  1191. user2group = (char **) malloc(2*sizeof(char *));
  1192. user2group[0] = strdup(u+1);
  1193. user2group[1] = NULL;
  1194. *q = '\0';
  1195. }
  1196. if (strstr(u, "+guess") == u) {
  1197. fprintf(stderr, "invalid user: %s\n", u+1);
  1198. exit(1);
  1199. }
  1200. if (!switch_user(u, 0)) {
  1201. fprintf(stderr, "Could not switch to user: %s\n", u+1);
  1202. exit(1);
  1203. } else {
  1204. if (!bequiet) {
  1205. fprintf(stderr, "Switched to user: %s\n", u+1);
  1206. }
  1207. started_as_root = 2;
  1208. }
  1209. free(u);
  1210. break;
  1211. }
  1212. }
  1213. static void quick_pw(char *str) {
  1214. char *p, *q;
  1215. char tmp[1024];
  1216. int db = 0;
  1217. if (db) fprintf(stderr, "quick_pw: %s\n", str);
  1218. if (! str || str[0] == '\0') {
  1219. exit(2);
  1220. }
  1221. if (str[0] != '%') {
  1222. exit(2);
  1223. }
  1224. /*
  1225. * "%-" or "%stdin" means read one line from stdin.
  1226. *
  1227. * "%env" means it is in $UNIXPW env var.
  1228. *
  1229. * starting "%/" or "%." means read the first line from that file.
  1230. *
  1231. * "%%" or "%" means prompt user.
  1232. *
  1233. * otherwise: %user:pass
  1234. */
  1235. if (!strcmp(str, "%-") || !strcmp(str, "%stdin")) {
  1236. if(fgets(tmp, 1024, stdin) == NULL) {
  1237. exit(2);
  1238. }
  1239. q = strdup(tmp);
  1240. } else if (!strcmp(str, "%env")) {
  1241. if (getenv("UNIXPW") == NULL) {
  1242. exit(2);
  1243. }
  1244. q = strdup(getenv("UNIXPW"));
  1245. } else if (!strcmp(str, "%%") || !strcmp(str, "%")) {
  1246. char *t, inp[1024];
  1247. fprintf(stdout, "username: ");
  1248. if(fgets(tmp, 128, stdin) == NULL) {
  1249. exit(2);
  1250. }
  1251. strcpy(inp, tmp);
  1252. t = strchr(inp, '\n');
  1253. if (t) {
  1254. *t = ':';
  1255. } else {
  1256. strcat(inp, ":");
  1257. }
  1258. fprintf(stdout, "password: ");
  1259. /* test mode: no_external_cmds does not apply */
  1260. system("stty -echo");
  1261. if(fgets(tmp, 128, stdin) == NULL) {
  1262. fprintf(stdout, "\n");
  1263. system("stty echo");
  1264. exit(2);
  1265. }
  1266. system("stty echo");
  1267. fprintf(stdout, "\n");
  1268. strcat(inp, tmp);
  1269. q = strdup(inp);
  1270. } else if (str[1] == '/' || str[1] == '.') {
  1271. FILE *in = fopen(str+1, "r");
  1272. if (in == NULL) {
  1273. exit(2);
  1274. }
  1275. if(fgets(tmp, 1024, in) == NULL) {
  1276. exit(2);
  1277. }
  1278. fclose(in);
  1279. q = strdup(tmp);
  1280. } else {
  1281. q = strdup(str+1);
  1282. }
  1283. p = (char *) malloc(strlen(q) + 10);
  1284. strcpy(p, q);
  1285. if (strchr(p, '\n') == NULL) {
  1286. strcat(p, "\n");
  1287. }
  1288. if ((q = strchr(p, ':')) == NULL) {
  1289. exit(2);
  1290. }
  1291. *q = '\0';
  1292. if (db) fprintf(stderr, "'%s' '%s'\n", p, q+1);
  1293. if (unixpw_cmd) {
  1294. if (cmd_verify(p, q+1)) {
  1295. fprintf(stdout, "Y %s\n", p);
  1296. exit(0);
  1297. } else {
  1298. fprintf(stdout, "N %s\n", p);
  1299. exit(1);
  1300. }
  1301. } else if (unixpw_nis) {
  1302. if (crypt_verify(p, q+1)) {
  1303. fprintf(stdout, "Y %s\n", p);
  1304. exit(0);
  1305. } else {
  1306. fprintf(stdout, "N %s\n", p);
  1307. exit(1);
  1308. }
  1309. } else {
  1310. char *ucmd = getenv("UNIXPW_CMD");
  1311. if (su_verify(p, q+1, ucmd, NULL, NULL, 1)) {
  1312. fprintf(stdout, "Y %s\n", p);
  1313. exit(0);
  1314. } else {
  1315. fprintf(stdout, "N %s\n", p);
  1316. exit(1);
  1317. }
  1318. }
  1319. /* NOTREACHED */
  1320. exit(2);
  1321. }
  1322. static void print_settings(int try_http, int bg, char *gui_str) {
  1323. fprintf(stderr, "\n");
  1324. fprintf(stderr, "Settings:\n");
  1325. fprintf(stderr, " display: %s\n", use_dpy ? use_dpy
  1326. : "null");
  1327. #if SMALL_FOOTPRINT < 2
  1328. fprintf(stderr, " authfile: %s\n", auth_file ? auth_file
  1329. : "null");
  1330. fprintf(stderr, " subwin: 0x%lx\n", subwin);
  1331. fprintf(stderr, " -sid mode: %d\n", rootshift);
  1332. fprintf(stderr, " clip: %s\n", clip_str ? clip_str
  1333. : "null");
  1334. fprintf(stderr, " flashcmap: %d\n", flash_cmap);
  1335. fprintf(stderr, " shiftcmap: %d\n", shift_cmap);
  1336. fprintf(stderr, " force_idx: %d\n", force_indexed_color);
  1337. fprintf(stderr, " cmap8to24: %d\n", cmap8to24);
  1338. fprintf(stderr, " 8to24_opts: %s\n", cmap8to24_str ? cmap8to24_str
  1339. : "null");
  1340. fprintf(stderr, " 24to32: %d\n", xform24to32);
  1341. fprintf(stderr, " visual: %s\n", visual_str ? visual_str
  1342. : "null");
  1343. fprintf(stderr, " overlay: %d\n", overlay);
  1344. fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor);
  1345. fprintf(stderr, " scaling: %d %.4f %.4f\n", scaling, scale_fac_x, scale_fac_y);
  1346. fprintf(stderr, " viewonly: %d\n", view_only);
  1347. fprintf(stderr, " shared: %d\n", shared);
  1348. fprintf(stderr, " conn_once: %d\n", connect_once);
  1349. fprintf(stderr, " timeout: %d\n", first_conn_timeout);
  1350. fprintf(stderr, " ping: %d\n", ping_interval);
  1351. fprintf(stderr, " inetd: %d\n", inetd);
  1352. fprintf(stderr, " tightfilexfer: %d\n", tightfilexfer);
  1353. fprintf(stderr, " http: %d\n", try_http);
  1354. fprintf(stderr, " connect: %s\n", client_connect
  1355. ? client_connect : "null");
  1356. fprintf(stderr, " connectfile %s\n", client_connect_file
  1357. ? client_connect_file : "null");
  1358. fprintf(stderr, " vnc_conn: %d\n", vnc_connect);
  1359. fprintf(stderr, " allow: %s\n", allow_list ? allow_list
  1360. : "null");
  1361. fprintf(stderr, " input: %s\n", allowed_input_str
  1362. ? allowed_input_str : "null");
  1363. fprintf(stderr, " passfile: %s\n", passwdfile ? passwdfile
  1364. : "null");
  1365. fprintf(stderr, " unixpw: %d\n", unixpw);
  1366. fprintf(stderr, " unixpw_lst: %s\n", unixpw_list ? unixpw_list:"null");
  1367. fprintf(stderr, " ssl: %s\n", openssl_pem ? openssl_pem:"null");
  1368. fprintf(stderr, " ssldir: %s\n", ssl_certs_dir ? ssl_certs_dir:"null");
  1369. fprintf(stderr, " ssltimeout %d\n", ssl_timeout_secs);
  1370. fprintf(stderr, " sslverify: %s\n", ssl_verify ? ssl_verify:"null");
  1371. fprintf(stderr, " stunnel: %d\n", use_stunnel);
  1372. fprintf(stderr, " accept: %s\n", accept_cmd ? accept_cmd
  1373. : "null");
  1374. fprintf(stderr, " accept: %s\n", afteraccept_cmd ? afteraccept_cmd
  1375. : "null");
  1376. fprintf(stderr, " gone: %s\n", gone_cmd ? gone_cmd
  1377. : "null");
  1378. fprintf(stderr, " users: %s\n", users_list ? users_list
  1379. : "null");
  1380. fprintf(stderr, " using_shm: %d\n", using_shm);
  1381. fprintf(stderr, " flipbytes: %d\n", flip_byte_order);
  1382. fprintf(stderr, " onetile: %d\n", single_copytile);
  1383. fprintf(stderr, " solid: %s\n", solid_str
  1384. ? solid_str : "null");
  1385. fprintf(stderr, " blackout: %s\n", blackout_str
  1386. ? blackout_str : "null");
  1387. fprintf(stderr, " xinerama: %d\n", xinerama);
  1388. fprintf(stderr, " xtrap: %d\n", xtrap_input);
  1389. fprintf(stderr, " xrandr: %d\n", xrandr);
  1390. fprintf(stderr, " xrandrmode: %s\n", xrandr_mode ? xrandr_mode
  1391. : "null");
  1392. fprintf(stderr, " padgeom: %s\n", pad_geometry
  1393. ? pad_geometry : "null");
  1394. fprintf(stderr, " logfile: %s\n", logfile ? logfile
  1395. : "null");
  1396. fprintf(stderr, " logappend: %d\n", logfile_append);
  1397. fprintf(stderr, " flag: %s\n", flagfile ? flagfile
  1398. : "null");
  1399. fprintf(stderr, " rm_flag: %s\n", rm_flagfile ? rm_flagfile
  1400. : "null");
  1401. fprintf(stderr, " rc_file: \"%s\"\n", rc_rcfile ? rc_rcfile
  1402. : "null");
  1403. fprintf(stderr, " norc: %d\n", rc_norc);
  1404. fprintf(stderr, " dbg: %d\n", crash_debug);
  1405. fprintf(stderr, " bg: %d\n", bg);
  1406. fprintf(stderr, " mod_tweak: %d\n", use_modifier_tweak);
  1407. fprintf(stderr, " isolevel3: %d\n", use_iso_level3);
  1408. fprintf(stderr, " xkb: %d\n", use_xkb_modtweak);
  1409. fprintf(stderr, " skipkeys: %s\n",
  1410. skip_keycodes ? skip_keycodes : "null");
  1411. fprintf(stderr, " sloppykeys: %d\n", sloppy_keys);
  1412. fprintf(stderr, " skip_dups: %d\n", skip_duplicate_key_events);
  1413. fprintf(stderr, " addkeysyms: %d\n", add_keysyms);
  1414. fprintf(stderr, " xkbcompat: %d\n", xkbcompat);
  1415. fprintf(stderr, " clearmods: %d\n", clear_mods);
  1416. fprintf(stderr, " remap: %s\n", remap_file ? remap_file
  1417. : "null");
  1418. fprintf(stderr, " norepeat: %d\n", no_autorepeat);
  1419. fprintf(stderr, " norepeatcnt:%d\n", no_repeat_countdown);
  1420. fprintf(stderr, " nofb: %d\n", nofb);
  1421. fprintf(stderr, " watchbell: %d\n", watch_bell);
  1422. fprintf(stderr, " watchsel: %d\n", watch_selection);
  1423. fprintf(stderr, " watchprim: %d\n", watch_primary);
  1424. fprintf(stderr, " seldir: %s\n", sel_direction ?
  1425. sel_direction : "null");
  1426. fprintf(stderr, " cursor: %d\n", show_cursor);
  1427. fprintf(stderr, " multicurs: %d\n", show_multiple_cursors);
  1428. fprintf(stderr, " curs_mode: %s\n", multiple_cursors_mode
  1429. ? multiple_cursors_mode : "null");
  1430. fprintf(stderr, " arrow: %d\n", alt_arrow);
  1431. fprintf(stderr, " xfixes: %d\n", use_xfixes);
  1432. fprintf(stderr, " alphacut: %d\n", alpha_threshold);
  1433. fprintf(stderr, " alphafrac: %.2f\n", alpha_frac);
  1434. fprintf(stderr, " alpharemove:%d\n", alpha_remove);
  1435. fprintf(stderr, " alphablend: %d\n", alpha_blend);
  1436. fprintf(stderr, " cursorshape:%d\n", cursor_shape_updates);
  1437. fprintf(stderr, " cursorpos: %d\n", cursor_pos_updates);
  1438. fprintf(stderr, " xwarpptr: %d\n", use_xwarppointer);
  1439. fprintf(stderr, " alwaysinj: %d\n", always_inject);
  1440. fprintf(stderr, " buttonmap: %s\n", pointer_remap
  1441. ? pointer_remap : "null");
  1442. fprintf(stderr, " dragging: %d\n", show_dragging);
  1443. fprintf(stderr, " ncache: %d\n", ncache);
  1444. fprintf(stderr, " wireframe: %s\n", wireframe_str ?
  1445. wireframe_str : WIREFRAME_PARMS);
  1446. fprintf(stderr, " wirecopy: %s\n", wireframe_copyrect ?
  1447. wireframe_copyrect : wireframe_copyrect_default);
  1448. fprintf(stderr, " scrollcopy: %s\n", scroll_copyrect ?
  1449. scroll_copyrect : scroll_copyrect_default);
  1450. fprintf(stderr, " scr_area: %d\n", scrollcopyrect_min_area);
  1451. fprintf(stderr, " scr_skip: %s\n", scroll_skip_str ?
  1452. scroll_skip_str : scroll_skip_str0);
  1453. fprintf(stderr, " scr_inc: %s\n", scroll_good_str ?
  1454. scroll_good_str : scroll_good_str0);
  1455. fprintf(stderr, " scr_keys: %s\n", scroll_key_list_str ?
  1456. scroll_key_list_str : "null");
  1457. fprintf(stderr, " scr_term: %s\n", scroll_term_str ?
  1458. scroll_term_str : "null");
  1459. fprintf(stderr, " scr_keyrep: %s\n", max_keyrepeat_str ?
  1460. max_keyrepeat_str : "null");
  1461. fprintf(stderr, " scr_parms: %s\n", scroll_copyrect_str ?
  1462. scroll_copyrect_str : SCROLL_COPYRECT_PARMS);
  1463. fprintf(stderr, " fixscreen: %s\n", screen_fixup_str ?
  1464. screen_fixup_str : "null");
  1465. fprintf(stderr, " noxrecord: %d\n", noxrecord);
  1466. fprintf(stderr, " grabbuster: %d\n", grab_buster);
  1467. fprintf(stderr, " ptr_mode: %d\n", pointer_mode);
  1468. fprintf(stderr, " inputskip: %d\n", ui_skip);
  1469. fprintf(stderr, " speeds: %s\n", speeds_str
  1470. ? speeds_str : "null");
  1471. fprintf(stderr, " wmdt: %s\n", wmdt_str
  1472. ? wmdt_str : "null");
  1473. fprintf(stderr, " debug_ptr: %d\n", debug_pointer);
  1474. fprintf(stderr, " debug_key: %d\n", debug_keyboard);
  1475. fprintf(stderr, " defer: %d\n", defer_update);
  1476. fprintf(stderr, " waitms: %d\n", waitms);
  1477. fprintf(stderr, " wait_ui: %.2f\n", wait_ui);
  1478. fprintf(stderr, " nowait_bog: %d\n", !wait_bog);
  1479. fprintf(stderr, " slow_fb: %.2f\n", slow_fb);
  1480. fprintf(stderr, " xrefresh: %.2f\n", xrefresh);
  1481. fprintf(stderr, " readtimeout: %d\n", rfbMaxClientWait/1000);
  1482. fprintf(stderr, " take_naps: %d\n", take_naps);
  1483. fprintf(stderr, " sb: %d\n", screen_blank);
  1484. fprintf(stderr, " fbpm: %d\n", !watch_fbpm);
  1485. fprintf(stderr, " dpms: %d\n", !watch_dpms);
  1486. fprintf(stderr, " xdamage: %d\n", use_xdamage);
  1487. fprintf(stderr, " xd_area: %d\n", xdamage_max_area);
  1488. fprintf(stderr, " xd_mem: %.3f\n", xdamage_memory);
  1489. fprintf(stderr, " sigpipe: %s\n", sigpipe
  1490. ? sigpipe : "null");
  1491. fprintf(stderr, " threads: %d\n", use_threads);
  1492. fprintf(stderr, " fs_frac: %.2f\n", fs_frac);
  1493. fprintf(stderr, " gaps_fill: %d\n", gaps_fill);
  1494. fprintf(stderr, " grow_fill: %d\n", grow_fill);
  1495. fprintf(stderr, " tile_fuzz: %d\n", tile_fuzz);
  1496. fprintf(stderr, " snapfb: %d\n", use_snapfb);
  1497. fprintf(stderr, " rawfb: %s\n", raw_fb_str
  1498. ? raw_fb_str : "null");
  1499. fprintf(stderr, " pipeinput: %s\n", pipeinput_str
  1500. ? pipeinput_str : "null");
  1501. fprintf(stderr, " gui: %d\n", launch_gui);
  1502. fprintf(stderr, " gui_mode: %s\n", gui_str
  1503. ? gui_str : "null");
  1504. fprintf(stderr, " noremote: %d\n", !accept_remote_cmds);
  1505. fprintf(stderr, " unsafe: %d\n", !safe_remote_only);
  1506. fprintf(stderr, " privremote: %d\n", priv_remote);
  1507. fprintf(stderr, " safer: %d\n", more_safe);
  1508. fprintf(stderr, " nocmds: %d\n", no_external_cmds);
  1509. fprintf(stderr, " deny_all: %d\n", deny_all);
  1510. fprintf(stderr, " pid: %d\n", getpid());
  1511. fprintf(stderr, "\n");
  1512. #endif
  1513. }
  1514. static void check_loop_mode(int argc, char* argv[], int force) {
  1515. int i;
  1516. int loop_mode = 0, loop_sleep = 2000, loop_max = 0;
  1517. if (force) {
  1518. loop_mode = 1;
  1519. }
  1520. for (i=1; i < argc; i++) {
  1521. char *p = argv[i];
  1522. if (strstr(p, "--") == p) {
  1523. p++;
  1524. }
  1525. if (strstr(p, "-loop") == p) {
  1526. char *q;
  1527. loop_mode = 1;
  1528. if ((q = strchr(p, ',')) != NULL) {
  1529. loop_max = atoi(q+1);
  1530. *q = '\0';
  1531. }
  1532. if (strstr(p, "-loopbg") == p) {
  1533. set_env("X11VNC_LOOP_MODE_BG", "1");
  1534. loop_sleep = 500;
  1535. }
  1536. q = strpbrk(p, "0123456789");
  1537. if (q) {
  1538. loop_sleep = atoi(q);
  1539. if (loop_sleep <= 0) {
  1540. loop_sleep = 20;
  1541. }
  1542. }
  1543. }
  1544. }
  1545. if (loop_mode && getenv("X11VNC_LOOP_MODE") == NULL) {
  1546. #if LIBVNCSERVER_HAVE_FORK
  1547. char **argv2;
  1548. int k, i = 1;
  1549. set_env("X11VNC_LOOP_MODE", "1");
  1550. argv2 = (char **) malloc((argc+1)*sizeof(char *));
  1551. for (k=0; k < argc+1; k++) {
  1552. argv2[k] = NULL;
  1553. if (k < argc) {
  1554. argv2[k] = argv[k];
  1555. }
  1556. }
  1557. while (1) {
  1558. int status;
  1559. pid_t p;
  1560. fprintf(stderr, "\n --- x11vnc loop: %d ---\n\n", i++);
  1561. fflush(stderr);
  1562. usleep(500 * 1000);
  1563. if ((p = fork()) > 0) {
  1564. fprintf(stderr, " --- x11vnc loop: waiting "
  1565. "for: %d\n\n", p);
  1566. wait(&status);
  1567. } else if (p == -1) {
  1568. fprintf(stderr, "could not fork\n");
  1569. perror("fork");
  1570. exit(1);
  1571. } else {
  1572. /* loop mode: no_external_cmds does not apply */
  1573. execvp(argv[0], argv2);
  1574. exit(1);
  1575. }
  1576. if (loop_max > 0 && i > loop_max) {
  1577. fprintf(stderr, "\n --- x11vnc loop: did %d"
  1578. " done. ---\n\n", loop_max);
  1579. break;
  1580. }
  1581. fprintf(stderr, "\n --- x11vnc loop: sleeping %d ms "
  1582. "---\n\n", loop_sleep);
  1583. usleep(loop_sleep * 1000);
  1584. }
  1585. exit(0);
  1586. #else
  1587. fprintf(stderr, "fork unavailable, cannot do -loop mode\n");
  1588. exit(1);
  1589. #endif
  1590. }
  1591. }
  1592. extern int appshare_main(int argc, char* argv[]);
  1593. static void check_appshare_mode(int argc, char* argv[]) {
  1594. #ifndef WIN32
  1595. int i;
  1596. for (i=1; i < argc; i++) {
  1597. char *p = argv[i];
  1598. if (strstr(p, "--") == p) {
  1599. p++;
  1600. }
  1601. if (strstr(p, "-appshare") == p) {
  1602. appshare_main(argc, argv);
  1603. exit(0);
  1604. }
  1605. }
  1606. #endif
  1607. }
  1608. static void store_homedir_passwd(char *file) {
  1609. #ifndef WIN32
  1610. char str1[32], str2[32], *p, *h, *f;
  1611. struct stat sbuf;
  1612. str1[0] = '\0';
  1613. str2[0] = '\0';
  1614. /* storepasswd */
  1615. if (no_external_cmds || !cmd_ok("storepasswd")) {
  1616. fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
  1617. exit(1);
  1618. }
  1619. fprintf(stderr, "Enter VNC password: ");
  1620. system("stty -echo");
  1621. if (fgets(str1, 32, stdin) == NULL) {
  1622. perror("fgets");
  1623. system("stty echo");
  1624. exit(1);
  1625. }
  1626. fprintf(stderr, "\n");
  1627. fprintf(stderr, "Verify password: ");
  1628. if (fgets(str2, 32, stdin) == NULL) {
  1629. perror("fgets");
  1630. system("stty echo");
  1631. exit(1);
  1632. }
  1633. fprintf(stderr, "\n");
  1634. system("stty echo");
  1635. if ((p = strchr(str1, '\n')) != NULL) {
  1636. *p = '\0';
  1637. }
  1638. if ((p = strchr(str2, '\n')) != NULL) {
  1639. *p = '\0';
  1640. }
  1641. if (strcmp(str1, str2)) {
  1642. fprintf(stderr, "** passwords differ.\n");
  1643. exit(1);
  1644. }
  1645. if (str1[0] == '\0') {
  1646. fprintf(stderr, "** no password supplied.\n");
  1647. exit(1);
  1648. }
  1649. if (file != NULL) {
  1650. f = file;
  1651. } else {
  1652. h = getenv("HOME");
  1653. if (! h) {
  1654. fprintf(stderr, "** $HOME not set.\n");
  1655. exit(1);
  1656. }
  1657. f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1);
  1658. sprintf(f, "%s/.vnc", h);
  1659. if (stat(f, &sbuf) != 0) {
  1660. if (mkdir(f, 0755) != 0) {
  1661. fprintf(stderr, "** could not create directory %s\n", f);
  1662. perror("mkdir");
  1663. exit(1);
  1664. }
  1665. } else if (! S_ISDIR(sbuf.st_mode)) {
  1666. fprintf(stderr, "** not a directory %s\n", f);
  1667. exit(1);
  1668. }
  1669. sprintf(f, "%s/.vnc/passwd", h);
  1670. }
  1671. fprintf(stderr, "Write password to %s? [y]/n ", f);
  1672. if (fgets(str2, 32, stdin) == NULL) {
  1673. perror("fgets");
  1674. exit(1);
  1675. }
  1676. if (str2[0] == 'n' || str2[0] == 'N') {
  1677. fprintf(stderr, "not creating password.\n");
  1678. exit(1);
  1679. }
  1680. if (rfbEncryptAndStorePasswd(str1, f) != 0) {
  1681. fprintf(stderr, "** error creating password: %s\n", f);
  1682. perror("storepasswd");
  1683. exit(1);
  1684. }
  1685. if (stat(f, &sbuf) != 0) {
  1686. fprintf(stderr, "** error creating password: %s\n", f);
  1687. perror("stat");
  1688. exit(1);
  1689. }
  1690. fprintf(stdout, "Password written to: %s\n", f);
  1691. exit(0);
  1692. #endif
  1693. }
  1694. void ncache_beta_tester_message(void) {
  1695. char msg[] =
  1696. "\n"
  1697. "******************************************************************************\n"
  1698. "\n"
  1699. "Hello! Exciting News!!\n"
  1700. "\n"
  1701. "You have been selected at random to beta-test the x11vnc '-ncache' VNC\n"
  1702. "client-side pixel caching feature!\n"
  1703. "\n"
  1704. "This scheme stores pixel data offscreen on the VNC viewer side for faster\n"
  1705. "retrieval. It should work with any VNC viewer.\n"
  1706. "\n"
  1707. "This method requires much testing and so we hope you will try it out and\n"
  1708. "perhaps even report back your observations. However, if you do not want\n"
  1709. "to test or use the feature, run x11vnc like this:\n"
  1710. "\n"
  1711. " x11vnc -noncache ...\n"
  1712. "\n"
  1713. "Your current setting is: -ncache %d\n"
  1714. "\n"
  1715. "The feature needs additional testing because we want to have x11vnc\n"
  1716. "performance enhancements on by default. Otherwise, only a relative few\n"
  1717. "would notice and use the -ncache option (e.g. the wireframe and scroll\n"
  1718. "detection features are on by default). A couple things to note:\n"
  1719. "\n"
  1720. " 1) It uses a large amount of RAM (on both viewer and server sides)\n"
  1721. "\n"
  1722. " 2) You can actually see the cached pixel data if you scroll down\n"
  1723. " to it in your viewer; adjust your viewer's size to hide it.\n"
  1724. "\n"
  1725. "More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching\n"
  1726. "\n"
  1727. "waiting for connections:\n"
  1728. ;
  1729. char msg2[] =
  1730. "\n"
  1731. "******************************************************************************\n"
  1732. "Have you tried the x11vnc '-ncache' VNC client-side pixel caching feature yet?\n"
  1733. "\n"
  1734. "The scheme stores pixel data offscreen on the VNC viewer side for faster\n"
  1735. "retrieval. It should work with any VNC viewer. Try it by running:\n"
  1736. "\n"
  1737. " x11vnc -ncache 10 ...\n"
  1738. "\n"
  1739. "One can also add -ncache_cr for smooth 'copyrect' window motion.\n"
  1740. "More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching\n"
  1741. "\n"
  1742. ;
  1743. if (raw_fb_str && !macosx_console) {
  1744. return;
  1745. }
  1746. if (quiet) {
  1747. return;
  1748. }
  1749. if (remote_direct) {
  1750. return;
  1751. }
  1752. if (nofb) {
  1753. return;
  1754. }
  1755. #ifdef NO_NCACHE
  1756. return;
  1757. #endif
  1758. if (ncache == 0) {
  1759. fprintf(stderr, "%s", msg2);
  1760. ncache0 = ncache = 0;
  1761. } else {
  1762. fprintf(stderr, msg, ncache);
  1763. }
  1764. }
  1765. #define SHOW_NO_PASSWORD_WARNING \
  1766. (!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
  1767. && !query_cmd && !remote_cmd && !unixpw && !got_gui_pw \
  1768. && ! ssl_verify && !inetd && !terminal_services_daemon)
  1769. static void do_sleepin(char *sleep) {
  1770. int n1, n2, nt;
  1771. double f1, f2, ft;
  1772. if (strchr(sleep, '-')) {
  1773. double s = atof(strchr(sleep, '-')+1);
  1774. if (sscanf(sleep, "%d-%d", &n1, &n2) == 2) {
  1775. if (n1 > n2) {
  1776. nt = n1;
  1777. n1 = n2;
  1778. n2 = nt;
  1779. }
  1780. s = n1 + rfac() * (n2 - n1);
  1781. } else if (sscanf(sleep, "%lf-%lf", &f1, &f2) == 2) {
  1782. if (f1 > f2) {
  1783. ft = f1;
  1784. f1 = f2;
  1785. f2 = ft;
  1786. }
  1787. s = f1 + rfac() * (f2 - f1);
  1788. }
  1789. if (getenv("DEBUG_SLEEPIN")) fprintf(stderr, "sleepin: %f secs\n", s);
  1790. usleep( (int) (1000*1000*s) );
  1791. } else {
  1792. n1 = atoi(sleep);
  1793. if (getenv("DEBUG_SLEEPIN")) fprintf(stderr, "sleepin: %d secs\n", n1);
  1794. if (n1 > 0) {
  1795. usleep(1000*1000*n1);
  1796. }
  1797. }
  1798. }
  1799. static void check_guess_auth_file(void) {
  1800. if (!strcasecmp(auth_file, "guess")) {
  1801. char line[4096], *cmd, *q, *disp = use_dpy ? use_dpy: "";
  1802. FILE *p;
  1803. int n;
  1804. if (!program_name) {
  1805. rfbLog("-auth guess: no program_name found.\n");
  1806. clean_up_exit(1);
  1807. }
  1808. if (strpbrk(program_name, " \t\r\n")) {
  1809. rfbLog("-auth guess: whitespace in program_name '%s'\n", program_name);
  1810. clean_up_exit(1);
  1811. }
  1812. if (no_external_cmds || !cmd_ok("findauth")) {
  1813. rfbLog("-auth guess: cannot run external commands in -nocmds mode:\n");
  1814. clean_up_exit(1);
  1815. }
  1816. cmd = (char *)malloc(100 + strlen(program_name) + strlen(disp));
  1817. sprintf(cmd, "%s -findauth %s -env _D_XDM=1", program_name, disp);
  1818. p = popen(cmd, "r");
  1819. if (!p) {
  1820. rfbLog("-auth guess: could not run cmd '%s'\n", cmd);
  1821. clean_up_exit(1);
  1822. }
  1823. memset(line, 0, sizeof(line));
  1824. n = fread(line, 1, sizeof(line), p);
  1825. pclose(p);
  1826. q = strrchr(line, '\n');
  1827. if (q) *q = '\0';
  1828. if (!strcmp(disp, "")) {
  1829. disp = getenv("DISPLAY");
  1830. if (!disp) {
  1831. disp = "unset";
  1832. }
  1833. }
  1834. if (strstr(line, "XAUTHORITY=") != line && !getenv("FD_XDM")) {
  1835. if (use_dpy == NULL || strstr(use_dpy, "cmd=FIND") == NULL) {
  1836. if (getuid() == 0 || geteuid() == 0) {
  1837. char *q = strstr(cmd, "_D_XDM=1");
  1838. if (q) {
  1839. *q = 'F';
  1840. rfbLog("-auth guess: failed for display='%s'\n", disp);
  1841. rfbLog("-auth guess: since we are root, retrying with FD_XDM=1\n");
  1842. p = popen(cmd, "r");
  1843. if (!p) {
  1844. rfbLog("-auth guess: could not run cmd '%s'\n", cmd);
  1845. clean_up_exit(1);
  1846. }
  1847. memset(line, 0, sizeof(line));
  1848. n = fread(line, 1, sizeof(line), p);
  1849. pclose(p);
  1850. q = strrchr(line, '\n');
  1851. if (q) *q = '\0';
  1852. }
  1853. }
  1854. }
  1855. }
  1856. if (!strcmp(line, "")) {
  1857. rfbLog("-auth guess: failed for display='%s'\n", disp);
  1858. clean_up_exit(1);
  1859. } else if (strstr(line, "XAUTHORITY=") != line) {
  1860. rfbLog("-auth guess: failed. '%s' for display='%s'\n", line, disp);
  1861. clean_up_exit(1);
  1862. } else if (!strcmp(line, "XAUTHORITY=")) {
  1863. rfbLog("-auth guess: using default XAUTHORITY for display='%s'\n", disp);
  1864. q = getenv("XAUTHORITY");
  1865. if (q) {
  1866. *(q-2) = '_'; /* yow */
  1867. }
  1868. auth_file = NULL;
  1869. } else {
  1870. rfbLog("-auth guess: using '%s' for disp='%s'\n", line, disp);
  1871. auth_file = strdup(line + strlen("XAUTHORITY="));
  1872. }
  1873. }
  1874. }
  1875. extern int is_decimal(char *);
  1876. int main(int argc, char* argv[]) {
  1877. int i, len, tmpi;
  1878. int ev, er, maj, min;
  1879. char *arg;
  1880. int remote_sync = 0;
  1881. char *remote_cmd = NULL;
  1882. char *query_cmd = NULL;
  1883. int query_retries = 0;
  1884. double query_delay = 0.5;
  1885. char *query_match = NULL;
  1886. char *gui_str = NULL;
  1887. int got_gui_pw = 0;
  1888. int pw_loc = -1, got_passwd = 0, got_rfbauth = 0, nopw = NOPW;
  1889. int got_viewpasswd = 0, got_localhost = 0, got_passwdfile = 0;
  1890. int vpw_loc = -1;
  1891. int dt = 0, bg = 0;
  1892. int got_rfbwait = 0;
  1893. int got_httpdir = 0, try_http = 0;
  1894. int orig_use_xdamage = use_xdamage;
  1895. int http_oneport_msg = 0;
  1896. XImage *fb0 = NULL;
  1897. int ncache_msg = 0;
  1898. char *got_rfbport_str = NULL;
  1899. int got_rfbport_pos = -1;
  1900. int got_tls = 0;
  1901. int got_inetd = 0;
  1902. int got_noxrandr = 0;
  1903. /* used to pass args we do not know about to rfbGetScreen(): */
  1904. int argc_vnc_max = 1024;
  1905. int argc_vnc = 1; char *argv_vnc[2048];
  1906. /* check for -loop mode: */
  1907. check_loop_mode(argc, argv, 0);
  1908. /* check for -appshare mode: */
  1909. check_appshare_mode(argc, argv);
  1910. dtime0(&x11vnc_start);
  1911. for (i=1; i < argc; i++) {
  1912. if (!strcmp(argv[i], "-inetd")) {
  1913. got_inetd = 1;
  1914. }
  1915. }
  1916. if (!getuid() || !geteuid()) {
  1917. started_as_root = 1;
  1918. if (0 && !got_inetd) {
  1919. rfbLog("getuid: %d geteuid: %d\n", getuid(), geteuid());
  1920. }
  1921. /* check for '-users =bob' */
  1922. immediate_switch_user(argc, argv);
  1923. }
  1924. for (i=0; i < 2048; i++) {
  1925. argv_vnc[i] = NULL;
  1926. }
  1927. argv_vnc[0] = strdup(argv[0]);
  1928. program_name = strdup(argv[0]);
  1929. program_pid = (int) getpid();
  1930. solid_default = strdup(solid_default); /* for freeing with -R */
  1931. len = 0;
  1932. for (i=1; i < argc; i++) {
  1933. len += strlen(argv[i]) + 4 + 1;
  1934. }
  1935. program_cmdline = (char *) malloc(len+1);
  1936. program_cmdline[0] = '\0';
  1937. for (i=1; i < argc; i++) {
  1938. char *s = argv[i];
  1939. if (program_cmdline[0]) {
  1940. strcat(program_cmdline, " ");
  1941. }
  1942. if (*s == '-') {
  1943. strcat(program_cmdline, s);
  1944. } else {
  1945. strcat(program_cmdline, "{{");
  1946. strcat(program_cmdline, s);
  1947. strcat(program_cmdline, "}}");
  1948. }
  1949. }
  1950. for (i=0; i<ICON_MODE_SOCKS; i++) {
  1951. icon_mode_socks[i] = -1;
  1952. }
  1953. check_rcfile(argc, argv);
  1954. /* kludge for the new array argv2 set in check_rcfile() */
  1955. # define argc argc2
  1956. # define argv argv2
  1957. # define CHECK_ARGC if (i >= argc-1) { \
  1958. fprintf(stderr, "not enough arguments for: %s\n", arg); \
  1959. exit(1); \
  1960. }
  1961. /*
  1962. * do a quick check for parameters that apply to "utility"
  1963. * commands, i.e. ones that do not run the server.
  1964. */
  1965. for (i=1; i < argc; i++) {
  1966. arg = argv[i];
  1967. if (strstr(arg, "--") == arg) {
  1968. arg++;
  1969. }
  1970. if (!strcmp(arg, "-ssldir")) {
  1971. CHECK_ARGC
  1972. ssl_certs_dir = strdup(argv[++i]);
  1973. }
  1974. }
  1975. /*
  1976. * do a quick check for -env parameters
  1977. */
  1978. for (i=1; i < argc; i++) {
  1979. char *p, *q;
  1980. arg = argv[i];
  1981. if (strstr(arg, "--") == arg) {
  1982. arg++;
  1983. }
  1984. if (!strcmp(arg, "-env")) {
  1985. CHECK_ARGC
  1986. p = strdup(argv[++i]);
  1987. q = strchr(p, '=');
  1988. if (! q) {
  1989. fprintf(stderr, "no -env '=' found: %s\n", p);
  1990. exit(1);
  1991. } else {
  1992. *q = '\0';
  1993. }
  1994. set_env(p, q+1);
  1995. free(p);
  1996. }
  1997. }
  1998. for (i=1; i < argc; i++) {
  1999. /* quick-n-dirty --option handling. */
  2000. arg = argv[i];
  2001. if (strstr(arg, "--") == arg) {
  2002. arg++;
  2003. }
  2004. if (!strcmp(arg, "-display")) {
  2005. CHECK_ARGC
  2006. use_dpy = strdup(argv[++i]);
  2007. if (strstr(use_dpy, "WAIT")) {
  2008. extern char find_display[];
  2009. extern char create_display[];
  2010. if (strstr(use_dpy, "cmd=FINDDISPLAY-print")) {
  2011. fprintf(stdout, "%s", find_display);
  2012. exit(0);
  2013. }
  2014. if (strstr(use_dpy, "cmd=FINDCREATEDISPLAY-print")) {
  2015. fprintf(stdout, "%s", create_display);
  2016. exit(0);
  2017. }
  2018. }
  2019. continue;
  2020. }
  2021. if (!strcmp(arg, "-reopen")) {
  2022. char *str = getenv("X11VNC_REOPEN_DISPLAY");
  2023. if (str) {
  2024. int rmax = atoi(str);
  2025. if (rmax > 0) {
  2026. set_env("X11VNC_REOPEN_DISPLAY", str);
  2027. }
  2028. } else {
  2029. set_env("X11VNC_REOPEN_DISPLAY", "1");
  2030. }
  2031. continue;
  2032. }
  2033. if (!strcmp(arg, "-find")) {
  2034. use_dpy = strdup("WAIT:cmd=FINDDISPLAY");
  2035. continue;
  2036. }
  2037. if (!strcmp(arg, "-finddpy") || strstr(arg, "-listdpy") == arg) {
  2038. int ic = 0;
  2039. use_dpy = strdup("WAIT:cmd=FINDDISPLAY-run");
  2040. if (argc > i+1) {
  2041. set_env("X11VNC_USER", argv[i+1]);
  2042. fprintf(stdout, "X11VNC_USER=%s\n", getenv("X11VNC_USER"));
  2043. }
  2044. if (strstr(arg, "-listdpy") == arg) {
  2045. set_env("FIND_DISPLAY_ALL", "1");
  2046. }
  2047. wait_for_client(&ic, NULL, 0);
  2048. exit(0);
  2049. continue;
  2050. }
  2051. if (!strcmp(arg, "-findauth")) {
  2052. got_findauth = 1;
  2053. if (argc > i+1) {
  2054. char *s = argv[i+1];
  2055. if (s[0] != '-') {
  2056. set_env("FINDAUTH_DISPLAY", argv[i+1]);
  2057. i++;
  2058. }
  2059. }
  2060. continue;
  2061. }
  2062. if (!strcmp(arg, "-create")) {
  2063. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb");
  2064. continue;
  2065. }
  2066. if (!strcmp(arg, "-create_xsrv")) {
  2067. CHECK_ARGC
  2068. use_dpy = (char *) malloc(strlen(argv[i+1])+100);
  2069. sprintf(use_dpy, "WAIT:cmd=FINDCREATEDISPLAY-%s", argv[++i]);
  2070. continue;
  2071. }
  2072. if (!strcmp(arg, "-xdummy")) {
  2073. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy");
  2074. continue;
  2075. }
  2076. if (!strcmp(arg, "-xdummy_xvfb")) {
  2077. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb");
  2078. continue;
  2079. }
  2080. if (!strcmp(arg, "-xvnc")) {
  2081. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc");
  2082. continue;
  2083. }
  2084. if (!strcmp(arg, "-xvnc_redirect")) {
  2085. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc.redirect");
  2086. continue;
  2087. }
  2088. if (!strcmp(arg, "-redirect")) {
  2089. char *q, *t, *t0 = "WAIT:cmd=FINDDISPLAY-vnc_redirect";
  2090. CHECK_ARGC
  2091. t = (char *) malloc(strlen(t0) + strlen(argv[++i]) + 2);
  2092. q = strrchr(argv[i], ':');
  2093. if (q) *q = ' ';
  2094. sprintf(t, "%s=%s", t0, argv[i]);
  2095. use_dpy = t;
  2096. continue;
  2097. }
  2098. if (!strcmp(arg, "-auth") || !strcmp(arg, "-xauth")) {
  2099. CHECK_ARGC
  2100. auth_file = strdup(argv[++i]);
  2101. continue;
  2102. }
  2103. if (!strcmp(arg, "-N")) {
  2104. display_N = 1;
  2105. continue;
  2106. }
  2107. if (!strcmp(arg, "-autoport")) {
  2108. CHECK_ARGC
  2109. auto_port = atoi(argv[++i]);
  2110. continue;
  2111. }
  2112. if (!strcmp(arg, "-reflect")) {
  2113. CHECK_ARGC
  2114. raw_fb_str = (char *) malloc(4 + strlen(argv[i+1]) + 1);
  2115. sprintf(raw_fb_str, "vnc:%s", argv[++i]);
  2116. shared = 1;
  2117. continue;
  2118. }
  2119. if (!strcmp(arg, "-tsd")) {
  2120. CHECK_ARGC
  2121. terminal_services_daemon = strdup(argv[++i]);
  2122. continue;
  2123. }
  2124. if (!strcmp(arg, "-id") || !strcmp(arg, "-sid")) {
  2125. CHECK_ARGC
  2126. if (!strcmp(arg, "-sid")) {
  2127. rootshift = 1;
  2128. } else {
  2129. rootshift = 0;
  2130. }
  2131. i++;
  2132. if (!strcmp("pick", argv[i])) {
  2133. if (started_as_root) {
  2134. fprintf(stderr, "unsafe: %s pick\n",
  2135. arg);
  2136. exit(1);
  2137. } else if (! pick_windowid(&subwin)) {
  2138. fprintf(stderr, "invalid %s pick\n",
  2139. arg);
  2140. exit(1);
  2141. }
  2142. } else if (! scan_hexdec(argv[i], &subwin)) {
  2143. fprintf(stderr, "invalid %s arg: %s\n", arg,
  2144. argv[i]);
  2145. exit(1);
  2146. }
  2147. continue;
  2148. }
  2149. if (!strcmp(arg, "-waitmapped")) {
  2150. subwin_wait_mapped = 1;
  2151. continue;
  2152. }
  2153. if (!strcmp(arg, "-clip")) {
  2154. CHECK_ARGC
  2155. clip_str = strdup(argv[++i]);
  2156. continue;
  2157. }
  2158. if (!strcmp(arg, "-flashcmap")) {
  2159. flash_cmap = 1;
  2160. continue;
  2161. }
  2162. if (!strcmp(arg, "-shiftcmap")) {
  2163. CHECK_ARGC
  2164. shift_cmap = atoi(argv[++i]);
  2165. continue;
  2166. }
  2167. if (!strcmp(arg, "-notruecolor")) {
  2168. force_indexed_color = 1;
  2169. continue;
  2170. }
  2171. if (!strcmp(arg, "-advertise_truecolor")) {
  2172. advertise_truecolor = 1;
  2173. if (i < argc-1) {
  2174. char *s = argv[i+1];
  2175. if (s[0] != '-') {
  2176. if (strstr(s, "reset")) {
  2177. advertise_truecolor_reset = 1;
  2178. }
  2179. i++;
  2180. }
  2181. }
  2182. continue;
  2183. }
  2184. if (!strcmp(arg, "-overlay")) {
  2185. overlay = 1;
  2186. continue;
  2187. }
  2188. if (!strcmp(arg, "-overlay_nocursor")) {
  2189. overlay = 1;
  2190. overlay_cursor = 0;
  2191. continue;
  2192. }
  2193. if (!strcmp(arg, "-overlay_yescursor")) {
  2194. overlay = 1;
  2195. overlay_cursor = 2;
  2196. continue;
  2197. }
  2198. if (!strcmp(arg, "-8to24")) {
  2199. #if !SKIP_8TO24
  2200. cmap8to24 = 1;
  2201. if (i < argc-1) {
  2202. char *s = argv[i+1];
  2203. if (s[0] != '-') {
  2204. cmap8to24_str = strdup(s);
  2205. i++;
  2206. }
  2207. }
  2208. #endif
  2209. continue;
  2210. }
  2211. if (!strcmp(arg, "-24to32")) {
  2212. xform24to32 = 1;
  2213. continue;
  2214. }
  2215. if (!strcmp(arg, "-visual")) {
  2216. CHECK_ARGC
  2217. visual_str = strdup(argv[++i]);
  2218. continue;
  2219. }
  2220. if (!strcmp(arg, "-scale")) {
  2221. CHECK_ARGC
  2222. scale_str = strdup(argv[++i]);
  2223. continue;
  2224. }
  2225. if (!strcmp(arg, "-geometry")) {
  2226. CHECK_ARGC
  2227. scale_str = strdup(argv[++i]);
  2228. continue;
  2229. }
  2230. if (!strcmp(arg, "-scale_cursor")) {
  2231. CHECK_ARGC
  2232. scale_cursor_str = strdup(argv[++i]);
  2233. continue;
  2234. }
  2235. if (!strcmp(arg, "-viewonly")) {
  2236. view_only = 1;
  2237. continue;
  2238. }
  2239. if (!strcmp(arg, "-noviewonly")) {
  2240. view_only = 0;
  2241. got_noviewonly = 1;
  2242. continue;
  2243. }
  2244. if (!strcmp(arg, "-shared")) {
  2245. shared = 1;
  2246. continue;
  2247. }
  2248. if (!strcmp(arg, "-noshared")) {
  2249. shared = 0;
  2250. continue;
  2251. }
  2252. if (!strcmp(arg, "-once")) {
  2253. connect_once = 1;
  2254. got_connect_once = 1;
  2255. continue;
  2256. }
  2257. if (!strcmp(arg, "-many") || !strcmp(arg, "-forever")) {
  2258. connect_once = 0;
  2259. continue;
  2260. }
  2261. if (strstr(arg, "-loop") == arg) {
  2262. ; /* handled above */
  2263. continue;
  2264. }
  2265. if (strstr(arg, "-appshare") == arg) {
  2266. ; /* handled above */
  2267. continue;
  2268. }
  2269. if (strstr(arg, "-freeze_when_obscured") == arg) {
  2270. freeze_when_obscured = 1;
  2271. continue;
  2272. }
  2273. if (!strcmp(arg, "-timeout")) {
  2274. CHECK_ARGC
  2275. first_conn_timeout = atoi(argv[++i]);
  2276. continue;
  2277. }
  2278. if (!strcmp(arg, "-sleepin")) {
  2279. CHECK_ARGC
  2280. do_sleepin(argv[++i]);
  2281. continue;
  2282. }
  2283. if (!strcmp(arg, "-users")) {
  2284. CHECK_ARGC
  2285. users_list = strdup(argv[++i]);
  2286. continue;
  2287. }
  2288. if (!strcmp(arg, "-inetd")) {
  2289. inetd = 1;
  2290. continue;
  2291. }
  2292. if (!strcmp(arg, "-notightfilexfer")) {
  2293. tightfilexfer = 0;
  2294. continue;
  2295. }
  2296. if (!strcmp(arg, "-tightfilexfer")) {
  2297. tightfilexfer = 1;
  2298. continue;
  2299. }
  2300. if (!strcmp(arg, "-http")) {
  2301. try_http = 1;
  2302. continue;
  2303. }
  2304. if (!strcmp(arg, "-http_ssl")) {
  2305. try_http = 1;
  2306. http_ssl = 1;
  2307. got_tls++;
  2308. continue;
  2309. }
  2310. if (!strcmp(arg, "-avahi") || !strcmp(arg, "-mdns") || !strcmp(arg, "-zeroconf")) {
  2311. avahi = 1;
  2312. continue;
  2313. }
  2314. if (!strcmp(arg, "-connect") ||
  2315. !strcmp(arg, "-connect_or_exit") ||
  2316. !strcmp(arg, "-coe")) {
  2317. CHECK_ARGC
  2318. if (!strcmp(arg, "-connect_or_exit")) {
  2319. connect_or_exit = 1;
  2320. } else if (!strcmp(arg, "-coe")) {
  2321. connect_or_exit = 1;
  2322. }
  2323. if (strchr(argv[++i], '/') && !strstr(argv[i], "repeater://")) {
  2324. struct stat sb;
  2325. client_connect_file = strdup(argv[i]);
  2326. if (stat(client_connect_file, &sb) != 0) {
  2327. FILE* f = fopen(client_connect_file, "w");
  2328. if (f != NULL) fclose(f);
  2329. }
  2330. } else {
  2331. client_connect = strdup(argv[i]);
  2332. }
  2333. continue;
  2334. }
  2335. if (!strcmp(arg, "-proxy")) {
  2336. CHECK_ARGC
  2337. connect_proxy = strdup(argv[++i]);
  2338. continue;
  2339. }
  2340. if (!strcmp(arg, "-vncconnect")) {
  2341. vnc_connect = 1;
  2342. continue;
  2343. }
  2344. if (!strcmp(arg, "-novncconnect")) {
  2345. vnc_connect = 0;
  2346. continue;
  2347. }
  2348. if (!strcmp(arg, "-allow")) {
  2349. CHECK_ARGC
  2350. allow_list = strdup(argv[++i]);
  2351. continue;
  2352. }
  2353. if (!strcmp(arg, "-localhost")) {
  2354. allow_list = strdup("127.0.0.1");
  2355. got_localhost = 1;
  2356. continue;
  2357. }
  2358. if (!strcmp(arg, "-unixsock")) {
  2359. CHECK_ARGC
  2360. unix_sock = strdup(argv[++i]);
  2361. continue;
  2362. }
  2363. if (!strcmp(arg, "-listen6")) {
  2364. CHECK_ARGC
  2365. #if X11VNC_IPV6
  2366. listen_str6 = strdup(argv[++i]);
  2367. #else
  2368. ++i;
  2369. #endif
  2370. continue;
  2371. }
  2372. if (!strcmp(arg, "-nolookup")) {
  2373. host_lookup = 0;
  2374. continue;
  2375. }
  2376. if (!strcmp(arg, "-6")) {
  2377. #if X11VNC_IPV6
  2378. ipv6_listen = 1;
  2379. got_ipv6_listen = 1;
  2380. #endif
  2381. continue;
  2382. }
  2383. if (!strcmp(arg, "-no6")) {
  2384. #if X11VNC_IPV6
  2385. ipv6_listen = 0;
  2386. got_ipv6_listen = 0;
  2387. #endif
  2388. continue;
  2389. }
  2390. if (!strcmp(arg, "-noipv6")) {
  2391. noipv6 = 1;
  2392. continue;
  2393. }
  2394. if (!strcmp(arg, "-noipv4")) {
  2395. noipv4 = 1;
  2396. continue;
  2397. }
  2398. if (!strcmp(arg, "-input")) {
  2399. CHECK_ARGC
  2400. allowed_input_str = strdup(argv[++i]);
  2401. continue;
  2402. }
  2403. if (!strcmp(arg, "-grabkbd")) {
  2404. grab_kbd = 1;
  2405. continue;
  2406. }
  2407. if (!strcmp(arg, "-grabptr")) {
  2408. grab_ptr = 1;
  2409. continue;
  2410. }
  2411. if (!strcmp(arg, "-ungrabboth")) {
  2412. ungrab_both = 1;
  2413. continue;
  2414. }
  2415. if (!strcmp(arg, "-grabalways")) {
  2416. grab_kbd = 1;
  2417. grab_ptr = 1;
  2418. grab_always = 1;
  2419. continue;
  2420. }
  2421. #ifdef ENABLE_GRABLOCAL
  2422. if (!strcmp(arg, "-grablocal")) {
  2423. CHECK_ARGC
  2424. grab_local = atoi(argv[++i]);
  2425. continue;
  2426. }
  2427. #endif
  2428. if (!strcmp(arg, "-viewpasswd")) {
  2429. vpw_loc = i;
  2430. CHECK_ARGC
  2431. viewonly_passwd = strdup(argv[++i]);
  2432. got_viewpasswd = 1;
  2433. continue;
  2434. }
  2435. if (!strcmp(arg, "-passwdfile")) {
  2436. CHECK_ARGC
  2437. passwdfile = strdup(argv[++i]);
  2438. got_passwdfile = 1;
  2439. continue;
  2440. }
  2441. if (!strcmp(arg, "-svc") || !strcmp(arg, "-service")) {
  2442. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb");
  2443. unixpw = 1;
  2444. users_list = strdup("unixpw=");
  2445. use_openssl = 1;
  2446. openssl_pem = strdup("SAVE");
  2447. continue;
  2448. }
  2449. if (!strcmp(arg, "-svc_xdummy")) {
  2450. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy");
  2451. unixpw = 1;
  2452. users_list = strdup("unixpw=");
  2453. use_openssl = 1;
  2454. openssl_pem = strdup("SAVE");
  2455. continue;
  2456. }
  2457. if (!strcmp(arg, "-svc_xdummy_xvfb")) {
  2458. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb");
  2459. unixpw = 1;
  2460. users_list = strdup("unixpw=");
  2461. use_openssl = 1;
  2462. openssl_pem = strdup("SAVE");
  2463. continue;
  2464. }
  2465. if (!strcmp(arg, "-svc_xvnc")) {
  2466. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvnc");
  2467. unixpw = 1;
  2468. users_list = strdup("unixpw=");
  2469. use_openssl = 1;
  2470. openssl_pem = strdup("SAVE");
  2471. continue;
  2472. }
  2473. if (!strcmp(arg, "-xdmsvc") || !strcmp(arg, "-xdm_service")) {
  2474. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp");
  2475. unixpw = 1;
  2476. users_list = strdup("unixpw=");
  2477. use_openssl = 1;
  2478. openssl_pem = strdup("SAVE");
  2479. continue;
  2480. }
  2481. if (!strcmp(arg, "-sshxdmsvc")) {
  2482. use_dpy = strdup("WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp");
  2483. allow_list = strdup("127.0.0.1");
  2484. got_localhost = 1;
  2485. continue;
  2486. }
  2487. if (!strcmp(arg, "-unixpw_system_greeter")) {
  2488. unixpw_system_greeter = 1;
  2489. continue;
  2490. }
  2491. if (!strcmp(arg, "-unixpw_cmd")
  2492. || !strcmp(arg, "-unixpw_cmd_unsafe")) {
  2493. CHECK_ARGC
  2494. unixpw_cmd = strdup(argv[++i]);
  2495. unixpw = 1;
  2496. if (strstr(arg, "_unsafe")) {
  2497. /* hidden option for testing. */
  2498. set_env("UNIXPW_DISABLE_SSL", "1");
  2499. set_env("UNIXPW_DISABLE_LOCALHOST", "1");
  2500. }
  2501. continue;
  2502. }
  2503. if (strstr(arg, "-unixpw") == arg) {
  2504. unixpw = 1;
  2505. if (strstr(arg, "-unixpw_nis")) {
  2506. unixpw_nis = 1;
  2507. }
  2508. if (i < argc-1) {
  2509. char *s = argv[i+1];
  2510. if (s[0] != '-') {
  2511. unixpw_list = strdup(s);
  2512. i++;
  2513. }
  2514. if (s[0] == '%') {
  2515. unixpw_list = NULL;
  2516. quick_pw(s);
  2517. exit(2);
  2518. }
  2519. }
  2520. if (strstr(arg, "_unsafe")) {
  2521. /* hidden option for testing. */
  2522. set_env("UNIXPW_DISABLE_SSL", "1");
  2523. set_env("UNIXPW_DISABLE_LOCALHOST", "1");
  2524. }
  2525. continue;
  2526. }
  2527. if (strstr(arg, "-nounixpw") == arg) {
  2528. unixpw = 0;
  2529. unixpw_nis = 0;
  2530. if (unixpw_list) {
  2531. unixpw_list = NULL;
  2532. }
  2533. if (unixpw_cmd) {
  2534. unixpw_cmd = NULL;
  2535. }
  2536. continue;
  2537. }
  2538. if (!strcmp(arg, "-vencrypt")) {
  2539. char *s;
  2540. CHECK_ARGC
  2541. s = strdup(argv[++i]);
  2542. got_tls++;
  2543. if (strstr(s, "never")) {
  2544. vencrypt_mode = VENCRYPT_NONE;
  2545. } else if (strstr(s, "support")) {
  2546. vencrypt_mode = VENCRYPT_SUPPORT;
  2547. } else if (strstr(s, "only")) {
  2548. vencrypt_mode = VENCRYPT_SOLE;
  2549. } else if (strstr(s, "force")) {
  2550. vencrypt_mode = VENCRYPT_FORCE;
  2551. } else {
  2552. fprintf(stderr, "invalid %s arg: %s\n", arg, s);
  2553. exit(1);
  2554. }
  2555. if (strstr(s, "nodh")) {
  2556. vencrypt_kx = VENCRYPT_NODH;
  2557. } else if (strstr(s, "nox509")) {
  2558. vencrypt_kx = VENCRYPT_NOX509;
  2559. }
  2560. if (strstr(s, "newdh")) {
  2561. create_fresh_dhparams = 1;
  2562. }
  2563. if (strstr(s, "noplain")) {
  2564. vencrypt_enable_plain_login = 0;
  2565. } else if (strstr(s, "plain")) {
  2566. vencrypt_enable_plain_login = 1;
  2567. }
  2568. free(s);
  2569. continue;
  2570. }
  2571. if (!strcmp(arg, "-anontls")) {
  2572. char *s;
  2573. CHECK_ARGC
  2574. s = strdup(argv[++i]);
  2575. got_tls++;
  2576. if (strstr(s, "never")) {
  2577. anontls_mode = ANONTLS_NONE;
  2578. } else if (strstr(s, "support")) {
  2579. anontls_mode = ANONTLS_SUPPORT;
  2580. } else if (strstr(s, "only")) {
  2581. anontls_mode = ANONTLS_SOLE;
  2582. } else if (strstr(s, "force")) {
  2583. anontls_mode = ANONTLS_FORCE;
  2584. } else {
  2585. fprintf(stderr, "invalid %s arg: %s\n", arg, s);
  2586. exit(1);
  2587. }
  2588. if (strstr(s, "newdh")) {
  2589. create_fresh_dhparams = 1;
  2590. }
  2591. free(s);
  2592. continue;
  2593. }
  2594. if (!strcmp(arg, "-sslonly")) {
  2595. vencrypt_mode = VENCRYPT_NONE;
  2596. anontls_mode = ANONTLS_NONE;
  2597. got_tls++;
  2598. continue;
  2599. }
  2600. if (!strcmp(arg, "-dhparams")) {
  2601. CHECK_ARGC
  2602. dhparams_file = strdup(argv[++i]);
  2603. got_tls++;
  2604. continue;
  2605. }
  2606. if (!strcmp(arg, "-nossl")) {
  2607. use_openssl = 0;
  2608. openssl_pem = NULL;
  2609. got_tls = -1000;
  2610. continue;
  2611. }
  2612. if (!strcmp(arg, "-ssl")) {
  2613. use_openssl = 1;
  2614. if (i < argc-1) {
  2615. char *s = argv[i+1];
  2616. if (s[0] != '-') {
  2617. if (!strcmp(s, "ADH")) {
  2618. openssl_pem = strdup("ANON");
  2619. } else if (!strcmp(s, "ANONDH")) {
  2620. openssl_pem = strdup("ANON");
  2621. } else if (!strcmp(s, "TMP")) {
  2622. openssl_pem = NULL;
  2623. } else {
  2624. openssl_pem = strdup(s);
  2625. }
  2626. i++;
  2627. } else {
  2628. openssl_pem = strdup("SAVE");
  2629. }
  2630. } else {
  2631. openssl_pem = strdup("SAVE");
  2632. }
  2633. continue;
  2634. }
  2635. if (!strcmp(arg, "-enc")) {
  2636. use_openssl = 1;
  2637. CHECK_ARGC
  2638. enc_str = strdup(argv[++i]);
  2639. continue;
  2640. }
  2641. if (!strcmp(arg, "-http_oneport")) {
  2642. http_oneport_msg = 1;
  2643. use_openssl = 1;
  2644. enc_str = strdup("none");
  2645. continue;
  2646. }
  2647. if (!strcmp(arg, "-ssltimeout")) {
  2648. CHECK_ARGC
  2649. ssl_timeout_secs = atoi(argv[++i]);
  2650. continue;
  2651. }
  2652. if (!strcmp(arg, "-sslnofail")) {
  2653. ssl_no_fail = 1;
  2654. continue;
  2655. }
  2656. if (!strcmp(arg, "-ssldir")) {
  2657. CHECK_ARGC
  2658. ssl_certs_dir = strdup(argv[++i]);
  2659. continue;
  2660. }
  2661. if (!strcmp(arg, "-sslverify")) {
  2662. CHECK_ARGC
  2663. ssl_verify = strdup(argv[++i]);
  2664. got_tls++;
  2665. continue;
  2666. }
  2667. if (!strcmp(arg, "-sslCRL")) {
  2668. CHECK_ARGC
  2669. ssl_crl = strdup(argv[++i]);
  2670. got_tls++;
  2671. continue;
  2672. }
  2673. if (!strcmp(arg, "-sslGenCA")) {
  2674. char *cdir = NULL;
  2675. if (i < argc-1) {
  2676. char *s = argv[i+1];
  2677. if (s[0] != '-') {
  2678. cdir = strdup(s);
  2679. i++;
  2680. }
  2681. }
  2682. sslGenCA(cdir);
  2683. exit(0);
  2684. continue;
  2685. }
  2686. if (!strcmp(arg, "-sslGenCert")) {
  2687. char *ty, *nm = NULL;
  2688. if (i >= argc-1) {
  2689. fprintf(stderr, "Must be:\n");
  2690. fprintf(stderr, " x11vnc -sslGenCert server ...\n");
  2691. fprintf(stderr, "or x11vnc -sslGenCert client ...\n");
  2692. exit(1);
  2693. }
  2694. ty = argv[i+1];
  2695. if (strcmp(ty, "server") && strcmp(ty, "client")) {
  2696. fprintf(stderr, "Must be:\n");
  2697. fprintf(stderr, " x11vnc -sslGenCert server ...\n");
  2698. fprintf(stderr, "or x11vnc -sslGenCert client ...\n");
  2699. exit(1);
  2700. }
  2701. if (i < argc-2) {
  2702. nm = argv[i+2];
  2703. }
  2704. sslGenCert(ty, nm);
  2705. exit(0);
  2706. continue;
  2707. }
  2708. if (!strcmp(arg, "-sslEncKey")) {
  2709. if (i < argc-1) {
  2710. char *s = argv[i+1];
  2711. sslEncKey(s, 0);
  2712. }
  2713. exit(0);
  2714. continue;
  2715. }
  2716. if (!strcmp(arg, "-sslCertInfo")) {
  2717. if (i < argc-1) {
  2718. char *s = argv[i+1];
  2719. sslEncKey(s, 1);
  2720. }
  2721. exit(0);
  2722. continue;
  2723. }
  2724. if (!strcmp(arg, "-sslDelCert")) {
  2725. if (i < argc-1) {
  2726. char *s = argv[i+1];
  2727. sslEncKey(s, 2);
  2728. }
  2729. exit(0);
  2730. continue;
  2731. }
  2732. if (!strcmp(arg, "-sslScripts")) {
  2733. sslScripts();
  2734. exit(0);
  2735. continue;
  2736. }
  2737. if (!strcmp(arg, "-stunnel")) {
  2738. use_stunnel = 1;
  2739. got_tls = -1000;
  2740. if (i < argc-1) {
  2741. char *s = argv[i+1];
  2742. if (s[0] != '-') {
  2743. if (!strcmp(s, "TMP")) {
  2744. stunnel_pem = NULL;
  2745. } else {
  2746. stunnel_pem = strdup(s);
  2747. }
  2748. i++;
  2749. } else {
  2750. stunnel_pem = strdup("SAVE");
  2751. }
  2752. } else {
  2753. stunnel_pem = strdup("SAVE");
  2754. }
  2755. continue;
  2756. }
  2757. if (!strcmp(arg, "-stunnel3")) {
  2758. use_stunnel = 3;
  2759. got_tls = -1000;
  2760. if (i < argc-1) {
  2761. char *s = argv[i+1];
  2762. if (s[0] != '-') {
  2763. if (!strcmp(s, "TMP")) {
  2764. stunnel_pem = NULL;
  2765. } else {
  2766. stunnel_pem = strdup(s);
  2767. }
  2768. i++;
  2769. } else {
  2770. stunnel_pem = strdup("SAVE");
  2771. }
  2772. } else {
  2773. stunnel_pem = strdup("SAVE");
  2774. }
  2775. continue;
  2776. }
  2777. if (!strcmp(arg, "-https")) {
  2778. https_port_num = 0;
  2779. try_http = 1;
  2780. got_tls++;
  2781. if (i < argc-1) {
  2782. char *s = argv[i+1];
  2783. if (s[0] != '-') {
  2784. https_port_num = atoi(s);
  2785. i++;
  2786. }
  2787. }
  2788. continue;
  2789. }
  2790. if (!strcmp(arg, "-httpsredir")) {
  2791. https_port_redir = -1;
  2792. got_tls++;
  2793. if (i < argc-1) {
  2794. char *s = argv[i+1];
  2795. if (s[0] != '-') {
  2796. https_port_redir = atoi(s);
  2797. i++;
  2798. }
  2799. }
  2800. continue;
  2801. }
  2802. if (!strcmp(arg, "-nopw")) {
  2803. nopw = 1;
  2804. continue;
  2805. }
  2806. if (!strcmp(arg, "-ssh")) {
  2807. CHECK_ARGC
  2808. ssh_str = strdup(argv[++i]);
  2809. continue;
  2810. }
  2811. if (!strcmp(arg, "-usepw")) {
  2812. usepw = 1;
  2813. continue;
  2814. }
  2815. if (!strcmp(arg, "-storepasswd")) {
  2816. if (argc == i+1) {
  2817. store_homedir_passwd(NULL);
  2818. exit(0);
  2819. }
  2820. if (argc == i+2) {
  2821. store_homedir_passwd(argv[i+1]);
  2822. exit(0);
  2823. }
  2824. if (argc >= i+4 || rfbEncryptAndStorePasswd(argv[i+1],
  2825. argv[i+2]) != 0) {
  2826. perror("storepasswd");
  2827. fprintf(stderr, "-storepasswd failed for file: %s\n",
  2828. argv[i+2]);
  2829. exit(1);
  2830. } else {
  2831. fprintf(stderr, "stored passwd in file: %s\n",
  2832. argv[i+2]);
  2833. exit(0);
  2834. }
  2835. continue;
  2836. }
  2837. if (!strcmp(arg, "-showrfbauth")) {
  2838. if (argc >= i+2) {
  2839. char *f = argv[i+1];
  2840. char *s = rfbDecryptPasswdFromFile(f);
  2841. if (!s) {
  2842. perror("showrfbauth");
  2843. fprintf(stderr, "rfbDecryptPasswdFromFile failed: %s\n", f);
  2844. exit(1);
  2845. }
  2846. fprintf(stdout, "rfbDecryptPasswdFromFile file: %s\n", f);
  2847. fprintf(stdout, "rfbDecryptPasswdFromFile pass: %s\n", s);
  2848. }
  2849. exit(0);
  2850. }
  2851. if (!strcmp(arg, "-accept")) {
  2852. CHECK_ARGC
  2853. accept_cmd = strdup(argv[++i]);
  2854. continue;
  2855. }
  2856. if (!strcmp(arg, "-afteraccept")) {
  2857. CHECK_ARGC
  2858. afteraccept_cmd = strdup(argv[++i]);
  2859. continue;
  2860. }
  2861. if (!strcmp(arg, "-gone")) {
  2862. CHECK_ARGC
  2863. gone_cmd = strdup(argv[++i]);
  2864. continue;
  2865. }
  2866. if (!strcmp(arg, "-noshm")) {
  2867. using_shm = 0;
  2868. continue;
  2869. }
  2870. if (!strcmp(arg, "-flipbyteorder")) {
  2871. flip_byte_order = 1;
  2872. continue;
  2873. }
  2874. if (!strcmp(arg, "-onetile")) {
  2875. single_copytile = 1;
  2876. continue;
  2877. }
  2878. if (!strcmp(arg, "-solid")) {
  2879. use_solid_bg = 1;
  2880. if (i < argc-1) {
  2881. char *s = argv[i+1];
  2882. if (s[0] != '-') {
  2883. solid_str = strdup(s);
  2884. i++;
  2885. }
  2886. }
  2887. if (! solid_str) {
  2888. solid_str = strdup(solid_default);
  2889. }
  2890. continue;
  2891. }
  2892. if (!strcmp(arg, "-blackout")) {
  2893. CHECK_ARGC
  2894. blackout_str = strdup(argv[++i]);
  2895. continue;
  2896. }
  2897. if (!strcmp(arg, "-xinerama")) {
  2898. xinerama = 1;
  2899. continue;
  2900. }
  2901. if (!strcmp(arg, "-noxinerama")) {
  2902. xinerama = 0;
  2903. continue;
  2904. }
  2905. if (!strcmp(arg, "-xtrap")) {
  2906. xtrap_input = 1;
  2907. continue;
  2908. }
  2909. if (!strcmp(arg, "-xrandr")) {
  2910. xrandr = 1;
  2911. if (i < argc-1) {
  2912. char *s = argv[i+1];
  2913. if (known_xrandr_mode(s)) {
  2914. xrandr_mode = strdup(s);
  2915. i++;
  2916. }
  2917. }
  2918. continue;
  2919. }
  2920. if (!strcmp(arg, "-noxrandr")) {
  2921. xrandr = 0;
  2922. xrandr_maybe = 0;
  2923. got_noxrandr = 1;
  2924. continue;
  2925. }
  2926. if (!strcmp(arg, "-rotate")) {
  2927. CHECK_ARGC
  2928. rotating_str = strdup(argv[++i]);
  2929. continue;
  2930. }
  2931. if (!strcmp(arg, "-padgeom")
  2932. || !strcmp(arg, "-padgeometry")) {
  2933. CHECK_ARGC
  2934. pad_geometry = strdup(argv[++i]);
  2935. continue;
  2936. }
  2937. if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) {
  2938. CHECK_ARGC
  2939. logfile_append = 0;
  2940. logfile = strdup(argv[++i]);
  2941. continue;
  2942. }
  2943. if (!strcmp(arg, "-oa") || !strcmp(arg, "-logappend")) {
  2944. CHECK_ARGC
  2945. logfile_append = 1;
  2946. logfile = strdup(argv[++i]);
  2947. continue;
  2948. }
  2949. if (!strcmp(arg, "-flag")) {
  2950. CHECK_ARGC
  2951. flagfile = strdup(argv[++i]);
  2952. continue;
  2953. }
  2954. if (!strcmp(arg, "-rmflag")) {
  2955. CHECK_ARGC
  2956. rm_flagfile = strdup(argv[++i]);
  2957. continue;
  2958. }
  2959. if (!strcmp(arg, "-rc")) {
  2960. i++; /* done above */
  2961. continue;
  2962. }
  2963. if (!strcmp(arg, "-norc")) {
  2964. ; /* done above */
  2965. continue;
  2966. }
  2967. if (!strcmp(arg, "-env")) {
  2968. i++; /* done above */
  2969. continue;
  2970. }
  2971. if (!strcmp(arg, "-prog")) {
  2972. CHECK_ARGC
  2973. if (program_name) {
  2974. free(program_name);
  2975. }
  2976. program_name = strdup(argv[++i]);
  2977. continue;
  2978. }
  2979. if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) {
  2980. print_help(0);
  2981. continue;
  2982. }
  2983. if (!strcmp(arg, "-?") || !strcmp(arg, "-opts")) {
  2984. print_help(1);
  2985. continue;
  2986. }
  2987. if (!strcmp(arg, "-V") || !strcmp(arg, "-version")) {
  2988. fprintf(stdout, "x11vnc: %s\n", lastmod);
  2989. exit(0);
  2990. continue;
  2991. }
  2992. if (!strcmp(arg, "-license") ||
  2993. !strcmp(arg, "-copying") || !strcmp(arg, "-warranty")) {
  2994. print_license();
  2995. continue;
  2996. }
  2997. if (!strcmp(arg, "-dbg")) {
  2998. crash_debug = 1;
  2999. continue;
  3000. }
  3001. if (!strcmp(arg, "-nodbg")) {
  3002. crash_debug = 0;
  3003. continue;
  3004. }
  3005. if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) {
  3006. quiet = 1;
  3007. continue;
  3008. }
  3009. if (!strcmp(arg, "-noquiet")) {
  3010. quiet = 0;
  3011. continue;
  3012. }
  3013. if (!strcmp(arg, "-v") || !strcmp(arg, "-verbose")) {
  3014. verbose = 1;
  3015. continue;
  3016. }
  3017. if (!strcmp(arg, "-bg") || !strcmp(arg, "-background")) {
  3018. #if LIBVNCSERVER_HAVE_SETSID
  3019. bg = 1;
  3020. opts_bg = bg;
  3021. #else
  3022. if (!got_inetd) {
  3023. fprintf(stderr, "warning: -bg mode not supported.\n");
  3024. }
  3025. #endif
  3026. continue;
  3027. }
  3028. if (!strcmp(arg, "-modtweak")) {
  3029. use_modifier_tweak = 1;
  3030. continue;
  3031. }
  3032. if (!strcmp(arg, "-nomodtweak")) {
  3033. use_modifier_tweak = 0;
  3034. got_nomodtweak = 1;
  3035. continue;
  3036. }
  3037. if (!strcmp(arg, "-isolevel3")) {
  3038. use_iso_level3 = 1;
  3039. continue;
  3040. }
  3041. if (!strcmp(arg, "-xkb")) {
  3042. use_modifier_tweak = 1;
  3043. use_xkb_modtweak = 1;
  3044. continue;
  3045. }
  3046. if (!strcmp(arg, "-noxkb")) {
  3047. use_xkb_modtweak = 0;
  3048. got_noxkb = 1;
  3049. continue;
  3050. }
  3051. if (!strcmp(arg, "-capslock")) {
  3052. watch_capslock = 1;
  3053. continue;
  3054. }
  3055. if (!strcmp(arg, "-skip_lockkeys")) {
  3056. skip_lockkeys = 1;
  3057. continue;
  3058. }
  3059. if (!strcmp(arg, "-noskip_lockkeys")) {
  3060. skip_lockkeys = 0;
  3061. continue;
  3062. }
  3063. if (!strcmp(arg, "-xkbcompat")) {
  3064. xkbcompat = 1;
  3065. continue;
  3066. }
  3067. if (!strcmp(arg, "-skip_keycodes")) {
  3068. CHECK_ARGC
  3069. skip_keycodes = strdup(argv[++i]);
  3070. continue;
  3071. }
  3072. if (!strcmp(arg, "-sloppy_keys")) {
  3073. sloppy_keys++;
  3074. continue;
  3075. }
  3076. if (!strcmp(arg, "-skip_dups")) {
  3077. skip_duplicate_key_events = 1;
  3078. continue;
  3079. }
  3080. if (!strcmp(arg, "-noskip_dups")) {
  3081. skip_duplicate_key_events = 0;
  3082. continue;
  3083. }
  3084. if (!strcmp(arg, "-add_keysyms")) {
  3085. add_keysyms++;
  3086. continue;
  3087. }
  3088. if (!strcmp(arg, "-noadd_keysyms")) {
  3089. add_keysyms = 0;
  3090. continue;
  3091. }
  3092. if (!strcmp(arg, "-clear_mods")) {
  3093. clear_mods = 1;
  3094. continue;
  3095. }
  3096. if (!strcmp(arg, "-clear_keys")) {
  3097. clear_mods = 2;
  3098. continue;
  3099. }
  3100. if (!strcmp(arg, "-clear_all")) {
  3101. clear_mods = 3;
  3102. continue;
  3103. }
  3104. if (!strcmp(arg, "-remap")) {
  3105. CHECK_ARGC
  3106. remap_file = strdup(argv[++i]);
  3107. continue;
  3108. }
  3109. if (!strcmp(arg, "-norepeat")) {
  3110. no_autorepeat = 1;
  3111. if (i < argc-1) {
  3112. char *s = argv[i+1];
  3113. if (*s == '-') {
  3114. s++;
  3115. }
  3116. if (isdigit((unsigned char) (*s))) {
  3117. no_repeat_countdown = atoi(argv[++i]);
  3118. }
  3119. }
  3120. continue;
  3121. }
  3122. if (!strcmp(arg, "-repeat")) {
  3123. no_autorepeat = 0;
  3124. continue;
  3125. }
  3126. if (!strcmp(arg, "-nofb")) {
  3127. nofb = 1;
  3128. continue;
  3129. }
  3130. if (!strcmp(arg, "-nobell")) {
  3131. watch_bell = 0;
  3132. sound_bell = 0;
  3133. continue;
  3134. }
  3135. if (!strcmp(arg, "-nosel")) {
  3136. watch_selection = 0;
  3137. watch_primary = 0;
  3138. watch_clipboard = 0;
  3139. continue;
  3140. }
  3141. if (!strcmp(arg, "-noprimary")) {
  3142. watch_primary = 0;
  3143. continue;
  3144. }
  3145. if (!strcmp(arg, "-nosetprimary")) {
  3146. set_primary = 0;
  3147. continue;
  3148. }
  3149. if (!strcmp(arg, "-noclipboard")) {
  3150. watch_clipboard = 0;
  3151. continue;
  3152. }
  3153. if (!strcmp(arg, "-nosetclipboard")) {
  3154. set_clipboard = 0;
  3155. continue;
  3156. }
  3157. if (!strcmp(arg, "-seldir")) {
  3158. CHECK_ARGC
  3159. sel_direction = strdup(argv[++i]);
  3160. continue;
  3161. }
  3162. if (!strcmp(arg, "-cursor")) {
  3163. show_cursor = 1;
  3164. if (i < argc-1) {
  3165. char *s = argv[i+1];
  3166. if (known_cursors_mode(s)) {
  3167. multiple_cursors_mode = strdup(s);
  3168. i++;
  3169. if (!strcmp(s, "none")) {
  3170. show_cursor = 0;
  3171. }
  3172. }
  3173. }
  3174. continue;
  3175. }
  3176. if (!strcmp(arg, "-nocursor")) {
  3177. multiple_cursors_mode = strdup("none");
  3178. show_cursor = 0;
  3179. continue;
  3180. }
  3181. if (!strcmp(arg, "-cursor_drag")) {
  3182. cursor_drag_changes = 1;
  3183. continue;
  3184. }
  3185. if (!strcmp(arg, "-nocursor_drag")) {
  3186. cursor_drag_changes = 0;
  3187. continue;
  3188. }
  3189. if (!strcmp(arg, "-arrow")) {
  3190. CHECK_ARGC
  3191. alt_arrow = atoi(argv[++i]);
  3192. continue;
  3193. }
  3194. if (!strcmp(arg, "-xfixes")) {
  3195. use_xfixes = 1;
  3196. continue;
  3197. }
  3198. if (!strcmp(arg, "-noxfixes")) {
  3199. use_xfixes = 0;
  3200. continue;
  3201. }
  3202. if (!strcmp(arg, "-alphacut")) {
  3203. CHECK_ARGC
  3204. alpha_threshold = atoi(argv[++i]);
  3205. continue;
  3206. }
  3207. if (!strcmp(arg, "-alphafrac")) {
  3208. CHECK_ARGC
  3209. alpha_frac = atof(argv[++i]);
  3210. continue;
  3211. }
  3212. if (!strcmp(arg, "-alpharemove")) {
  3213. alpha_remove = 1;
  3214. continue;
  3215. }
  3216. if (!strcmp(arg, "-noalphablend")) {
  3217. alpha_blend = 0;
  3218. continue;
  3219. }
  3220. if (!strcmp(arg, "-nocursorshape")) {
  3221. cursor_shape_updates = 0;
  3222. continue;
  3223. }
  3224. if (!strcmp(arg, "-cursorpos")) {
  3225. cursor_pos_updates = 1;
  3226. got_cursorpos = 1;
  3227. continue;
  3228. }
  3229. if (!strcmp(arg, "-nocursorpos")) {
  3230. cursor_pos_updates = 0;
  3231. continue;
  3232. }
  3233. if (!strcmp(arg, "-xwarppointer")) {
  3234. use_xwarppointer = 1;
  3235. continue;
  3236. }
  3237. if (!strcmp(arg, "-noxwarppointer")) {
  3238. use_xwarppointer = 0;
  3239. got_noxwarppointer = 1;
  3240. continue;
  3241. }
  3242. if (!strcmp(arg, "-always_inject")) {
  3243. always_inject = 1;
  3244. continue;
  3245. }
  3246. if (!strcmp(arg, "-buttonmap")) {
  3247. CHECK_ARGC
  3248. pointer_remap = strdup(argv[++i]);
  3249. continue;
  3250. }
  3251. if (!strcmp(arg, "-nodragging")) {
  3252. show_dragging = 0;
  3253. continue;
  3254. }
  3255. #ifndef NO_NCACHE
  3256. if (!strcmp(arg, "-ncache") || !strcmp(arg, "-nc")) {
  3257. if (i < argc-1) {
  3258. char *s = argv[i+1];
  3259. if (s[0] != '-') {
  3260. ncache = atoi(s);
  3261. i++;
  3262. } else {
  3263. ncache = ncache_default;
  3264. }
  3265. } else {
  3266. ncache = ncache_default;
  3267. }
  3268. if (ncache % 2 != 0) {
  3269. ncache++;
  3270. }
  3271. continue;
  3272. }
  3273. if (!strcmp(arg, "-noncache") || !strcmp(arg, "-nonc")) {
  3274. ncache = 0;
  3275. continue;
  3276. }
  3277. if (!strcmp(arg, "-ncache_cr") || !strcmp(arg, "-nc_cr")) {
  3278. ncache_copyrect = 1;
  3279. continue;
  3280. }
  3281. if (!strcmp(arg, "-ncache_no_moveraise") || !strcmp(arg, "-nc_no_moveraise")) {
  3282. ncache_wf_raises = 1;
  3283. continue;
  3284. }
  3285. if (!strcmp(arg, "-ncache_no_dtchange") || !strcmp(arg, "-nc_no_dtchange")) {
  3286. ncache_dt_change = 0;
  3287. continue;
  3288. }
  3289. if (!strcmp(arg, "-ncache_no_rootpixmap") || !strcmp(arg, "-nc_no_rootpixmap")) {
  3290. ncache_xrootpmap = 0;
  3291. continue;
  3292. }
  3293. if (!strcmp(arg, "-ncache_keep_anims") || !strcmp(arg, "-nc_keep_anims")) {
  3294. ncache_keep_anims = 1;
  3295. continue;
  3296. }
  3297. if (!strcmp(arg, "-ncache_old_wm") || !strcmp(arg, "-nc_old_wm")) {
  3298. ncache_old_wm = 1;
  3299. continue;
  3300. }
  3301. if (!strcmp(arg, "-ncache_pad") || !strcmp(arg, "-nc_pad")) {
  3302. CHECK_ARGC
  3303. ncache_pad = atoi(argv[++i]);
  3304. continue;
  3305. }
  3306. if (!strcmp(arg, "-debug_ncache")) {
  3307. ncdb++;
  3308. continue;
  3309. }
  3310. #endif
  3311. if (!strcmp(arg, "-wireframe")
  3312. || !strcmp(arg, "-wf")) {
  3313. wireframe = 1;
  3314. if (i < argc-1) {
  3315. char *s = argv[i+1];
  3316. if (*s != '-') {
  3317. wireframe_str = strdup(argv[++i]);
  3318. }
  3319. }
  3320. continue;
  3321. }
  3322. if (!strcmp(arg, "-nowireframe")
  3323. || !strcmp(arg, "-nowf")) {
  3324. wireframe = 0;
  3325. continue;
  3326. }
  3327. if (!strcmp(arg, "-nowireframelocal")
  3328. || !strcmp(arg, "-nowfl")) {
  3329. wireframe_local = 0;
  3330. continue;
  3331. }
  3332. if (!strcmp(arg, "-wirecopyrect")
  3333. || !strcmp(arg, "-wcr")) {
  3334. CHECK_ARGC
  3335. set_wirecopyrect_mode(argv[++i]);
  3336. got_wirecopyrect = 1;
  3337. continue;
  3338. }
  3339. if (!strcmp(arg, "-nowirecopyrect")
  3340. || !strcmp(arg, "-nowcr")) {
  3341. set_wirecopyrect_mode("never");
  3342. continue;
  3343. }
  3344. if (!strcmp(arg, "-debug_wireframe")
  3345. || !strcmp(arg, "-dwf")) {
  3346. debug_wireframe++;
  3347. continue;
  3348. }
  3349. if (!strcmp(arg, "-scrollcopyrect")
  3350. || !strcmp(arg, "-scr")) {
  3351. CHECK_ARGC
  3352. set_scrollcopyrect_mode(argv[++i]);
  3353. got_scrollcopyrect = 1;
  3354. continue;
  3355. }
  3356. if (!strcmp(arg, "-noscrollcopyrect")
  3357. || !strcmp(arg, "-noscr")) {
  3358. set_scrollcopyrect_mode("never");
  3359. continue;
  3360. }
  3361. if (!strcmp(arg, "-scr_area")) {
  3362. int tn;
  3363. CHECK_ARGC
  3364. tn = atoi(argv[++i]);
  3365. if (tn >= 0) {
  3366. scrollcopyrect_min_area = tn;
  3367. }
  3368. continue;
  3369. }
  3370. if (!strcmp(arg, "-scr_skip")) {
  3371. CHECK_ARGC
  3372. scroll_skip_str = strdup(argv[++i]);
  3373. continue;
  3374. }
  3375. if (!strcmp(arg, "-scr_inc")) {
  3376. CHECK_ARGC
  3377. scroll_good_str = strdup(argv[++i]);
  3378. continue;
  3379. }
  3380. if (!strcmp(arg, "-scr_keys")) {
  3381. CHECK_ARGC
  3382. scroll_key_list_str = strdup(argv[++i]);
  3383. continue;
  3384. }
  3385. if (!strcmp(arg, "-scr_term")) {
  3386. CHECK_ARGC
  3387. scroll_term_str = strdup(argv[++i]);
  3388. continue;
  3389. }
  3390. if (!strcmp(arg, "-scr_keyrepeat")) {
  3391. CHECK_ARGC
  3392. max_keyrepeat_str = strdup(argv[++i]);
  3393. continue;
  3394. }
  3395. if (!strcmp(arg, "-scr_parms")) {
  3396. CHECK_ARGC
  3397. scroll_copyrect_str = strdup(argv[++i]);
  3398. continue;
  3399. }
  3400. if (!strcmp(arg, "-fixscreen")) {
  3401. CHECK_ARGC
  3402. screen_fixup_str = strdup(argv[++i]);
  3403. continue;
  3404. }
  3405. if (!strcmp(arg, "-debug_scroll")
  3406. || !strcmp(arg, "-ds")) {
  3407. debug_scroll++;
  3408. continue;
  3409. }
  3410. if (!strcmp(arg, "-noxrecord")) {
  3411. noxrecord = 1;
  3412. continue;
  3413. }
  3414. if (!strcmp(arg, "-pointer_mode")
  3415. || !strcmp(arg, "-pm")) {
  3416. char *p, *s;
  3417. CHECK_ARGC
  3418. s = argv[++i];
  3419. if ((p = strchr(s, ':')) != NULL) {
  3420. ui_skip = atoi(p+1);
  3421. if (! ui_skip) ui_skip = 1;
  3422. *p = '\0';
  3423. }
  3424. if (atoi(s) < 1 || atoi(s) > pointer_mode_max) {
  3425. if (!got_inetd) {
  3426. rfbLog("pointer_mode out of range 1-%d: %d\n",
  3427. pointer_mode_max, atoi(s));
  3428. }
  3429. } else {
  3430. pointer_mode = atoi(s);
  3431. got_pointer_mode = pointer_mode;
  3432. }
  3433. continue;
  3434. }
  3435. if (!strcmp(arg, "-input_skip")) {
  3436. CHECK_ARGC
  3437. ui_skip = atoi(argv[++i]);
  3438. if (! ui_skip) ui_skip = 1;
  3439. continue;
  3440. }
  3441. if (!strcmp(arg, "-allinput")) {
  3442. all_input = 1;
  3443. continue;
  3444. }
  3445. if (!strcmp(arg, "-noallinput")) {
  3446. all_input = 0;
  3447. continue;
  3448. }
  3449. if (!strcmp(arg, "-input_eagerly")) {
  3450. handle_events_eagerly = 1;
  3451. continue;
  3452. }
  3453. if (!strcmp(arg, "-noinput_eagerly")) {
  3454. handle_events_eagerly = 0;
  3455. continue;
  3456. }
  3457. if (!strcmp(arg, "-speeds")) {
  3458. CHECK_ARGC
  3459. speeds_str = strdup(argv[++i]);
  3460. continue;
  3461. }
  3462. if (!strcmp(arg, "-wmdt")) {
  3463. CHECK_ARGC
  3464. wmdt_str = strdup(argv[++i]);
  3465. continue;
  3466. }
  3467. if (!strcmp(arg, "-debug_pointer")
  3468. || !strcmp(arg, "-dp")) {
  3469. debug_pointer++;
  3470. continue;
  3471. }
  3472. if (!strcmp(arg, "-debug_keyboard")
  3473. || !strcmp(arg, "-dk")) {
  3474. debug_keyboard++;
  3475. continue;
  3476. }
  3477. if (!strcmp(arg, "-debug_xdamage")) {
  3478. debug_xdamage++;
  3479. continue;
  3480. }
  3481. if (!strcmp(arg, "-defer")) {
  3482. CHECK_ARGC
  3483. defer_update = atoi(argv[++i]);
  3484. got_defer = 1;
  3485. continue;
  3486. }
  3487. if (!strcmp(arg, "-setdefer")) {
  3488. CHECK_ARGC
  3489. set_defer = atoi(argv[++i]);
  3490. continue;
  3491. }
  3492. if (!strcmp(arg, "-wait")) {
  3493. CHECK_ARGC
  3494. waitms = atoi(argv[++i]);
  3495. got_waitms = 1;
  3496. continue;
  3497. }
  3498. if (!strcmp(arg, "-extra_fbur")) {
  3499. CHECK_ARGC
  3500. extra_fbur = atoi(argv[++i]);
  3501. continue;
  3502. }
  3503. if (!strcmp(arg, "-wait_ui")) {
  3504. CHECK_ARGC
  3505. wait_ui = atof(argv[++i]);
  3506. continue;
  3507. }
  3508. if (!strcmp(arg, "-nowait_bog")) {
  3509. wait_bog = 0;
  3510. continue;
  3511. }
  3512. if (!strcmp(arg, "-slow_fb")) {
  3513. CHECK_ARGC
  3514. slow_fb = atof(argv[++i]);
  3515. continue;
  3516. }
  3517. if (!strcmp(arg, "-xrefresh")) {
  3518. CHECK_ARGC
  3519. xrefresh = atof(argv[++i]);
  3520. continue;
  3521. }
  3522. if (!strcmp(arg, "-readtimeout")) {
  3523. CHECK_ARGC
  3524. rfbMaxClientWait = atoi(argv[++i]) * 1000;
  3525. continue;
  3526. }
  3527. if (!strcmp(arg, "-ping")) {
  3528. CHECK_ARGC
  3529. ping_interval = atoi(argv[++i]);
  3530. continue;
  3531. }
  3532. if (!strcmp(arg, "-nap")) {
  3533. take_naps = 1;
  3534. continue;
  3535. }
  3536. if (!strcmp(arg, "-nonap")) {
  3537. take_naps = 0;
  3538. continue;
  3539. }
  3540. if (!strcmp(arg, "-sb")) {
  3541. CHECK_ARGC
  3542. screen_blank = atoi(argv[++i]);
  3543. continue;
  3544. }
  3545. if (!strcmp(arg, "-nofbpm")) {
  3546. watch_fbpm = 1;
  3547. continue;
  3548. }
  3549. if (!strcmp(arg, "-fbpm")) {
  3550. watch_fbpm = 0;
  3551. continue;
  3552. }
  3553. if (!strcmp(arg, "-nodpms")) {
  3554. watch_dpms = 1;
  3555. continue;
  3556. }
  3557. if (!strcmp(arg, "-dpms")) {
  3558. watch_dpms = 0;
  3559. continue;
  3560. }
  3561. if (!strcmp(arg, "-forcedpms")) {
  3562. force_dpms = 1;
  3563. continue;
  3564. }
  3565. if (!strcmp(arg, "-clientdpms")) {
  3566. client_dpms = 1;
  3567. continue;
  3568. }
  3569. if (!strcmp(arg, "-noserverdpms")) {
  3570. no_ultra_dpms = 1;
  3571. continue;
  3572. }
  3573. if (!strcmp(arg, "-noultraext")) {
  3574. no_ultra_ext = 1;
  3575. continue;
  3576. }
  3577. if (!strcmp(arg, "-chatwindow")) {
  3578. chat_window = 1;
  3579. if (argc_vnc + 1 < argc_vnc_max) {
  3580. if (!got_inetd) {
  3581. rfbLog("setting '-rfbversion 3.6' for -chatwindow.\n");
  3582. }
  3583. argv_vnc[argc_vnc++] = strdup("-rfbversion");
  3584. argv_vnc[argc_vnc++] = strdup("3.6");
  3585. }
  3586. continue;
  3587. }
  3588. if (!strcmp(arg, "-xdamage")) {
  3589. use_xdamage++;
  3590. continue;
  3591. }
  3592. if (!strcmp(arg, "-noxdamage")) {
  3593. use_xdamage = 0;
  3594. continue;
  3595. }
  3596. if (!strcmp(arg, "-xd_area")) {
  3597. int tn;
  3598. CHECK_ARGC
  3599. tn = atoi(argv[++i]);
  3600. if (tn >= 0) {
  3601. xdamage_max_area = tn;
  3602. }
  3603. continue;
  3604. }
  3605. if (!strcmp(arg, "-xd_mem")) {
  3606. double f;
  3607. CHECK_ARGC
  3608. f = atof(argv[++i]);
  3609. if (f >= 0.0) {
  3610. xdamage_memory = f;
  3611. }
  3612. continue;
  3613. }
  3614. if (!strcmp(arg, "-sigpipe") || !strcmp(arg, "-sig")) {
  3615. CHECK_ARGC
  3616. if (known_sigpipe_mode(argv[++i])) {
  3617. sigpipe = strdup(argv[i]);
  3618. } else {
  3619. fprintf(stderr, "invalid -sigpipe arg: %s, must"
  3620. " be \"ignore\" or \"exit\"\n", argv[i]);
  3621. exit(1);
  3622. }
  3623. continue;
  3624. }
  3625. #if LIBVNCSERVER_HAVE_LIBPTHREAD
  3626. if (!strcmp(arg, "-threads")) {
  3627. #if defined(X11VNC_THREADED)
  3628. use_threads = 1;
  3629. #else
  3630. if (getenv("X11VNC_THREADED")) {
  3631. use_threads = 1;
  3632. } else if (1) {
  3633. /* we re-enable it due to threaded mode bugfixes. */
  3634. use_threads = 1;
  3635. } else {
  3636. if (!got_inetd) {
  3637. rfbLog("\n");
  3638. rfbLog("The -threads mode is unstable and not tested or maintained.\n");
  3639. rfbLog("It is disabled in the source code. If you really need\n");
  3640. rfbLog("the feature you can reenable it at build time by setting\n");
  3641. rfbLog("-DX11VNC_THREADED in CPPFLAGS. Or set X11VNC_THREADED=1\n");
  3642. rfbLog("in your runtime environment.\n");
  3643. rfbLog("\n");
  3644. usleep(500*1000);
  3645. }
  3646. }
  3647. #endif
  3648. continue;
  3649. }
  3650. if (!strcmp(arg, "-nothreads")) {
  3651. use_threads = 0;
  3652. continue;
  3653. }
  3654. #endif
  3655. if (!strcmp(arg, "-fs")) {
  3656. CHECK_ARGC
  3657. fs_frac = atof(argv[++i]);
  3658. continue;
  3659. }
  3660. if (!strcmp(arg, "-gaps")) {
  3661. CHECK_ARGC
  3662. gaps_fill = atoi(argv[++i]);
  3663. continue;
  3664. }
  3665. if (!strcmp(arg, "-grow")) {
  3666. CHECK_ARGC
  3667. grow_fill = atoi(argv[++i]);
  3668. continue;
  3669. }
  3670. if (!strcmp(arg, "-fuzz")) {
  3671. CHECK_ARGC
  3672. tile_fuzz = atoi(argv[++i]);
  3673. continue;
  3674. }
  3675. if (!strcmp(arg, "-debug_tiles")
  3676. || !strcmp(arg, "-dbt")) {
  3677. debug_tiles++;
  3678. continue;
  3679. }
  3680. if (!strcmp(arg, "-debug_grabs")) {
  3681. debug_grabs++;
  3682. continue;
  3683. }
  3684. if (!strcmp(arg, "-debug_sel")) {
  3685. debug_sel++;
  3686. continue;
  3687. }
  3688. if (!strcmp(arg, "-grab_buster")) {
  3689. grab_buster++;
  3690. continue;
  3691. }
  3692. if (!strcmp(arg, "-nograb_buster")) {
  3693. grab_buster = 0;
  3694. continue;
  3695. }
  3696. if (!strcmp(arg, "-snapfb")) {
  3697. use_snapfb = 1;
  3698. continue;
  3699. }
  3700. if (!strcmp(arg, "-rand")) {
  3701. /* equiv. to -nopw -rawfb rand for quick tests */
  3702. raw_fb_str = strdup("rand");
  3703. nopw = 1;
  3704. continue;
  3705. }
  3706. if (!strcmp(arg, "-rawfb")) {
  3707. CHECK_ARGC
  3708. raw_fb_str = strdup(argv[++i]);
  3709. if (strstr(raw_fb_str, "vnc:") == raw_fb_str) {
  3710. shared = 1;
  3711. }
  3712. continue;
  3713. }
  3714. if (!strcmp(arg, "-freqtab")) {
  3715. CHECK_ARGC
  3716. freqtab = strdup(argv[++i]);
  3717. continue;
  3718. }
  3719. if (!strcmp(arg, "-pipeinput")) {
  3720. CHECK_ARGC
  3721. pipeinput_str = strdup(argv[++i]);
  3722. continue;
  3723. }
  3724. if (!strcmp(arg, "-macnodim")) {
  3725. macosx_nodimming = 1;
  3726. continue;
  3727. }
  3728. if (!strcmp(arg, "-macnosleep")) {
  3729. macosx_nosleep = 1;
  3730. continue;
  3731. }
  3732. if (!strcmp(arg, "-macnosaver")) {
  3733. macosx_noscreensaver = 1;
  3734. continue;
  3735. }
  3736. if (!strcmp(arg, "-macnowait")) {
  3737. macosx_wait_for_switch = 0;
  3738. continue;
  3739. }
  3740. if (!strcmp(arg, "-macwheel")) {
  3741. CHECK_ARGC
  3742. macosx_mouse_wheel_speed = atoi(argv[++i]);
  3743. continue;
  3744. }
  3745. if (!strcmp(arg, "-macnoswap")) {
  3746. macosx_swap23 = 0;
  3747. continue;
  3748. }
  3749. if (!strcmp(arg, "-macnoresize")) {
  3750. macosx_resize = 0;
  3751. continue;
  3752. }
  3753. if (!strcmp(arg, "-maciconanim")) {
  3754. CHECK_ARGC
  3755. macosx_icon_anim_time = atoi(argv[++i]);
  3756. continue;
  3757. }
  3758. if (!strcmp(arg, "-macmenu")) {
  3759. macosx_ncache_macmenu = 1;
  3760. continue;
  3761. }
  3762. if (!strcmp(arg, "-macuskbd")) {
  3763. macosx_us_kbd = 1;
  3764. continue;
  3765. }
  3766. if (!strcmp(arg, "-macnoopengl")) {
  3767. macosx_no_opengl = 1;
  3768. continue;
  3769. }
  3770. if (!strcmp(arg, "-macnorawfb")) {
  3771. macosx_no_rawfb = 1;
  3772. continue;
  3773. }
  3774. if (!strcmp(arg, "-gui")) {
  3775. launch_gui = 1;
  3776. if (i < argc-1) {
  3777. char *s = argv[i+1];
  3778. if (*s != '-') {
  3779. gui_str = strdup(s);
  3780. if (strstr(gui_str, "setp")) {
  3781. got_gui_pw = 1;
  3782. }
  3783. i++;
  3784. }
  3785. }
  3786. continue;
  3787. }
  3788. if (!strcmp(arg, "-remote") || !strcmp(arg, "-R")
  3789. || !strcmp(arg, "-r") || !strcmp(arg, "-remote-control")) {
  3790. char *str;
  3791. CHECK_ARGC
  3792. i++;
  3793. str = argv[i];
  3794. if (*str == '-') {
  3795. /* accidental leading '-' */
  3796. str++;
  3797. }
  3798. if (!strcmp(str, "ping")) {
  3799. query_cmd = strdup(str);
  3800. } else {
  3801. remote_cmd = strdup(str);
  3802. }
  3803. if (remote_cmd && strchr(remote_cmd, ':') == NULL) {
  3804. /* interpret -R -scale 3/4 at least */
  3805. if (i < argc-1 && *(argv[i+1]) != '-') {
  3806. int n;
  3807. /* it must be the parameter value */
  3808. i++;
  3809. n = strlen(remote_cmd) + strlen(argv[i]) + 2;
  3810. str = (char *) malloc(n);
  3811. sprintf(str, "%s:%s", remote_cmd, argv[i]);
  3812. free(remote_cmd);
  3813. remote_cmd = str;
  3814. }
  3815. }
  3816. if (!getenv("QUERY_VERBOSE")) {
  3817. quiet = 1;
  3818. }
  3819. xkbcompat = 0;
  3820. continue;
  3821. }
  3822. if (!strcmp(arg, "-query") || !strcmp(arg, "-Q")) {
  3823. CHECK_ARGC
  3824. query_cmd = strdup(argv[++i]);
  3825. if (!getenv("QUERY_VERBOSE")) {
  3826. quiet = 1;
  3827. }
  3828. xkbcompat = 0;
  3829. continue;
  3830. }
  3831. if (!strcmp(arg, "-query_retries")) {
  3832. char *s;
  3833. CHECK_ARGC
  3834. s = strdup(argv[++i]);
  3835. /* n[:t][/match] */
  3836. if (strchr(s, '/')) {
  3837. char *q = strchr(s, '/');
  3838. query_match = strdup(q+1);
  3839. *q = '\0';
  3840. }
  3841. if (strchr(s, ':')) {
  3842. char *q = strchr(s, ':');
  3843. query_delay = atof(q+1);
  3844. }
  3845. query_retries = atoi(s);
  3846. free(s);
  3847. continue;
  3848. }
  3849. if (!strcmp(arg, "-QD")) {
  3850. CHECK_ARGC
  3851. query_cmd = strdup(argv[++i]);
  3852. query_default = 1;
  3853. continue;
  3854. }
  3855. if (!strcmp(arg, "-sync")) {
  3856. remote_sync = 1;
  3857. continue;
  3858. }
  3859. if (!strcmp(arg, "-nosync")) {
  3860. remote_sync = 0;
  3861. continue;
  3862. }
  3863. if (!strcmp(arg, "-remote_prefix")) {
  3864. CHECK_ARGC
  3865. remote_prefix = strdup(argv[++i]);
  3866. continue;
  3867. }
  3868. if (!strcmp(arg, "-noremote")) {
  3869. accept_remote_cmds = 0;
  3870. continue;
  3871. }
  3872. if (!strcmp(arg, "-yesremote")) {
  3873. accept_remote_cmds = 1;
  3874. continue;
  3875. }
  3876. if (!strcmp(arg, "-unsafe")) {
  3877. safe_remote_only = 0;
  3878. continue;
  3879. }
  3880. if (!strcmp(arg, "-privremote")) {
  3881. priv_remote = 1;
  3882. continue;
  3883. }
  3884. if (!strcmp(arg, "-safer")) {
  3885. more_safe = 1;
  3886. continue;
  3887. }
  3888. if (!strcmp(arg, "-nocmds")) {
  3889. no_external_cmds = 1;
  3890. continue;
  3891. }
  3892. if (!strcmp(arg, "-allowedcmds")) {
  3893. CHECK_ARGC
  3894. allowed_external_cmds = strdup(argv[++i]);
  3895. continue;
  3896. }
  3897. if (!strcmp(arg, "-deny_all")) {
  3898. deny_all = 1;
  3899. continue;
  3900. }
  3901. if (!strcmp(arg, "-httpdir")) {
  3902. CHECK_ARGC
  3903. http_dir = strdup(argv[++i]);
  3904. got_httpdir = 1;
  3905. continue;
  3906. }
  3907. if (1) {
  3908. if (!strcmp(arg, "-desktop") && i < argc-1) {
  3909. dt = 1;
  3910. rfb_desktop_name = strdup(argv[i+1]);
  3911. }
  3912. if (!strcmp(arg, "-passwd")) {
  3913. pw_loc = i;
  3914. got_passwd = 1;
  3915. }
  3916. if (!strcmp(arg, "-rfbauth")) {
  3917. got_rfbauth = 1;
  3918. }
  3919. if (!strcmp(arg, "-rfbwait")) {
  3920. got_rfbwait = 1;
  3921. }
  3922. if (!strcmp(arg, "-deferupdate")) {
  3923. got_deferupdate = 1;
  3924. }
  3925. if (!strcmp(arg, "-rfbport") && i < argc-1) {
  3926. got_rfbport = 1;
  3927. if (!strcasecmp(argv[i+1], "prompt")) {
  3928. ;
  3929. } else if (!is_decimal(argv[i+1])) {
  3930. if (!got_inetd) {
  3931. rfbLog("Invalid -rfbport value: '%s'\n", argv[i+1]);
  3932. rfbLog("setting it to '-1' to induce failure.\n");
  3933. argv[i+1] = strdup("-1");
  3934. }
  3935. }
  3936. got_rfbport_str = strdup(argv[i+1]);
  3937. got_rfbport_pos = argc_vnc+1;
  3938. got_rfbport_val = atoi(argv[i+1]);
  3939. }
  3940. if (!strcmp(arg, "-httpport") && i < argc-1) {
  3941. if (!is_decimal(argv[i+1])) {
  3942. rfbLog("Invalid -httpport value: '%s'\n", argv[i+1]);
  3943. clean_up_exit(1);
  3944. }
  3945. }
  3946. if (!strcmp(arg, "-alwaysshared ")) {
  3947. got_alwaysshared = 1;
  3948. }
  3949. if (!strcmp(arg, "-nevershared")) {
  3950. got_nevershared = 1;
  3951. }
  3952. if (!strcmp(arg, "-listen") && i < argc-1) {
  3953. listen_str = strdup(argv[i+1]);
  3954. }
  3955. /* otherwise copy it for libvncserver use below. */
  3956. if (!strcmp(arg, "-ultrafilexfer")) {
  3957. got_ultrafilexfer = 1;
  3958. } else if (argc_vnc < argc_vnc_max) {
  3959. argv_vnc[argc_vnc++] = strdup(arg);
  3960. } else {
  3961. rfbLog("too many arguments.\n");
  3962. exit(1);
  3963. }
  3964. continue;
  3965. }
  3966. }
  3967. if (! getenv("NO_LIBXCB_ALLOW_SLOPPY_LOCK")) {
  3968. /* libxcb is a bit too strict for us sometimes... */
  3969. set_env("LIBXCB_ALLOW_SLOPPY_LOCK", "1");
  3970. }
  3971. if (getenv("PATH") == NULL || !strcmp(getenv("PATH"), "")) {
  3972. /* set a minimal PATH, usually only null in inetd. */
  3973. set_env("PATH", "/bin:/usr/bin");
  3974. }
  3975. /* handle -findauth case now that cmdline has been read */
  3976. if (got_findauth) {
  3977. char *s;
  3978. int ic = 0;
  3979. if (use_dpy != NULL) {
  3980. set_env("DISPLAY", use_dpy);
  3981. }
  3982. use_dpy = strdup("WAIT:cmd=FINDDISPLAY-run");
  3983. s = getenv("FINDAUTH_DISPLAY");
  3984. if (s && strcmp("", s)) {
  3985. set_env("DISPLAY", s);
  3986. }
  3987. s = getenv("DISPLAY");
  3988. if (s && strcmp("", s)) {
  3989. set_env("X11VNC_SKIP_DISPLAY", s);
  3990. } else {
  3991. set_env("X11VNC_SKIP_DISPLAY", ":0");
  3992. }
  3993. set_env("X11VNC_SKIP_DISPLAY_NEGATE", "1");
  3994. set_env("FIND_DISPLAY_XAUTHORITY_PATH", "1");
  3995. set_env("FIND_DISPLAY_NO_SHOW_XAUTH", "1");
  3996. set_env("FIND_DISPLAY_NO_SHOW_DISPLAY", "1");
  3997. wait_for_client(&ic, NULL, 0);
  3998. exit(0);
  3999. }
  4000. #ifndef WIN32
  4001. /* set OS struct UT */
  4002. uname(&UT);
  4003. #endif
  4004. orig_use_xdamage = use_xdamage;
  4005. if (!auto_port && getenv("AUTO_PORT")) {
  4006. auto_port = atoi(getenv("AUTO_PORT"));
  4007. }
  4008. if (getenv("X11VNC_LOOP_MODE")) {
  4009. if (bg && !getenv("X11VNC_LOOP_MODE_BG")) {
  4010. if (! quiet) {
  4011. fprintf(stderr, "disabling -bg in -loop "
  4012. "mode\n");
  4013. }
  4014. bg = 0;
  4015. } else if (!bg && getenv("X11VNC_LOOP_MODE_BG")) {
  4016. if (! quiet) {
  4017. fprintf(stderr, "enabling -bg in -loopbg "
  4018. "mode\n");
  4019. }
  4020. bg = 1;
  4021. }
  4022. if (inetd) {
  4023. if (! quiet) {
  4024. fprintf(stderr, "disabling -inetd in -loop "
  4025. "mode\n");
  4026. }
  4027. inetd = 0;
  4028. }
  4029. }
  4030. if (launch_gui && (query_cmd || remote_cmd)) {
  4031. launch_gui = 0;
  4032. gui_str = NULL;
  4033. }
  4034. if (more_safe) {
  4035. launch_gui = 0;
  4036. }
  4037. #ifdef MACOSX
  4038. if (! use_dpy) {
  4039. /* we need this for gui since no X properties */
  4040. if (!client_connect_file && !client_connect) {
  4041. char *user = get_user_name();
  4042. char *str = (char *) malloc(strlen(user) + strlen("/tmp/x11vnc-macosx-remote.") + 1);
  4043. struct stat sb;
  4044. sprintf(str, "/tmp/x11vnc-macosx-remote.%s", user);
  4045. if (!remote_cmd && !query_cmd) {
  4046. unlink(str);
  4047. if (stat(str, &sb) != 0) {
  4048. int fd = open(str, O_WRONLY|O_EXCL|O_CREAT, 0600);
  4049. if (fd >= 0) {
  4050. close(fd);
  4051. client_connect_file = str;
  4052. }
  4053. }
  4054. } else {
  4055. client_connect_file = str;
  4056. }
  4057. if (client_connect_file) {
  4058. if (!got_inetd) {
  4059. rfbLog("MacOS X: set -connect file to %s\n", client_connect_file);
  4060. }
  4061. }
  4062. }
  4063. }
  4064. #endif
  4065. if (got_rfbport_str != NULL && !strcasecmp(got_rfbport_str, "prompt")) {
  4066. char *opts, tport[32];
  4067. if (gui_str) {
  4068. opts = (char *) malloc(strlen(gui_str) + 32);
  4069. sprintf(opts, "%s,portprompt", gui_str);
  4070. } else {
  4071. opts = strdup("portprompt");
  4072. }
  4073. got_rfbport_val = -1;
  4074. do_gui(opts, 0);
  4075. if (got_rfbport_val == -1) {
  4076. rfbLog("Port prompt indicated cancel.\n");
  4077. clean_up_exit(1);
  4078. }
  4079. if (!got_inetd) {
  4080. rfbLog("Port prompt selected: %d\n", got_rfbport_val);
  4081. }
  4082. sprintf(tport, "%d", got_rfbport_val);
  4083. argv_vnc[got_rfbport_pos] = strdup(tport);
  4084. free(opts);
  4085. }
  4086. {
  4087. char num[32];
  4088. sprintf(num, "%d", got_rfbport_val);
  4089. set_env("X11VNC_GOT_RFBPORT_VAL", num);
  4090. }
  4091. if (got_ultrafilexfer && argc_vnc + 2 < argc_vnc_max) {
  4092. argv_vnc[argc_vnc++] = strdup("-rfbversion");
  4093. argv_vnc[argc_vnc++] = strdup("3.6");
  4094. argv_vnc[argc_vnc++] = strdup("-permitfiletransfer");
  4095. }
  4096. if (launch_gui) {
  4097. int sleep = 0;
  4098. if (SHOW_NO_PASSWORD_WARNING && !nopw) {
  4099. sleep = 1;
  4100. }
  4101. do_gui(gui_str, sleep);
  4102. }
  4103. if (logfile) {
  4104. int n;
  4105. char *pstr = "%VNCDISPLAY";
  4106. if (strstr(logfile, pstr)) {
  4107. char *h = this_host();
  4108. char *s, *q, *newlog;
  4109. int n, p = got_rfbport_val;
  4110. /* we don't really know the port yet... so guess */
  4111. if (p < 0) {
  4112. p = auto_port;
  4113. }
  4114. if (p <= 0) {
  4115. p = 5900;
  4116. }
  4117. s = (char *) malloc(strlen(h) + 32);
  4118. sprintf(s, "%s:%d", h, p);
  4119. n = 1;
  4120. q = logfile;
  4121. while (1) {
  4122. char *t = strstr(q, pstr);
  4123. if (!t) break;
  4124. n++;
  4125. q = t+1;
  4126. }
  4127. newlog = (char *) malloc(strlen(logfile) + n * strlen(pstr));
  4128. newlog[0] = '\0';
  4129. q = logfile;
  4130. while (1) {
  4131. char *t = strstr(q, pstr);
  4132. if (!t) {
  4133. strcat(newlog, q);
  4134. break;
  4135. }
  4136. strncat(newlog, q, t - q);
  4137. strcat(newlog, s);
  4138. q = t + strlen(pstr);
  4139. }
  4140. logfile = newlog;
  4141. if (!quiet && !got_inetd) {
  4142. rfbLog("Expanded logfile to '%s'\n", newlog);
  4143. }
  4144. free(s);
  4145. }
  4146. pstr = "%HOME";
  4147. if (strstr(logfile, pstr)) {
  4148. char *h = get_home_dir();
  4149. char *s, *q, *newlog;
  4150. s = (char *) malloc(strlen(h) + 32);
  4151. sprintf(s, "%s", h);
  4152. n = 1;
  4153. q = logfile;
  4154. while (1) {
  4155. char *t = strstr(q, pstr);
  4156. if (!t) break;
  4157. n++;
  4158. q = t+1;
  4159. }
  4160. newlog = (char *) malloc(strlen(logfile) + n * strlen(pstr));
  4161. newlog[0] = '\0';
  4162. q = logfile;
  4163. while (1) {
  4164. char *t = strstr(q, pstr);
  4165. if (!t) {
  4166. strcat(newlog, q);
  4167. break;
  4168. }
  4169. strncat(newlog, q, t - q);
  4170. strcat(newlog, s);
  4171. q = t + strlen(pstr);
  4172. }
  4173. logfile = newlog;
  4174. if (!quiet && !got_inetd) {
  4175. rfbLog("Expanded logfile to '%s'\n", newlog);
  4176. }
  4177. free(s);
  4178. }
  4179. if (logfile_append) {
  4180. n = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666);
  4181. } else {
  4182. n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
  4183. }
  4184. if (n < 0) {
  4185. fprintf(stderr, "error opening logfile: %s\n", logfile);
  4186. perror("open");
  4187. exit(1);
  4188. }
  4189. if (dup2(n, 2) < 0) {
  4190. fprintf(stderr, "dup2 failed\n");
  4191. perror("dup2");
  4192. exit(1);
  4193. }
  4194. if (n > 2) {
  4195. close(n);
  4196. }
  4197. }
  4198. if (ipv6_listen) {
  4199. if (inetd) {
  4200. ipv6_listen = 0;
  4201. }
  4202. }
  4203. if (inetd && quiet && !logfile) {
  4204. int n;
  4205. /*
  4206. * Redir stderr to /dev/null under -inetd and -quiet
  4207. * but no -o logfile. Typical problem:
  4208. * Xlib: extension "RECORD" missing on display ":1.0".
  4209. * If they want this info, they should use -o logfile,
  4210. * or no -q and 2>logfile.
  4211. */
  4212. n = open("/dev/null", O_WRONLY);
  4213. if (n >= 0) {
  4214. if (dup2(n, 2) >= 0) {
  4215. if (n > 2) {
  4216. close(n);
  4217. }
  4218. }
  4219. }
  4220. }
  4221. if (! quiet && ! inetd) {
  4222. int i;
  4223. if (http_oneport_msg) {
  4224. rfbLog("setting '-enc none' for -http_oneport mode.\n");
  4225. }
  4226. for (i=1; i < argc_vnc; i++) {
  4227. rfbLog("passing arg to libvncserver: %s\n", argv_vnc[i]);
  4228. if (!strcmp(argv_vnc[i], "-passwd")) {
  4229. i++;
  4230. }
  4231. }
  4232. }
  4233. if (remote_cmd || query_cmd) {
  4234. /*
  4235. * no need to open DISPLAY, just write it to the file now
  4236. * similar for query_default.
  4237. */
  4238. if (client_connect_file || query_default) {
  4239. int i, rc = 1;
  4240. for (i=0; i <= query_retries; i++) {
  4241. rc = do_remote_query(remote_cmd, query_cmd,
  4242. remote_sync, query_default);
  4243. if (rc == 0) {
  4244. if (query_match) {
  4245. if (query_result && strstr(query_result, query_match)) {
  4246. break;
  4247. }
  4248. rc = 1;
  4249. } else {
  4250. break;
  4251. }
  4252. }
  4253. if (i < query_retries) {
  4254. fprintf(stderr, "sleep: %.3f\n", query_delay);
  4255. usleep( (int) (query_delay * 1000 * 1000) );
  4256. }
  4257. }
  4258. fflush(stderr);
  4259. fflush(stdout);
  4260. exit(rc);
  4261. }
  4262. }
  4263. if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile && !unixpw) {
  4264. char *f, *h = getenv("HOME");
  4265. struct stat sbuf;
  4266. int found = 0, set_rfbauth = 0;
  4267. if (!h) {
  4268. rfbLog("HOME unset in -usepw mode.\n");
  4269. exit(1);
  4270. }
  4271. f = (char *) malloc(strlen(h)+strlen("/.vnc/passwdfile") + 1);
  4272. sprintf(f, "%s/.vnc/passwd", h);
  4273. if (stat(f, &sbuf) == 0) {
  4274. found = 1;
  4275. if (! quiet) {
  4276. rfbLog("-usepw: found %s\n", f);
  4277. }
  4278. got_rfbauth = 1;
  4279. set_rfbauth = 1;
  4280. }
  4281. sprintf(f, "%s/.vnc/passwdfile", h);
  4282. if (! found && stat(f, &sbuf) == 0) {
  4283. found = 1;
  4284. if (! quiet) {
  4285. rfbLog("-usepw: found %s\n", f);
  4286. }
  4287. got_passwdfile = 1;
  4288. passwdfile = strdup(f);
  4289. }
  4290. #if LIBVNCSERVER_HAVE_FORK
  4291. #if LIBVNCSERVER_HAVE_SYS_WAIT_H
  4292. #if LIBVNCSERVER_HAVE_WAITPID
  4293. if (! found) {
  4294. pid_t pid = fork();
  4295. if (pid < 0) {
  4296. ;
  4297. } else if (pid == 0) {
  4298. execlp(argv[0], argv[0], "-storepasswd",
  4299. (char *) NULL);
  4300. exit(1);
  4301. } else {
  4302. int s;
  4303. waitpid(pid, &s, 0);
  4304. if (WIFEXITED(s) && WEXITSTATUS(s) == 0) {
  4305. got_rfbauth = 1;
  4306. set_rfbauth = 1;
  4307. found = 1;
  4308. }
  4309. }
  4310. }
  4311. #endif
  4312. #endif
  4313. #endif
  4314. if (set_rfbauth) {
  4315. sprintf(f, "%s/.vnc/passwd", h);
  4316. if (argc_vnc < 100) {
  4317. argv_vnc[argc_vnc++] = strdup("-rfbauth");
  4318. } else {
  4319. exit(1);
  4320. }
  4321. if (argc_vnc < 100) {
  4322. argv_vnc[argc_vnc++] = strdup(f);
  4323. } else {
  4324. exit(1);
  4325. }
  4326. }
  4327. if (! found) {
  4328. fprintf(stderr, "x11vnc -usepw: could not find"
  4329. " a password to use.\n");
  4330. exit(1);
  4331. }
  4332. free(f);
  4333. }
  4334. if (got_rfbauth && (got_passwd || got_viewpasswd || got_passwdfile)) {
  4335. fprintf(stderr, "option -rfbauth is incompatible with:\n");
  4336. fprintf(stderr, " -passwd, -viewpasswd, and -passwdfile\n");
  4337. exit(1);
  4338. }
  4339. if (got_passwdfile && (got_passwd || got_viewpasswd)) {
  4340. fprintf(stderr, "option -passwdfile is incompatible with:\n");
  4341. fprintf(stderr, " -passwd and -viewpasswd\n");
  4342. exit(1);
  4343. }
  4344. /*
  4345. * If -passwd was used, clear it out of argv. This does not
  4346. * work on all UNIX, have to use execvp() in general...
  4347. */
  4348. if (pw_loc > 0) {
  4349. int i;
  4350. for (i=pw_loc; i <= pw_loc+1; i++) {
  4351. if (i < argc) {
  4352. char *p = argv[i];
  4353. strzero(p);
  4354. }
  4355. }
  4356. } else if (passwdfile) {
  4357. /* read passwd(s) from file */
  4358. if (strstr(passwdfile, "cmd:") == passwdfile ||
  4359. strstr(passwdfile, "custom:") == passwdfile) {
  4360. char tstr[100], *q;
  4361. sprintf(tstr, "%f", dnow());
  4362. if ((q = strrchr(tstr, '.')) == NULL) {
  4363. q = tstr;
  4364. } else {
  4365. q++;
  4366. }
  4367. /* never used under cmd:, used to force auth */
  4368. argv_vnc[argc_vnc++] = strdup("-passwd");
  4369. argv_vnc[argc_vnc++] = strdup(q);
  4370. } else if (read_passwds(passwdfile)) {
  4371. argv_vnc[argc_vnc++] = strdup("-passwd");
  4372. argv_vnc[argc_vnc++] = strdup(passwd_list[0]);
  4373. }
  4374. got_passwd = 1;
  4375. pw_loc = 100; /* just for pw_loc check below */
  4376. }
  4377. if (vpw_loc > 0) {
  4378. int i;
  4379. for (i=vpw_loc; i <= vpw_loc+1; i++) {
  4380. if (i < argc) {
  4381. char *p = argv[i];
  4382. strzero(p);
  4383. }
  4384. }
  4385. }
  4386. #ifdef HARDWIRE_PASSWD
  4387. if (!got_rfbauth && !got_passwd) {
  4388. argv_vnc[argc_vnc++] = strdup("-passwd");
  4389. argv_vnc[argc_vnc++] = strdup(HARDWIRE_PASSWD);
  4390. got_passwd = 1;
  4391. pw_loc = 100;
  4392. }
  4393. #endif
  4394. #ifdef HARDWIRE_VIEWPASSWD
  4395. if (!got_rfbauth && got_passwd && !viewonly_passwd && !passwd_list) {
  4396. viewonly_passwd = strdup(HARDWIRE_VIEWPASSWD);
  4397. }
  4398. #endif
  4399. if (viewonly_passwd && pw_loc < 0) {
  4400. rfbLog("-passwd must be supplied when using -viewpasswd\n");
  4401. exit(1);
  4402. }
  4403. if (1) {
  4404. /* mix things up a little bit */
  4405. unsigned char buf[CHALLENGESIZE];
  4406. int k, kmax = (int) (50 * rfac()) + 10;
  4407. for (k=0; k < kmax; k++) {
  4408. rfbRandomBytes(buf);
  4409. }
  4410. }
  4411. if (SHOW_NO_PASSWORD_WARNING) {
  4412. char message[] = "-rfbauth, -passwdfile, -passwd password, "
  4413. "or -unixpw required.";
  4414. if (! nopw) {
  4415. nopassword_warning_msg(got_localhost);
  4416. }
  4417. #if PASSWD_REQUIRED
  4418. rfbLog("%s\n", message);
  4419. exit(1);
  4420. #endif
  4421. #if PASSWD_UNLESS_NOPW
  4422. if (! nopw) {
  4423. rfbLog("%s\n", message);
  4424. exit(1);
  4425. }
  4426. #endif
  4427. message[0] = '\0'; /* avoid compiler warning */
  4428. }
  4429. if (more_safe) {
  4430. if (! quiet) {
  4431. rfbLog("-safer mode:\n");
  4432. rfbLog(" vnc_connect=0\n");
  4433. rfbLog(" accept_remote_cmds=0\n");
  4434. rfbLog(" safe_remote_only=1\n");
  4435. rfbLog(" launch_gui=0\n");
  4436. }
  4437. vnc_connect = 0;
  4438. accept_remote_cmds = 0;
  4439. safe_remote_only = 1;
  4440. launch_gui = 0;
  4441. }
  4442. if (users_list && strchr(users_list, '.')) {
  4443. char *p, *q, *tmp = (char *) malloc(strlen(users_list)+1);
  4444. char *str = strdup(users_list);
  4445. int i, n, db = 1;
  4446. tmp[0] = '\0';
  4447. n = strlen(users_list) + 1;
  4448. user2group = (char **) malloc(n * sizeof(char *));
  4449. for (i=0; i<n; i++) {
  4450. user2group[i] = NULL;
  4451. }
  4452. i = 0;
  4453. p = strtok(str, ",");
  4454. if (db) fprintf(stderr, "users_list: %s\n", users_list);
  4455. while (p) {
  4456. if (tmp[0] != '\0') {
  4457. strcat(tmp, ",");
  4458. }
  4459. q = strchr(p, '.');
  4460. if (q) {
  4461. char *s = strchr(p, '=');
  4462. if (! s) {
  4463. s = p;
  4464. } else {
  4465. s++;
  4466. }
  4467. if (s[0] == '+') s++;
  4468. user2group[i++] = strdup(s);
  4469. if (db) fprintf(stderr, "u2g: %s\n", s);
  4470. *q = '\0';
  4471. }
  4472. strcat(tmp, p);
  4473. p = strtok(NULL, ",");
  4474. }
  4475. free(str);
  4476. users_list = tmp;
  4477. if (db) fprintf(stderr, "users_list: %s\n", users_list);
  4478. }
  4479. if (got_tls > 0 && !use_openssl) {
  4480. rfbLog("SSL: Error: you did not supply the '-ssl ...' option even\n");
  4481. rfbLog("SSL: though you supplied one of these related options:\n");
  4482. rfbLog("SSL: -sslonly, -sslverify, -sslCRL, -vencrypt, -anontls,\n");
  4483. rfbLog("SSL: -dhparams, -https, -http_ssl, or -httpsredir.\n");
  4484. rfbLog("SSL: Restart with, for example, '-ssl SAVE' on the cmd line.\n");
  4485. rfbLog("SSL: See the '-ssl' x11vnc -help description for more info.\n");
  4486. if (!getenv("X11VNC_FORCE_NO_OPENSSL")) {
  4487. exit(1);
  4488. }
  4489. }
  4490. if (unixpw) {
  4491. if (inetd) {
  4492. use_stunnel = 0;
  4493. }
  4494. if (! use_stunnel && ! use_openssl) {
  4495. if (getenv("UNIXPW_DISABLE_SSL")) {
  4496. rfbLog("Skipping -ssl/-stunnel requirement"
  4497. " due to\n");
  4498. rfbLog("UNIXPW_DISABLE_SSL setting.\n");
  4499. if (!getenv("UNIXPW_DISABLE_LOCALHOST")) {
  4500. if (!got_localhost) {
  4501. rfbLog("Forcing -localhost mode.\n");
  4502. }
  4503. allow_list = strdup("127.0.0.1");
  4504. got_localhost = 1;
  4505. }
  4506. } else if (have_ssh_env()) {
  4507. char *s = getenv("SSH_CONNECTION");
  4508. if (! s) s = getenv("SSH_CLIENT");
  4509. if (! s) s = "SSH_CONNECTION";
  4510. fprintf(stderr, "\n");
  4511. rfbLog("Skipping -ssl/-stunnel constraint in"
  4512. " -unixpw mode,\n");
  4513. rfbLog("assuming your SSH encryption"
  4514. " is:\n");
  4515. rfbLog(" %s\n", s);
  4516. if (!getenv("UNIXPW_DISABLE_LOCALHOST")) {
  4517. if (!got_localhost) {
  4518. rfbLog("Setting -localhost in SSH + -unixpw mode.\n");
  4519. }
  4520. allow_list = strdup("127.0.0.1");
  4521. got_localhost = 1;
  4522. }
  4523. rfbLog("If you *actually* want SSL, restart"
  4524. " with -ssl on the cmdline\n");
  4525. if (! nopw) {
  4526. usleep(2000*1000);
  4527. }
  4528. } else {
  4529. if (openssl_present()) {
  4530. rfbLog("set -ssl in -unixpw mode.\n");
  4531. use_openssl = 1;
  4532. } else if (inetd) {
  4533. rfbLog("could not set -ssl in -inetd"
  4534. " + -unixpw mode.\n");
  4535. exit(1);
  4536. } else {
  4537. rfbLog("set -stunnel in -unixpw mode.\n");
  4538. use_stunnel = 1;
  4539. }
  4540. }
  4541. rfbLog("\n");
  4542. }
  4543. if (use_threads && !getenv("UNIXPW_THREADS")) {
  4544. if (! quiet) {
  4545. rfbLog("disabling -threads under -unixpw\n");
  4546. rfbLog("\n");
  4547. }
  4548. use_threads = 0;
  4549. }
  4550. }
  4551. if (use_stunnel && ! got_localhost) {
  4552. if (! getenv("STUNNEL_DISABLE_LOCALHOST") &&
  4553. ! getenv("UNIXPW_DISABLE_LOCALHOST")) {
  4554. if (! quiet) {
  4555. rfbLog("Setting -localhost in -stunnel mode.\n");
  4556. }
  4557. allow_list = strdup("127.0.0.1");
  4558. got_localhost = 1;
  4559. }
  4560. }
  4561. if (ssl_verify && ! use_stunnel && ! use_openssl) {
  4562. rfbLog("-sslverify must be used with -ssl or -stunnel\n");
  4563. exit(1);
  4564. }
  4565. if (https_port_num >= 0 && ! use_openssl) {
  4566. rfbLog("-https must be used with -ssl\n");
  4567. exit(1);
  4568. }
  4569. if (use_threads && !got_noxrandr) {
  4570. xrandr = 1;
  4571. if (! quiet) {
  4572. rfbLog("enabling -xrandr in -threads mode.\n");
  4573. }
  4574. }
  4575. /* fixup settings that do not make sense */
  4576. if (use_threads && nofb && cursor_pos_updates) {
  4577. if (! quiet) {
  4578. rfbLog("disabling -threads under -nofb -cursorpos\n");
  4579. }
  4580. use_threads = 0;
  4581. }
  4582. if (tile_fuzz < 1) {
  4583. tile_fuzz = 1;
  4584. }
  4585. if (waitms < 0) {
  4586. waitms = 0;
  4587. }
  4588. if (alpha_threshold < 0) {
  4589. alpha_threshold = 0;
  4590. }
  4591. if (alpha_threshold > 256) {
  4592. alpha_threshold = 256;
  4593. }
  4594. if (alpha_frac < 0.0) {
  4595. alpha_frac = 0.0;
  4596. }
  4597. if (alpha_frac > 1.0) {
  4598. alpha_frac = 1.0;
  4599. }
  4600. if (alpha_blend) {
  4601. alpha_remove = 0;
  4602. }
  4603. if (cmap8to24 && overlay) {
  4604. if (! quiet) {
  4605. rfbLog("disabling -overlay in -8to24 mode.\n");
  4606. }
  4607. overlay = 0;
  4608. }
  4609. if (tightfilexfer && view_only) {
  4610. if (! quiet) {
  4611. rfbLog("setting -notightfilexfer in -viewonly mode.\n");
  4612. }
  4613. /* how to undo via -R? */
  4614. tightfilexfer = 0;
  4615. }
  4616. if (inetd) {
  4617. shared = 0;
  4618. connect_once = 1;
  4619. bg = 0;
  4620. if (use_stunnel) {
  4621. exit(1);
  4622. }
  4623. }
  4624. http_try_it = try_http;
  4625. if (flip_byte_order && using_shm && ! quiet) {
  4626. rfbLog("warning: -flipbyte order only works with -noshm\n");
  4627. }
  4628. if (! wireframe_copyrect) {
  4629. set_wirecopyrect_mode(NULL);
  4630. }
  4631. if (! scroll_copyrect) {
  4632. set_scrollcopyrect_mode(NULL);
  4633. }
  4634. if (screen_fixup_str) {
  4635. parse_fixscreen();
  4636. }
  4637. initialize_scroll_matches();
  4638. initialize_scroll_term();
  4639. initialize_max_keyrepeat();
  4640. /* increase rfbwait if threaded */
  4641. if (use_threads && ! got_rfbwait) {
  4642. /* ??? lower this ??? */
  4643. rfbMaxClientWait = 604800000;
  4644. }
  4645. /* no framebuffer (Win2VNC) mode */
  4646. if (nofb) {
  4647. /* disable things that do not make sense with no fb */
  4648. set_nofb_params(0);
  4649. if (! got_deferupdate && ! got_defer) {
  4650. /* reduce defer time under -nofb */
  4651. defer_update = defer_update_nofb;
  4652. }
  4653. if (got_pointer_mode < 0) {
  4654. pointer_mode = POINTER_MODE_NOFB;
  4655. }
  4656. }
  4657. if (ncache < 0) {
  4658. ncache_beta_tester = 1;
  4659. ncache_msg = 1;
  4660. if (ncache == -1) {
  4661. ncache = 0;
  4662. }
  4663. ncache = -ncache;
  4664. if (try_http || got_httpdir) {
  4665. /* JVM usually not set to handle all the memory */
  4666. ncache = 0;
  4667. ncache_msg = 0;
  4668. }
  4669. if (subwin) {
  4670. ncache = 0;
  4671. ncache_msg = 0;
  4672. }
  4673. }
  4674. if (raw_fb_str) {
  4675. set_raw_fb_params(0);
  4676. }
  4677. if (! got_deferupdate) {
  4678. char tmp[40];
  4679. sprintf(tmp, "%d", defer_update);
  4680. argv_vnc[argc_vnc++] = strdup("-deferupdate");
  4681. argv_vnc[argc_vnc++] = strdup(tmp);
  4682. }
  4683. if (debug_pointer || debug_keyboard) {
  4684. if (!logfile) {
  4685. if (bg || quiet) {
  4686. rfbLog("disabling -bg/-q under -debug_pointer"
  4687. "/-debug_keyboard\n");
  4688. bg = 0;
  4689. quiet = 0;
  4690. }
  4691. }
  4692. }
  4693. /* initialize added_keysyms[] array to zeros */
  4694. add_keysym(NoSymbol);
  4695. /* tie together cases of -localhost vs. -listen localhost */
  4696. if (! listen_str) {
  4697. if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
  4698. listen_str = strdup("localhost");
  4699. argv_vnc[argc_vnc++] = strdup("-listen");
  4700. argv_vnc[argc_vnc++] = strdup(listen_str);
  4701. }
  4702. } else if (!strcmp(listen_str, "localhost") ||
  4703. !strcmp(listen_str, "127.0.0.1")) {
  4704. allow_list = strdup("127.0.0.1");
  4705. }
  4706. initialize_crash_handler();
  4707. if (! quiet) {
  4708. if (verbose) {
  4709. print_settings(try_http, bg, gui_str);
  4710. }
  4711. rfbLog("x11vnc version: %s pid: %d\n", lastmod, getpid());
  4712. } else {
  4713. rfbLogEnable(0);
  4714. }
  4715. X_INIT;
  4716. SCR_INIT;
  4717. CLIENT_INIT;
  4718. INPUT_INIT;
  4719. POINTER_INIT;
  4720. /* open the X display: */
  4721. #if LIBVNCSERVER_HAVE_XKEYBOARD
  4722. /*
  4723. * Disable XKEYBOARD before calling XOpenDisplay()
  4724. * this should be used if there is ambiguity in the keymapping.
  4725. */
  4726. if (xkbcompat) {
  4727. Bool rc = XkbIgnoreExtension(True);
  4728. if (! quiet) {
  4729. rfbLog("Disabling xkb XKEYBOARD extension. rc=%d\n",
  4730. rc);
  4731. }
  4732. if (watch_bell) {
  4733. watch_bell = 0;
  4734. if (! quiet) rfbLog("Disabling bell.\n");
  4735. }
  4736. }
  4737. #else
  4738. watch_bell = 0;
  4739. use_xkb_modtweak = 0;
  4740. #endif
  4741. #ifdef LIBVNCSERVER_WITH_TIGHTVNC_FILETRANSFER
  4742. if (tightfilexfer) {
  4743. rfbLog("rfbRegisterTightVNCFileTransferExtension: 6\n");
  4744. rfbRegisterTightVNCFileTransferExtension();
  4745. } else {
  4746. if (0) rfbLog("rfbUnregisterTightVNCFileTransferExtension: 3\n");
  4747. rfbUnregisterTightVNCFileTransferExtension();
  4748. }
  4749. #endif
  4750. initialize_allowed_input();
  4751. if (display_N && !got_rfbport) {
  4752. char *ud = use_dpy;
  4753. if (ud == NULL) {
  4754. ud = getenv("DISPLAY");
  4755. }
  4756. if (ud && strstr(ud, "cmd=") == NULL) {
  4757. char *p;
  4758. ud = strdup(ud);
  4759. p = strrchr(ud, ':');
  4760. if (p) {
  4761. int N;
  4762. char *q = strchr(p, '.');
  4763. if (q) {
  4764. *q = '\0';
  4765. }
  4766. N = atoi(p+1);
  4767. if (argc_vnc+1 < argc_vnc_max) {
  4768. char Nstr[16];
  4769. sprintf(Nstr, "%d", (5900 + N) % 65536);
  4770. argv_vnc[argc_vnc++] = strdup("-rfbport");
  4771. argv_vnc[argc_vnc++] = strdup(Nstr);
  4772. got_rfbport = 1;
  4773. }
  4774. }
  4775. free(ud);
  4776. }
  4777. }
  4778. if (users_list && strstr(users_list, "lurk=")) {
  4779. if (use_dpy) {
  4780. rfbLog("warning: -display does not make sense in "
  4781. "\"lurk=\" mode...\n");
  4782. }
  4783. if (auth_file != NULL && strcmp(auth_file, "guess")) {
  4784. set_env("XAUTHORITY", auth_file);
  4785. }
  4786. lurk_loop(users_list);
  4787. } else if (use_dpy && strstr(use_dpy, "WAIT:") == use_dpy) {
  4788. char *mcm = multiple_cursors_mode;
  4789. if (strstr(use_dpy, "Xdummy")) {
  4790. if (!xrandr && !got_noxrandr) {
  4791. if (! quiet) {
  4792. rfbLog("Enabling -xrandr for possible use of Xdummy server.\n");
  4793. }
  4794. xrandr = 1;
  4795. }
  4796. }
  4797. waited_for_client = wait_for_client(&argc_vnc, argv_vnc,
  4798. try_http && ! got_httpdir);
  4799. if (!mcm && multiple_cursors_mode) {
  4800. free(multiple_cursors_mode);
  4801. multiple_cursors_mode = NULL;
  4802. }
  4803. }
  4804. if (auth_file) {
  4805. check_guess_auth_file();
  4806. if (auth_file != NULL) {
  4807. set_env("XAUTHORITY", auth_file);
  4808. }
  4809. }
  4810. #ifdef MACOSX
  4811. if (use_dpy && !strcmp(use_dpy, "console")) {
  4812. ;
  4813. } else
  4814. #endif
  4815. if (use_dpy && strcmp(use_dpy, "")) {
  4816. dpy = XOpenDisplay_wr(use_dpy);
  4817. #ifdef MACOSX
  4818. } else if (!subwin && getenv("DISPLAY")
  4819. && strstr(getenv("DISPLAY"), "/tmp/") ) {
  4820. /* e.g. /tmp/launch-XlspvM/:0 on leopard */
  4821. rfbLog("MacOSX: Ignoring $DISPLAY '%s'\n", getenv("DISPLAY"));
  4822. rfbLog("MacOSX: Use -display $DISPLAY to force it.\n");
  4823. #endif
  4824. } else if (raw_fb_str != NULL && raw_fb_str[0] != '+' && !got_noviewonly) {
  4825. rfbLog("Not opening DISPLAY in -rawfb mode (force via -rawfb +str)\n");
  4826. dpy = NULL; /* don't open it. */
  4827. } else if ( (use_dpy = getenv("DISPLAY")) ) {
  4828. if (strstr(use_dpy, "localhost") == use_dpy) {
  4829. rfbLog("\n");
  4830. rfbLog("WARNING: DISPLAY starts with localhost: '%s'\n", use_dpy);
  4831. rfbLog("WARNING: Is this an SSH X11 port forwarding? You most\n");
  4832. rfbLog("WARNING: likely don't want x11vnc to use that DISPLAY.\n");
  4833. rfbLog("WARNING: You probably should supply something\n");
  4834. rfbLog("WARNING: like: -display :0 to access the physical\n");
  4835. rfbLog("WARNING: X display on the machine where x11vnc is running.\n");
  4836. rfbLog("\n");
  4837. usleep(500 * 1000);
  4838. } else if (using_shm && use_dpy[0] != ':') {
  4839. rfbLog("\n");
  4840. rfbLog("WARNING: DISPLAY might not be local: '%s'\n", use_dpy);
  4841. rfbLog("WARNING: Is this the DISPLAY of another machine? Usually,\n");
  4842. rfbLog("WARNING: x11vnc is run on the same machine with the\n");
  4843. rfbLog("WARNING: physical X display to be exported by VNC. If\n");
  4844. rfbLog("WARNING: that is what you really meant, supply something\n");
  4845. rfbLog("WARNING: like: -display :0 on the x11vnc command line.\n");
  4846. rfbLog("\n");
  4847. usleep(250 * 1000);
  4848. }
  4849. dpy = XOpenDisplay_wr(use_dpy);
  4850. } else {
  4851. dpy = XOpenDisplay_wr("");
  4852. }
  4853. last_open_xdisplay = time(NULL);
  4854. if (terminal_services_daemon != NULL) {
  4855. terminal_services(terminal_services_daemon);
  4856. exit(0);
  4857. }
  4858. if (dpy && !xrandr && !got_noxrandr) {
  4859. #if !NO_X11
  4860. Atom trap_xrandr = XInternAtom(dpy, "X11VNC_TRAP_XRANDR", True);
  4861. if (trap_xrandr != None) {
  4862. if (! quiet) {
  4863. rfbLog("Enabling -xrandr due to X11VNC_TRAP_XRANDR atom.\n");
  4864. }
  4865. xrandr = 1;
  4866. }
  4867. #endif
  4868. }
  4869. #ifdef MACOSX
  4870. if (! dpy && ! raw_fb_str) {
  4871. raw_fb_str = strdup("console");
  4872. }
  4873. #endif
  4874. if (! dpy && raw_fb_str) {
  4875. rfbLog("Continuing without X display in -rawfb mode.\n");
  4876. goto raw_fb_pass_go_and_collect_200_dollars;
  4877. }
  4878. if (! dpy && ! use_dpy && ! getenv("DISPLAY")) {
  4879. int i, s = 4;
  4880. rfbLogEnable(1);
  4881. rfbLog("\a\n");
  4882. rfbLog("*** XOpenDisplay failed. No -display or DISPLAY.\n");
  4883. rfbLog("*** Trying \":0\" in %d seconds. Press Ctrl-C to"
  4884. " abort.\n", s);
  4885. rfbLog("*** ");
  4886. for (i=1; i<=s; i++) {
  4887. fprintf(stderr, "%d ", i);
  4888. sleep(1);
  4889. }
  4890. fprintf(stderr, "\n");
  4891. use_dpy = ":0";
  4892. dpy = XOpenDisplay_wr(use_dpy);
  4893. last_open_xdisplay = time(NULL);
  4894. if (dpy) {
  4895. rfbLog("*** XOpenDisplay of \":0\" successful.\n");
  4896. }
  4897. rfbLog("\n");
  4898. if (quiet) rfbLogEnable(0);
  4899. }
  4900. if (! dpy) {
  4901. char *d = use_dpy;
  4902. if (!d) d = getenv("DISPLAY");
  4903. if (!d) d = "null";
  4904. rfbLogEnable(1);
  4905. fprintf(stderr, "\n");
  4906. rfbLog("***************************************\n", d);
  4907. rfbLog("*** XOpenDisplay failed (%s)\n", d);
  4908. xopen_display_fail_message(d);
  4909. exit(1);
  4910. } else if (use_dpy) {
  4911. if (! quiet) rfbLog("Using X display %s\n", use_dpy);
  4912. } else {
  4913. if (! quiet) rfbLog("Using default X display.\n");
  4914. }
  4915. if (clip_str != NULL && dpy != NULL) {
  4916. check_xinerama_clip();
  4917. }
  4918. scr = DefaultScreen(dpy);
  4919. rootwin = RootWindow(dpy, scr);
  4920. #if !NO_X11
  4921. if (dpy) {
  4922. Window w = XCreateSimpleWindow(dpy, rootwin, 0, 0, 1, 1, 0, 0, 0);
  4923. if (! quiet) rfbLog("rootwin: 0x%lx reswin: 0x%lx dpy: 0x%x\n", rootwin, w, dpy);
  4924. if (w != None) {
  4925. XDestroyWindow(dpy, w);
  4926. }
  4927. XSync(dpy, False);
  4928. }
  4929. #endif
  4930. if (ncache_beta_tester) {
  4931. int h = DisplayHeight(dpy, scr);
  4932. int w = DisplayWidth(dpy, scr);
  4933. int mem = (w * h * 4) / (1000 * 1000), MEM = 96;
  4934. if (mem < 1) mem = 1;
  4935. /* limit poor, unsuspecting beta tester's viewer to 96 MB */
  4936. if ( (ncache+2) * mem > MEM ) {
  4937. int n = (MEM/mem) - 2;
  4938. if (n < 0) n = 0;
  4939. n = 2 * (n / 2);
  4940. if (n < ncache) {
  4941. ncache = n;
  4942. }
  4943. }
  4944. }
  4945. if (grab_always) {
  4946. Window save = window;
  4947. window = rootwin;
  4948. adjust_grabs(1, 0);
  4949. window = save;
  4950. }
  4951. if ( (remote_cmd && strstr(remote_cmd, "DIRECT:") == remote_cmd)
  4952. || (query_cmd && strstr(query_cmd, "DIRECT:") == query_cmd )) {
  4953. /* handled below after most everything is setup. */
  4954. if (getenv("QUERY_VERBOSE")) {
  4955. quiet = 0;
  4956. } else {
  4957. quiet = 1;
  4958. remote_direct = 1;
  4959. }
  4960. if (!auto_port) {
  4961. auto_port = 5970;
  4962. }
  4963. } else if (remote_cmd || query_cmd) {
  4964. int i, rc = 1;
  4965. for (i=0; i <= query_retries; i++) {
  4966. rc = do_remote_query(remote_cmd, query_cmd, remote_sync,
  4967. query_default);
  4968. if (rc == 0) {
  4969. if (query_match) {
  4970. if (query_result && strstr(query_result, query_match)) {
  4971. break;
  4972. }
  4973. rc = 1;
  4974. } else {
  4975. break;
  4976. }
  4977. }
  4978. if (i < query_retries) {
  4979. fprintf(stderr, "sleep: %.3f\n", query_delay);
  4980. usleep( (int) (query_delay * 1000 * 1000) );
  4981. }
  4982. }
  4983. XFlush_wr(dpy);
  4984. fflush(stderr);
  4985. fflush(stdout);
  4986. usleep(30 * 1000); /* still needed? */
  4987. XCloseDisplay_wr(dpy);
  4988. exit(rc);
  4989. }
  4990. if (! quiet && ! raw_fb_str) {
  4991. rfbLog("\n");
  4992. rfbLog("------------------ USEFUL INFORMATION ------------------\n");
  4993. }
  4994. if (priv_remote) {
  4995. if (! remote_control_access_ok()) {
  4996. rfbLog("** Disabling remote commands in -privremote mode.\n");
  4997. accept_remote_cmds = 0;
  4998. }
  4999. }
  5000. sync_tod_with_servertime();
  5001. if (grab_buster) {
  5002. spawn_grab_buster();
  5003. }
  5004. #if LIBVNCSERVER_HAVE_LIBXFIXES
  5005. if (! XFixesQueryExtension(dpy, &xfixes_base_event_type, &er)) {
  5006. if (! quiet && ! raw_fb_str) {
  5007. rfbLog("Disabling XFIXES mode: display does not support it.\n");
  5008. }
  5009. xfixes_base_event_type = 0;
  5010. xfixes_present = 0;
  5011. } else {
  5012. xfixes_present = 1;
  5013. }
  5014. #endif
  5015. if (! xfixes_present) {
  5016. use_xfixes = 0;
  5017. }
  5018. #if LIBVNCSERVER_HAVE_LIBXDAMAGE
  5019. if (! XDamageQueryExtension(dpy, &xdamage_base_event_type, &er)) {
  5020. if (! quiet && ! raw_fb_str) {
  5021. rfbLog("Disabling X DAMAGE mode: display does not support it.\n");
  5022. }
  5023. xdamage_base_event_type = 0;
  5024. xdamage_present = 0;
  5025. } else {
  5026. xdamage_present = 1;
  5027. }
  5028. #endif
  5029. if (! xdamage_present) {
  5030. use_xdamage = 0;
  5031. }
  5032. if (! quiet && xdamage_present && use_xdamage && ! raw_fb_str) {
  5033. rfbLog("X DAMAGE available on display, using it for polling hints.\n");
  5034. rfbLog(" To disable this behavior use: '-noxdamage'\n");
  5035. rfbLog("\n");
  5036. rfbLog(" Most compositing window managers like 'compiz' or 'beryl'\n");
  5037. rfbLog(" cause X DAMAGE to fail, and so you may not see any screen\n");
  5038. rfbLog(" updates via VNC. Either disable 'compiz' (recommended) or\n");
  5039. rfbLog(" supply the x11vnc '-noxdamage' command line option.\n");
  5040. }
  5041. if (! quiet && wireframe && ! raw_fb_str) {
  5042. rfbLog("\n");
  5043. rfbLog("Wireframing: -wireframe mode is in effect for window moves.\n");
  5044. rfbLog(" If this yields undesired behavior (poor response, painting\n");
  5045. rfbLog(" errors, etc) it may be disabled:\n");
  5046. rfbLog(" - use '-nowf' to disable wireframing completely.\n");
  5047. rfbLog(" - use '-nowcr' to disable the Copy Rectangle after the\n");
  5048. rfbLog(" moved window is released in the new position.\n");
  5049. rfbLog(" Also see the -help entry for tuning parameters.\n");
  5050. rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
  5051. rfbLog(" repaint the screen, also see the -fixscreen option for\n");
  5052. rfbLog(" periodic repaints.\n");
  5053. if (scale_str && !strstr(scale_str, "nocr")) {
  5054. rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
  5055. }
  5056. }
  5057. overlay_present = 0;
  5058. #if defined(SOLARIS_OVERLAY) && !NO_X11
  5059. if (! XQueryExtension(dpy, "SUN_OVL", &maj, &ev, &er)) {
  5060. if (! quiet && overlay && ! raw_fb_str) {
  5061. rfbLog("Disabling -overlay: SUN_OVL extension not available.\n");
  5062. }
  5063. } else {
  5064. overlay_present = 1;
  5065. }
  5066. #endif
  5067. #if defined(IRIX_OVERLAY) && !NO_X11
  5068. if (! XReadDisplayQueryExtension(dpy, &ev, &er)) {
  5069. if (! quiet && overlay && ! raw_fb_str) {
  5070. rfbLog("Disabling -overlay: IRIX ReadDisplay extension not available.\n");
  5071. }
  5072. } else {
  5073. overlay_present = 1;
  5074. }
  5075. #endif
  5076. if (overlay && !overlay_present) {
  5077. overlay = 0;
  5078. overlay_cursor = 0;
  5079. }
  5080. /* cursor shapes setup */
  5081. if (! multiple_cursors_mode) {
  5082. multiple_cursors_mode = strdup("default");
  5083. }
  5084. if (show_cursor) {
  5085. if(!strcmp(multiple_cursors_mode, "default")
  5086. && xfixes_present && use_xfixes) {
  5087. free(multiple_cursors_mode);
  5088. multiple_cursors_mode = strdup("most");
  5089. if (! quiet && ! raw_fb_str) {
  5090. rfbLog("\n");
  5091. rfbLog("XFIXES available on display, resetting cursor mode\n");
  5092. rfbLog(" to: '-cursor most'.\n");
  5093. rfbLog(" to disable this behavior use: '-cursor arrow'\n");
  5094. rfbLog(" or '-noxfixes'.\n");
  5095. }
  5096. }
  5097. if(!strcmp(multiple_cursors_mode, "most")) {
  5098. if (xfixes_present && use_xfixes &&
  5099. overlay_cursor == 1) {
  5100. if (! quiet && ! raw_fb_str) {
  5101. rfbLog("using XFIXES for cursor drawing.\n");
  5102. }
  5103. overlay_cursor = 0;
  5104. }
  5105. }
  5106. }
  5107. if (overlay) {
  5108. using_shm = 0;
  5109. if (flash_cmap && ! quiet && ! raw_fb_str) {
  5110. rfbLog("warning: -flashcmap may be incompatible with -overlay\n");
  5111. }
  5112. if (show_cursor && overlay_cursor) {
  5113. char *s = multiple_cursors_mode;
  5114. if (*s == 'X' || !strcmp(s, "some") ||
  5115. !strcmp(s, "arrow")) {
  5116. /*
  5117. * user wants these modes, so disable fb cursor
  5118. */
  5119. overlay_cursor = 0;
  5120. } else {
  5121. /*
  5122. * "default" and "most", we turn off
  5123. * show_cursor since it will automatically
  5124. * be in the framebuffer.
  5125. */
  5126. show_cursor = 0;
  5127. }
  5128. }
  5129. }
  5130. initialize_cursors_mode();
  5131. /* check for XTEST */
  5132. if (! XTestQueryExtension_wr(dpy, &ev, &er, &maj, &min)) {
  5133. if (! quiet && ! raw_fb_str) {
  5134. rfbLog("\n");
  5135. rfbLog("WARNING: XTEST extension not available (either missing from\n");
  5136. rfbLog(" display or client library libXtst missing at build time).\n");
  5137. rfbLog(" MOST user input (pointer and keyboard) will be DISCARDED.\n");
  5138. rfbLog(" If display does have XTEST, be sure to build x11vnc with\n");
  5139. rfbLog(" a working libXtst build environment (e.g. libxtst-dev,\n");
  5140. rfbLog(" or other packages).\n");
  5141. rfbLog("No XTEST extension, switching to -xwarppointer mode for\n");
  5142. rfbLog(" pointer motion input.\n");
  5143. }
  5144. xtest_present = 0;
  5145. use_xwarppointer = 1;
  5146. } else {
  5147. xtest_present = 1;
  5148. xtest_base_event_type = ev;
  5149. if (maj <= 1 || (maj == 2 && min <= 2)) {
  5150. /* no events defined as of 2.2 */
  5151. xtest_base_event_type = 0;
  5152. }
  5153. }
  5154. if (! XETrapQueryExtension_wr(dpy, &ev, &er, &maj)) {
  5155. xtrap_present = 0;
  5156. } else {
  5157. xtrap_present = 1;
  5158. xtrap_base_event_type = ev;
  5159. }
  5160. /*
  5161. * Window managers will often grab the display during resize,
  5162. * etc, using XGrabServer(). To avoid deadlock (our user resize
  5163. * input is not processed) we tell the server to process our
  5164. * requests during all grabs:
  5165. */
  5166. disable_grabserver(dpy, 0);
  5167. /* check for RECORD */
  5168. if (! XRecordQueryVersion_wr(dpy, &maj, &min)) {
  5169. xrecord_present = 0;
  5170. if (! quiet) {
  5171. rfbLog("\n");
  5172. rfbLog("The RECORD X extension was not found on the display.\n");
  5173. rfbLog("If your system has disabled it by default, you can\n");
  5174. rfbLog("enable it to get a nice x11vnc performance speedup\n");
  5175. rfbLog("for scrolling by putting this into the \"Module\" section\n");
  5176. rfbLog("of /etc/X11/xorg.conf or /etc/X11/XF86Config:\n");
  5177. rfbLog("\n");
  5178. rfbLog(" Section \"Module\"\n");
  5179. rfbLog(" ...\n");
  5180. rfbLog(" Load \"record\"\n");
  5181. rfbLog(" ...\n");
  5182. rfbLog(" EndSection\n");
  5183. rfbLog("\n");
  5184. }
  5185. } else {
  5186. xrecord_present = 1;
  5187. }
  5188. initialize_xrecord();
  5189. tmpi = 1;
  5190. if (scroll_copyrect) {
  5191. if (strstr(scroll_copyrect, "never")) {
  5192. tmpi = 0;
  5193. }
  5194. } else if (scroll_copyrect_default) {
  5195. if (strstr(scroll_copyrect_default, "never")) {
  5196. tmpi = 0;
  5197. }
  5198. }
  5199. if (! xrecord_present) {
  5200. tmpi = 0;
  5201. }
  5202. #if !LIBVNCSERVER_HAVE_RECORD
  5203. tmpi = 0;
  5204. #endif
  5205. if (! quiet && tmpi && ! raw_fb_str) {
  5206. rfbLog("\n");
  5207. rfbLog("Scroll Detection: -scrollcopyrect mode is in effect to\n");
  5208. rfbLog(" use RECORD extension to try to detect scrolling windows\n");
  5209. rfbLog(" (induced by either user keystroke or mouse input).\n");
  5210. rfbLog(" If this yields undesired behavior (poor response, painting\n");
  5211. rfbLog(" errors, etc) it may be disabled via: '-noscr'\n");
  5212. rfbLog(" Also see the -help entry for tuning parameters.\n");
  5213. rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
  5214. rfbLog(" repaint the screen, also see the -fixscreen option for\n");
  5215. rfbLog(" periodic repaints.\n");
  5216. if (scale_str && !strstr(scale_str, "nocr")) {
  5217. rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
  5218. }
  5219. }
  5220. if (! quiet && ncache && ! raw_fb_str) {
  5221. rfbLog("\n");
  5222. rfbLog("Client Side Caching: -ncache mode is in effect to provide\n");
  5223. rfbLog(" client-side pixel data caching. This speeds up\n");
  5224. rfbLog(" iconifying/deiconifying windows, moving and raising\n");
  5225. rfbLog(" windows, and reposting menus. In the simple CopyRect\n");
  5226. rfbLog(" encoding scheme used (no compression) a huge amount\n");
  5227. rfbLog(" of extra memory (20-100MB) is used on both the server and\n");
  5228. rfbLog(" client sides. This mode works with any VNC viewer.\n");
  5229. rfbLog(" However, in most you can actually see the cached pixel\n");
  5230. rfbLog(" data by scrolling down, so you need to re-adjust its size.\n");
  5231. rfbLog(" See http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching.\n");
  5232. rfbLog(" If this mode yields undesired behavior (poor response,\n");
  5233. rfbLog(" painting errors, etc) it may be disabled via: '-ncache 0'\n");
  5234. rfbLog(" You can press 3 Alt_L's (Left \"Alt\" key) in a row to \n");
  5235. rfbLog(" repaint the screen, also see the -fixscreen option for\n");
  5236. rfbLog(" periodic repaints.\n");
  5237. if (scale_str) {
  5238. rfbLog(" Note: '-scale' is on and this can cause more problems.\n");
  5239. }
  5240. }
  5241. if (ncache && getenv("NCACHE_DEBUG")) {
  5242. ncdb = 1;
  5243. }
  5244. /* check for OS with small shm limits */
  5245. if (using_shm && ! single_copytile) {
  5246. if (limit_shm()) {
  5247. single_copytile = 1;
  5248. }
  5249. }
  5250. single_copytile_orig = single_copytile;
  5251. /* check for MIT-SHM */
  5252. if (! XShmQueryExtension_wr(dpy)) {
  5253. xshm_present = 0;
  5254. if (! using_shm) {
  5255. if (! quiet && ! raw_fb_str) {
  5256. rfbLog("info: display does not support XShm.\n");
  5257. }
  5258. } else {
  5259. if (! quiet && ! raw_fb_str) {
  5260. rfbLog("\n");
  5261. rfbLog("warning: XShm extension is not available.\n");
  5262. rfbLog("For best performance the X Display should be local. (i.e.\n");
  5263. rfbLog("the x11vnc and X server processes should be running on\n");
  5264. rfbLog("the same machine.)\n");
  5265. #if LIBVNCSERVER_HAVE_XSHM
  5266. rfbLog("Restart with -noshm to override this.\n");
  5267. }
  5268. exit(1);
  5269. #else
  5270. rfbLog("Switching to -noshm mode.\n");
  5271. }
  5272. using_shm = 0;
  5273. #endif
  5274. }
  5275. } else {
  5276. #if !NO_X11
  5277. int op, ev, er;
  5278. if (XQueryExtension(dpy, "MIT-SHM", &op, &ev, &er)) {
  5279. xshm_opcode = op;
  5280. if (0) fprintf(stderr, "xshm_opcode: %d %d %d\n", op, ev, er);
  5281. }
  5282. #endif
  5283. }
  5284. #if LIBVNCSERVER_HAVE_XKEYBOARD
  5285. /* check for XKEYBOARD */
  5286. initialize_xkb();
  5287. initialize_watch_bell();
  5288. if (!xkb_present && use_xkb_modtweak) {
  5289. if (! quiet && ! raw_fb_str) {
  5290. rfbLog("warning: disabling xkb modtweak. XKEYBOARD ext. not present.\n");
  5291. }
  5292. use_xkb_modtweak = 0;
  5293. }
  5294. #endif
  5295. if (xkb_present && !use_xkb_modtweak && !got_noxkb) {
  5296. if (use_modifier_tweak) {
  5297. switch_to_xkb_if_better();
  5298. }
  5299. }
  5300. #if LIBVNCSERVER_HAVE_LIBXRANDR
  5301. if (! XRRQueryExtension(dpy, &xrandr_base_event_type, &er)) {
  5302. if (xrandr && ! quiet && ! raw_fb_str) {
  5303. rfbLog("Disabling -xrandr mode: display does not support X RANDR.\n");
  5304. }
  5305. xrandr_base_event_type = 0;
  5306. xrandr = 0;
  5307. xrandr_maybe = 0;
  5308. xrandr_present = 0;
  5309. } else {
  5310. xrandr_present = 1;
  5311. }
  5312. #endif
  5313. check_pm();
  5314. if (! quiet && ! raw_fb_str) {
  5315. rfbLog("--------------------------------------------------------\n");
  5316. rfbLog("\n");
  5317. }
  5318. raw_fb_pass_go_and_collect_200_dollars:
  5319. if (! dpy || raw_fb_str) {
  5320. int doit = 0;
  5321. /* XXX this needs improvement (esp. for remote control) */
  5322. if (! raw_fb_str || strstr(raw_fb_str, "console") == raw_fb_str) {
  5323. #ifdef MACOSX
  5324. doit = 1;
  5325. #endif
  5326. }
  5327. if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
  5328. doit = 1;
  5329. }
  5330. if (doit) {
  5331. if (! multiple_cursors_mode) {
  5332. multiple_cursors_mode = strdup("most");
  5333. }
  5334. initialize_cursors_mode();
  5335. use_xdamage = orig_use_xdamage;
  5336. if (use_xdamage) {
  5337. xdamage_present = 1;
  5338. initialize_xdamage();
  5339. }
  5340. }
  5341. }
  5342. if (! dt) {
  5343. static char str[] = "-desktop";
  5344. argv_vnc[argc_vnc++] = str;
  5345. argv_vnc[argc_vnc++] = choose_title(use_dpy);
  5346. rfb_desktop_name = strdup(argv_vnc[argc_vnc-1]);
  5347. }
  5348. /*
  5349. * Create the XImage corresponding to the display framebuffer.
  5350. */
  5351. fb0 = initialize_xdisplay_fb();
  5352. /*
  5353. * In some cases (UINPUT touchscreens) we need the dpy_x dpy_y
  5354. * to initialize pipeinput. So we do it after fb is created.
  5355. */
  5356. initialize_pipeinput();
  5357. /*
  5358. * n.b. we do not have to X_LOCK any X11 calls until watch_loop()
  5359. * is called since we are single-threaded until then.
  5360. */
  5361. initialize_screen(&argc_vnc, argv_vnc, fb0);
  5362. if (waited_for_client) {
  5363. if (fake_fb) {
  5364. free(fake_fb);
  5365. fake_fb = NULL;
  5366. }
  5367. if (use_solid_bg && client_count) {
  5368. solid_bg(0);
  5369. }
  5370. if (accept_cmd && strstr(accept_cmd, "popup") == accept_cmd) {
  5371. rfbClientIteratorPtr iter;
  5372. rfbClientPtr cl, cl0 = NULL;
  5373. int i = 0;
  5374. iter = rfbGetClientIterator(screen);
  5375. while( (cl = rfbClientIteratorNext(iter)) ) {
  5376. i++;
  5377. if (i != 1) {
  5378. rfbLog("WAIT popup: too many clients\n");
  5379. clean_up_exit(1);
  5380. }
  5381. cl0 = cl;
  5382. }
  5383. rfbReleaseClientIterator(iter);
  5384. if (i != 1 || cl0 == NULL) {
  5385. rfbLog("WAIT popup: no clients.\n");
  5386. clean_up_exit(1);
  5387. }
  5388. if (! accept_client(cl0)) {
  5389. rfbLog("WAIT popup: denied.\n");
  5390. clean_up_exit(1);
  5391. }
  5392. rfbLog("waited_for_client: popup accepted.\n");
  5393. cl0->onHold = FALSE;
  5394. }
  5395. if (macosx_console) {
  5396. refresh_screen(1);
  5397. }
  5398. if (dpy && xdmcp_insert != NULL) {
  5399. #if !NO_X11
  5400. char c;
  5401. int n = strlen(xdmcp_insert);
  5402. KeyCode k, k2;
  5403. KeySym sym;
  5404. int i, ok = 1;
  5405. for (i = 0; i < n; i++) {
  5406. c = xdmcp_insert[i];
  5407. sym = (KeySym) c;
  5408. if (sym < ' ' || sym > 0x7f) {
  5409. ok = 0;
  5410. break;
  5411. }
  5412. k = XKeysymToKeycode(dpy, sym);
  5413. if (k == NoSymbol) {
  5414. ok = 0;
  5415. break;
  5416. }
  5417. }
  5418. if (ok) {
  5419. XFlush_wr(dpy);
  5420. usleep(2*1000*1000);
  5421. if (!quiet) {
  5422. rfbLog("sending XDM '%s'\n", xdmcp_insert);
  5423. }
  5424. for (i = 0; i < n; i++) {
  5425. c = xdmcp_insert[i];
  5426. sym = (KeySym) c;
  5427. k = XKeysymToKeycode(dpy, sym);
  5428. if (isupper(c)) {
  5429. k2 = XKeysymToKeycode(dpy, XK_Shift_L);
  5430. XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
  5431. XFlush_wr(dpy);
  5432. usleep(100*1000);
  5433. }
  5434. if (0) fprintf(stderr, "C/k %c/%x\n", c, k);
  5435. XTestFakeKeyEvent_wr(dpy, k, True, CurrentTime);
  5436. XFlush_wr(dpy);
  5437. usleep(100*1000);
  5438. XTestFakeKeyEvent_wr(dpy, k, False, CurrentTime);
  5439. XFlush_wr(dpy);
  5440. usleep(100*1000);
  5441. if (isupper(c)) {
  5442. k2 = XKeysymToKeycode(dpy, XK_Shift_L);
  5443. XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
  5444. XFlush_wr(dpy);
  5445. usleep(100*1000);
  5446. }
  5447. }
  5448. k2 = XKeysymToKeycode(dpy, XK_Tab);
  5449. XTestFakeKeyEvent_wr(dpy, k2, True, CurrentTime);
  5450. XFlush_wr(dpy);
  5451. usleep(100*1000);
  5452. XTestFakeKeyEvent_wr(dpy, k2, False, CurrentTime);
  5453. XFlush_wr(dpy);
  5454. usleep(100*1000);
  5455. }
  5456. free(xdmcp_insert);
  5457. #endif
  5458. }
  5459. check_redir_services();
  5460. }
  5461. if (! waited_for_client) {
  5462. if (try_http && ! got_httpdir && check_httpdir()) {
  5463. http_connections(1);
  5464. }
  5465. if (ssh_str != NULL) {
  5466. ssh_remote_tunnel(ssh_str, screen->port);
  5467. }
  5468. }
  5469. initialize_tiles();
  5470. /* rectangular blackout regions */
  5471. initialize_blackouts_and_xinerama();
  5472. /* created shm or XImages when using_shm = 0 */
  5473. initialize_polling_images();
  5474. initialize_signals();
  5475. initialize_speeds();
  5476. if (speeds_read_rate_measured > 80) {
  5477. /* framebuffer read is fast at > 80 MB/sec */
  5478. int same = 0;
  5479. if (waitms == defer_update) {
  5480. same = 1;
  5481. }
  5482. if (! got_waitms) {
  5483. waitms /= 2;
  5484. if (waitms < 5) {
  5485. waitms = 5;
  5486. }
  5487. if (!quiet) {
  5488. rfbLog("fast read: reset -wait ms to: %d\n", waitms);
  5489. }
  5490. }
  5491. if (! got_deferupdate && ! got_defer) {
  5492. if (defer_update > 10) {
  5493. if (same) {
  5494. defer_update = waitms;
  5495. } else {
  5496. defer_update = 10;
  5497. }
  5498. if (screen) {
  5499. screen->deferUpdateTime = defer_update;
  5500. }
  5501. rfbLog("fast read: reset -defer ms to: %d\n", defer_update);
  5502. }
  5503. }
  5504. }
  5505. initialize_keyboard_and_pointer();
  5506. if (inetd && use_openssl) {
  5507. if (! waited_for_client) {
  5508. accept_openssl(OPENSSL_INETD, -1);
  5509. }
  5510. }
  5511. if (! inetd && ! use_openssl) {
  5512. if (! screen->port || screen->listenSock < 0) {
  5513. if (got_rfbport && got_rfbport_val == 0) {
  5514. ;
  5515. } else if (ipv6_listen && ipv6_listen_fd >= 0) {
  5516. rfbLog("Info: listening only on IPv6 interface.\n");
  5517. } else {
  5518. rfbLogEnable(1);
  5519. rfbLog("Error: could not obtain listening port.\n");
  5520. if (!got_rfbport && !got_ipv6_listen) {
  5521. rfbLog("If this system is IPv6-only, use the -6 option.\n");
  5522. }
  5523. clean_up_exit(1);
  5524. }
  5525. }
  5526. }
  5527. #ifdef MACOSX
  5528. if (remote_cmd || query_cmd) {
  5529. ;
  5530. } else if (macosx_console) {
  5531. double dt = dnow();
  5532. copy_screen();
  5533. dt = dnow() - dt;
  5534. rfbLog("macosx_console: copied screen in %.3f sec %.1f MB/sec\n",
  5535. dt, dpy_x * dpy_y * bpp / (1e+6 * 8 * dt));
  5536. }
  5537. #endif
  5538. if (! quiet) {
  5539. rfbLog("screen setup finished.\n");
  5540. if (SHOW_NO_PASSWORD_WARNING && !nopw) {
  5541. rfbLog("\n");
  5542. rfbLog("WARNING: You are running x11vnc WITHOUT"
  5543. " a password. See\n");
  5544. rfbLog("WARNING: the warning message printed above"
  5545. " for more info.\n");
  5546. }
  5547. }
  5548. set_vnc_desktop_name();
  5549. if (ncache_beta_tester && (ncache != 0 || ncache_msg)) {
  5550. ncache_beta_tester_message();
  5551. }
  5552. if (remote_cmd || query_cmd) {
  5553. /* This is DIRECT: case */
  5554. do_remote_query(remote_cmd, query_cmd, remote_sync, query_default);
  5555. if (getenv("SLEEP")) sleep(atoi(getenv("SLEEP")));
  5556. clean_up_exit(0);
  5557. }
  5558. #if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
  5559. if (bg) {
  5560. int p, n;
  5561. if (getenv("X11VNC_LOOP_MODE_BG")) {
  5562. if (screen && screen->listenSock >= 0) {
  5563. close(screen->listenSock);
  5564. FD_CLR(screen->listenSock,&screen->allFds);
  5565. screen->listenSock = -1;
  5566. }
  5567. if (screen && screen->httpListenSock >= 0) {
  5568. close(screen->httpListenSock);
  5569. screen->httpListenSock = -1;
  5570. }
  5571. if (openssl_sock >= 0) {
  5572. close(openssl_sock);
  5573. openssl_sock = -1;
  5574. }
  5575. if (https_sock >= 0) {
  5576. close(https_sock);
  5577. https_sock = -1;
  5578. }
  5579. if (openssl_sock6 >= 0) {
  5580. close(openssl_sock6);
  5581. openssl_sock6 = -1;
  5582. }
  5583. if (https_sock6 >= 0) {
  5584. close(https_sock6);
  5585. https_sock6 = -1;
  5586. }
  5587. if (ipv6_listen_fd >= 0) {
  5588. close(ipv6_listen_fd);
  5589. ipv6_listen_fd = -1;
  5590. }
  5591. if (ipv6_http_fd >= 0) {
  5592. close(ipv6_http_fd);
  5593. ipv6_http_fd = -1;
  5594. }
  5595. }
  5596. /* fork into the background now */
  5597. if ((p = fork()) > 0) {
  5598. exit(0);
  5599. } else if (p == -1) {
  5600. rfbLogEnable(1);
  5601. fprintf(stderr, "could not fork\n");
  5602. perror("fork");
  5603. clean_up_exit(1);
  5604. }
  5605. if (setsid() == -1) {
  5606. rfbLogEnable(1);
  5607. fprintf(stderr, "setsid failed\n");
  5608. perror("setsid");
  5609. clean_up_exit(1);
  5610. }
  5611. /* adjust our stdio */
  5612. n = open("/dev/null", O_RDONLY);
  5613. dup2(n, 0);
  5614. dup2(n, 1);
  5615. if (! logfile) {
  5616. dup2(n, 2);
  5617. }
  5618. if (n > 2) {
  5619. close(n);
  5620. }
  5621. }
  5622. #endif
  5623. watch_loop();
  5624. return(0);
  5625. #undef argc
  5626. #undef argv
  5627. }