blob: 09d07150ed392a50ee902a2193e4a4ec1917daac [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.
Pierre Ossman8eb35082012-03-27 12:50:54 +0000168#ifdef WIN32
169 HICON lg, sm;
170
171 lg = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
172 IMAGE_ICON, GetSystemMetrics(SM_CXICON),
173 GetSystemMetrics(SM_CYICON),
174 LR_DEFAULTCOLOR | LR_SHARED);
175 sm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON),
176 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
177 GetSystemMetrics(SM_CYSMICON),
178 LR_DEFAULTCOLOR | LR_SHARED);
179
180 Fl_Window::default_icons(lg, sm);
181#elif ! defined(__APPLE__)
182 const int icon_sizes[] = {48, 32, 24, 16};
183
184 Fl_PNG_Image *icons[4];
185 int count;
186
187 count = 0;
188
189 // FIXME: Follow icon theme specification
190 for (size_t i = 0;i < sizeof(icon_sizes)/sizeof(icon_sizes[0]);i++) {
191 char icon_path[PATH_MAX];
192 bool exists;
193
Pierre Ossman6a007bd2012-09-11 10:56:21 +0000194 sprintf(icon_path, "%s/icons/hicolor/%dx%d/apps/tigervnc.png",
Pierre Ossman8eb35082012-03-27 12:50:54 +0000195 DATA_DIR, icon_sizes[i], icon_sizes[i]);
196
197#ifndef WIN32
198 struct stat st;
199 if (stat(icon_path, &st) != 0)
200#else
201 struct _stat st;
202 if (_stat(icon_path, &st) != 0)
203 return(false);
204#endif
205 exists = false;
206 else
207 exists = true;
208
209 if (exists) {
210 icons[count] = new Fl_PNG_Image(icon_path);
211 if (icons[count]->w() == 0 ||
212 icons[count]->h() == 0 ||
213 icons[count]->d() != 4) {
214 delete icons[count];
215 continue;
216 }
217
218 count++;
219 }
220 }
221
222 Fl_Window::default_icons((const Fl_RGB_Image**)icons, count);
223
224 for (int i = 0;i < count;i++)
225 delete icons[i];
226#endif
Pierre Ossman8eb35082012-03-27 12:50:54 +0000227
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000228 // This makes the "icon" in dialogs rounded, which fits better
229 // with the above schemes.
230 fl_message_icon()->box(FL_UP_BOX);
231
232 // Turn off the annoying behaviour where popups track the mouse.
233 fl_message_hotspot(false);
234
235 // Avoid empty titles for popups
236 fl_message_title_default(_("TigerVNC Viewer"));
237
238#ifdef WIN32
239 // Most "normal" Windows apps use this font for UI elements.
240 Fl::set_font(FL_HELVETICA, "Tahoma");
241#endif
242
243 // FLTK exposes these so that we can translate them.
244 fl_no = _("No");
245 fl_yes = _("Yes");
246 fl_ok = _("OK");
247 fl_cancel = _("Cancel");
248 fl_close = _("Close");
Pierre Ossmanb8858222011-04-29 11:51:38 +0000249
250#ifdef __APPLE__
Peter Åstrandb7c55242011-08-29 13:14:51 +0000251 /* Needs trailing space */
252 static char fltk_about[16];
253 snprintf(fltk_about, sizeof(fltk_about), "%s ", _("About"));
254 Fl_Mac_App_Menu::about = fltk_about;
255 static char fltk_hide[16];
256 snprintf(fltk_hide, sizeof(fltk_hide), "%s ", _("Hide"));
257 Fl_Mac_App_Menu::hide = fltk_hide;
258 static char fltk_quit[16];
259 snprintf(fltk_quit, sizeof(fltk_quit), "%s ", _("Quit"));
260 Fl_Mac_App_Menu::quit = fltk_quit;
261
Pierre Ossman41ba6032011-06-16 11:09:31 +0000262 Fl_Mac_App_Menu::print = ""; // Don't want the print item
263 Fl_Mac_App_Menu::services = _("Services");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000264 Fl_Mac_App_Menu::hide_others = _("Hide Others");
265 Fl_Mac_App_Menu::show = _("Show All");
Pierre Ossman41ba6032011-06-16 11:09:31 +0000266
Pierre Ossmanb8858222011-04-29 11:51:38 +0000267 fl_mac_set_about(about_callback, NULL);
Pierre Ossmana71a2762015-03-04 09:57:06 +0100268
269 Fl_Sys_Menu_Bar *menubar;
270 char buffer[1024];
271 menubar = new Fl_Sys_Menu_Bar(0, 0, 500, 25);
272 // Fl_Sys_Menu_Bar overrides methods without them being virtual,
273 // which means we cannot use our generic Fl_Menu_ helpers.
274 if (fltk_menu_escape(_("&File"), buffer, sizeof(buffer)) < sizeof(buffer))
275 menubar->add(buffer, 0, 0, 0, FL_SUBMENU);
276 if (fltk_menu_escape(_("&New Connection"), buffer, sizeof(buffer)) < sizeof(buffer))
277 menubar->insert(1, buffer, FL_COMMAND | 'n', new_connection_cb);
Pierre Ossmanb8858222011-04-29 11:51:38 +0000278#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000279}
280
281static void mkvnchomedir()
282{
283 // Create .vnc in the user's home directory if it doesn't already exist
284 char* homeDir = NULL;
285
286 if (getvnchomedir(&homeDir) == -1) {
287 vlog.error(_("Could not create VNC home directory: can't obtain home "
288 "directory path."));
289 } else {
290 int result = mkdir(homeDir, 0755);
291 if (result == -1 && errno != EEXIST)
292 vlog.error(_("Could not create VNC home directory: %s."), strerror(errno));
293 delete [] homeDir;
294 }
295}
296
297static void usage(const char *programName)
298{
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100299#ifdef WIN32
300 // If we don't have a console then we need to create one for output
301 if (GetConsoleWindow() == NULL) {
302 HANDLE handle;
303 int fd;
304
305 AllocConsole();
306
307 handle = GetStdHandle(STD_ERROR_HANDLE);
308 fd = _open_osfhandle((intptr_t)handle, O_TEXT);
309 *stderr = *fdopen(fd, "w");
310 }
311#endif
312
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000313 fprintf(stderr,
314 "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
315 " %s [parameters] -listen [port] [parameters]\n",
316 programName, programName);
317 fprintf(stderr,"\n"
318 "Parameters can be turned on with -<param> or off with -<param>=0\n"
319 "Parameters which take a value can be specified as "
320 "-<param> <value>\n"
321 "Other valid forms are <param>=<value> -<param>=<value> "
322 "--<param>=<value>\n"
323 "Parameter names are case-insensitive. The parameters are:\n\n");
324 Configuration::listParams(79, 14);
Pierre Ossman5bf17ad2015-02-17 13:23:00 +0100325
326#ifdef WIN32
327 // Just wait for the user to kill the console window
328 Sleep(INFINITE);
329#endif
330
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000331 exit(1);
332}
333
Adam Tkac8ac4b302013-01-23 13:55:46 +0000334#ifndef WIN32
335static int
336interpretViaParam(char *remoteHost, int *remotePort, int localPort)
337{
338 const int SERVER_PORT_OFFSET = 5900;
339 char *pos = strchr(vncServerName, ':');
340 if (pos == NULL)
341 *remotePort = SERVER_PORT_OFFSET;
342 else {
343 int portOffset = SERVER_PORT_OFFSET;
344 size_t len;
345 *pos++ = '\0';
346 len = strlen(pos);
347 if (*pos == ':') {
348 /* Two colons is an absolute port number, not an offset. */
349 pos++;
350 len--;
351 portOffset = 0;
352 }
353 if (!len || strspn (pos, "-0123456789") != len )
354 return 1;
355 *remotePort = atoi(pos) + portOffset;
356 }
357
358 if (*vncServerName != '\0')
359 strncpy(remoteHost, vncServerName, VNCSERVERNAMELEN);
360 else
361 strncpy(remoteHost, "localhost", VNCSERVERNAMELEN);
362
363 remoteHost[VNCSERVERNAMELEN - 1] = '\0';
364
365 snprintf(vncServerName, VNCSERVERNAMELEN, "localhost::%d", localPort);
366 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
Adam Tkac8ac4b302013-01-23 13:55:46 +0000367
368 return 0;
369}
370
371static void
372createTunnel(const char *gatewayHost, const char *remoteHost,
373 int remotePort, int localPort)
374{
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200375 const char *cmd = getenv("VNC_VIA_CMD");
376 char *cmd2, *percent;
Adam Tkac8ac4b302013-01-23 13:55:46 +0000377 char lport[10], rport[10];
378 sprintf(lport, "%d", localPort);
379 sprintf(rport, "%d", remotePort);
380 setenv("G", gatewayHost, 1);
381 setenv("H", remoteHost, 1);
382 setenv("R", rport, 1);
383 setenv("L", lport, 1);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000384 if (!cmd)
385 cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20";
386 /* Compatibility with TigerVNC's method. */
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200387 cmd2 = strdup(cmd);
388 while ((percent = strchr(cmd2, '%')) != NULL)
Adam Tkac8ac4b302013-01-23 13:55:46 +0000389 *percent = '$';
Pierre Ossmanf8d525b2014-07-09 17:02:27 +0200390 system(cmd2);
391 free(cmd2);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000392}
393
394static int mktunnel()
395{
396 const char *gatewayHost;
397 char remoteHost[VNCSERVERNAMELEN];
398 int localPort = findFreeTcpPort();
399 int remotePort;
400
401 gatewayHost = strDup(via.getValueStr());
402 if (interpretViaParam(remoteHost, &remotePort, localPort) != 0)
403 return 1;
404 createTunnel(gatewayHost, remoteHost, remotePort, localPort);
405
406 return 0;
407}
408#endif /* !WIN32 */
409
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000410int main(int argc, char** argv)
411{
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000412 UserDialog dlg;
413
Pierre Ossmana71a2762015-03-04 09:57:06 +0100414 argv0 = argv[0];
415
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000416 setlocale(LC_ALL, "");
Pierre Ossman0878eca2012-03-27 13:03:22 +0000417 bindtextdomain(PACKAGE_NAME, LOCALE_DIR);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000418 textdomain(PACKAGE_NAME);
419
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200420 // Generate the about string now that we get the proper translation
Pierre Ossman63471c92015-03-03 16:49:50 +0100421 snprintf(aboutText, sizeof(aboutText),
422 _("TigerVNC Viewer %d-bit v%s\n"
423 "Built on: %s\n"
424 "Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\n"
425 "See http://www.tigervnc.org for information on TigerVNC."),
Pierre Ossman5945d732014-09-22 13:13:15 +0200426 (int)sizeof(size_t)*8, PACKAGE_VERSION,
Pierre Ossmanc1341682015-02-20 17:12:57 +0100427 BUILD_TIMESTAMP, 2015);
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200428
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000429 rfb::SecurityClient::setDefaults();
430
431 // Write about text to console, still using normal locale codeset
Pierre Ossmandc96cb42014-09-22 12:19:26 +0200432 fprintf(stderr,"\n%s\n", aboutText);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000433
434 // Set gettext codeset to what our GUI toolkit uses. Since we are
435 // passing strings from strerror/gai_strerror to the GUI, these must
436 // be in GUI codeset as well.
437 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
438 bind_textdomain_codeset("libc", "UTF-8");
439
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000440 rfb::initStdIOLoggers();
Pierre Ossmanc8719ad2012-04-26 14:27:52 +0000441#ifdef WIN32
442 rfb::initFileLogger("C:\\temp\\vncviewer.log");
443#else
444 rfb::initFileLogger("/tmp/vncviewer.log");
445#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000446 rfb::LogWriter::setLogParams("*:stderr:30");
447
448#ifdef SIGHUP
449 signal(SIGHUP, CleanupSignalHandler);
450#endif
451 signal(SIGINT, CleanupSignalHandler);
452 signal(SIGTERM, CleanupSignalHandler);
453
454 init_fltk();
455
Pierre Ossman6b9622d2014-07-21 16:42:12 +0200456#if !defined(WIN32) && !defined(__APPLE__)
457 fl_open_display();
458 XkbSetDetectableAutoRepeat(fl_display, True, NULL);
459#endif
460
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000461 Configuration::enableViewerParams();
462
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000463 /* Load the default parameter settings */
464 const char* defaultServerName;
465 try {
466 defaultServerName = loadViewerParameters(NULL);
467 } catch (rfb::Exception& e) {
Pierre Ossman3620e192015-03-03 16:50:15 +0100468 defaultServerName = "";
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000469 fl_alert("%s", e.str());
470 }
471
DRC5aa06502011-06-23 22:04:46 +0000472 int i = 1;
473 if (!Fl::args(argc, argv, i) || i < argc)
474 for (; i < argc; i++) {
475 if (Configuration::setParam(argv[i]))
476 continue;
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000477
DRC5aa06502011-06-23 22:04:46 +0000478 if (argv[i][0] == '-') {
479 if (i+1 < argc) {
480 if (Configuration::setParam(&argv[i][1], argv[i+1])) {
481 i++;
482 continue;
483 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000484 }
DRC5aa06502011-06-23 22:04:46 +0000485 usage(argv[0]);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000486 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000487
Adam Tkac8ac4b302013-01-23 13:55:46 +0000488 strncpy(vncServerName, argv[i], VNCSERVERNAMELEN);
489 vncServerName[VNCSERVERNAMELEN - 1] = '\0';
DRC5aa06502011-06-23 22:04:46 +0000490 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000491
492 if (!::autoSelect.hasBeenSet()) {
493 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000494 if (::preferredEncoding.hasBeenSet() || ::fullColour.hasBeenSet() ||
495 ::fullColourAlias.hasBeenSet()) {
496 ::autoSelect.setParam(false);
497 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000498 }
499 if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) {
500 // Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set
501 if (!::autoSelect && (::lowColourLevel.hasBeenSet() ||
502 ::lowColourLevelAlias.hasBeenSet())) {
503 ::fullColour.setParam(false);
504 }
505 }
506 if (!::customCompressLevel.hasBeenSet()) {
507 // Default to CustomCompressLevel=1 if CompressLevel is used.
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000508 if(::compressLevel.hasBeenSet()) {
509 ::customCompressLevel.setParam(true);
510 }
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000511 }
512
513 mkvnchomedir();
514
515 CSecurity::upg = &dlg;
516#ifdef HAVE_GNUTLS
517 CSecurityTLS::msg = &dlg;
518#endif
519
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000520 Socket *sock = NULL;
521
DRC3e7ed812013-02-26 10:34:22 +0000522#ifndef WIN32
Adam Tkac571089b2013-02-19 14:30:32 +0000523 /* Specifying -via and -listen together is nonsense */
524 if (listenMode && strlen(via.getValueStr()) > 0) {
Pierre Ossman744e55c2014-12-03 14:00:54 +0100525 // TRANSLATORS: "Parameters" are command line arguments, or settings
526 // from a file or the Windows registry.
Pierre Ossman8ca4c1d2014-09-22 12:54:26 +0200527 vlog.error(_("Parameters -listen and -via are incompatible"));
528 fl_alert(_("Parameters -listen and -via are incompatible"));
Adam Tkac571089b2013-02-19 14:30:32 +0000529 exit_vncviewer();
530 return 1;
531 }
DRC3e7ed812013-02-26 10:34:22 +0000532#endif
Adam Tkac571089b2013-02-19 14:30:32 +0000533
534 if (listenMode) {
Tim Waugh892d10a2015-03-11 13:12:07 +0000535 std::list<TcpListener> listeners;
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000536 try {
537 int port = 5500;
538 if (isdigit(vncServerName[0]))
539 port = atoi(vncServerName);
540
Tim Waugh892d10a2015-03-11 13:12:07 +0000541 createTcpListeners(&listeners, 0, port);
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000542
Peter Åstrand (astrand)4ab2f8a2015-03-18 10:31:01 +0100543 vlog.info(_("Listening on port %d"), port);
Tim Waugh892d10a2015-03-11 13:12:07 +0000544
545 /* Wait for a connection */
546 while (sock == NULL) {
547 fd_set rfds;
548 FD_ZERO(&rfds);
549 for (std::list<TcpListener>::iterator i = listeners.begin();
550 i != listeners.end();
551 i++)
552 FD_SET((*i).getFd(), &rfds);
553
554 int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
555 if (n < 0) {
556 if (errno == EINTR) {
557 vlog.debug("Interrupted select() system call");
558 continue;
559 } else {
560 throw rdr::SystemException("select", errno);
561 }
562 }
563
564 for (std::list<TcpListener>::iterator i = listeners.begin ();
565 i != listeners.end();
566 i++)
567 if (FD_ISSET((*i).getFd(), &rfds)) {
568 sock = (*i).accept();
569 if (sock)
570 /* Got a connection */
571 break;
572 }
573 }
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000574 } catch (rdr::Exception& e) {
575 vlog.error("%s", e.str());
576 fl_alert("%s", e.str());
577 exit_vncviewer();
578 return 1;
579 }
580
581 } else {
582 if (vncServerName[0] == '\0') {
583 ServerDialog::run(defaultServerName, vncServerName);
584 if (vncServerName[0] == '\0')
585 return 1;
586 }
Pierre Ossman561ff0c2011-05-13 14:04:59 +0000587
Adam Tkac8ac4b302013-01-23 13:55:46 +0000588#ifndef WIN32
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000589 if (strlen (via.getValueStr()) > 0 && mktunnel() != 0)
590 usage(argv[0]);
Adam Tkac8ac4b302013-01-23 13:55:46 +0000591#endif
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000592 }
Adam Tkac8ac4b302013-01-23 13:55:46 +0000593
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000594 CConn *cc = new CConn(vncServerName, sock);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000595
596 while (!exitMainloop) {
597 int next_timer;
598
599 next_timer = Timer::checkTimeouts();
600 if (next_timer == 0)
601 next_timer = INT_MAX;
602
603 if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
604 vlog.error(_("Internal FLTK error. Exiting."));
605 break;
606 }
607 }
608
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000609 delete cc;
610
611 if (exitError != NULL)
Pierre Ossmanf52740e2012-04-25 15:43:56 +0000612 fl_alert("%s", exitError);
Pierre Ossmane2ef5c12011-07-12 16:56:34 +0000613
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000614 return 0;
615}