blob: a6244cba99ba5a2b86be6c56bc4fc0d81dd230a4 [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>
47
48#include "i18n.h"
49#include "parameters.h"
50#include "CConn.h"
51#include "UserDialog.h"
52
53rfb::LogWriter vlog("main");
54
55using namespace network;
56using namespace rfb;
57using namespace std;
58
59char aboutText[1024];
60
61static bool exitMainloop = false;
62
63void exit_vncviewer()
64{
65 exitMainloop = true;
66}
67
68static void CleanupSignalHandler(int sig)
69{
70 // CleanupSignalHandler allows C++ object cleanup to happen because it calls
71 // exit() rather than the default which is to abort.
72 vlog.info("CleanupSignalHandler called");
73 exit(1);
74}
75
76static void init_fltk()
77{
78 // Basic text size (10pt @ 96 dpi => 13px)
79 FL_NORMAL_SIZE = 13;
80
81#ifndef __APPLE__
82 // Select a FLTK scheme and background color that looks somewhat
83 // close to modern Linux and Windows.
84 Fl::scheme("gtk+");
85 Fl::background(220, 220, 220);
86#else
87 // On Mac OS X there is another scheme that fits better though.
88 Fl::scheme("plastic");
89#endif
90
91 // This makes the "icon" in dialogs rounded, which fits better
92 // with the above schemes.
93 fl_message_icon()->box(FL_UP_BOX);
94
95 // Turn off the annoying behaviour where popups track the mouse.
96 fl_message_hotspot(false);
97
98 // Avoid empty titles for popups
99 fl_message_title_default(_("TigerVNC Viewer"));
100
101#ifdef WIN32
102 // Most "normal" Windows apps use this font for UI elements.
103 Fl::set_font(FL_HELVETICA, "Tahoma");
104#endif
105
106 // FLTK exposes these so that we can translate them.
107 fl_no = _("No");
108 fl_yes = _("Yes");
109 fl_ok = _("OK");
110 fl_cancel = _("Cancel");
111 fl_close = _("Close");
112}
113
114static void mkvnchomedir()
115{
116 // Create .vnc in the user's home directory if it doesn't already exist
117 char* homeDir = NULL;
118
119 if (getvnchomedir(&homeDir) == -1) {
120 vlog.error(_("Could not create VNC home directory: can't obtain home "
121 "directory path."));
122 } else {
123 int result = mkdir(homeDir, 0755);
124 if (result == -1 && errno != EEXIST)
125 vlog.error(_("Could not create VNC home directory: %s."), strerror(errno));
126 delete [] homeDir;
127 }
128}
129
130static void usage(const char *programName)
131{
132 fprintf(stderr,
133 "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
134 " %s [parameters] -listen [port] [parameters]\n",
135 programName, programName);
136 fprintf(stderr,"\n"
137 "Parameters can be turned on with -<param> or off with -<param>=0\n"
138 "Parameters which take a value can be specified as "
139 "-<param> <value>\n"
140 "Other valid forms are <param>=<value> -<param>=<value> "
141 "--<param>=<value>\n"
142 "Parameter names are case-insensitive. The parameters are:\n\n");
143 Configuration::listParams(79, 14);
144 exit(1);
145}
146
147int main(int argc, char** argv)
148{
149 char* vncServerName = 0;
150 UserDialog dlg;
151
152 const char englishAbout[] = N_("TigerVNC Viewer version %s\n"
153 "Copyright (C) 2002-2005 RealVNC Ltd.\n"
154 "Copyright (C) 2000-2006 TightVNC Group\n"
155 "Copyright (C) 2004-2009 Peter Astrand for Cendio AB\n"
156 "See http://www.tigervnc.org for information on TigerVNC.");
157
158 setlocale(LC_ALL, "");
159 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
160 textdomain(PACKAGE_NAME);
161
162 rfb::SecurityClient::setDefaults();
163
164 // Write about text to console, still using normal locale codeset
165 snprintf(aboutText, sizeof(aboutText),
166 gettext(englishAbout), PACKAGE_VERSION);
167 fprintf(stderr,"\n%s\n", aboutText);
168
169 // Set gettext codeset to what our GUI toolkit uses. Since we are
170 // passing strings from strerror/gai_strerror to the GUI, these must
171 // be in GUI codeset as well.
172 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
173 bind_textdomain_codeset("libc", "UTF-8");
174
175 // Re-create the aboutText for the GUI, now using GUI codeset
176 snprintf(aboutText, sizeof(aboutText),
177 gettext(englishAbout), PACKAGE_VERSION);
178
179 rfb::initStdIOLoggers();
180 rfb::LogWriter::setLogParams("*:stderr:30");
181
182#ifdef SIGHUP
183 signal(SIGHUP, CleanupSignalHandler);
184#endif
185 signal(SIGINT, CleanupSignalHandler);
186 signal(SIGTERM, CleanupSignalHandler);
187
188 init_fltk();
189
190 Configuration::enableViewerParams();
191
192 for (int i = 1; i < argc; i++) {
193 if (Configuration::setParam(argv[i]))
194 continue;
195
196 if (argv[i][0] == '-') {
197 if (i+1 < argc) {
198 if (Configuration::setParam(&argv[i][1], argv[i+1])) {
199 i++;
200 continue;
201 }
202 }
203 usage(argv[0]);
204 }
205
206 vncServerName = argv[i];
207 }
208
209 if (!::autoSelect.hasBeenSet()) {
210 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
211 ::autoSelect.setParam(!::preferredEncoding.hasBeenSet() &&
212 !::fullColour.hasBeenSet() &&
213 !::fullColourAlias.hasBeenSet());
214 }
215 if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) {
216 // Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set
217 if (!::autoSelect && (::lowColourLevel.hasBeenSet() ||
218 ::lowColourLevelAlias.hasBeenSet())) {
219 ::fullColour.setParam(false);
220 }
221 }
222 if (!::customCompressLevel.hasBeenSet()) {
223 // Default to CustomCompressLevel=1 if CompressLevel is used.
224 ::customCompressLevel.setParam(::compressLevel.hasBeenSet());
225 }
226
227 mkvnchomedir();
228
229 CSecurity::upg = &dlg;
230#ifdef HAVE_GNUTLS
231 CSecurityTLS::msg = &dlg;
232#endif
233
234 CConn cc(vncServerName);
235
236 while (!exitMainloop) {
237 int next_timer;
238
239 next_timer = Timer::checkTimeouts();
240 if (next_timer == 0)
241 next_timer = INT_MAX;
242
243 if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
244 vlog.error(_("Internal FLTK error. Exiting."));
245 break;
246 }
247 }
248
249 return 0;
250}