blob: aa742ce29864ec03f8607f08f9265a156de34c08 [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
3 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
20#include <string.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <errno.h>
24#include <signal.h>
25#include <locale.h>
26#include <sys/stat.h>
27
28#ifdef WIN32
29#include <direct.h>
30#define mkdir(path, mode) _mkdir(path)
31#endif
32
33#include <os/os.h>
34#include <rfb/Logger_stdio.h>
35#include <rfb/SecurityClient.h>
36#include <rfb/Security.h>
37#ifdef HAVE_GNUTLS
38#include <rfb/CSecurityTLS.h>
39#endif
40#include <rfb/LogWriter.h>
41#include <rfb/Timer.h>
42#include <network/TcpSocket.h>
43
44#include <FL/Fl.H>
45#include <FL/Fl_Widget.H>
46#include <FL/fl_ask.H>
Pierre Ossmanb8858222011-04-29 11:51:38 +000047#include <FL/x.H>
Pierre Ossman5156d5e2011-03-09 09:42:34 +000048
49#include "i18n.h"
50#include "parameters.h"
51#include "CConn.h"
Pierre Ossman561ff0c2011-05-13 14:04:59 +000052#include "ServerDialog.h"
Pierre Ossman5156d5e2011-03-09 09:42:34 +000053#include "UserDialog.h"
54
55rfb::LogWriter vlog("main");
56
57using namespace network;
58using namespace rfb;
59using namespace std;
60
Pierre Ossmanb8858222011-04-29 11:51:38 +000061static char aboutText[1024];
Pierre Ossman5156d5e2011-03-09 09:42:34 +000062
63static bool exitMainloop = false;
64
65void exit_vncviewer()
66{
67 exitMainloop = true;
68}
69
Pierre Ossmanb8858222011-04-29 11:51:38 +000070void about_vncviewer()
71{
72 fl_message_title(_("About TigerVNC Viewer"));
73 fl_message(aboutText);
74}
75
76static void about_callback(Fl_Widget *widget, void *data)
77{
78 about_vncviewer();
79}
80
Pierre Ossman5156d5e2011-03-09 09:42:34 +000081static void CleanupSignalHandler(int sig)
82{
83 // CleanupSignalHandler allows C++ object cleanup to happen because it calls
84 // exit() rather than the default which is to abort.
85 vlog.info("CleanupSignalHandler called");
86 exit(1);
87}
88
89static void init_fltk()
90{
91 // Basic text size (10pt @ 96 dpi => 13px)
92 FL_NORMAL_SIZE = 13;
93
94#ifndef __APPLE__
95 // Select a FLTK scheme and background color that looks somewhat
96 // close to modern Linux and Windows.
97 Fl::scheme("gtk+");
98 Fl::background(220, 220, 220);
99#else
100 // On Mac OS X there is another scheme that fits better though.
101 Fl::scheme("plastic");
102#endif
103
104 // This makes the "icon" in dialogs rounded, which fits better
105 // with the above schemes.
106 fl_message_icon()->box(FL_UP_BOX);
107
108 // Turn off the annoying behaviour where popups track the mouse.
109 fl_message_hotspot(false);
110
111 // Avoid empty titles for popups
112 fl_message_title_default(_("TigerVNC Viewer"));
113
114#ifdef WIN32
115 // Most "normal" Windows apps use this font for UI elements.
116 Fl::set_font(FL_HELVETICA, "Tahoma");
117#endif
118
119 // FLTK exposes these so that we can translate them.
120 fl_no = _("No");
121 fl_yes = _("Yes");
122 fl_ok = _("OK");
123 fl_cancel = _("Cancel");
124 fl_close = _("Close");
Pierre Ossmanb8858222011-04-29 11:51:38 +0000125
126#ifdef __APPLE__
Pierre Ossman41ba6032011-06-16 11:09:31 +0000127 Fl_Mac_App_Menu::about = _("About ");
128 Fl_Mac_App_Menu::print = ""; // Don't want the print item
129 Fl_Mac_App_Menu::services = _("Services");
130 Fl_Mac_App_Menu::hide = _("Hide ");
131 Fl_Mac_App_Menu::hide_others = _("Hide Others");
132 Fl_Mac_App_Menu::show = _("Show All");
133 Fl_Mac_App_Menu::quit = _("Quit ");
134
Pierre Ossmanb8858222011-04-29 11:51:38 +0000135 fl_mac_set_about(about_callback, NULL);
136#endif
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000137}
138
139static void mkvnchomedir()
140{
141 // Create .vnc in the user's home directory if it doesn't already exist
142 char* homeDir = NULL;
143
144 if (getvnchomedir(&homeDir) == -1) {
145 vlog.error(_("Could not create VNC home directory: can't obtain home "
146 "directory path."));
147 } else {
148 int result = mkdir(homeDir, 0755);
149 if (result == -1 && errno != EEXIST)
150 vlog.error(_("Could not create VNC home directory: %s."), strerror(errno));
151 delete [] homeDir;
152 }
153}
154
155static void usage(const char *programName)
156{
157 fprintf(stderr,
158 "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
159 " %s [parameters] -listen [port] [parameters]\n",
160 programName, programName);
161 fprintf(stderr,"\n"
162 "Parameters can be turned on with -<param> or off with -<param>=0\n"
163 "Parameters which take a value can be specified as "
164 "-<param> <value>\n"
165 "Other valid forms are <param>=<value> -<param>=<value> "
166 "--<param>=<value>\n"
167 "Parameter names are case-insensitive. The parameters are:\n\n");
168 Configuration::listParams(79, 14);
169 exit(1);
170}
171
172int main(int argc, char** argv)
173{
Pierre Ossman561ff0c2011-05-13 14:04:59 +0000174 const char* vncServerName = NULL;
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000175 UserDialog dlg;
176
177 const char englishAbout[] = N_("TigerVNC Viewer version %s\n"
178 "Copyright (C) 2002-2005 RealVNC Ltd.\n"
179 "Copyright (C) 2000-2006 TightVNC Group\n"
180 "Copyright (C) 2004-2009 Peter Astrand for Cendio AB\n"
181 "See http://www.tigervnc.org for information on TigerVNC.");
182
183 setlocale(LC_ALL, "");
184 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
185 textdomain(PACKAGE_NAME);
186
187 rfb::SecurityClient::setDefaults();
188
189 // Write about text to console, still using normal locale codeset
190 snprintf(aboutText, sizeof(aboutText),
191 gettext(englishAbout), PACKAGE_VERSION);
192 fprintf(stderr,"\n%s\n", aboutText);
193
194 // Set gettext codeset to what our GUI toolkit uses. Since we are
195 // passing strings from strerror/gai_strerror to the GUI, these must
196 // be in GUI codeset as well.
197 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
198 bind_textdomain_codeset("libc", "UTF-8");
199
200 // Re-create the aboutText for the GUI, now using GUI codeset
201 snprintf(aboutText, sizeof(aboutText),
202 gettext(englishAbout), PACKAGE_VERSION);
203
204 rfb::initStdIOLoggers();
205 rfb::LogWriter::setLogParams("*:stderr:30");
206
207#ifdef SIGHUP
208 signal(SIGHUP, CleanupSignalHandler);
209#endif
210 signal(SIGINT, CleanupSignalHandler);
211 signal(SIGTERM, CleanupSignalHandler);
212
213 init_fltk();
214
215 Configuration::enableViewerParams();
216
217 for (int i = 1; i < argc; i++) {
218 if (Configuration::setParam(argv[i]))
219 continue;
220
221 if (argv[i][0] == '-') {
222 if (i+1 < argc) {
223 if (Configuration::setParam(&argv[i][1], argv[i+1])) {
224 i++;
225 continue;
226 }
227 }
228 usage(argv[0]);
229 }
230
231 vncServerName = argv[i];
232 }
233
234 if (!::autoSelect.hasBeenSet()) {
235 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
236 ::autoSelect.setParam(!::preferredEncoding.hasBeenSet() &&
237 !::fullColour.hasBeenSet() &&
238 !::fullColourAlias.hasBeenSet());
239 }
240 if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) {
241 // Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set
242 if (!::autoSelect && (::lowColourLevel.hasBeenSet() ||
243 ::lowColourLevelAlias.hasBeenSet())) {
244 ::fullColour.setParam(false);
245 }
246 }
247 if (!::customCompressLevel.hasBeenSet()) {
248 // Default to CustomCompressLevel=1 if CompressLevel is used.
249 ::customCompressLevel.setParam(::compressLevel.hasBeenSet());
250 }
251
252 mkvnchomedir();
253
254 CSecurity::upg = &dlg;
255#ifdef HAVE_GNUTLS
256 CSecurityTLS::msg = &dlg;
257#endif
258
Pierre Ossman561ff0c2011-05-13 14:04:59 +0000259 if (vncServerName == NULL) {
260 vncServerName = ServerDialog::run();
261 if ((vncServerName == NULL) || (vncServerName[0] == '\0'))
262 return 1;
263 }
264
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000265 CConn cc(vncServerName);
266
267 while (!exitMainloop) {
268 int next_timer;
269
270 next_timer = Timer::checkTimeouts();
271 if (next_timer == 0)
272 next_timer = INT_MAX;
273
274 if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
275 vlog.error(_("Internal FLTK error. Exiting."));
276 break;
277 }
278 }
279
280 return 0;
281}