void CApp::parseArgs(int argc, const char* const* argv, int& i) { // about these use of assert() here: // previously an /analyze warning was displayed if we only used assert and // did not return on failure. however, this warning does not appear to show // any more (could be because new compiler args have been added). // the asserts are programmer benefit only; the os should never pass 0 args, // because the first is always the binary name. the only way assert would // evaluate to true, is if this parse function were implemented incorrectly, // which is unlikely because it's old code and has a specific use. // we should avoid using anything other than assert here, because it will // look like important code, which it's not really. assert(argsBase().m_pname != NULL); assert(argv != NULL); assert(argc >= 1); // set defaults argsBase().m_name = ARCH->getHostName(); LOG((CLOG_INFO "CApp::parseArgs call")); // parse options for (i = 1; i < argc; ++i) { if (parseArg(argc, argv, i)) { continue; } else if (isArg(i, argc, argv, "--", NULL)) { // remaining arguments are not options ++i; break; } else if (argv[i][0] == '-') { std::cerr << "Unrecognized option: " << argv[i] << std::endl; m_bye(kExitArgs); } else { // this and remaining arguments are not options break; } } #if SYSAPI_WIN32 // suggest that user installs as a windows service. when launched as // service, process should automatically detect that it should run in // daemon mode. if (argsBase().m_daemon) { LOG((CLOG_ERR "The --daemon argument is not supported on Windows. " "Instead, install %s as a service (--service install).", argsBase().m_pname)); m_bye(kExitArgs); } #endif }
void CApp::setupFileLogging() { if (argsBase().m_logFile != NULL) { m_fileLog = new CFileLogOutputter(argsBase().m_logFile); CLOG->insert(m_fileLog); LOG((CLOG_DEBUG1 "logging to file (%s) enabled", argsBase().m_logFile)); } }
int ClientApp::mainLoop() { // create socket multiplexer. this must happen after daemonization // on unix because threads evaporate across a fork(). SocketMultiplexer multiplexer; setSocketMultiplexer(&multiplexer); // start client, etc appUtil().startNode(); // init ipc client after node start, since create a new screen wipes out // the event queue (the screen ctors call adoptBuffer). if (argsBase().m_enableIpc) { initIpcClient(); } // run event loop. if startClient() failed we're supposed to retry // later. the timer installed by startClient() will take care of // that. DAEMON_RUNNING(true); #if defined(MAC_OS_X_VERSION_10_7) Thread thread( new TMethodJob<ClientApp>( this, &ClientApp::runEventsLoop, NULL)); // wait until carbon loop is ready OSXScreen* screen = dynamic_cast<OSXScreen*>( m_clientScreen->getPlatformScreen()); screen->waitForCarbonLoop(); runCocoaApp(); #else m_events->loop(); #endif DAEMON_RUNNING(false); // close down LOG((CLOG_DEBUG1 "stopping client")); stopClient(); updateStatus(); LOG((CLOG_NOTE "stopped client")); if (argsBase().m_enableIpc) { cleanupIpcClient(); } return kExitSuccess; }
void CApp::initApp(int argc, const char** argv) { LOG ((CLOG_INFO "CApp::initApp call")); // parse command line parseArgs(argc, argv); // setup file logging after parsing args setupFileLogging(); // load configuration loadConfig(); if (!argsBase().m_disableTray) { // create a log buffer so we can show the latest message // as a tray icon tooltip CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000); CLOG->insert(logBuffer, true); // make the task bar receiver. the user can control this app // through the task bar. m_taskBarReceiver = m_createTaskBarReceiver(logBuffer); } }
bool CArgParser::checkUnexpectedArgs() { #if SYSAPI_WIN32 // suggest that user installs as a windows service. when launched as // service, process should automatically detect that it should run in // daemon mode. if (argsBase().m_daemon) { LOG((CLOG_ERR "the --daemon argument is not supported on windows. " "instead, install %s as a service (--service install)", argsBase().m_pname)); return true; } #endif return false; }
void CApp::loggingFilterWarning() { if (CLOG->getFilter() > CLOG->getConsoleMaxLevel()) { if (argsBase().m_logFile == NULL) { LOG((CLOG_WARN "log messages above %s are NOT sent to console (use file logging)", CLOG->getFilterName(CLOG->getConsoleMaxLevel()))); } } }
synergy::Screen* ClientApp::openClientScreen() { synergy::Screen* screen = createScreen(); screen->setEnableDragDrop(argsBase().m_enableDragDrop); m_events->adoptHandler(m_events->forIScreen().error(), screen->getEventTarget(), new TMethodEventJob<ClientApp>( this, &ClientApp::handleScreenError)); return screen; }
bool CApp::isArg( int argi, int argc, const char* const* argv, const char* name1, const char* name2, int minRequiredParameters) { if ((name1 != NULL && strcmp(argv[argi], name1) == 0) || (name2 != NULL && strcmp(argv[argi], name2) == 0)) { // match. check args left. if (argi + minRequiredParameters >= argc) { LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE, argsBase().m_pname, argv[argi], argsBase().m_pname)); m_bye(kExitArgs); } return true; } // no match return false; }
int CApp::run(int argc, char** argv) { #if SYSAPI_WIN32 // record window instance for tray icon, etc CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); #endif #if MAC_OS_X_VERSION_10_7 // dock hide only supported on lion :( ProcessSerialNumber psn = { 0, kCurrentProcess }; GetCurrentProcess(&psn); TransformProcessType(&psn, kProcessTransformToBackgroundApplication); #endif CArch arch; // install application in to arch ARCH->adoptApp(this); // create an instance of log CLOG; // HACK: fail by default (saves us setting result in each catch) int result = kExitFailed; try { result = ARCH->run(argc, argv); } catch (XExitApp& e) { // instead of showing a nasty error, just exit with the error code. // not sure if i like this behaviour, but it's probably better than // using the exit(int) function! result = e.getCode(); } catch (XBase& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (XArch& e) { LOG((CLOG_CRIT "Init failed: %s" BYE, e.what().c_str(), argsBase().m_pname)); } catch (std::exception& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (...) { LOG((CLOG_CRIT "An unexpected exception occurred.\n")); } delete CLOG; ARCH->beforeAppExit(); return result; }
int CClientApp::mainLoop() { // create socket multiplexer. this must happen after daemonization // on unix because threads evaporate across a fork(). CSocketMultiplexer multiplexer; // start client, etc appUtil().startNode(); // init ipc client after node start, since create a new screen wipes out // the event queue (the screen ctors call adoptBuffer). if (argsBase().m_enableIpc) { initIpcClient(); } // load all available plugins. ARCH->plugin().init(s_clientScreen->getEventTarget()); // run event loop. if startClient() failed we're supposed to retry // later. the timer installed by startClient() will take care of // that. DAEMON_RUNNING(true); EVENTQUEUE->loop(); DAEMON_RUNNING(false); // close down LOG((CLOG_DEBUG1 "stopping client")); stopClient(); updateStatus(); LOG((CLOG_NOTE "stopped client")); if (argsBase().m_enableIpc) { cleanupIpcClient(); } return kExitSuccess; }
void CApp::version() { char buffer[500]; sprintf( buffer, "%s %s, protocol version %d.%d\n%s", argsBase().m_pname, kVersion, kProtocolMajorVersion, kProtocolMinorVersion, kCopyright ); std::cout << buffer << std::endl; }
int CApp::run(int argc, char** argv) { #if SYSAPI_WIN32 // record window instance for tray icon, etc CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); #endif CArch arch; LOG((CLOG_INFO "CApp::run call")); // install application in to arch ARCH->adoptApp(this); // create an instance of log CLOG; // HACK: fail by default (saves us setting result in each catch) int result = kExitFailed; try { result = ARCH->run(argc, argv); } catch (XExitApp& e) { // instead of showing a nasty error, just exit with the error code. // not sure if i like this behaviour, but it's probably better than // using the exit(int) function! result = e.getCode(); } catch (XBase& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (XArch& e) { LOG((CLOG_CRIT "Init failed: %s" BYE, e.what().c_str(), argsBase().m_pname)); } catch (std::exception& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (...) { LOG((CLOG_CRIT "An unexpected exception occurred.\n")); } delete CLOG; ARCH->beforeAppExit(); return result; }
CScreen* CServerApp::openServerScreen() { CScreen* screen = createScreen(); screen->setEnableDragDrop(argsBase().m_enableDragDrop); m_events->adoptHandler(m_events->forIScreen().error(), screen->getEventTarget(), new TMethodEventJob<CServerApp>( this, &CServerApp::handleScreenError)); m_events->adoptHandler(m_events->forIScreen().suspend(), screen->getEventTarget(), new TMethodEventJob<CServerApp>( this, &CServerApp::handleSuspend)); m_events->adoptHandler(m_events->forIScreen().resume(), screen->getEventTarget(), new TMethodEventJob<CServerApp>( this, &CServerApp::handleResume)); return screen; }
int CApp::run(int argc, char** argv) { #if MAC_OS_X_VERSION_10_7 // dock hide only supported on lion :( ProcessSerialNumber psn = { 0, kCurrentProcess }; GetCurrentProcess(&psn); TransformProcessType(&psn, kProcessTransformToBackgroundApplication); #endif // install application in to arch appUtil().adoptApp(this); // HACK: fail by default (saves us setting result in each catch) int result = kExitFailed; try { result = appUtil().run(argc, argv); } catch (XExitApp& e) { // instead of showing a nasty error, just exit with the error code. // not sure if i like this behaviour, but it's probably better than // using the exit(int) function! result = e.getCode(); } catch (XBase& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (XArch& e) { LOG((CLOG_CRIT "Init failed: %s" BYE, e.what().c_str(), argsBase().m_pname)); } catch (std::exception& e) { LOG((CLOG_CRIT "Exception: %s\n", e.what())); } catch (...) { LOG((CLOG_CRIT "An unexpected exception occurred.\n")); } appUtil().beforeAppExit(); return result; }
void App::initApp(int argc, const char** argv) { // parse command line parseArgs(argc, argv); ARCH->setProfileDirectory(argsBase().m_profileDirectory); ARCH->setPluginDirectory(argsBase().m_pluginDirectory); // set log filter if (!CLOG->setFilter(argsBase().m_logFilter)) { LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, argsBase().m_pname, argsBase().m_logFilter, argsBase().m_pname)); m_bye(kExitArgs); } loggingFilterWarning(); if (argsBase().m_enableDragDrop) { LOG((CLOG_INFO "drag and drop enabled")); } // setup file logging after parsing args setupFileLogging(); // load configuration loadConfig(); if (!argsBase().m_disableTray) { // create a log buffer so we can show the latest message // as a tray icon tooltip BufferedLogOutputter* logBuffer = new BufferedLogOutputter(1000); CLOG->insert(logBuffer, true); // make the task bar receiver. the user can control this app // through the task bar. m_taskBarReceiver = m_createTaskBarReceiver(logBuffer, m_events); } }
bool CApp::parseArg(const int& argc, const char* const* argv, int& i) { if (ARCH->parseArg(argc, argv, i)) { // handled by platform util return true; } else if (isArg(i, argc, argv, "-d", "--debug", 1)) { // change logging level argsBase().m_logFilter = argv[++i]; } else if (isArg(i, argc, argv, "-l", "--log", 1)) { argsBase().m_logFile = argv[++i]; } else if (isArg(i, argc, argv, "-f", "--no-daemon")) { // not a daemon argsBase().m_daemon = false; } else if (isArg(i, argc, argv, NULL, "--daemon")) { // daemonize argsBase().m_daemon = true; } else if (isArg(i, argc, argv, "-n", "--name", 1)) { // save screen name argsBase().m_name = argv[++i]; } else if (isArg(i, argc, argv, "-1", "--no-restart")) { // don't try to restart argsBase().m_restartable = false; } else if (isArg(i, argc, argv, NULL, "--restart")) { // try to restart argsBase().m_restartable = true; } else if (isArg(i, argc, argv, "-z", NULL)) { argsBase().m_backend = true; } else if (isArg(i, argc, argv, NULL, "--no-hooks")) { argsBase().m_noHooks = true; } else if (isArg(i, argc, argv, "-h", "--help")) { help(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--version")) { version(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--no-tray")) { argsBase().m_disableTray = true; } else { // option not supported here return false; } return true; }
void CArgParser::updateCommonArgs(const char* const* argv) { argsBase().m_name = ARCH->getHostName(); argsBase().m_pname = ARCH->getBasename(argv[0]); }
bool CApp::parseArg(const int& argc, const char* const* argv, int& i) { if (appUtil().parseArg(argc, argv, i)) { // handled by platform util return true; } else if (isArg(i, argc, argv, "-d", "--debug", 1)) { // change logging level argsBase().m_logFilter = argv[++i]; } else if (isArg(i, argc, argv, "-l", "--log", 1)) { argsBase().m_logFile = argv[++i]; } else if (isArg(i, argc, argv, "-f", "--no-daemon")) { // not a daemon argsBase().m_daemon = false; } else if (isArg(i, argc, argv, NULL, "--daemon")) { // daemonize argsBase().m_daemon = true; } else if (isArg(i, argc, argv, "-n", "--name", 1)) { // save screen name argsBase().m_name = argv[++i]; } else if (isArg(i, argc, argv, "-1", "--no-restart")) { // don't try to restart argsBase().m_restartable = false; } else if (isArg(i, argc, argv, NULL, "--restart")) { // try to restart argsBase().m_restartable = true; } else if (isArg(i, argc, argv, "-z", NULL)) { argsBase().m_backend = true; } else if (isArg(i, argc, argv, NULL, "--no-hooks")) { argsBase().m_noHooks = true; } else if (isArg(i, argc, argv, "-h", "--help")) { help(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--version")) { version(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, "-u", "--usb-list")) { // enumerate compatible usb devices list std::cout << CUSBAddress::getConnectedCompatibleDeviceNames(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--no-tray")) { argsBase().m_disableTray = true; } else if (isArg(i, argc, argv, NULL, "--ipc")) { argsBase().m_enableIpc = true; } else if (isArg(i, argc, argv, NULL, "--server")) { // HACK: stop error happening when using portable (synergyp) } else if (isArg(i, argc, argv, NULL, "--client")) { // HACK: stop error happening when using portable (synergyp) } else if (isArg(i, argc, argv, NULL, "--crypto-pass")) { argsBase().m_crypto.m_pass = argv[++i]; } else if (isArg(i, argc, argv, NULL, "--crypto-mode")) { argsBase().m_crypto.setMode(argv[++i]); } #if VNC_SUPPORT else if (isArg(i, argc, argv, NULL, "--vnc")) { argsBase().m_enableVnc = true; } #endif else { // option not supported here return false; } return true; }
int CServerApp::mainLoop() { // create socket multiplexer. this must happen after daemonization // on unix because threads evaporate across a fork(). CSocketMultiplexer multiplexer; setSocketMultiplexer(&multiplexer); // if configuration has no screens then add this system // as the default if (args().m_config->begin() == args().m_config->end()) { args().m_config->addScreen(args().m_name); } // set the contact address, if provided, in the config. // otherwise, if the config doesn't have an address, use // the default. if (m_synergyAddress->isValid()) { args().m_config->setSynergyAddress(*m_synergyAddress); } else if (!args().m_config->getSynergyAddress().isValid()) { args().m_config->setSynergyAddress(CNetworkAddress(kDefaultPort)); } // canonicalize the primary screen name CString primaryName = args().m_config->getCanonicalName(args().m_name); if (primaryName.empty()) { LOG((CLOG_CRIT "unknown screen name `%s'", args().m_name.c_str())); return kExitFailed; } // start server, etc appUtil().startNode(); // init ipc client after node start, since create a new screen wipes out // the event queue (the screen ctors call adoptBuffer). if (argsBase().m_enableIpc) { initIpcClient(); } // load all available plugins. ARCH->plugin().init(m_serverScreen->getEventTarget(), m_events); // handle hangup signal by reloading the server's configuration ARCH->setSignalHandler(CArch::kHANGUP, &reloadSignalHandler, NULL); m_events->adoptHandler(m_events->forCServerApp().reloadConfig(), m_events->getSystemTarget(), new TMethodEventJob<CServerApp>(this, &CServerApp::reloadConfig)); // handle force reconnect event by disconnecting clients. they'll // reconnect automatically. m_events->adoptHandler(m_events->forCServerApp().forceReconnect(), m_events->getSystemTarget(), new TMethodEventJob<CServerApp>(this, &CServerApp::forceReconnect)); // to work around the sticky meta keys problem, we'll give users // the option to reset the state of synergys m_events->adoptHandler(m_events->forCServerApp().resetServer(), m_events->getSystemTarget(), new TMethodEventJob<CServerApp>(this, &CServerApp::resetServer)); // run event loop. if startServer() failed we're supposed to retry // later. the timer installed by startServer() will take care of // that. DAEMON_RUNNING(true); #if defined(MAC_OS_X_VERSION_10_7) CThread thread( new TMethodJob<CServerApp>( this, &CServerApp::runEventsLoop, NULL)); // wait until carbon loop is ready COSXScreen* screen = dynamic_cast<COSXScreen*>( m_serverScreen->getPlatformScreen()); screen->waitForCarbonLoop(); runCocoaApp(); #else m_events->loop(); #endif DAEMON_RUNNING(false); // close down LOG((CLOG_DEBUG1 "stopping server")); m_events->removeHandler(m_events->forCServerApp().forceReconnect(), m_events->getSystemTarget()); m_events->removeHandler(m_events->forCServerApp().reloadConfig(), m_events->getSystemTarget()); cleanupServer(); updateStatus(); LOG((CLOG_NOTE "stopped server")); if (argsBase().m_enableIpc) { cleanupIpcClient(); } return kExitSuccess; }
void App::initApp(int argc, const char** argv) { // parse command line parseArgs(argc, argv); #if WINAPI_XWINDOWS // for use on linux, tell the core process what user id it should run as. // this is a simple way to allow the core process to talk to X. this avoids // the "WARNING: primary screen unavailable: unable to open screen" error. // a better way would be to use xauth cookie and dbus to get access to X. if (argsBase().m_runAsUid >= 0) { if (setuid(argsBase().m_runAsUid) == 0) { LOG((CLOG_DEBUG "process uid was set to: %d", argsBase().m_runAsUid)); } else { LOG((CLOG_WARN "failed to set process uid to: %d", argsBase().m_runAsUid)); } } #endif ARCH->setProfileDirectory(argsBase().m_profileDirectory); ARCH->setPluginDirectory(argsBase().m_pluginDirectory); // set log filter if (!CLOG->setFilter(argsBase().m_logFilter)) { LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, argsBase().m_pname, argsBase().m_logFilter, argsBase().m_pname)); m_bye(kExitArgs); } loggingFilterWarning(); if (argsBase().m_enableDragDrop) { LOG((CLOG_INFO "drag and drop enabled")); } // setup file logging after parsing args setupFileLogging(); // load configuration loadConfig(); }
bool CApp::parseArg(const int& argc, const char* const* argv, int& i) { LOG((CLOG_INFO "CApp::parseArg call")); LOG((CLOG_INFO "CARCH->parseArg(")); if (ARCH->parseArg(argc, argv, i)) { // handled by platform util return true; } else if (isArg(i,argc,argv, "-hw", "--helloworld",1)) { // custom common argument std::cout<<"custom argument: "<<argv[++i]<<"\n"; m_bye(kExitArgs); } else if (isArg(i, argc, argv, "-d", "--debug", 1)) { // change logging level argsBase().m_logFilter = argv[++i]; } else if (isArg(i, argc, argv, "-l", "--log", 1)) { argsBase().m_logFile = argv[++i]; } else if (isArg(i, argc, argv, "-f", "--no-daemon")) { // not a daemon argsBase().m_daemon = false; } else if (isArg(i, argc, argv, NULL, "--daemon")) { // daemonize argsBase().m_daemon = true; } else if (isArg(i, argc, argv, "-n", "--name", 1)) { // save screen name argsBase().m_name = argv[++i]; } else if (isArg(i, argc, argv, "-1", "--no-restart")) { // don't try to restart argsBase().m_restartable = false; } else if (isArg(i, argc, argv, NULL, "--restart")) { // try to restart argsBase().m_restartable = true; } else if (isArg(i, argc, argv, "-z", NULL)) { argsBase().m_backend = true; } else if (isArg(i, argc, argv, NULL, "--no-hooks")) { argsBase().m_noHooks = true; } else if (isArg(i, argc, argv, "-h", "--help")) { help(); m_bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--version")) { version(); m_bye(kExitSuccess); } else { // option not supported here return false; } return true; }
bool CArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) { if (isArg(i, argc, argv, "-d", "--debug", 1)) { // change logging level argsBase().m_logFilter = argv[++i]; } else if (isArg(i, argc, argv, "-l", "--log", 1)) { argsBase().m_logFile = argv[++i]; } else if (isArg(i, argc, argv, "-f", "--no-daemon")) { // not a daemon argsBase().m_daemon = false; } else if (isArg(i, argc, argv, NULL, "--daemon")) { // daemonize argsBase().m_daemon = true; } else if (isArg(i, argc, argv, "-n", "--name", 1)) { // save screen name argsBase().m_name = argv[++i]; } else if (isArg(i, argc, argv, "-1", "--no-restart")) { // don't try to restart argsBase().m_restartable = false; } else if (isArg(i, argc, argv, NULL, "--restart")) { // try to restart argsBase().m_restartable = true; } else if (isArg(i, argc, argv, "-z", NULL)) { argsBase().m_backend = true; } else if (isArg(i, argc, argv, NULL, "--no-hooks")) { argsBase().m_noHooks = true; } else if (isArg(i, argc, argv, "-h", "--help")) { if (m_app) { m_app->help(); } argsBase().m_shouldExit = true; } else if (isArg(i, argc, argv, NULL, "--version")) { if (m_app) { m_app->version(); } argsBase().m_shouldExit = true; } else if (isArg(i, argc, argv, NULL, "--no-tray")) { argsBase().m_disableTray = true; } else if (isArg(i, argc, argv, NULL, "--ipc")) { argsBase().m_enableIpc = true; } else if (isArg(i, argc, argv, NULL, "--server")) { // HACK: stop error happening when using portable (synergyp) } else if (isArg(i, argc, argv, NULL, "--client")) { // HACK: stop error happening when using portable (synergyp) } else if (isArg(i, argc, argv, NULL, "--crypto-pass")) { argsBase().m_crypto.m_pass = argv[++i]; argsBase().m_crypto.setMode("cfb"); } else if (isArg(i, argc, argv, NULL, "--enable-drag-drop")) { bool useDragDrop = true; #ifdef WINAPI_XWINDOWS useDragDrop = false; LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported on linux.")); #endif #ifdef WINAPI_MSWINDOWS OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if (osvi.dwMajorVersion < 6) { useDragDrop = false; LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported below vista.")); } #endif if (useDragDrop) { argsBase().m_enableDragDrop = true; } } else { // option not supported here return false; } return true; }