00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CClient.h"
00016 #include "CScreen.h"
00017 #include "ProtocolTypes.h"
00018 #include "Version.h"
00019 #include "XScreen.h"
00020 #include "CNetworkAddress.h"
00021 #include "CSocketMultiplexer.h"
00022 #include "CTCPSocketFactory.h"
00023 #include "XSocket.h"
00024 #include "CThread.h"
00025 #include "CEventQueue.h"
00026 #include "CFunctionEventJob.h"
00027 #include "CFunctionJob.h"
00028 #include "CLog.h"
00029 #include "CString.h"
00030 #include "CStringUtil.h"
00031 #include "LogOutputters.h"
00032 #include "CArch.h"
00033 #include "XArch.h"
00034 #include <cstring>
00035
00036 #define DAEMON_RUNNING(running_)
00037 #if WINAPI_MSWINDOWS
00038 #include "CArchMiscWindows.h"
00039 #include "CMSWindowsScreen.h"
00040 #include "CMSWindowsUtil.h"
00041 #include "CMSWindowsClientTaskBarReceiver.h"
00042 #include "resource.h"
00043 #undef DAEMON_RUNNING
00044 #define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
00045 #elif WINAPI_XWINDOWS
00046 #include "CXWindowsScreen.h"
00047 #include "CXWindowsClientTaskBarReceiver.h"
00048 #elif WINAPI_CARBON
00049 #include "COSXScreen.h"
00050 #include "COSXClientTaskBarReceiver.h"
00051 #endif
00052
00053
00054 #if SYSAPI_WIN32
00055 #define DAEMON_NAME "Synergy Client"
00056 #elif SYSAPI_UNIX
00057 #define DAEMON_NAME "synergyc"
00058 #endif
00059
00060 typedef int (*StartupFunc)(int, char**);
00061 static bool startClient();
00062 static void parse(int argc, const char* const* argv);
00063
00064
00065
00066
00067
00068 #define ARG CArgs::s_instance
00069
00070 class CArgs {
00071 public:
00072 CArgs() :
00073 m_pname(NULL),
00074 m_backend(false),
00075 m_restartable(true),
00076 m_daemon(true),
00077 m_yscroll(0),
00078 m_logFilter(NULL),
00079 m_display(NULL),
00080 m_serverAddress(NULL)
00081 { s_instance = this; }
00082 ~CArgs() { s_instance = NULL; }
00083
00084 public:
00085 static CArgs* s_instance;
00086 const char* m_pname;
00087 bool m_backend;
00088 bool m_restartable;
00089 bool m_daemon;
00090 int m_yscroll;
00091 const char* m_logFilter;
00092 const char* m_display;
00093 CString m_name;
00094 CNetworkAddress* m_serverAddress;
00095 };
00096
00097 CArgs* CArgs::s_instance = NULL;
00098
00099
00100
00101
00102
00103
00104 static
00105 CScreen*
00106 createScreen()
00107 {
00108 #if WINAPI_MSWINDOWS
00109 return new CScreen(new CMSWindowsScreen(false));
00110 #elif WINAPI_XWINDOWS
00111 return new CScreen(new CXWindowsScreen(ARG->m_display, false, ARG->m_yscroll));
00112 #elif WINAPI_CARBON
00113 return new CScreen(new COSXScreen(false));
00114 #endif
00115 }
00116
00117 static
00118 CClientTaskBarReceiver*
00119 createTaskBarReceiver(const CBufferedLogOutputter* logBuffer)
00120 {
00121 #if WINAPI_MSWINDOWS
00122 return new CMSWindowsClientTaskBarReceiver(
00123 CMSWindowsScreen::getInstance(), logBuffer);
00124 #elif WINAPI_XWINDOWS
00125 return new CXWindowsClientTaskBarReceiver(logBuffer);
00126 #elif WINAPI_CARBON
00127 return new COSXClientTaskBarReceiver(logBuffer);
00128 #endif
00129 }
00130
00131
00132
00133
00134
00135
00136 static CClient* s_client = NULL;
00137 static CScreen* s_clientScreen = NULL;
00138 static CClientTaskBarReceiver* s_taskBarReceiver = NULL;
00139
00140 static bool s_suspened = false;
00141
00142 #define RETRY_TIME 1.0
00143
00144 static
00145 void
00146 updateStatus()
00147 {
00148 s_taskBarReceiver->updateStatus(s_client, "");
00149 }
00150
00151 static
00152 void
00153 updateStatus(const CString& msg)
00154 {
00155 s_taskBarReceiver->updateStatus(s_client, msg);
00156 }
00157
00158 static
00159 void
00160 resetRestartTimeout()
00161 {
00162
00163
00164 }
00165
00166 static
00167 double
00168 nextRestartTimeout()
00169 {
00170
00171 return RETRY_TIME;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 }
00188
00189 static
00190 void
00191 handleScreenError(const CEvent&, void*)
00192 {
00193 LOG((CLOG_CRIT "error on screen"));
00194 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00195 }
00196
00197 static
00198 CScreen*
00199 openClientScreen()
00200 {
00201 CScreen* screen = createScreen();
00202 EVENTQUEUE->adoptHandler(IScreen::getErrorEvent(),
00203 screen->getEventTarget(),
00204 new CFunctionEventJob(
00205 &handleScreenError));
00206 return screen;
00207 }
00208
00209 static
00210 void
00211 closeClientScreen(CScreen* screen)
00212 {
00213 if (screen != NULL) {
00214 EVENTQUEUE->removeHandler(IScreen::getErrorEvent(),
00215 screen->getEventTarget());
00216 delete screen;
00217 }
00218 }
00219
00220 static
00221 void
00222 handleClientRestart(const CEvent&, void* vtimer)
00223 {
00224
00225 CEventQueueTimer* timer = reinterpret_cast<CEventQueueTimer*>(vtimer);
00226 EVENTQUEUE->deleteTimer(timer);
00227 EVENTQUEUE->removeHandler(CEvent::kTimer, timer);
00228
00229
00230 startClient();
00231 }
00232
00233 static
00234 void
00235 scheduleClientRestart(double retryTime)
00236 {
00237
00238 LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime));
00239 CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL);
00240 EVENTQUEUE->adoptHandler(CEvent::kTimer, timer,
00241 new CFunctionEventJob(&handleClientRestart, timer));
00242 }
00243
00244 static
00245 void
00246 handleClientConnected(const CEvent&, void*)
00247 {
00248 LOG((CLOG_NOTE "connected to server"));
00249 resetRestartTimeout();
00250 updateStatus();
00251 }
00252
00253 static
00254 void
00255 handleClientFailed(const CEvent& e, void*)
00256 {
00257 CClient::CFailInfo* info =
00258 reinterpret_cast<CClient::CFailInfo*>(e.getData());
00259
00260 updateStatus(CString("Failed to connect to server: ") + info->m_what);
00261 if (!ARG->m_restartable || !info->m_retry) {
00262 LOG((CLOG_ERR "failed to connect to server: %s", info->m_what));
00263 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00264 }
00265 else {
00266 LOG((CLOG_WARN "failed to connect to server: %s", info->m_what));
00267 if (!s_suspened) {
00268 scheduleClientRestart(nextRestartTimeout());
00269 }
00270 }
00271 }
00272
00273 static
00274 void
00275 handleClientDisconnected(const CEvent&, void*)
00276 {
00277 LOG((CLOG_NOTE "disconnected from server"));
00278 if (!ARG->m_restartable) {
00279 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00280 }
00281 else if (!s_suspened) {
00282 s_client->connect();
00283 }
00284 updateStatus();
00285 }
00286
00287 static
00288 CClient*
00289 openClient(const CString& name, const CNetworkAddress& address, CScreen* screen)
00290 {
00291 CClient* client = new CClient(name, address,
00292 new CTCPSocketFactory, NULL, screen);
00293 EVENTQUEUE->adoptHandler(CClient::getConnectedEvent(),
00294 client->getEventTarget(),
00295 new CFunctionEventJob(handleClientConnected));
00296 EVENTQUEUE->adoptHandler(CClient::getConnectionFailedEvent(),
00297 client->getEventTarget(),
00298 new CFunctionEventJob(handleClientFailed));
00299 EVENTQUEUE->adoptHandler(CClient::getDisconnectedEvent(),
00300 client->getEventTarget(),
00301 new CFunctionEventJob(handleClientDisconnected));
00302 return client;
00303 }
00304
00305 static
00306 void
00307 closeClient(CClient* client)
00308 {
00309 if (client == NULL) {
00310 return;
00311 }
00312
00313 EVENTQUEUE->removeHandler(CClient::getConnectedEvent(), client);
00314 EVENTQUEUE->removeHandler(CClient::getConnectionFailedEvent(), client);
00315 EVENTQUEUE->removeHandler(CClient::getDisconnectedEvent(), client);
00316 delete client;
00317 }
00318
00319 static
00320 bool
00321 startClient()
00322 {
00323 double retryTime;
00324 CScreen* clientScreen = NULL;
00325 try {
00326 if (s_clientScreen == NULL) {
00327 clientScreen = openClientScreen();
00328 s_client = openClient(ARG->m_name,
00329 *ARG->m_serverAddress, clientScreen);
00330 s_clientScreen = clientScreen;
00331 LOG((CLOG_NOTE "started client"));
00332 }
00333 s_client->connect();
00334 updateStatus();
00335 return true;
00336 }
00337 catch (XScreenUnavailable& e) {
00338 LOG((CLOG_WARN "cannot open secondary screen: %s", e.what()));
00339 closeClientScreen(clientScreen);
00340 updateStatus(CString("Cannot open secondary screen: ") + e.what());
00341 retryTime = e.getRetryTime();
00342 }
00343 catch (XScreenOpenFailure& e) {
00344 LOG((CLOG_CRIT "cannot open secondary screen: %s", e.what()));
00345 closeClientScreen(clientScreen);
00346 return false;
00347 }
00348 catch (XBase& e) {
00349 LOG((CLOG_CRIT "failed to start client: %s", e.what()));
00350 closeClientScreen(clientScreen);
00351 return false;
00352 }
00353
00354 if (ARG->m_restartable) {
00355 scheduleClientRestart(retryTime);
00356 return true;
00357 }
00358 else {
00359
00360 return false;
00361 }
00362 }
00363
00364 static
00365 void
00366 stopClient()
00367 {
00368 closeClient(s_client);
00369 closeClientScreen(s_clientScreen);
00370 s_client = NULL;
00371 s_clientScreen = NULL;
00372 }
00373
00374 static
00375 int
00376 mainLoop()
00377 {
00378
00379
00380 CSocketMultiplexer multiplexer;
00381
00382
00383 CEventQueue eventQueue;
00384
00385
00386
00387 LOG((CLOG_DEBUG1 "starting client"));
00388 if (!startClient()) {
00389 return kExitFailed;
00390 }
00391
00392
00393
00394
00395 CEvent event;
00396 DAEMON_RUNNING(true);
00397 EVENTQUEUE->getEvent(event);
00398 while (event.getType() != CEvent::kQuit) {
00399 EVENTQUEUE->dispatchEvent(event);
00400 CEvent::deleteData(event);
00401 EVENTQUEUE->getEvent(event);
00402 }
00403 DAEMON_RUNNING(false);
00404
00405
00406 LOG((CLOG_DEBUG1 "stopping client"));
00407 stopClient();
00408 updateStatus();
00409 LOG((CLOG_NOTE "stopped client"));
00410
00411 return kExitSuccess;
00412 }
00413
00414 static
00415 int
00416 daemonMainLoop(int, const char**)
00417 {
00418 #if SYSAPI_WIN32
00419 CSystemLogger sysLogger(DAEMON_NAME, false);
00420 #else
00421 CSystemLogger sysLogger(DAEMON_NAME, true);
00422 #endif
00423 return mainLoop();
00424 }
00425
00426 static
00427 int
00428 standardStartup(int argc, char** argv)
00429 {
00430 if (!ARG->m_daemon) {
00431 ARCH->showConsole(false);
00432 }
00433
00434
00435 parse(argc, argv);
00436
00437
00438 if (ARG->m_daemon) {
00439 return ARCH->daemonize(DAEMON_NAME, &daemonMainLoop);
00440 }
00441 else {
00442 return mainLoop();
00443 }
00444 }
00445
00446 static
00447 int
00448 run(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
00449 {
00450
00451 ARG->m_serverAddress = new CNetworkAddress;
00452 ARG->m_pname = ARCH->getBasename(argv[0]);
00453
00454
00455 if (outputter != NULL) {
00456 CLOG->insert(outputter);
00457 }
00458
00459
00460 CBufferedLogOutputter logBuffer(1000);
00461 CLOG->insert(&logBuffer, true);
00462
00463
00464
00465 s_taskBarReceiver = createTaskBarReceiver(&logBuffer);
00466
00467
00468 int result = startup(argc, argv);
00469
00470
00471 delete s_taskBarReceiver;
00472
00473
00474 CLOG->remove(&logBuffer);
00475
00476 delete ARG->m_serverAddress;
00477 return result;
00478 }
00479
00480
00481
00482
00483
00484
00485 #define BYE "\nTry `%s --help' for more information."
00486
00487 static void (*bye)(int) = &exit;
00488
00489 static
00490 void
00491 version()
00492 {
00493 LOG((CLOG_PRINT "%s %s, protocol version %d.%d\n%s",
00494 ARG->m_pname,
00495 kVersion,
00496 kProtocolMajorVersion,
00497 kProtocolMinorVersion,
00498 kCopyright));
00499 }
00500
00501 static
00502 void
00503 help()
00504 {
00505 #if WINAPI_XWINDOWS
00506 # define USAGE_DISPLAY_ARG \
00507 " [--display <display>]"
00508 # define USAGE_DISPLAY_INFO \
00509 " --display <display> connect to the X server at <display>\n"
00510 #else
00511 # define USAGE_DISPLAY_ARG
00512 # define USAGE_DISPLAY_INFO
00513 #endif
00514
00515 LOG((CLOG_PRINT
00516 "Usage: %s"
00517 " [--daemon|--no-daemon]"
00518 " [--debug <level>]"
00519 USAGE_DISPLAY_ARG
00520 " [--name <screen-name>]"
00521 " [--yscroll <delta>]"
00522 " [--restart|--no-restart]"
00523 " <server-address>"
00524 "\n\n"
00525 "Start the synergy mouse/keyboard sharing server.\n"
00526 "\n"
00527 " -d, --debug <level> filter out log messages with priorty below level.\n"
00528 " level may be: FATAL, ERROR, WARNING, NOTE, INFO,\n"
00529 " DEBUG, DEBUG1, DEBUG2.\n"
00530 USAGE_DISPLAY_INFO
00531 " -f, --no-daemon run the client in the foreground.\n"
00532 "* --daemon run the client as a daemon.\n"
00533 " -n, --name <screen-name> use screen-name instead the hostname to identify\n"
00534 " ourself to the server.\n"
00535 " --yscroll <delta> defines the vertical scrolling delta, which is\n"
00536 " 120 by default.\n"
00537 " -1, --no-restart do not try to restart the client if it fails for\n"
00538 " some reason.\n"
00539 "* --restart restart the client automatically if it fails.\n"
00540 " -h, --help display this help and exit.\n"
00541 " --version display version information and exit.\n"
00542 "\n"
00543 "* marks defaults.\n"
00544 "\n"
00545 "The server address is of the form: [<hostname>][:<port>]. The hostname\n"
00546 "must be the address or hostname of the server. The port overrides the\n"
00547 "default port, %d.\n"
00548 "\n"
00549 "Where log messages go depends on the platform and whether or not the\n"
00550 "client is running as a daemon.",
00551 ARG->m_pname, kDefaultPort));
00552
00553 }
00554
00555 static
00556 bool
00557 isArg(int argi, int argc, const char* const* argv,
00558 const char* name1, const char* name2,
00559 int minRequiredParameters = 0)
00560 {
00561 if ((name1 != NULL && strcmp(argv[argi], name1) == 0) ||
00562 (name2 != NULL && strcmp(argv[argi], name2) == 0)) {
00563
00564 if (argi + minRequiredParameters >= argc) {
00565 LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
00566 ARG->m_pname, argv[argi], ARG->m_pname));
00567 bye(kExitArgs);
00568 }
00569 return true;
00570 }
00571
00572
00573 return false;
00574 }
00575
00576 static
00577 void
00578 parse(int argc, const char* const* argv)
00579 {
00580 assert(ARG->m_pname != NULL);
00581 assert(argv != NULL);
00582 assert(argc >= 1);
00583
00584
00585 ARG->m_name = ARCH->getHostName();
00586
00587
00588 int i;
00589 for (i = 1; i < argc; ++i) {
00590 if (isArg(i, argc, argv, "-d", "--debug", 1)) {
00591
00592 ARG->m_logFilter = argv[++i];
00593 }
00594
00595 else if (isArg(i, argc, argv, "-n", "--name", 1)) {
00596
00597 ARG->m_name = argv[++i];
00598 }
00599
00600 else if (isArg(i, argc, argv, NULL, "--camp")) {
00601
00602 }
00603
00604 else if (isArg(i, argc, argv, NULL, "--no-camp")) {
00605
00606 }
00607
00608 else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
00609
00610 ARG->m_daemon = false;
00611 }
00612
00613 else if (isArg(i, argc, argv, NULL, "--daemon")) {
00614
00615 ARG->m_daemon = true;
00616 }
00617
00618 #if WINAPI_XWINDOWS
00619 else if (isArg(i, argc, argv, "-display", "--display", 1)) {
00620
00621 ARG->m_display = argv[++i];
00622 }
00623 #endif
00624
00625 else if (isArg(i, argc, argv, NULL, "--yscroll", 1)) {
00626
00627 ARG->m_yscroll = atoi(argv[++i]);
00628 }
00629
00630 else if (isArg(i, argc, argv, "-1", "--no-restart")) {
00631
00632 ARG->m_restartable = false;
00633 }
00634
00635 else if (isArg(i, argc, argv, NULL, "--restart")) {
00636
00637 ARG->m_restartable = true;
00638 }
00639
00640 else if (isArg(i, argc, argv, "-z", NULL)) {
00641 ARG->m_backend = true;
00642 }
00643
00644 else if (isArg(i, argc, argv, "-h", "--help")) {
00645 help();
00646 bye(kExitSuccess);
00647 }
00648
00649 else if (isArg(i, argc, argv, NULL, "--version")) {
00650 version();
00651 bye(kExitSuccess);
00652 }
00653
00654 else if (isArg(i, argc, argv, "--", NULL)) {
00655
00656 ++i;
00657 break;
00658 }
00659
00660 else if (argv[i][0] == '-') {
00661 LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
00662 ARG->m_pname, argv[i], ARG->m_pname));
00663 bye(kExitArgs);
00664 }
00665
00666 else {
00667
00668 break;
00669 }
00670 }
00671
00672
00673 if (i == argc) {
00674 LOG((CLOG_PRINT "%s: a server address or name is required" BYE,
00675 ARG->m_pname, ARG->m_pname));
00676 bye(kExitArgs);
00677 }
00678 if (i + 1 != argc) {
00679 LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
00680 ARG->m_pname, argv[i], ARG->m_pname));
00681 bye(kExitArgs);
00682 }
00683
00684
00685 try {
00686 *ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
00687 ARG->m_serverAddress->resolve();
00688 }
00689 catch (XSocketAddress& e) {
00690
00691
00692
00693
00694 if (!ARG->m_restartable || e.getError() == XSocketAddress::kBadPort) {
00695 LOG((CLOG_PRINT "%s: %s" BYE,
00696 ARG->m_pname, e.what(), ARG->m_pname));
00697 bye(kExitFailed);
00698 }
00699 }
00700
00701
00702
00703 if (ARG->m_daemon && ARG->m_logFilter == NULL) {
00704 #if SYSAPI_WIN32
00705 if (CArchMiscWindows::isWindows95Family()) {
00706
00707
00708 ARG->m_logFilter = "FATAL";
00709 }
00710 else
00711 #endif
00712 {
00713 ARG->m_logFilter = "NOTE";
00714 }
00715 }
00716
00717
00718 if (!CLOG->setFilter(ARG->m_logFilter)) {
00719 LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
00720 ARG->m_pname, ARG->m_logFilter, ARG->m_pname));
00721 bye(kExitArgs);
00722 }
00723
00724
00725 LOG((CLOG_INFO "%s Client on %s %s", kAppVersion, ARCH->getOSName().c_str(), ARCH->getPlatformName().c_str()));
00726
00727 #ifdef WIN32
00728 #ifdef _AMD64_
00729 LOG((CLOG_WARN "This is an experimental x64 build of %s. Use it at your own risk.", kApplication));
00730 #endif
00731 #endif
00732 }
00733
00734
00735
00736
00737
00738
00739 #if SYSAPI_WIN32
00740
00741 static bool s_hasImportantLogMessages = false;
00742
00743
00744
00745
00746
00747
00748
00749 class CMessageBoxOutputter : public ILogOutputter {
00750 public:
00751 CMessageBoxOutputter() { }
00752 virtual ~CMessageBoxOutputter() { }
00753
00754
00755 virtual void open(const char*) { }
00756 virtual void close() { }
00757 virtual void show(bool) { }
00758 virtual bool write(ELevel level, const char* message);
00759 virtual const char* getNewline() const { return ""; }
00760 };
00761
00762 bool
00763 CMessageBoxOutputter::write(ELevel level, const char* message)
00764 {
00765
00766 if (level <= CLog::kWARNING) {
00767 s_hasImportantLogMessages = true;
00768 }
00769
00770
00771
00772
00773 if (!ARG->m_backend && level <= CLog::kFATAL) {
00774 MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING);
00775 return false;
00776 }
00777 else {
00778 return true;
00779 }
00780 }
00781
00782 static
00783 void
00784 byeThrow(int x)
00785 {
00786 CArchMiscWindows::daemonFailed(x);
00787 }
00788
00789 static
00790 int
00791 daemonNTMainLoop(int argc, const char** argv)
00792 {
00793 parse(argc, argv);
00794 ARG->m_backend = false;
00795 return CArchMiscWindows::runDaemon(mainLoop);
00796 }
00797
00798 static
00799 int
00800 daemonNTStartup(int, char**)
00801 {
00802 CSystemLogger sysLogger(DAEMON_NAME, false);
00803 bye = &byeThrow;
00804 return ARCH->daemonize(DAEMON_NAME, &daemonNTMainLoop);
00805 }
00806
00807 static
00808 int
00809 foregroundStartup(int argc, char** argv)
00810 {
00811 ARCH->showConsole(false);
00812
00813
00814 parse(argc, argv);
00815
00816
00817 return mainLoop();
00818 }
00819
00820 static
00821 void
00822 showError(HINSTANCE instance, const char* title, UINT id, const char* arg)
00823 {
00824 CString fmt = CMSWindowsUtil::getString(instance, id);
00825 CString msg = CStringUtil::format(fmt.c_str(), arg);
00826 MessageBox(NULL, msg.c_str(), title, MB_OK | MB_ICONWARNING);
00827 }
00828
00829 int WINAPI
00830 WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
00831 {
00832 try {
00833 CArchMiscWindows::setIcons((HICON)LoadImage(instance,
00834 MAKEINTRESOURCE(IDI_SYNERGY),
00835 IMAGE_ICON,
00836 32, 32, LR_SHARED),
00837 (HICON)LoadImage(instance,
00838 MAKEINTRESOURCE(IDI_SYNERGY),
00839 IMAGE_ICON,
00840 16, 16, LR_SHARED));
00841 CArch arch(instance);
00842 CMSWindowsScreen::init(instance);
00843 CLOG;
00844 CThread::getCurrentThread().setPriority(-14);
00845 CArgs args;
00846
00847
00848 ARCH->openConsole((CString(kAppVersion) + " " + "Client").c_str());
00849
00850
00851
00852
00853
00854
00855
00856 StartupFunc startup = &standardStartup;
00857 if (!CArchMiscWindows::isWindows95Family()) {
00858 if (__argc <= 1) {
00859 startup = &daemonNTStartup;
00860 }
00861 else {
00862 startup = &foregroundStartup;
00863 }
00864 }
00865
00866
00867 int result = run(__argc, __argv, new CMessageBoxOutputter, startup);
00868
00869
00870
00871 if (args.m_backend && s_hasImportantLogMessages) {
00872 showError(instance, args.m_pname, IDS_FAILED, "");
00873 }
00874
00875 delete CLOG;
00876 return result;
00877 }
00878 catch (XBase& e) {
00879 showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, e.what());
00880
00881 }
00882 catch (XArch& e) {
00883 showError(instance, __argv[0], IDS_INIT_FAILED, e.what().c_str());
00884 }
00885 catch (...) {
00886 showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, "<unknown>");
00887
00888 }
00889 return kExitFailed;
00890 }
00891
00892 #elif SYSAPI_UNIX
00893
00894 int
00895 main(int argc, char** argv)
00896 {
00897 CArgs args;
00898 try {
00899 int result;
00900 CArch arch;
00901 CLOG;
00902 CArgs args;
00903 result = run(argc, argv, NULL, &standardStartup);
00904 delete CLOG;
00905 return result;
00906 }
00907 catch (XBase& e) {
00908 LOG((CLOG_CRIT "Uncaught exception: %s\n", e.what()));
00909 throw;
00910 }
00911 catch (XArch& e) {
00912 LOG((CLOG_CRIT "Initialization failed: %s" BYE, e.what().c_str()));
00913 return kExitFailed;
00914 }
00915 catch (...) {
00916 LOG((CLOG_CRIT "Uncaught exception: <unknown exception>\n"));
00917 throw;
00918 }
00919 }
00920
00921 #else
00922
00923 #error no main() for platform
00924
00925 #endif