/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ // // All-new VNC viewer for X. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TXWindow.h" #include "CConn.h" #include #define _(String) gettext (String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) rfb::LogWriter vlog("main"); using namespace network; using namespace rfb; IntParameter pointerEventInterval("PointerEventInterval", "Time in milliseconds to rate-limit" " successive pointer events", 0); IntParameter wmDecorationWidth("WMDecorationWidth", "Width of window manager " "decoration around a window", 6); IntParameter wmDecorationHeight("WMDecorationHeight", "Height of window " "manager decoration around a window", 24); StringParameter passwordFile("PasswordFile", "Password file for VNC authentication", ""); AliasParameter rfbauth("passwd", "Alias for PasswordFile", &passwordFile); BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true); BoolParameter dotWhenNoCursor("DotWhenNoCursor", "Show the dot cursor when the server sends an " "invisible cursor", true); BoolParameter autoSelect("AutoSelect", "Auto select pixel format and encoding. " "Default if PreferredEncoding and FullColor are not specified.", true); BoolParameter fullColour("FullColor", "Use full color", true); AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour); IntParameter lowColourLevel("LowColorLevel", "Color level to use on slow connections. " "0 = Very Low (8 colors), 1 = Low (64 colors), " "2 = Medium (256 colors)", 2); AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel); StringParameter preferredEncoding("PreferredEncoding", "Preferred encoding to use (Tight, ZRLE, Hextile or" " Raw)", "Tight"); BoolParameter fullScreen("FullScreen", "Full screen mode", false); BoolParameter viewOnly("ViewOnly", "Don't send any mouse or keyboard events to the server", false); BoolParameter shared("Shared", "Don't disconnect other viewers upon connection - " "share the desktop instead", false); BoolParameter acceptClipboard("AcceptClipboard", "Accept clipboard changes from the server", true); BoolParameter sendClipboard("SendClipboard", "Send clipboard changes to the server", true); BoolParameter sendPrimary("SendPrimary", "Send the primary selection and cut buffer to the " "server as well as the clipboard selection", true); BoolParameter listenMode("listen", "Listen for connections from VNC servers", false); StringParameter geometry("geometry", "X geometry specification", ""); StringParameter displayname("display", "The X display", ""); BoolParameter customCompressLevel("CustomCompressLevel", "Use custom compression level. " "Default if CompressLevel is specified.", false); IntParameter compressLevel("CompressLevel", "Use specified compression level" "0 = Low, 9 = High", 6); BoolParameter noJpeg("NoJPEG", "Disable lossy JPEG compression in Tight encoding.", false); IntParameter qualityLevel("QualityLevel", "JPEG quality level. " "0 = Low, 9 = High", 6); char aboutText[1024]; char* programName; extern char buildtime[]; static void CleanupSignalHandler(int sig) { // CleanupSignalHandler allows C++ object cleanup to happen because it calls // exit() rather than the default which is to abort. vlog.info("CleanupSignalHandler called"); exit(1); } // XLoginIconifier is a class which iconifies the XDM login window when it has // grabbed the keyboard, thus releasing the grab, allowing the viewer to use // the keyboard. It remaps the xlogin window on exit. class XLoginIconifier { public: Display* dpy; Window xlogin; XLoginIconifier() : dpy(0), xlogin(0) {} void iconify(Display* dpy_) { dpy = dpy_; if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, GrabModeSync, CurrentTime) == GrabSuccess) { XUngrabKeyboard(dpy, CurrentTime); } else { xlogin = TXWindow::windowWithName(dpy, DefaultRootWindow(dpy), "xlogin"); if (xlogin) { XIconifyWindow(dpy, xlogin, DefaultScreen(dpy)); XSync(dpy, False); } } } ~XLoginIconifier() { if (xlogin) { fprintf(stderr,"~XLoginIconifier remapping xlogin\n"); XMapWindow(dpy, xlogin); XFlush(dpy); sleep(1); } } }; static XLoginIconifier xloginIconifier; static void usage() { fprintf(stderr, "\nusage: %s [parameters] [host:displayNum] [parameters]\n" " %s [parameters] -listen [port] [parameters]\n", programName,programName); fprintf(stderr,"\n" "Parameters can be turned on with - or off with -=0\n" "Parameters which take a value can be specified as " "- \n" "Other valid forms are = -= " "--=\n" "Parameter names are case-insensitive. The parameters are:\n\n"); Configuration::listParams(79, 14); exit(1); } int main(int argc, char** argv) { setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); snprintf(aboutText, sizeof(aboutText), _("TightVNC viewer for X version 4.0 - built %s\n" "Copyright (C) 2002-2004 RealVNC Ltd.\n" "Copyright (C) 2000-2004 Constantin Kaplinsky.\n" "Copyright (C) 2004 Peter Astrand, Cendio AB\n" "See http://www.tightvnc.com for information on TightVNC."), buildtime); fprintf(stderr,"\n%s\n", aboutText); rfb::initStdIOLoggers(); rfb::LogWriter::setLogParams("*:stderr:30"); signal(SIGHUP, CleanupSignalHandler); signal(SIGINT, CleanupSignalHandler); signal(SIGTERM, CleanupSignalHandler); programName = argv[0]; char* vncServerName = 0; Display* dpy; for (int i = 1; i < argc; i++) { if (Configuration::setParam(argv[i])) continue; if (argv[i][0] == '-') { if (i+1 < argc) { if (Configuration::setParam(&argv[i][1], argv[i+1])) { i++; continue; } } usage(); } if (vncServerName) usage(); vncServerName = argv[i]; } if (!::autoSelect.hasBeenSet()) { // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used ::autoSelect.setParam(!::preferredEncoding.hasBeenSet() && !::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()); } if (!::customCompressLevel.hasBeenSet()) { // Default to CustomCompressLevel=1 if CompressLevel is used. ::customCompressLevel.setParam(::compressLevel.hasBeenSet()); } try { TcpSocket::initTcpSockets(); Socket* sock = 0; if (listenMode) { int port = 5500; if (vncServerName && isdigit(vncServerName[0])) port = atoi(vncServerName); TcpListener listener(port); vlog.info("Listening on port %d\n",port); while (true) { sock = listener.accept(); int pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) break; // child delete sock; int status; while (wait3(&status, WNOHANG, 0) > 0) ; } } CharArray displaynameStr(displayname.getData()); if (!(dpy = XOpenDisplay(TXWindow::strEmptyToNull(displaynameStr.buf)))) { fprintf(stderr,"%s: unable to open display \"%s\"\n", programName, XDisplayName(displaynameStr.buf)); exit(1); } TXWindow::init(dpy, "Vncviewer"); xloginIconifier.iconify(dpy); CConn cc(dpy, argc, argv, sock, vncServerName); // X events are processed whenever reading from the socket would block. while (true) { cc.getInStream()->check(1); cc.processMsg(); } } catch (rdr::Exception &e) { vlog.error(e.str()); } return 0; }