blob: 876e9142e9ffb07ea6853755a911c5cea9f48ddd [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
Pierre Ossmandc96cb42014-09-22 12:19:26 +020085static char aboutText[1024];
86
Adam Tkac8ac4b302013-01-23 13:55:46 +000087char vncServerName[VNCSERVERNAMELEN] = { '\0' };
88
Pierre Ossmana71a2762015-03-04 09:57:06 +010089static const char *argv0 = NULL;
90
Pierre Ossman5156d5e2011-03-09 09:42:34 +000091static bool exitMainloop = false;
Pierre Ossmane2ef5c12011-07-12 16:56:34 +000092static const char *exitError = NULL;
Pierre Ossman5156d5e2011-03-09 09:42:34 +000093
Pierre Ossmane2ef5c12011-07-12 16:56:34 +000094void exit_vncviewer(const char *error)
Pierre Ossman5156d5e2011-03-09 09:42:34 +000095{
Pierre Ossmane2ef5c12011-07-12 16:56:34 +000096 // Prioritise the first error we get as that is probably the most
97 // relevant one.
98 if ((error != NULL) && (exitError == NULL))
99 exitError = strdup(error);
100
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000101 exitMainloop = true;
102}
103
Pierre Ossmanb8858222011-04-29 11:51:38 +0000104void about_vncviewer()
105{
106 fl_message_title(_("About TigerVNC Viewer"));
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200107 fl_message("%s", aboutText);
Pierre Ossmanb8858222011-04-29 11:51:38 +0000108}
109
Pierre Ossman8d713a92015-03-04 09:54:27 +0100110#ifdef __APPLE__
Pierre Ossmanb8858222011-04-29 11:51:38 +0000111static void about_callback(Fl_Widget *widget, void *data)
112{
113 about_vncviewer();
114}
Pierre Ossmana71a2762015-03-04 09:57:06 +0100115
116static void new_connection_cb(Fl_Widget *widget, void *data)
117{
118 const char *argv[2];
119 pid_t pid;
120
121 pid = fork();
122 if (pid == -1) {
123 vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
124 return;
125 }
126
127 if (pid != 0)
128 return;
129
130 argv[0] = argv0;
131 argv[1] = NULL;
132
133 execvp(argv[0], (char * const *)argv);
134
135 vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
136 _exit(1);
137}
Pierre Ossman8d713a92015-03-04 09:54:27 +0100138#endif
Pierre Ossmanb8858222011-04-29 11:51:38 +0000139
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000140static void CleanupSignalHandler(int sig)
141{
142 // CleanupSignalHandler allows C++ object cleanup to happen because it calls
143 // exit() rather than the default which is to abort.
Pierre Ossmanc76bd2b2014-12-03 14:01:31 +0100144 vlog.info(_("Termination signal %d has been received. TigerVNC Viewer will now exit."), sig);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000145 exit(1);
146}
147
148static void init_fltk()
149{
150 // Basic text size (10pt @ 96 dpi => 13px)
151 FL_NORMAL_SIZE = 13;
152
153#ifndef __APPLE__
154 // Select a FLTK scheme and background color that looks somewhat
155 // close to modern Linux and Windows.
156 Fl::scheme("gtk+");
157 Fl::background(220, 220, 220);
158#else
159 // On Mac OS X there is another scheme that fits better though.
160 Fl::scheme("plastic");
161#endif
162
Henrik Andersson3b837032011-09-19 13:46:55 +0000163 // Proper Gnome Shell integration requires that we set a sensible
164 // WM_CLASS for the window.
165 Fl_Window::default_xclass("vncviewer");
166
Pierre Ossman8eb35082012-03-27 12:50:54 +0000167 // Set the default icon for all windows.
168#ifdef HAVE_FLTK_ICONS
169#ifdef WIN32
170 HICON lg, sm;
171
172 lg = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
173 IMAGE_ICON, GetSystemMetrics(SM_CXICON),
174 GetSystemMetrics(SM_CYICON),
175 LR_DEFAULTCOLOR | LR_SHARED);
176 sm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
177 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
178 GetSystemMetrics(SM_CYSMICON),
179 LR_DEFAULTCOLOR | LR_SHARED);
180
181 Fl_Window::default_icons(lg, sm);
182#elif ! defined(__APPLE__)
183 const int icon_sizes[] = {48, 32, 24, 16};
184
185 Fl_PNG_Image *icons[4];
186 int count;
187
188 count = 0;
189
190 // FIXME: Follow icon theme specification
191 for (size_t i = 0;i < sizeof(icon_sizes)/sizeof(icon_sizes[0]);i++) {
192 char icon_path[PATH_MAX];
193 bool exists;
194
Pierre Ossman6a007bd2012-09-11 10:56:21 +0000195 sprintf(icon_path, "%s/icons/hicolor/%dx%d/apps/tigervnc.png",
Pierre Ossman8eb35082012-03-27 12:50:54 +0000196 DATA_DIR, icon_sizes[i], icon_sizes[i]);
197
198#ifndef WIN32
199 struct stat st;
200 if (stat(icon_path, &st) != 0)
201#else
202 struct _stat st;
203 if (_stat(icon_path, &st) != 0)
204 return(false);
205#endif
206 exists = false;
207 else
208 exists = true;
209
210 if (exists) {
211 icons[count] = new Fl_PNG_Image(icon_path);
212 if (icons[count]->w() == 0 ||
213 icons[count]->h() == 0 ||
214 icons[count]->d() != 4) {
215 delete icons[count];
216 continue;
217 }
218
219 count++;
220 }
221 }
222
223 Fl_Window::default_icons((const Fl_RGB_Image**)icons, count);
224
225 for (int i = 0;i < count;i++)
226 delete icons[i];
227#endif
228#endif // FLTK_HAVE_ICONS
229
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000230 // This makes the "icon" in dialogs rounded, which fits better
231 // with the above schemes.
232 fl_message_icon()->box(FL_UP_BOX);
233
234 // Turn off the annoying behaviour where popups track the mouse.
235 fl_message_hotspot(false);
236
237 // Avoid empty titles for popups
238 fl_message_title_default(_("TigerVNC Viewer"));
239
240#ifdef WIN32
241 // Most "normal" Windows apps use this font for UI elements.
242 Fl::set_font(FL_HELVETICA, "Tahoma");
243#endif
244
245 // FLTK exposes these so that we can translate them.
246 fl_no = _("No");
247 fl_yes = _("Yes");
248 fl_ok = _("OK");
249 fl_cancel = _("Cancel");
250 fl_close = _("Close");
Pierre Ossmanb8858222011-04-29 11:51:38 +0000251
252#ifdef __APPLE__
Peter Åstrandb7c55242011-08-29 13:14:51 +0000253 /* Needs trailing space */
254 static char fltk_about[16];
255 snprintf(fltk_about, sizeof(fltk_about), "%s ", _("About"));
256 Fl_Mac_App_Menu::about = fltk_about;
257 static char fltk_hide[16];
258 snprintf(fltk_hide, sizeof(fltk_hide), "%s ", _("Hide"));
259 Fl_Mac_App_Menu::hide = fltk_hide;
260 static char fltk_quit[16];
261 snprintf(fltk_quit, sizeof(fltk_quit), "%s ", _("Quit"));
262 Fl_Mac_App_Menu::quit = fltk_quit;
263
Pierre Ossman41ba6032011-06-16 11:09:31 +0000264 Fl_Mac_App_Menu::print = ""; // Don't want the print item
265 Fl_Mac_App_Menu::services = _("Services");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000266 Fl_Mac_App_Menu::hide_others = _("Hide Others");
267 Fl_Mac_App_Menu::show = _("Show All");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000268
Pierre Ossmanb8858222011-04-29 11:51:38 +0000269 fl_mac_set_about(about_callback, NULL);
Pierre Ossmana71a2762015-03-04 09:57:06 +0100270
271 Fl_Sys_Menu_Bar *menubar;
272 char buffer[1024];
273 menubar = new Fl_Sys_Menu_Bar(0, 0, 500, 25);
274 // Fl_Sys_Menu_Bar overrides methods without them being virtual,
275 // which means we cannot use our generic Fl_Menu_ helpers.
276 if (fltk_menu_escape(_("&File"), buffer, sizeof(buffer)) < sizeof(buffer))
277 menubar->add(buffer, 0, 0, 0, FL_SUBMENU);
278 if (fltk_menu_escape(_("&New Connection"), buffer, sizeof(buffer)) < sizeof(buffer))
279 menubar->insert(1, buffer, FL_COMMAND | 'n', new_connection_cb);
Pierre Ossmanb8858222011-04-29 11:51:38 +0000280#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000281}
282
283static void mkvnchomedir()
284{
285 // Create .vnc in the user's home directory if it doesn't already exist
286 char* homeDir = NULL;
287
288 if (getvnchomedir(&homeDir) == -1) {
289 vlog.error(_("Could not create VNC home directory: can't obtain home "
290 "directory path."));
291 } else {
292 int result = mkdir(homeDir, 0755);
293 if (result == -1 && errno != EEXIST)
294 vlog.error(_("Could not create VNC home directory: %s."), strerror(errno));
295 delete [] homeDir;
296 }
297}
298
299static void usage(const char *programName)
300{
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100301#ifdef WIN32
302 // If we don't have a console then we need to create one for output
303 if (GetConsoleWindow() == NULL) {
304 HANDLE handle;
305 int fd;
306
307 AllocConsole();
308
309 handle = GetStdHandle(STD_ERROR_HANDLE);
310 fd = _open_osfhandle((intptr_t)handle, O_TEXT);
311 *stderr = *fdopen(fd, "w");
312 }
313#endif
314
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000315 fprintf(stderr,
316 "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
317 " %s [parameters] -listen [port] [parameters]\n",
318 programName, programName);
319 fprintf(stderr,"\n"
320 "Parameters can be turned on with -<param> or off with -<param>=0\n"
321 "Parameters which take a value can be specified as "
322 "-<param> <value>\n"
323 "Other valid forms are <param>=<value> -<param>=<value> "
324 "--<param>=<value>\n"
325 "Parameter names are case-insensitive. The parameters are:\n\n");
326 Configuration::listParams(79, 14);
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100327
328#ifdef WIN32
329 // Just wait for the user to kill the console window
330 Sleep(INFINITE);
331#endif
332
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000333 exit(1);
334}
335
Adam Tkac8ac4b302013-01-23 13:55:46 +0000336#ifndef WIN32
337static int
338interpretViaParam(char *remoteHost, int *remotePort, int localPort)
339{
340 const int SERVER_PORT_OFFSET = 5900;
341 char *pos = strchr(vncServerName, ':');
342 if (pos == NULL)
343 *remotePort = SERVER_PORT_OFFSET;
344 else {
345 int portOffset = SERVER_PORT_OFFSET;
346 size_t len;
347 *pos++ = '\0';
348 len = strlen(pos);
349 if (*pos == ':') {
350 /* Two colons is an absolute port number, not an offset. */
351 pos++;
352 len--;
353 portOffset = 0;
354 }
355 if (!len || strspn (pos, "-0123456789") != len )
356 return 1;
357 *remotePort = atoi(pos) + portOffset;
358 }
359
360 if (*vncServerName != '\0')
361 strncpy(remoteHost, vncServerName, VNCSERVERNAMELEN);
362 else
363 strncpy(remoteHost, "localhost", VNCSERVERNAMELEN);
364
365 remoteHost[VNCSERVERNAMELEN - 1] = '\0';
366
367 snprintf(vncServerName, VNCSERVERNAMELEN, "localhost::%d", localPort);
368 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
Adam Tkac8ac4b302013-01-23 13:55:46 +0000369
370 return 0;
371}
372
373static void
374createTunnel(const char *gatewayHost, const char *remoteHost,
375 int remotePort, int localPort)
376{
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200377 const char *cmd = getenv("VNC_VIA_CMD");
378 char *cmd2, *percent;
Adam Tkac8ac4b302013-01-23 13:55:46 +0000379 char lport[10], rport[10];
380 sprintf(lport, "%d", localPort);
381 sprintf(rport, "%d", remotePort);
382 setenv("G", gatewayHost, 1);
383 setenv("H", remoteHost, 1);
384 setenv("R", rport, 1);
385 setenv("L", lport, 1);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000386 if (!cmd)
387 cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20";
388 /* Compatibility with TigerVNC's method. */
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200389 cmd2 = strdup(cmd);
390 while ((percent = strchr(cmd2, '%')) != NULL)
Adam Tkac8ac4b302013-01-23 13:55:46 +0000391 *percent = '$';
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200392 system(cmd2);
393 free(cmd2);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000394}
395
396static int mktunnel()
397{
398 const char *gatewayHost;
399 char remoteHost[VNCSERVERNAMELEN];
400 int localPort = findFreeTcpPort();
401 int remotePort;
402
403 gatewayHost = strDup(via.getValueStr());
404 if (interpretViaParam(remoteHost, &remotePort, localPort) != 0)
405 return 1;
406 createTunnel(gatewayHost, remoteHost, remotePort, localPort);
407
408 return 0;
409}
410#endif /* !WIN32 */
411
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000412int main(int argc, char** argv)
413{
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000414 UserDialog dlg;
415
Pierre Ossmana71a2762015-03-04 09:57:06 +0100416 argv0 = argv[0];
417
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000418 setlocale(LC_ALL, "");
Pierre Ossman0878eca2012-03-27 13:03:22 +0000419 bindtextdomain(PACKAGE_NAME, LOCALE_DIR);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000420 textdomain(PACKAGE_NAME);
421
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200422 // Generate the about string now that we get the proper translation
Pierre Ossman63471c92015-03-03 16:49:50 +0100423 snprintf(aboutText, sizeof(aboutText),
424 _("TigerVNC Viewer %d-bit v%s\n"
425 "Built on: %s\n"
426 "Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\n"
427 "See http://www.tigervnc.org for information on TigerVNC."),
Pierre Ossman5945d732014-09-22 13:13:15 +0200428 (int)sizeof(size_t)*8, PACKAGE_VERSION,
Pierre Ossmanc1341682015-02-20 17:12:57 +0100429 BUILD_TIMESTAMP, 2015);
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200430
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000431 rfb::SecurityClient::setDefaults();
432
433 // Write about text to console, still using normal locale codeset
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200434 fprintf(stderr,"\n%s\n", aboutText);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000435
436 // Set gettext codeset to what our GUI toolkit uses. Since we are
437 // passing strings from strerror/gai_strerror to the GUI, these must
438 // be in GUI codeset as well.
439 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
440 bind_textdomain_codeset("libc", "UTF-8");
441
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000442 rfb::initStdIOLoggers();
Pierre Ossmanc8719ad2012-04-26 14:27:52 +0000443#ifdef WIN32
444 rfb::initFileLogger("C:\\temp\\vncviewer.log");
445#else
446 rfb::initFileLogger("/tmp/vncviewer.log");
447#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000448 rfb::LogWriter::setLogParams("*:stderr:30");
449
450#ifdef SIGHUP
451 signal(SIGHUP, CleanupSignalHandler);
452#endif
453 signal(SIGINT, CleanupSignalHandler);
454 signal(SIGTERM, CleanupSignalHandler);
455
456 init_fltk();
457
Pierre Ossman6b9622d2014-07-21 16:42:12 +0200458#if !defined(WIN32) && !defined(__APPLE__)
459 fl_open_display();
460 XkbSetDetectableAutoRepeat(fl_display, True, NULL);
461#endif
462
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000463 Configuration::enableViewerParams();
464
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000465 /* Load the default parameter settings */
466 const char* defaultServerName;
467 try {
468 defaultServerName = loadViewerParameters(NULL);
469 } catch (rfb::Exception& e) {
Pierre Ossman3620e192015-03-03 16:50:15 +0100470 defaultServerName = "";
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000471 fl_alert("%s", e.str());
472 }
473
DRC5aa06502011-06-23 22:04:46 +0000474 int i = 1;
475 if (!Fl::args(argc, argv, i) || i < argc)
476 for (; i < argc; i++) {
477 if (Configuration::setParam(argv[i]))
478 continue;
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000479
DRC5aa06502011-06-23 22:04:46 +0000480 if (argv[i][0] == '-') {
481 if (i+1 < argc) {
482 if (Configuration::setParam(&argv[i][1], argv[i+1])) {
483 i++;
484 continue;
485 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000486 }
DRC5aa06502011-06-23 22:04:46 +0000487 usage(argv[0]);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000488 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000489
Adam Tkac8ac4b302013-01-23 13:55:46 +0000490 strncpy(vncServerName, argv[i], VNCSERVERNAMELEN);
491 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
DRC5aa06502011-06-23 22:04:46 +0000492 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000493
494 if (!::autoSelect.hasBeenSet()) {
495 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000496 if (::preferredEncoding.hasBeenSet() || ::fullColour.hasBeenSet() ||
497 ::fullColourAlias.hasBeenSet()) {
498 ::autoSelect.setParam(false);
499 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000500 }
501 if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) {
502 // Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set
503 if (!::autoSelect && (::lowColourLevel.hasBeenSet() ||
504 ::lowColourLevelAlias.hasBeenSet())) {
505 ::fullColour.setParam(false);
506 }
507 }
508 if (!::customCompressLevel.hasBeenSet()) {
509 // Default to CustomCompressLevel=1 if CompressLevel is used.
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000510 if(::compressLevel.hasBeenSet()) {
511 ::customCompressLevel.setParam(true);
512 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000513 }
514
515 mkvnchomedir();
516
517 CSecurity::upg = &dlg;
518#ifdef HAVE_GNUTLS
519 CSecurityTLS::msg = &dlg;
520#endif
521
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000522 Socket *sock = NULL;
523
DRC3e7ed812013-02-26 10:34:22 +0000524#ifndef WIN32
Adam Tkac571089b2013-02-19 14:30:32 +0000525 /* Specifying -via and -listen together is nonsense */
526 if (listenMode && strlen(via.getValueStr()) > 0) {
Pierre Ossman744e55c2014-12-03 14:00:54 +0100527 // TRANSLATORS: "Parameters" are command line arguments, or settings
528 // from a file or the Windows registry.
Pierre Ossman8ca4c1d2014-09-22 12:54:26 +0200529 vlog.error(_("Parameters -listen and -via are incompatible"));
530 fl_alert(_("Parameters -listen and -via are incompatible"));
Adam Tkac571089b2013-02-19 14:30:32 +0000531 exit_vncviewer();
532 return 1;
533 }
DRC3e7ed812013-02-26 10:34:22 +0000534#endif
Adam Tkac571089b2013-02-19 14:30:32 +0000535
536 if (listenMode) {
Tim Waugh892d10a2015-03-11 13:12:07 +0000537 std::list<TcpListener> listeners;
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000538 try {
539 int port = 5500;
540 if (isdigit(vncServerName[0]))
541 port = atoi(vncServerName);
542
Tim Waugh892d10a2015-03-11 13:12:07 +0000543 createTcpListeners(&listeners, 0, port);
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000544
Pierre Ossman8ca4c1d2014-09-22 12:54:26 +0200545 vlog.info(_("Listening on port %d\n"), port);
Tim Waugh892d10a2015-03-11 13:12:07 +0000546
547 /* Wait for a connection */
548 while (sock == NULL) {
549 fd_set rfds;
550 FD_ZERO(&rfds);
551 for (std::list<TcpListener>::iterator i = listeners.begin();
552 i != listeners.end();
553 i++)
554 FD_SET((*i).getFd(), &rfds);
555
556 int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
557 if (n < 0) {
558 if (errno == EINTR) {
559 vlog.debug("Interrupted select() system call");
560 continue;
561 } else {
562 throw rdr::SystemException("select", errno);
563 }
564 }
565
566 for (std::list<TcpListener>::iterator i = listeners.begin ();
567 i != listeners.end();
568 i++)
569 if (FD_ISSET((*i).getFd(), &rfds)) {
570 sock = (*i).accept();
571 if (sock)
572 /* Got a connection */
573 break;
574 }
575 }
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000576 } catch (rdr::Exception& e) {
577 vlog.error("%s", e.str());
578 fl_alert("%s", e.str());
579 exit_vncviewer();
580 return 1;
581 }
582
583 } else {
584 if (vncServerName[0] == '\0') {
585 ServerDialog::run(defaultServerName, vncServerName);
586 if (vncServerName[0] == '\0')
587 return 1;
588 }
Pierre Ossman561ff0c2011-05-13 14:04:59 +0000589
Adam Tkac8ac4b302013-01-23 13:55:46 +0000590#ifndef WIN32
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000591 if (strlen (via.getValueStr()) > 0 && mktunnel() != 0)
592 usage(argv[0]);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000593#endif
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000594 }
Adam Tkac8ac4b302013-01-23 13:55:46 +0000595
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000596 CConn *cc = new CConn(vncServerName, sock);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000597
598 while (!exitMainloop) {
599 int next_timer;
600
601 next_timer = Timer::checkTimeouts();
602 if (next_timer == 0)
603 next_timer = INT_MAX;
604
605 if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
606 vlog.error(_("Internal FLTK error. Exiting."));
607 break;
608 }
609 }
610
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000611 delete cc;
612
613 if (exitError != NULL)
Pierre Ossmanf52740e2012-04-25 15:43:56 +0000614 fl_alert("%s", exitError);
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000615
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000616 return 0;
617}