blob: 09c8b2fe84aa5ddc83825e0da5307f4209bcb800 [file] [log] [blame]
Pierre Ossman5156d5e2011-03-09 09:42:34 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
DRCb65bb932011-06-24 03:17:00 +00003 * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
Pierre Ossman5156d5e2011-03-09 09:42:34 +00004 *
5 * This is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 * USA.
19 */
20
Peter Åstrandc359f362011-08-23 12:04:46 +000021#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
Pierre Ossman5156d5e2011-03-09 09:42:34 +000025#include <string.h>
26#include <stdio.h>
Pierre Ossman2a7a8d62013-02-15 08:33:39 +000027#include <ctype.h>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000028#include <stdlib.h>
29#include <errno.h>
30#include <signal.h>
31#include <locale.h>
Pierre Ossman5bf17ad2015-02-17 13:23:00 +010032#include <fcntl.h>
Pierre Ossmana71a2762015-03-04 09:57:06 +010033#include <unistd.h>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000034#include <sys/stat.h>
35
36#ifdef WIN32
Peter Åstrand (astrand)11167e12015-02-05 11:10:32 +010037#include <os/winerrno.h>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000038#include <direct.h>
39#define mkdir(path, mode) _mkdir(path)
40#endif
41
Pierre Ossman6b9622d2014-07-21 16:42:12 +020042#if !defined(WIN32) && !defined(__APPLE__)
43#include <X11/Xlib.h>
44#include <X11/XKBlib.h>
45#endif
46
Pierre Ossman5156d5e2011-03-09 09:42:34 +000047#include <rfb/Logger_stdio.h>
48#include <rfb/SecurityClient.h>
49#include <rfb/Security.h>
50#ifdef HAVE_GNUTLS
51#include <rfb/CSecurityTLS.h>
52#endif
53#include <rfb/LogWriter.h>
54#include <rfb/Timer.h>
Peter Åstrand8a2b0812012-08-08 11:49:01 +000055#include <rfb/Exception.h>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000056#include <network/TcpSocket.h>
DRC4426f002011-10-12 20:02:55 +000057#include <os/os.h>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000058
59#include <FL/Fl.H>
60#include <FL/Fl_Widget.H>
Pierre Ossman8eb35082012-03-27 12:50:54 +000061#include <FL/Fl_PNG_Image.H>
Pierre Ossmana71a2762015-03-04 09:57:06 +010062#include <FL/Fl_Sys_Menu_Bar.H>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000063#include <FL/fl_ask.H>
Pierre Ossmanb8858222011-04-29 11:51:38 +000064#include <FL/x.H>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000065
66#include "i18n.h"
67#include "parameters.h"
68#include "CConn.h"
Pierre Ossman561ff0c2011-05-13 14:04:59 +000069#include "ServerDialog.h"
Pierre Ossman5156d5e2011-03-09 09:42:34 +000070#include "UserDialog.h"
Adam Tkac8ac4b302013-01-23 13:55:46 +000071#include "vncviewer.h"
Pierre Ossmana71a2762015-03-04 09:57:06 +010072#include "fltk_layout.h"
Pierre Ossman5156d5e2011-03-09 09:42:34 +000073
DRCb65bb932011-06-24 03:17:00 +000074#ifdef WIN32
Pierre Ossman8eb35082012-03-27 12:50:54 +000075#include "resource.h"
DRCb65bb932011-06-24 03:17:00 +000076#include "win32.h"
77#endif
78
Pierre Ossman5156d5e2011-03-09 09:42:34 +000079rfb::LogWriter vlog("main");
80
81using namespace network;
82using namespace rfb;
83using namespace std;
84
Adam Tkac8ac4b302013-01-23 13:55:46 +000085char vncServerName[VNCSERVERNAMELEN] = { '\0' };
86
Pierre Ossmana71a2762015-03-04 09:57:06 +010087static const char *argv0 = NULL;
88
Pierre Ossman5156d5e2011-03-09 09:42:34 +000089static bool exitMainloop = false;
Pierre Ossmane2ef5c12011-07-12 16:56:34 +000090static const char *exitError = NULL;
Pierre Ossman5156d5e2011-03-09 09:42:34 +000091
Pierre Ossmanccd09ba2015-04-07 14:58:45 +020092static const char *about_text()
93{
94 static char buffer[1024];
95
96 // This is used in multiple places with potentially different
97 // encodings, so we need to make sure we get a fresh string every
98 // time.
99 snprintf(buffer, sizeof(buffer),
100 _("TigerVNC Viewer %d-bit v%s\n"
101 "Built on: %s\n"
102 "Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\n"
103 "See http://www.tigervnc.org for information on TigerVNC."),
104 (int)sizeof(size_t)*8, PACKAGE_VERSION,
105 BUILD_TIMESTAMP, 2015);
106
107 return buffer;
108}
109
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000110void exit_vncviewer(const char *error)
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000111{
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000112 // Prioritise the first error we get as that is probably the most
113 // relevant one.
114 if ((error != NULL) && (exitError == NULL))
115 exitError = strdup(error);
116
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000117 exitMainloop = true;
118}
119
Pierre Ossmanb8858222011-04-29 11:51:38 +0000120void about_vncviewer()
121{
122 fl_message_title(_("About TigerVNC Viewer"));
Pierre Ossmanccd09ba2015-04-07 14:58:45 +0200123 fl_message("%s", about_text());
Pierre Ossmanb8858222011-04-29 11:51:38 +0000124}
125
Pierre Ossman8d713a92015-03-04 09:54:27 +0100126#ifdef __APPLE__
Pierre Ossmanb8858222011-04-29 11:51:38 +0000127static void about_callback(Fl_Widget *widget, void *data)
128{
129 about_vncviewer();
130}
Pierre Ossmana71a2762015-03-04 09:57:06 +0100131
132static void new_connection_cb(Fl_Widget *widget, void *data)
133{
134 const char *argv[2];
135 pid_t pid;
136
137 pid = fork();
138 if (pid == -1) {
139 vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
140 return;
141 }
142
143 if (pid != 0)
144 return;
145
146 argv[0] = argv0;
147 argv[1] = NULL;
148
149 execvp(argv[0], (char * const *)argv);
150
151 vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
152 _exit(1);
153}
Pierre Ossman8d713a92015-03-04 09:54:27 +0100154#endif
Pierre Ossmanb8858222011-04-29 11:51:38 +0000155
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000156static void CleanupSignalHandler(int sig)
157{
158 // CleanupSignalHandler allows C++ object cleanup to happen because it calls
159 // exit() rather than the default which is to abort.
Pierre Ossmanc76bd2b2014-12-03 14:01:31 +0100160 vlog.info(_("Termination signal %d has been received. TigerVNC Viewer will now exit."), sig);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000161 exit(1);
162}
163
164static void init_fltk()
165{
166 // Basic text size (10pt @ 96 dpi => 13px)
167 FL_NORMAL_SIZE = 13;
168
169#ifndef __APPLE__
170 // Select a FLTK scheme and background color that looks somewhat
171 // close to modern Linux and Windows.
172 Fl::scheme("gtk+");
173 Fl::background(220, 220, 220);
174#else
175 // On Mac OS X there is another scheme that fits better though.
176 Fl::scheme("plastic");
177#endif
178
Henrik Andersson3b837032011-09-19 13:46:55 +0000179 // Proper Gnome Shell integration requires that we set a sensible
180 // WM_CLASS for the window.
181 Fl_Window::default_xclass("vncviewer");
182
Pierre Ossman8eb35082012-03-27 12:50:54 +0000183 // Set the default icon for all windows.
Pierre Ossman8eb35082012-03-27 12:50:54 +0000184#ifdef WIN32
185 HICON lg, sm;
186
187 lg = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
188 IMAGE_ICON, GetSystemMetrics(SM_CXICON),
189 GetSystemMetrics(SM_CYICON),
190 LR_DEFAULTCOLOR | LR_SHARED);
191 sm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
192 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
193 GetSystemMetrics(SM_CYSMICON),
194 LR_DEFAULTCOLOR | LR_SHARED);
195
196 Fl_Window::default_icons(lg, sm);
197#elif ! defined(__APPLE__)
198 const int icon_sizes[] = {48, 32, 24, 16};
199
200 Fl_PNG_Image *icons[4];
201 int count;
202
203 count = 0;
204
205 // FIXME: Follow icon theme specification
206 for (size_t i = 0;i < sizeof(icon_sizes)/sizeof(icon_sizes[0]);i++) {
207 char icon_path[PATH_MAX];
208 bool exists;
209
Pierre Ossman6a007bd2012-09-11 10:56:21 +0000210 sprintf(icon_path, "%s/icons/hicolor/%dx%d/apps/tigervnc.png",
Pierre Ossman8eb35082012-03-27 12:50:54 +0000211 DATA_DIR, icon_sizes[i], icon_sizes[i]);
212
213#ifndef WIN32
214 struct stat st;
215 if (stat(icon_path, &st) != 0)
216#else
217 struct _stat st;
218 if (_stat(icon_path, &st) != 0)
219 return(false);
220#endif
221 exists = false;
222 else
223 exists = true;
224
225 if (exists) {
226 icons[count] = new Fl_PNG_Image(icon_path);
227 if (icons[count]->w() == 0 ||
228 icons[count]->h() == 0 ||
229 icons[count]->d() != 4) {
230 delete icons[count];
231 continue;
232 }
233
234 count++;
235 }
236 }
237
238 Fl_Window::default_icons((const Fl_RGB_Image**)icons, count);
239
240 for (int i = 0;i < count;i++)
241 delete icons[i];
242#endif
Pierre Ossman8eb35082012-03-27 12:50:54 +0000243
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000244 // This makes the "icon" in dialogs rounded, which fits better
245 // with the above schemes.
246 fl_message_icon()->box(FL_UP_BOX);
247
248 // Turn off the annoying behaviour where popups track the mouse.
249 fl_message_hotspot(false);
250
251 // Avoid empty titles for popups
252 fl_message_title_default(_("TigerVNC Viewer"));
253
254#ifdef WIN32
255 // Most "normal" Windows apps use this font for UI elements.
256 Fl::set_font(FL_HELVETICA, "Tahoma");
257#endif
258
259 // FLTK exposes these so that we can translate them.
260 fl_no = _("No");
261 fl_yes = _("Yes");
262 fl_ok = _("OK");
263 fl_cancel = _("Cancel");
264 fl_close = _("Close");
Pierre Ossmanb8858222011-04-29 11:51:38 +0000265
266#ifdef __APPLE__
Peter Åstrandb7c55242011-08-29 13:14:51 +0000267 /* Needs trailing space */
268 static char fltk_about[16];
269 snprintf(fltk_about, sizeof(fltk_about), "%s ", _("About"));
270 Fl_Mac_App_Menu::about = fltk_about;
271 static char fltk_hide[16];
272 snprintf(fltk_hide, sizeof(fltk_hide), "%s ", _("Hide"));
273 Fl_Mac_App_Menu::hide = fltk_hide;
274 static char fltk_quit[16];
275 snprintf(fltk_quit, sizeof(fltk_quit), "%s ", _("Quit"));
276 Fl_Mac_App_Menu::quit = fltk_quit;
277
Pierre Ossman41ba6032011-06-16 11:09:31 +0000278 Fl_Mac_App_Menu::print = ""; // Don't want the print item
279 Fl_Mac_App_Menu::services = _("Services");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000280 Fl_Mac_App_Menu::hide_others = _("Hide Others");
281 Fl_Mac_App_Menu::show = _("Show All");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000282
Pierre Ossmanb8858222011-04-29 11:51:38 +0000283 fl_mac_set_about(about_callback, NULL);
Pierre Ossmana71a2762015-03-04 09:57:06 +0100284
285 Fl_Sys_Menu_Bar *menubar;
286 char buffer[1024];
287 menubar = new Fl_Sys_Menu_Bar(0, 0, 500, 25);
288 // Fl_Sys_Menu_Bar overrides methods without them being virtual,
289 // which means we cannot use our generic Fl_Menu_ helpers.
290 if (fltk_menu_escape(_("&File"), buffer, sizeof(buffer)) < sizeof(buffer))
291 menubar->add(buffer, 0, 0, 0, FL_SUBMENU);
292 if (fltk_menu_escape(_("&New Connection"), buffer, sizeof(buffer)) < sizeof(buffer))
293 menubar->insert(1, buffer, FL_COMMAND | 'n', new_connection_cb);
Pierre Ossmanb8858222011-04-29 11:51:38 +0000294#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000295}
296
297static void mkvnchomedir()
298{
299 // Create .vnc in the user's home directory if it doesn't already exist
300 char* homeDir = NULL;
301
302 if (getvnchomedir(&homeDir) == -1) {
303 vlog.error(_("Could not create VNC home directory: can't obtain home "
304 "directory path."));
305 } else {
306 int result = mkdir(homeDir, 0755);
307 if (result == -1 && errno != EEXIST)
308 vlog.error(_("Could not create VNC home directory: %s."), strerror(errno));
309 delete [] homeDir;
310 }
311}
312
313static void usage(const char *programName)
314{
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100315#ifdef WIN32
316 // If we don't have a console then we need to create one for output
317 if (GetConsoleWindow() == NULL) {
318 HANDLE handle;
319 int fd;
320
321 AllocConsole();
322
323 handle = GetStdHandle(STD_ERROR_HANDLE);
324 fd = _open_osfhandle((intptr_t)handle, O_TEXT);
325 *stderr = *fdopen(fd, "w");
326 }
327#endif
328
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000329 fprintf(stderr,
330 "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
331 " %s [parameters] -listen [port] [parameters]\n",
332 programName, programName);
333 fprintf(stderr,"\n"
334 "Parameters can be turned on with -<param> or off with -<param>=0\n"
335 "Parameters which take a value can be specified as "
336 "-<param> <value>\n"
337 "Other valid forms are <param>=<value> -<param>=<value> "
338 "--<param>=<value>\n"
339 "Parameter names are case-insensitive. The parameters are:\n\n");
340 Configuration::listParams(79, 14);
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100341
342#ifdef WIN32
343 // Just wait for the user to kill the console window
344 Sleep(INFINITE);
345#endif
346
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000347 exit(1);
348}
349
Adam Tkac8ac4b302013-01-23 13:55:46 +0000350#ifndef WIN32
351static int
352interpretViaParam(char *remoteHost, int *remotePort, int localPort)
353{
354 const int SERVER_PORT_OFFSET = 5900;
355 char *pos = strchr(vncServerName, ':');
356 if (pos == NULL)
357 *remotePort = SERVER_PORT_OFFSET;
358 else {
359 int portOffset = SERVER_PORT_OFFSET;
360 size_t len;
361 *pos++ = '\0';
362 len = strlen(pos);
363 if (*pos == ':') {
364 /* Two colons is an absolute port number, not an offset. */
365 pos++;
366 len--;
367 portOffset = 0;
368 }
369 if (!len || strspn (pos, "-0123456789") != len )
370 return 1;
371 *remotePort = atoi(pos) + portOffset;
372 }
373
374 if (*vncServerName != '\0')
375 strncpy(remoteHost, vncServerName, VNCSERVERNAMELEN);
376 else
377 strncpy(remoteHost, "localhost", VNCSERVERNAMELEN);
378
379 remoteHost[VNCSERVERNAMELEN - 1] = '\0';
380
381 snprintf(vncServerName, VNCSERVERNAMELEN, "localhost::%d", localPort);
382 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
Adam Tkac8ac4b302013-01-23 13:55:46 +0000383
384 return 0;
385}
386
387static void
388createTunnel(const char *gatewayHost, const char *remoteHost,
389 int remotePort, int localPort)
390{
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200391 const char *cmd = getenv("VNC_VIA_CMD");
392 char *cmd2, *percent;
Adam Tkac8ac4b302013-01-23 13:55:46 +0000393 char lport[10], rport[10];
394 sprintf(lport, "%d", localPort);
395 sprintf(rport, "%d", remotePort);
396 setenv("G", gatewayHost, 1);
397 setenv("H", remoteHost, 1);
398 setenv("R", rport, 1);
399 setenv("L", lport, 1);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000400 if (!cmd)
401 cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20";
402 /* Compatibility with TigerVNC's method. */
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200403 cmd2 = strdup(cmd);
404 while ((percent = strchr(cmd2, '%')) != NULL)
Adam Tkac8ac4b302013-01-23 13:55:46 +0000405 *percent = '$';
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200406 system(cmd2);
407 free(cmd2);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000408}
409
410static int mktunnel()
411{
412 const char *gatewayHost;
413 char remoteHost[VNCSERVERNAMELEN];
414 int localPort = findFreeTcpPort();
415 int remotePort;
416
417 gatewayHost = strDup(via.getValueStr());
418 if (interpretViaParam(remoteHost, &remotePort, localPort) != 0)
419 return 1;
420 createTunnel(gatewayHost, remoteHost, remotePort, localPort);
421
422 return 0;
423}
424#endif /* !WIN32 */
425
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000426int main(int argc, char** argv)
427{
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000428 UserDialog dlg;
429
Pierre Ossmana71a2762015-03-04 09:57:06 +0100430 argv0 = argv[0];
431
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000432 setlocale(LC_ALL, "");
Pierre Ossman0878eca2012-03-27 13:03:22 +0000433 bindtextdomain(PACKAGE_NAME, LOCALE_DIR);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000434 textdomain(PACKAGE_NAME);
435
436 rfb::SecurityClient::setDefaults();
437
438 // Write about text to console, still using normal locale codeset
Pierre Ossmanccd09ba2015-04-07 14:58:45 +0200439 fprintf(stderr,"\n%s\n", about_text());
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000440
441 // Set gettext codeset to what our GUI toolkit uses. Since we are
442 // passing strings from strerror/gai_strerror to the GUI, these must
443 // be in GUI codeset as well.
444 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
445 bind_textdomain_codeset("libc", "UTF-8");
446
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000447 rfb::initStdIOLoggers();
Pierre Ossmanc8719ad2012-04-26 14:27:52 +0000448#ifdef WIN32
449 rfb::initFileLogger("C:\\temp\\vncviewer.log");
450#else
451 rfb::initFileLogger("/tmp/vncviewer.log");
452#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000453 rfb::LogWriter::setLogParams("*:stderr:30");
454
455#ifdef SIGHUP
456 signal(SIGHUP, CleanupSignalHandler);
457#endif
458 signal(SIGINT, CleanupSignalHandler);
459 signal(SIGTERM, CleanupSignalHandler);
460
461 init_fltk();
462
Pierre Ossman6b9622d2014-07-21 16:42:12 +0200463#if !defined(WIN32) && !defined(__APPLE__)
464 fl_open_display();
465 XkbSetDetectableAutoRepeat(fl_display, True, NULL);
466#endif
467
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000468 Configuration::enableViewerParams();
469
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000470 /* Load the default parameter settings */
471 const char* defaultServerName;
472 try {
473 defaultServerName = loadViewerParameters(NULL);
474 } catch (rfb::Exception& e) {
Pierre Ossman3620e192015-03-03 16:50:15 +0100475 defaultServerName = "";
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000476 fl_alert("%s", e.str());
477 }
478
DRC5aa06502011-06-23 22:04:46 +0000479 int i = 1;
480 if (!Fl::args(argc, argv, i) || i < argc)
481 for (; i < argc; i++) {
482 if (Configuration::setParam(argv[i]))
483 continue;
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000484
DRC5aa06502011-06-23 22:04:46 +0000485 if (argv[i][0] == '-') {
486 if (i+1 < argc) {
487 if (Configuration::setParam(&argv[i][1], argv[i+1])) {
488 i++;
489 continue;
490 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000491 }
DRC5aa06502011-06-23 22:04:46 +0000492 usage(argv[0]);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000493 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000494
Adam Tkac8ac4b302013-01-23 13:55:46 +0000495 strncpy(vncServerName, argv[i], VNCSERVERNAMELEN);
496 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
DRC5aa06502011-06-23 22:04:46 +0000497 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000498
499 if (!::autoSelect.hasBeenSet()) {
500 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000501 if (::preferredEncoding.hasBeenSet() || ::fullColour.hasBeenSet() ||
502 ::fullColourAlias.hasBeenSet()) {
503 ::autoSelect.setParam(false);
504 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000505 }
506 if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) {
507 // Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set
508 if (!::autoSelect && (::lowColourLevel.hasBeenSet() ||
509 ::lowColourLevelAlias.hasBeenSet())) {
510 ::fullColour.setParam(false);
511 }
512 }
513 if (!::customCompressLevel.hasBeenSet()) {
514 // Default to CustomCompressLevel=1 if CompressLevel is used.
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000515 if(::compressLevel.hasBeenSet()) {
516 ::customCompressLevel.setParam(true);
517 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000518 }
519
520 mkvnchomedir();
521
522 CSecurity::upg = &dlg;
523#ifdef HAVE_GNUTLS
524 CSecurityTLS::msg = &dlg;
525#endif
526
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000527 Socket *sock = NULL;
528
DRC3e7ed812013-02-26 10:34:22 +0000529#ifndef WIN32
Adam Tkac571089b2013-02-19 14:30:32 +0000530 /* Specifying -via and -listen together is nonsense */
531 if (listenMode && strlen(via.getValueStr()) > 0) {
Pierre Ossman744e55c2014-12-03 14:00:54 +0100532 // TRANSLATORS: "Parameters" are command line arguments, or settings
533 // from a file or the Windows registry.
Pierre Ossman8ca4c1d2014-09-22 12:54:26 +0200534 vlog.error(_("Parameters -listen and -via are incompatible"));
535 fl_alert(_("Parameters -listen and -via are incompatible"));
Adam Tkac571089b2013-02-19 14:30:32 +0000536 exit_vncviewer();
537 return 1;
538 }
DRC3e7ed812013-02-26 10:34:22 +0000539#endif
Adam Tkac571089b2013-02-19 14:30:32 +0000540
541 if (listenMode) {
Tim Waugh892d10a2015-03-11 13:12:07 +0000542 std::list<TcpListener> listeners;
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000543 try {
544 int port = 5500;
545 if (isdigit(vncServerName[0]))
546 port = atoi(vncServerName);
547
Tim Waugh892d10a2015-03-11 13:12:07 +0000548 createTcpListeners(&listeners, 0, port);
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000549
Peter Åstrand (astrand)4ab2f8a2015-03-18 10:31:01 +0100550 vlog.info(_("Listening on port %d"), port);
Tim Waugh892d10a2015-03-11 13:12:07 +0000551
552 /* Wait for a connection */
553 while (sock == NULL) {
554 fd_set rfds;
555 FD_ZERO(&rfds);
556 for (std::list<TcpListener>::iterator i = listeners.begin();
557 i != listeners.end();
558 i++)
559 FD_SET((*i).getFd(), &rfds);
560
561 int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
562 if (n < 0) {
563 if (errno == EINTR) {
564 vlog.debug("Interrupted select() system call");
565 continue;
566 } else {
567 throw rdr::SystemException("select", errno);
568 }
569 }
570
571 for (std::list<TcpListener>::iterator i = listeners.begin ();
572 i != listeners.end();
573 i++)
574 if (FD_ISSET((*i).getFd(), &rfds)) {
575 sock = (*i).accept();
576 if (sock)
577 /* Got a connection */
578 break;
579 }
580 }
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000581 } catch (rdr::Exception& e) {
582 vlog.error("%s", e.str());
583 fl_alert("%s", e.str());
584 exit_vncviewer();
585 return 1;
586 }
587
588 } else {
589 if (vncServerName[0] == '\0') {
590 ServerDialog::run(defaultServerName, vncServerName);
591 if (vncServerName[0] == '\0')
592 return 1;
593 }
Pierre Ossman561ff0c2011-05-13 14:04:59 +0000594
Adam Tkac8ac4b302013-01-23 13:55:46 +0000595#ifndef WIN32
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000596 if (strlen (via.getValueStr()) > 0 && mktunnel() != 0)
597 usage(argv[0]);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000598#endif
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000599 }
Adam Tkac8ac4b302013-01-23 13:55:46 +0000600
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000601 CConn *cc = new CConn(vncServerName, sock);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000602
603 while (!exitMainloop) {
604 int next_timer;
605
606 next_timer = Timer::checkTimeouts();
607 if (next_timer == 0)
608 next_timer = INT_MAX;
609
610 if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
611 vlog.error(_("Internal FLTK error. Exiting."));
612 break;
613 }
614 }
615
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000616 delete cc;
617
618 if (exitError != NULL)
Pierre Ossmanf52740e2012-04-25 15:43:56 +0000619 fl_alert("%s", exitError);
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000620
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000621 return 0;
622}