Refactored some platform dependent code into a new library,

lib/arch.  This should make porting easier.  Will probably
continue to refactor a little more, moving platform dependent
event handling stuff into lib/platform.
This commit is contained in:
crs
2003-01-04 22:01:32 +00:00
parent 62303391a8
commit f65921bc3f
169 changed files with 9676 additions and 5601 deletions

View File

@@ -12,8 +12,11 @@
* GNU General Public License for more details.
*/
#include "CPlatform.h"
#include "CLog.h"
#include "ILogOutputter.h"
#include "CArch.h"
#include "CStringUtil.h"
#include "XArch.h"
#include "CAutoStart.h"
#include "LaunchUtil.h"
#include "resource.h"
@@ -23,6 +26,37 @@
#define CLIENT_DAEMON_INFO "Shares this system's mouse and keyboard with others."
#define SERVER_DAEMON_INFO "Shares this system's mouse and keyboard with others."
//
// CAutoStartOutputter
//
// This class detects a message above a certain level and saves it
//
class CAutoStartOutputter : public ILogOutputter {
public:
CAutoStartOutputter(CString* msg) : m_msg(msg) { }
virtual ~CAutoStartOutputter() { }
// ILogOutputter overrides
virtual void open(const char*) { }
virtual void close() { }
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const { return ""; }
private:
CString* m_msg;
};
bool
CAutoStartOutputter::write(ELevel level, const char* message)
{
if (level <= CLog::kERROR) {
*m_msg = message;
}
return false;
}
//
// CAutoStart
//
@@ -51,8 +85,7 @@ void
CAutoStart::doModal()
{
// install our log outputter
CLog::Outputter oldOutputter = CLog::getOutputter();
CLog::setOutputter(&CAutoStart::onLog);
CLOG->insert(new CAutoStartOutputter(&m_errorMessage));
// reset saved flag
m_userConfigSaved = false;
@@ -61,8 +94,8 @@ CAutoStart::doModal()
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART),
m_parent, dlgProc, (LPARAM)this);
// restore log outputter
CLog::setOutputter(oldOutputter);
// remove log outputter
CLOG->pop_front();
}
bool
@@ -74,19 +107,16 @@ CAutoStart::wasUserConfigSaved() const
void
CAutoStart::update()
{
// need a platform object
CPlatform platform;
// get installation state
const bool installedSystem = platform.isDaemonInstalled(
const bool installedSystem = ARCH->isDaemonInstalled(
m_name.c_str(), true);
const bool installedUser = platform.isDaemonInstalled(
const bool installedUser = ARCH->isDaemonInstalled(
m_name.c_str(), false);
// get user's permissions
const bool canInstallSystem = platform.canInstallDaemon(
const bool canInstallSystem = ARCH->canInstallDaemon(
m_name.c_str(), true);
const bool canInstallUser = platform.canInstallDaemon(
const bool canInstallUser = ARCH->canInstallDaemon(
m_name.c_str(), false);
// update messages
@@ -165,22 +195,25 @@ CAutoStart::onInstall(bool allUsers)
m_errorMessage = "";
// install
CPlatform platform;
if (!platform.installDaemon(m_name.c_str(),
try {
ARCH->installDaemon(m_name.c_str(),
m_isServer ? SERVER_DAEMON_INFO : CLIENT_DAEMON_INFO,
appPath.c_str(), m_cmdLine.c_str(), allUsers)) {
appPath.c_str(), m_cmdLine.c_str(), allUsers);
askOkay(m_hwnd, getString(IDS_INSTALL_TITLE),
getString(allUsers ?
IDS_INSTALLED_SYSTEM :
IDS_INSTALLED_USER));
return true;
}
catch (XArchDaemon& e) {
if (m_errorMessage.empty()) {
m_errorMessage = getString(IDS_INSTALL_GENERIC_ERROR);
m_errorMessage = CStringUtil::format(
getString(IDS_INSTALL_GENERIC_ERROR).c_str(),
e.what().c_str());
}
showError(m_hwnd, m_errorMessage);
return false;
}
askOkay(m_hwnd, getString(IDS_INSTALL_TITLE),
getString(allUsers ?
IDS_INSTALLED_SYSTEM :
IDS_INSTALLED_USER));
return true;
}
bool
@@ -190,30 +223,23 @@ CAutoStart::onUninstall(bool allUsers)
m_errorMessage = "";
// uninstall
CPlatform platform;
if (platform.uninstallDaemon(m_name.c_str(), allUsers) !=
IPlatform::kSuccess) {
try {
ARCH->uninstallDaemon(m_name.c_str(), allUsers);
askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE),
getString(allUsers ?
IDS_UNINSTALLED_SYSTEM :
IDS_UNINSTALLED_USER));
return true;
}
catch (XArchDaemon& e) {
if (m_errorMessage.empty()) {
m_errorMessage = getString(IDS_UNINSTALL_GENERIC_ERROR);
m_errorMessage = CStringUtil::format(
getString(IDS_UNINSTALL_GENERIC_ERROR).c_str(),
e.what().c_str());
}
showError(m_hwnd, m_errorMessage);
return false;
}
askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE),
getString(allUsers ?
IDS_UNINSTALLED_SYSTEM :
IDS_UNINSTALLED_USER));
return true;
}
bool
CAutoStart::onLog(int priority, const char* message)
{
if (priority <= CLog::kERROR) {
s_singleton->m_errorMessage = message;
}
return true;
}
BOOL

View File

@@ -57,9 +57,6 @@ private:
bool onInstall(bool allUsers);
bool onUninstall(bool allUsers);
// log handling
static bool onLog(int priority, const char* message);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);

View File

@@ -13,8 +13,8 @@
*/
#include "CConfig.h"
#include "CPlatform.h"
#include "LaunchUtil.h"
#include "CArch.h"
#include "resource.h"
#include "stdfstream.h"
@@ -107,10 +107,9 @@ CString
getAppPath(const CString& appName)
{
// prepare path to app
CPlatform platform;
char myPathname[MAX_PATH];
GetModuleFileName(s_instance, myPathname, MAX_PATH);
const char* myBasename = platform.getBasename(myPathname);
const char* myBasename = ARCH->getBasename(myPathname);
CString appPath = CString(myPathname, myBasename - myPathname);
appPath += appName;
return appPath;
@@ -136,24 +135,20 @@ loadConfig(const CString& pathname, CConfig& config)
bool
loadConfig(CConfig& config)
{
CPlatform platform;
// load configuration
bool configLoaded = false;
CString path = platform.getUserDirectory();
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
CPlatform platform;
// try loading the user's configuration
path = platform.addPathComponent(path, CONFIG_NAME);
path = ARCH->concatPath(path, CONFIG_NAME);
if (loadConfig(path, config)) {
configLoaded = true;
}
else {
// try the system-wide config file
path = platform.getSystemDirectory();
path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = platform.addPathComponent(path, CONFIG_NAME);
path = ARCH->concatPath(path, CONFIG_NAME);
if (loadConfig(path, config)) {
configLoaded = true;
}
@@ -183,13 +178,11 @@ saveConfig(const CString& pathname, const CConfig& config)
bool
saveConfig(const CConfig& config, bool sysOnly)
{
CPlatform platform;
// try saving the user's configuration
if (!sysOnly) {
CString path = platform.getUserDirectory();
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
path = platform.addPathComponent(path, CONFIG_NAME);
path = ARCH->concatPath(path, CONFIG_NAME);
if (saveConfig(path, config)) {
return true;
}
@@ -198,9 +191,9 @@ saveConfig(const CConfig& config, bool sysOnly)
// try the system-wide config file
else {
CString path = platform.getSystemDirectory();
CString path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = platform.addPathComponent(path, CONFIG_NAME);
path = ARCH->concatPath(path, CONFIG_NAME);
if (saveConfig(path, config)) {
return true;
}

View File

@@ -14,9 +14,9 @@
#include "CConfig.h"
#include "ProtocolTypes.h"
#include "CPlatform.h"
#include "CNetwork.h"
#include "CLog.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "Version.h"
#include "stdvector.h"
#include "resource.h"
@@ -62,10 +62,26 @@ static const char* s_debugName[][2] = {
};
static const int s_defaultDebug = 3; // INFO
static HWND s_mainWindow;
static CConfig s_config;
static CConfig s_oldConfig;
static CStringList s_screens;
//
// program arguments
//
#define ARG CArgs::s_instance
class CArgs {
public:
CArgs() { s_instance = this; }
~CArgs() { s_instance = NULL; }
public:
static CArgs* s_instance;
CConfig m_config;
CConfig m_oldConfig;
CStringList m_screens;
};
CArgs* CArgs::s_instance = NULL;
static
BOOL CALLBACK
@@ -117,7 +133,7 @@ static
void
enableSaveControls(HWND hwnd)
{
enableItem(hwnd, IDC_MAIN_SAVE, s_config != s_oldConfig);
enableItem(hwnd, IDC_MAIN_SAVE, ARG->m_config != ARG->m_oldConfig);
}
static
@@ -171,8 +187,8 @@ updateNeighbor(HWND hwnd, const CString& screen, EDirection direction)
// add all screens to combo box
if (!screen.empty()) {
for (CConfig::const_iterator index = s_config.begin();
index != s_config.end(); ++index) {
for (CConfig::const_iterator index = ARG->m_config.begin();
index != ARG->m_config.end(); ++index) {
SendMessage(hwnd, CB_INSERTSTRING,
(WPARAM)-1, (LPARAM)index->c_str());
}
@@ -184,7 +200,7 @@ updateNeighbor(HWND hwnd, const CString& screen, EDirection direction)
// select neighbor in combo box
LRESULT index = 0;
if (!screen.empty()) {
const CString& neighbor = s_config.getNeighbor(screen, direction);
const CString& neighbor = ARG->m_config.getNeighbor(screen, direction);
if (!neighbor.empty()) {
index = SendMessage(hwnd, CB_FINDSTRINGEXACT,
0, (LPARAM)neighbor.c_str());
@@ -205,7 +221,7 @@ updateNeighbors(HWND hwnd)
HWND child = getItem(hwnd, IDC_MAIN_SERVER_SCREENS_LIST);
LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0);
if (index != LB_ERR) {
screen = s_screens[index];
screen = ARG->m_screens[index];
}
// set neighbor combo boxes
@@ -230,7 +246,7 @@ addScreen(HWND hwnd)
if (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD),
hwnd, addDlgProc, (LPARAM)&info) != 0) {
// get current number of screens
UInt32 i = s_screens.size();
UInt32 i = ARG->m_screens.size();
// add screen to list control
HWND child = getItem(hwnd, IDC_MAIN_SERVER_SCREENS_LIST);
@@ -239,15 +255,15 @@ addScreen(HWND hwnd)
SendMessage(child, LB_ADDSTRING, 0, (LPARAM)item.c_str());
// add screen to screen list
s_screens.push_back(info.m_screen);
ARG->m_screens.push_back(info.m_screen);
// add screen to config
s_config.addScreen(info.m_screen);
ARG->m_config.addScreen(info.m_screen);
// add aliases to config
for (CStringList::const_iterator index = info.m_aliases.begin();
index != info.m_aliases.end(); ++index) {
s_config.addAlias(info.m_screen, *index);
ARG->m_config.addAlias(info.m_screen, *index);
}
// update neighbors
@@ -271,9 +287,9 @@ editScreen(HWND hwnd)
// fill in screen info
CScreenInfo info;
info.m_screen = s_screens[index];
for (CConfig::all_const_iterator index = s_config.beginAll();
index != s_config.endAll(); ++index) {
info.m_screen = ARG->m_screens[index];
for (CConfig::all_const_iterator index = ARG->m_config.beginAll();
index != ARG->m_config.endAll(); ++index) {
if (CStringUtil::CaselessCmp::equal(index->second, info.m_screen) &&
!CStringUtil::CaselessCmp::equal(index->second, index->first)) {
info.m_aliases.push_back(index->first);
@@ -287,21 +303,21 @@ editScreen(HWND hwnd)
if (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD),
hwnd, addDlgProc, (LPARAM)&info) != 0) {
// replace screen
s_screens[index] = info.m_screen;
ARG->m_screens[index] = info.m_screen;
// remove old aliases
for (CStringList::const_iterator index = oldInfo.m_aliases.begin();
index != oldInfo.m_aliases.end(); ++index) {
s_config.removeAlias(*index);
ARG->m_config.removeAlias(*index);
}
// replace name
s_config.renameScreen(oldInfo.m_screen, info.m_screen);
ARG->m_config.renameScreen(oldInfo.m_screen, info.m_screen);
// add new aliases
for (CStringList::const_iterator index = info.m_aliases.begin();
index != info.m_aliases.end(); ++index) {
s_config.addAlias(info.m_screen, *index);
ARG->m_config.addAlias(info.m_screen, *index);
}
// update list
@@ -331,16 +347,16 @@ removeScreen(HWND hwnd)
}
// get screen name
CString name = s_screens[index];
CString name = ARG->m_screens[index];
// remove screen from list control
SendMessage(child, LB_DELETESTRING, index, 0);
// remove screen from screen list
s_screens.erase(&s_screens[index]);
ARG->m_screens.erase(&ARG->m_screens[index]);
// remove screen from config (this also removes aliases)
s_config.removeScreen(name);
ARG->m_config.removeScreen(name);
// update neighbors
updateNeighbors(hwnd);
@@ -361,20 +377,20 @@ changeNeighbor(HWND hwnd, HWND combo, EDirection direction)
}
// get screen name
CString screen = s_screens[index];
CString screen = ARG->m_screens[index];
// get selected neighbor
index = SendMessage(combo, CB_GETCURSEL, 0, 0);
// remove old connection
s_config.disconnect(screen, direction);
ARG->m_config.disconnect(screen, direction);
// add new connection
if (index != LB_ERR && index != 0) {
LRESULT size = SendMessage(combo, CB_GETLBTEXTLEN, index, 0);
char* neighbor = new char[size + 1];
SendMessage(combo, CB_GETLBTEXT, index, (LPARAM)neighbor);
s_config.connect(screen, direction, CString(neighbor));
ARG->m_config.connect(screen, direction, CString(neighbor));
delete[] neighbor;
}
@@ -444,14 +460,14 @@ getCommandLine(HWND hwnd, bool testing)
// get and verify screen name
HWND child = getItem(hwnd, IDC_MAIN_ADVANCED_NAME_EDIT);
CString name = getWindowText(child);
if (!s_config.isValidScreenName(name)) {
if (!ARG->m_config.isValidScreenName(name)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
name.c_str()));
SetFocus(child);
return CString();
}
if (!isClient && !s_config.isScreen(name)) {
if (!isClient && !ARG->m_config.isScreen(name)) {
showError(hwnd, CStringUtil::format(
getString(IDS_UNKNOWN_SCREEN_NAME).c_str(),
name.c_str()));
@@ -490,7 +506,7 @@ getCommandLine(HWND hwnd, bool testing)
// check server name
child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
CString server = getWindowText(child);
if (!s_config.isValidScreenName(server)) {
if (!ARG->m_config.isValidScreenName(server)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SERVER_NAME).c_str(),
server.c_str()));
@@ -649,15 +665,13 @@ static
void
initMainWindow(HWND hwnd)
{
CPlatform platform;
// append version number to title
CString titleFormat = getString(IDS_TITLE);
setWindowText(hwnd, CStringUtil::format(titleFormat.c_str(), VERSION));
// load configuration
bool configLoaded = loadConfig(s_config);
s_oldConfig = s_config;
bool configLoaded = loadConfig(ARG->m_config);
ARG->m_oldConfig = ARG->m_config;
enableSaveControls(hwnd);
// choose client/server radio buttons
@@ -673,9 +687,9 @@ initMainWindow(HWND hwnd)
if (configLoaded) {
int i = 1;
child = getItem(hwnd, IDC_MAIN_SERVER_SCREENS_LIST);
for (CConfig::const_iterator index = s_config.begin();
index != s_config.end(); ++i, ++index) {
s_screens.push_back(*index);
for (CConfig::const_iterator index = ARG->m_config.begin();
index != ARG->m_config.end(); ++i, ++index) {
ARG->m_screens.push_back(*index);
CString item = CStringUtil::print("%d. %s", i, index->c_str());
SendMessage(child, LB_ADDSTRING, 0, (LPARAM)item.c_str());
}
@@ -687,9 +701,9 @@ initMainWindow(HWND hwnd)
child = getItem(hwnd, IDC_MAIN_ADVANCED_PORT_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
CNetwork::gethostname(buffer, sizeof(buffer));
CString hostname = ARCH->getHostName();
child = getItem(hwnd, IDC_MAIN_ADVANCED_NAME_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)hostname.c_str());
child = getItem(hwnd, IDC_MAIN_DEBUG);
for (unsigned int i = 0; i < sizeof(s_debugName) /
@@ -746,7 +760,7 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
tokenize(newAliases, getWindowText(child));
// name must be valid
if (!s_config.isValidScreenName(newName)) {
if (!ARG->m_config.isValidScreenName(newName)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
newName.c_str()));
@@ -756,7 +770,7 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
// aliases must be valid
for (CStringList::const_iterator index = newAliases.begin();
index != newAliases.end(); ++index) {
if (!s_config.isValidScreenName(*index)) {
if (!ARG->m_config.isValidScreenName(*index)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
index->c_str()));
@@ -775,7 +789,7 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
// name must not exist in config but allow same name. also
// allow name if it exists in the old alias list but not the
// new one.
if (s_config.isScreen(newName) &&
if (ARG->m_config.isScreen(newName) &&
!CStringUtil::CaselessCmp::equal(newName, info->m_screen) &&
!isNameInList(info->m_aliases, newName)) {
showError(hwnd, CStringUtil::format(
@@ -788,7 +802,7 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
// allow an alias to be the old name.
for (CStringList::const_iterator index = newAliases.begin();
index != newAliases.end(); ++index) {
if (s_config.isScreen(*index) &&
if (ARG->m_config.isScreen(*index) &&
!CStringUtil::CaselessCmp::equal(*index, info->m_screen) &&
!isNameInList(info->m_aliases, *index)) {
showError(hwnd, CStringUtil::format(
@@ -830,7 +844,7 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (LOWORD(wParam)) {
case IDCANCEL:
// test for unsaved data
if (s_config != s_oldConfig) {
if (ARG->m_config != ARG->m_oldConfig) {
if (!askVerify(hwnd, getString(IDS_UNSAVED_DATA_REALLY_QUIT))) {
return 0;
}
@@ -846,14 +860,14 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST);
// save data
if (s_config != s_oldConfig) {
if (!saveConfig(s_config, false)) {
if (ARG->m_config != ARG->m_oldConfig) {
if (!saveConfig(ARG->m_config, false)) {
showError(hwnd, CStringUtil::format(
getString(IDS_SAVE_FAILED).c_str(),
getErrorString(GetLastError()).c_str()));
return 0;
}
s_oldConfig = s_config;
ARG->m_oldConfig = ARG->m_config;
enableSaveControls(hwnd);
}
@@ -892,11 +906,11 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!cmdLine.empty()) {
// run dialog
CAutoStart autoStart(hwnd,
isClientChecked(hwnd) ? NULL : &s_config,
isClientChecked(hwnd) ? NULL : &ARG->m_config,
cmdLine);
autoStart.doModal();
if (autoStart.wasUserConfigSaved()) {
s_oldConfig = s_config;
ARG->m_oldConfig = ARG->m_config;
enableSaveControls(hwnd);
}
}
@@ -904,13 +918,13 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
case IDC_MAIN_SAVE:
if (!saveConfig(s_config, false)) {
if (!saveConfig(ARG->m_config, false)) {
showError(hwnd, CStringUtil::format(
getString(IDS_SAVE_FAILED).c_str(),
getErrorString(GetLastError()).c_str()));
}
else {
s_oldConfig = s_config;
ARG->m_oldConfig = ARG->m_config;
enableSaveControls(hwnd);
}
return 0;
@@ -981,10 +995,11 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int nCmdShow)
{
s_instance = instance;
CArch arch;
CLOG;
CArgs args;
// initialize network library
CNetwork::init();
s_instance = instance;
// register main window (dialog) class
WNDCLASSEX classInfo;
@@ -1009,13 +1024,14 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int nCmdShow)
RegisterClassEx(&classInfo);
// create main window
s_mainWindow = CreateDialog(s_instance, MAKEINTRESOURCE(IDD_MAIN), 0, NULL);
HWND m_mainWindow = CreateDialog(s_instance,
MAKEINTRESOURCE(IDD_MAIN), 0, NULL);
// prep window
initMainWindow(s_mainWindow);
initMainWindow(m_mainWindow);
// show window
ShowWindow(s_mainWindow, nCmdShow);
ShowWindow(m_mainWindow, nCmdShow);
// main loop
MSG msg;
@@ -1032,7 +1048,7 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int nCmdShow)
break;
default:
if (!IsDialogMessage(s_mainWindow, &msg)) {
if (!IsDialogMessage(m_mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -71,7 +71,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

View File

@@ -241,8 +241,8 @@ BEGIN
"Synergy is not configured to start automatically."
IDS_INSTALL_LABEL "Install"
IDS_UNINSTALL_LABEL "Uninstall"
IDS_INSTALL_GENERIC_ERROR "Install failed for an unknown reason."
IDS_UNINSTALL_GENERIC_ERROR "Uninstall failed for an unknown reason."
IDS_INSTALL_GENERIC_ERROR "Install failed: %{1}."
IDS_UNINSTALL_GENERIC_ERROR "Uninstall failed: %{1}."
IDS_INSTALL_TITLE "Installed Auto-Start"
IDS_INSTALLED_SYSTEM "Installed auto-start. Synergy will now automatically start each time you start your computer."
IDS_INSTALLED_USER "Installed auto-start. Synergy will now automatically start each time you log in."

View File

@@ -38,6 +38,7 @@ synergyc_LDADD = \
$(DEPTH)/lib/io/libio.a \
$(DEPTH)/lib/mt/libmt.a \
$(DEPTH)/lib/base/libbase.a \
$(DEPTH)/lib/arch/libarch.a \
$(X_LIBS) \
$(X_PRE_LIBS) \
-lXtst \
@@ -46,6 +47,8 @@ synergyc_LDADD = \
$(X_EXTRA_LIBS) \
$(NULL)
INCLUDES = \
-I$(VDEPTH)/lib/common \
-I$(VDEPTH)/lib/arch \
-I$(VDEPTH)/lib/base \
-I$(VDEPTH)/lib/mt \
-I$(VDEPTH)/lib/io \

View File

@@ -14,11 +14,9 @@
#include "CClient.h"
#include "ISecondaryScreenFactory.h"
#include "CPlatform.h"
#include "ProtocolTypes.h"
#include "Version.h"
#include "XScreen.h"
#include "CNetwork.h"
#include "CNetworkAddress.h"
#include "CTCPSocketFactory.h"
#include "XSocket.h"
@@ -28,12 +26,18 @@
#include "CThread.h"
#include "XThread.h"
#include "CLog.h"
#include "LogOutputters.h"
#include "CString.h"
#include "CArch.h"
#include "CArchMiscWindows.h"
#include <cstring>
#define DAEMON_RUNNING(running_)
#if WINDOWS_LIKE
#include "CMSWindowsSecondaryScreen.h"
#include "resource.h"
#undef DAEMON_RUNNING
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
#elif UNIX_LIKE
#include "CXWindowsSecondaryScreen.h"
#endif
@@ -49,35 +53,33 @@
// program arguments
//
static const char* pname = NULL;
static bool s_backend = false;
static bool s_restartable = true;
static bool s_daemon = true;
static bool s_camp = true;
static const char* s_logFilter = NULL;
static CString s_name;
static CNetworkAddress s_serverAddress;
#define ARG CArgs::s_instance
class CArgs {
public:
CArgs() :
m_pname(NULL),
m_backend(false),
m_restartable(true),
m_daemon(true),
m_camp(true),
m_logFilter(NULL)
{ s_instance = this; }
~CArgs() { s_instance = NULL; }
//
// logging thread safety
//
public:
static CArgs* s_instance;
const char* m_pname;
bool m_backend;
bool m_restartable;
bool m_daemon;
bool m_camp;
const char* m_logFilter;
CString m_name;
CNetworkAddress m_serverAddress;
};
static CMutex* s_logMutex = NULL;
static
void
logLock(bool lock)
{
assert(s_logMutex != NULL);
if (lock) {
s_logMutex->lock();
}
else {
s_logMutex->unlock();
}
}
CArgs* CArgs::s_instance = NULL;
//
@@ -113,27 +115,17 @@ static CClient* s_client = NULL;
static
int
realMain(CMutex* mutex)
realMain(void)
{
// caller should have mutex locked on entry
// initialize threading library
CThread::init();
// make logging thread safe
CMutex logMutex;
s_logMutex = &logMutex;
CLog::setLock(&logLock);
int result = kExitSuccess;
do {
bool opened = false;
bool locked = true;
try {
// create client
s_client = new CClient(s_name);
s_client->camp(s_camp);
s_client->setAddress(s_serverAddress);
s_client = new CClient(ARG->m_name);
s_client->camp(ARG->m_camp);
s_client->setAddress(ARG->m_serverAddress);
s_client->setScreenFactory(new CSecondaryScreenFactory);
s_client->setSocketFactory(new CTCPSocketFactory);
s_client->setStreamFilterFactory(NULL);
@@ -144,9 +136,7 @@ realMain(CMutex* mutex)
opened = true;
// run client
if (mutex != NULL) {
mutex->unlock();
}
DAEMON_RUNNING(true);
locked = false;
s_client->mainLoop();
locked = true;
@@ -160,8 +150,8 @@ realMain(CMutex* mutex)
// clean up
#define FINALLY do { \
if (!locked && mutex != NULL) { \
mutex->lock(); \
if (!locked) { \
DAEMON_RUNNING(false); \
} \
if (s_client != NULL) { \
if (opened) { \
@@ -175,8 +165,8 @@ realMain(CMutex* mutex)
}
catch (XScreenUnavailable& e) {
// wait before retrying if we're going to retry
if (s_restartable) {
CThread::sleep(e.getRetryTime());
if (ARG->m_restartable) {
ARCH->sleep(e.getRetryTime());
}
else {
result = kExitFailed;
@@ -189,8 +179,8 @@ realMain(CMutex* mutex)
}
catch (...) {
// don't try to restart and fail
s_restartable = false;
result = kExitFailed;
ARG->m_restartable = false;
result = kExitFailed;
FINALLY;
}
#undef FINALLY
@@ -200,19 +190,10 @@ realMain(CMutex* mutex)
}
catch (XThread&) {
// terminated
s_restartable = false;
result = kExitTerminated;
ARG->m_restartable = false;
result = kExitTerminated;
}
catch (...) {
CLog::setLock(NULL);
s_logMutex = NULL;
throw;
}
} while (s_restartable);
// clean up
CLog::setLock(NULL);
s_logMutex = NULL;
} while (ARG->m_restartable);
return result;
}
@@ -233,7 +214,7 @@ version()
LOG((CLOG_PRINT
"%s %s, protocol version %d.%d\n"
"%s",
pname,
ARG->m_pname,
kVersion,
kProtocolMajorVersion,
kProtocolMinorVersion,
@@ -279,7 +260,7 @@ help()
"\n"
"Where log messages go depends on the platform and whether or not the\n"
"client is running as a daemon.",
pname, kDefaultPort));
ARG->m_pname, kDefaultPort));
}
@@ -294,7 +275,7 @@ isArg(int argi, int argc, const char** argv,
// match. check args left.
if (argi + minRequiredParameters >= argc) {
LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
pname, argv[argi], pname));
ARG->m_pname, argv[argi], ARG->m_pname));
bye(kExitArgs);
}
return true;
@@ -308,61 +289,58 @@ static
void
parse(int argc, const char** argv)
{
assert(pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
assert(ARG->m_pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
// set defaults
char hostname[256];
if (CNetwork::gethostname(hostname, sizeof(hostname)) != CNetwork::Error) {
s_name = hostname;
}
ARG->m_name = ARCH->getHostName();
// parse options
int i;
for (i = 1; i < argc; ++i) {
if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
s_logFilter = argv[++i];
ARG->m_logFilter = argv[++i];
}
else if (isArg(i, argc, argv, "-n", "--name", 1)) {
// save screen name
s_name = argv[++i];
ARG->m_name = argv[++i];
}
else if (isArg(i, argc, argv, NULL, "--camp")) {
// enable camping
s_camp = true;
ARG->m_camp = true;
}
else if (isArg(i, argc, argv, NULL, "--no-camp")) {
// disable camping
s_camp = false;
ARG->m_camp = false;
}
else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
// not a daemon
s_daemon = false;
ARG->m_daemon = false;
}
else if (isArg(i, argc, argv, NULL, "--daemon")) {
// daemonize
s_daemon = true;
ARG->m_daemon = true;
}
else if (isArg(i, argc, argv, "-1", "--no-restart")) {
// don't try to restart
s_restartable = false;
ARG->m_restartable = false;
}
else if (isArg(i, argc, argv, NULL, "--restart")) {
// try to restart
s_restartable = true;
ARG->m_restartable = true;
}
else if (isArg(i, argc, argv, "-z", NULL)) {
s_backend = true;
ARG->m_backend = true;
}
else if (isArg(i, argc, argv, "-h", "--help")) {
@@ -383,7 +361,7 @@ parse(int argc, const char** argv)
else if (argv[i][0] == '-') {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
pname, argv[i], pname));
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
@@ -396,49 +374,60 @@ parse(int argc, const char** argv)
// exactly one non-option argument (server-address)
if (i == argc) {
LOG((CLOG_PRINT "%s: a server address or name is required" BYE,
pname, pname));
ARG->m_pname, ARG->m_pname));
bye(kExitArgs);
}
if (i + 1 != argc) {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
pname, argv[i], pname));
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
// save server address
try {
s_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
}
catch (XSocketAddress& e) {
LOG((CLOG_PRINT "%s: %s" BYE,
pname, e.what(), pname));
ARG->m_pname, e.what(), ARG->m_pname));
bye(kExitFailed);
}
// increase default filter level for daemon. the user must
// explicitly request another level for a daemon.
if (s_daemon && s_logFilter == NULL) {
if (ARG->m_daemon && ARG->m_logFilter == NULL) {
#if WINDOWS_LIKE
if (CPlatform::isWindows95Family()) {
if (CArchMiscWindows::isWindows95Family()) {
// windows 95 has no place for logging so avoid showing
// the log console window.
s_logFilter = "FATAL";
ARG->m_logFilter = "FATAL";
}
else
#endif
{
s_logFilter = "NOTE";
ARG->m_logFilter = "NOTE";
}
}
// set log filter
if (!CLog::setFilter(s_logFilter)) {
if (!CLOG->setFilter(ARG->m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
pname, s_logFilter, pname));
ARG->m_pname, ARG->m_logFilter, ARG->m_pname));
bye(kExitArgs);
}
}
static
void
useSystemLog()
{
// redirect log messages
ILogOutputter* logger = new CSystemLogOutputter;
logger->open(DAEMON_NAME);
CLOG->insert(new CStopLogOutputter);
CLOG->insert(logger);
}
//
// platform dependent entry points
//
@@ -449,24 +438,41 @@ parse(int argc, const char** argv)
static bool s_hasImportantLogMessages = false;
static
//
// CMessageBoxOutputter
//
// This class writes severe log messages to a message box
//
class CMessageBoxOutputter : public ILogOutputter {
public:
CMessageBoxOutputter() { }
virtual ~CMessageBoxOutputter() { }
// ILogOutputter overrides
virtual void open(const char*) { }
virtual void close() { }
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const { return ""; }
};
bool
logMessageBox(int priority, const char* msg)
CMessageBoxOutputter::write(ELevel level, const char* message)
{
// note any important messages the user may need to know about
if (priority <= CLog::kWARNING) {
if (level <= CLog::kWARNING) {
s_hasImportantLogMessages = true;
}
// FATAL and PRINT messages get a dialog box if not running as
// backend. if we're running as a backend the user will have
// a chance to see the messages when we exit.
if (!s_backend && priority <= CLog::kFATAL) {
MessageBox(NULL, msg, pname, MB_OK | MB_ICONWARNING);
return true;
if (!ARG->m_backend && level <= CLog::kFATAL) {
MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING);
return false;
}
else {
return false;
return true;
}
}
@@ -474,7 +480,7 @@ static
void
byeThrow(int x)
{
throw CWin32Platform::CDaemonFailed(x);
CArchMiscWindows::daemonFailed(x);
}
static
@@ -486,10 +492,9 @@ daemonStop(void)
static
int
daemonStartup(IPlatform* iplatform, int argc, const char** argv)
daemonStartup(int argc, const char** argv)
{
// get platform pointer
CWin32Platform* platform = static_cast<CWin32Platform*>(iplatform);
useSystemLog();
// catch errors that would normally exit
bye = &byeThrow;
@@ -498,35 +503,35 @@ daemonStartup(IPlatform* iplatform, int argc, const char** argv)
parse(argc, argv);
// cannot run as backend if running as a service
s_backend = false;
ARG->m_backend = false;
// run as a service
return platform->runDaemon(realMain, daemonStop);
return CArchMiscWindows::runDaemon(realMain, daemonStop);
}
static
int
daemonStartup95(IPlatform*, int, const char**)
daemonStartup95(int, const char**)
{
return realMain(NULL);
useSystemLog();
return realMain();
}
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
{
CPlatform platform;
CArch arch;
CLOG;
CArgs args;
// save instance
CMSWindowsScreen::init(instance);
// get program name
pname = platform.getBasename(__argv[0]);
// initialize network library
CNetwork::init();
ARG->m_pname = ARCH->getBasename(__argv[0]);
// send PRINT and FATAL output to a message box
CLog::setOutputter(&logMessageBox);
CLOG->insert(new CMessageBoxOutputter);
// windows NT family starts services using no command line options.
// since i'm not sure how to tell the difference between that and
@@ -534,10 +539,10 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// arguments and we're on NT then we're being invoked as a service.
// users on NT can use `--daemon' or `--no-daemon' to force us out
// of the service code path.
if (__argc <= 1 && !CWin32Platform::isWindows95Family()) {
int result = platform.daemonize(DAEMON_NAME, &daemonStartup);
if (__argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
int result = ARCH->daemonize(DAEMON_NAME, &daemonStartup);
if (result == -1) {
LOG((CLOG_CRIT "failed to start as a service" BYE, pname));
LOG((CLOG_CRIT "failed to start as a service" BYE, ARG->m_pname));
return kExitFailed;
}
return result;
@@ -548,38 +553,36 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// daemonize if requested
int result;
if (s_daemon) {
// redirect log messages
platform.installDaemonLogger(DAEMON_NAME);
if (ARG->m_daemon) {
// start as a daemon
if (CWin32Platform::isWindows95Family()) {
result = platform.daemonize(DAEMON_NAME, &daemonStartup95);
if (result == -1) {
LOG((CLOG_CRIT "failed to start as a service" BYE, pname));
if (CArchMiscWindows::isWindows95Family()) {
try {
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
}
catch (XArchDaemon&) {
LOG((CLOG_CRIT "failed to start as a service" BYE, ARG->m_pname));
result = kExitFailed;
}
}
else {
// cannot start a service from the command line so just
// run normally (except with log messages redirected).
result = realMain(NULL);
useSystemLog();
result = realMain();
}
}
else {
// run
result = realMain(NULL);
result = realMain();
}
CNetwork::cleanup();
// let user examine any messages if we're running as a backend
// by putting up a dialog box before exiting.
if (s_backend && s_hasImportantLogMessages) {
if (ARG->m_backend && s_hasImportantLogMessages) {
char msg[1024];
msg[0] = '\0';
LoadString(instance, IDS_FAILED, msg, sizeof(msg) / sizeof(msg[0]));
MessageBox(NULL, msg, pname, MB_OK | MB_ICONWARNING);
MessageBox(NULL, msg, ARG->m_pname, MB_OK | MB_ICONWARNING);
}
return result;
@@ -589,40 +592,40 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
static
int
daemonStartup(IPlatform*, int, const char**)
daemonStartup(int, const char**)
{
return realMain(NULL);
useSystemLog();
return realMain();
}
int
main(int argc, char** argv)
{
CPlatform platform;
CArch arch;
CLOG;
CArgs args;
// get program name
pname = platform.getBasename(argv[0]);
// initialize network library
CNetwork::init();
ARG->m_pname = ARCH->getBasename(argv[0]);
// parse command line
parse(argc, const_cast<const char**>(argv));
// daemonize if requested
int result;
if (s_daemon) {
result = platform.daemonize(DAEMON_NAME, &daemonStartup);
if (result == -1) {
if (ARG->m_daemon) {
try {
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup);
}
catch (XArchDaemon&) {
LOG((CLOG_CRIT "failed to daemonize"));
return kExitFailed;
result = kExitFailed;
}
}
else {
result = realMain(NULL);
result = realMain();
}
CNetwork::cleanup();
return result;
}

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\base" /I "..\..\lib\io" /I "..\..\lib\mt" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\client" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\io" /I "..\..\lib\mt" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\client" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -54,7 +54,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../../Release/synergyc.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "synergyc - Win32 Debug"
@@ -70,7 +70,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\base" /I "..\..\lib\io" /I "..\..\lib\mt" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\client" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\io" /I "..\..\lib\mt" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\client" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../../Debug/synergyc.exe" /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF

View File

@@ -39,6 +39,7 @@ synergys_LDADD = \
$(DEPTH)/lib/io/libio.a \
$(DEPTH)/lib/mt/libmt.a \
$(DEPTH)/lib/base/libbase.a \
$(DEPTH)/lib/arch/libarch.a \
$(X_LIBS) \
$(X_PRE_LIBS) \
-lXtst \
@@ -47,6 +48,8 @@ synergys_LDADD = \
$(X_EXTRA_LIBS) \
$(NULL)
INCLUDES = \
-I$(VDEPTH)/lib/common \
-I$(VDEPTH)/lib/arch \
-I$(VDEPTH)/lib/base \
-I$(VDEPTH)/lib/mt \
-I$(VDEPTH)/lib/io \

View File

@@ -15,11 +15,9 @@
#include "CServer.h"
#include "CConfig.h"
#include "IPrimaryScreenFactory.h"
#include "CPlatform.h"
#include "ProtocolTypes.h"
#include "Version.h"
#include "XScreen.h"
#include "CNetwork.h"
#include "CTCPSocketFactory.h"
#include "XSocket.h"
#include "CLock.h"
@@ -27,12 +25,18 @@
#include "CThread.h"
#include "XThread.h"
#include "CLog.h"
#include "LogOutputters.h"
#include "CArch.h"
#include "CArchMiscWindows.h"
#include "stdfstream.h"
#include <cstring>
#define DAEMON_RUNNING(running_)
#if WINDOWS_LIKE
#include "CMSWindowsPrimaryScreen.h"
#include "resource.h"
#undef DAEMON_RUNNING
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
#elif UNIX_LIKE
#include "CXWindowsPrimaryScreen.h"
#endif
@@ -57,37 +61,35 @@
// program arguments
//
static const char* pname = NULL;
static bool s_backend = false;
static bool s_restartable = true;
static bool s_daemon = true;
static const char* s_configFile = NULL;
static const char* s_logFilter = NULL;
static CString s_name;
static CNetworkAddress s_synergyAddress;
static CNetworkAddress s_httpAddress;
static CConfig s_config;
#define ARG CArgs::s_instance
class CArgs {
public:
CArgs() :
m_pname(NULL),
m_backend(false),
m_restartable(true),
m_daemon(true),
m_configFile(NULL),
m_logFilter(NULL)
{ s_instance = this; }
~CArgs() { s_instance = NULL; }
//
// logging thread safety
//
public:
static CArgs* s_instance;
const char* m_pname;
bool m_backend;
bool m_restartable;
bool m_daemon;
const char* m_configFile;
const char* m_logFilter;
CString m_name;
CNetworkAddress m_synergyAddress;
CNetworkAddress m_httpAddress;
CConfig m_config;
};
static CMutex* s_logMutex = NULL;
static
void
logLock(bool lock)
{
assert(s_logMutex != NULL);
if (lock) {
s_logMutex->lock();
}
else {
s_logMutex->unlock();
}
}
CArgs* CArgs::s_instance = NULL;
//
@@ -124,18 +126,8 @@ static CServer* s_server = NULL;
static
int
realMain(CMutex* mutex)
realMain(void)
{
// caller should have mutex locked on entry
// initialize threading library
CThread::init();
// make logging thread safe
CMutex logMutex;
s_logMutex = &logMutex;
CLog::setLock(&logLock);
int result = kExitSuccess;
do {
bool opened = false;
@@ -143,28 +135,28 @@ realMain(CMutex* mutex)
try {
// if configuration has no screens then add this system
// as the default
if (s_config.begin() == s_config.end()) {
s_config.addScreen(s_name);
if (ARG->m_config.begin() == ARG->m_config.end()) {
ARG->m_config.addScreen(ARG->m_name);
}
// set the contact address, if provided, in the config.
// otherwise, if the config doesn't have an address, use
// the default.
if (s_synergyAddress.isValid()) {
s_config.setSynergyAddress(s_synergyAddress);
if (ARG->m_synergyAddress.isValid()) {
ARG->m_config.setSynergyAddress(ARG->m_synergyAddress);
}
else if (!s_config.getSynergyAddress().isValid()) {
s_config.setSynergyAddress(CNetworkAddress(kDefaultPort));
else if (!ARG->m_config.getSynergyAddress().isValid()) {
ARG->m_config.setSynergyAddress(CNetworkAddress(kDefaultPort));
}
// set HTTP address if provided
if (s_httpAddress.isValid()) {
s_config.setHTTPAddress(s_httpAddress);
if (ARG->m_httpAddress.isValid()) {
ARG->m_config.setHTTPAddress(ARG->m_httpAddress);
}
// create server
s_server = new CServer(s_name);
s_server->setConfig(s_config);
s_server = new CServer(ARG->m_name);
s_server->setConfig(ARG->m_config);
s_server->setScreenFactory(new CPrimaryScreenFactory);
s_server->setSocketFactory(new CTCPSocketFactory);
s_server->setStreamFilterFactory(NULL);
@@ -174,18 +166,16 @@ realMain(CMutex* mutex)
s_server->open();
opened = true;
// run server (unlocked)
if (mutex != NULL) {
mutex->unlock();
}
// run server
DAEMON_RUNNING(true);
locked = false;
s_server->mainLoop();
locked = true;
// clean up
#define FINALLY do { \
if (!locked && mutex != NULL) { \
mutex->lock(); \
if (!locked) { \
DAEMON_RUNNING(false); \
} \
if (s_server != NULL) { \
if (opened) { \
@@ -199,8 +189,8 @@ realMain(CMutex* mutex)
}
catch (XScreenUnavailable& e) {
// wait before retrying if we're going to retry
if (s_restartable) {
CThread::sleep(e.getRetryTime());
if (ARG->m_restartable) {
ARCH->sleep(e.getRetryTime());
}
else {
result = kExitFailed;
@@ -213,8 +203,8 @@ realMain(CMutex* mutex)
}
catch (...) {
// don't try to restart and fail
s_restartable = false;
result = kExitFailed;
ARG->m_restartable = false;
result = kExitFailed;
FINALLY;
}
#undef FINALLY
@@ -224,19 +214,10 @@ realMain(CMutex* mutex)
}
catch (XThread&) {
// terminated
s_restartable = false;
result = kExitTerminated;
ARG->m_restartable = false;
result = kExitTerminated;
}
catch (...) {
CLog::setLock(NULL);
s_logMutex = NULL;
throw;
}
} while (s_restartable);
// clean up
CLog::setLock(NULL);
s_logMutex = NULL;
} while (ARG->m_restartable);
return result;
}
@@ -257,7 +238,7 @@ version()
LOG((CLOG_PRINT
"%s %s, protocol version %d.%d\n"
"%s",
pname,
ARG->m_pname,
kVersion,
kProtocolMajorVersion,
kProtocolMinorVersion,
@@ -287,8 +268,6 @@ help()
#endif
CPlatform platform;
LOG((CLOG_PRINT
"Usage: %s"
" [--address <address>]"
@@ -333,13 +312,13 @@ PLATFORM_EXTRA
"\n"
"Where log messages go depends on the platform and whether or not the\n"
"server is running as a daemon.",
pname,
ARG->m_pname,
kDefaultPort,
platform.addPathComponent(
platform.getUserDirectory(),
ARCH->concatPath(
ARCH->getUserDirectory(),
USR_CONFIG_NAME).c_str(),
platform.addPathComponent(
platform.getSystemDirectory(),
ARCH->concatPath(
ARCH->getSystemDirectory(),
SYS_CONFIG_NAME).c_str()));
}
@@ -354,7 +333,7 @@ isArg(int argi, int argc, const char** argv,
// match. check args left.
if (argi + minRequiredParameters >= argc) {
LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
pname, argv[argi], pname));
ARG->m_pname, argv[argi], ARG->m_pname));
bye(kExitArgs);
}
return true;
@@ -368,32 +347,30 @@ static
void
parse(int argc, const char** argv)
{
assert(pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
assert(ARG->m_pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
// set defaults
char hostname[256];
if (CNetwork::gethostname(hostname, sizeof(hostname)) != CNetwork::Error) {
s_name = hostname;
}
ARG->m_name = ARCH->getHostName();
// parse options
int i;
for (i = 1; i < argc; ++i) {
if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
s_logFilter = argv[++i];
ARG->m_logFilter = argv[++i];
}
else if (isArg(i, argc, argv, "-a", "--address", 1)) {
// save listen address
try {
s_synergyAddress = CNetworkAddress(argv[i + 1], kDefaultPort);
ARG->m_synergyAddress = CNetworkAddress(argv[i + 1],
kDefaultPort);
}
catch (XSocketAddress& e) {
LOG((CLOG_PRINT "%s: %s" BYE,
pname, e.what(), pname));
ARG->m_pname, e.what(), ARG->m_pname));
bye(kExitArgs);
}
++i;
@@ -402,11 +379,12 @@ parse(int argc, const char** argv)
else if (isArg(i, argc, argv, NULL, "--http", 1)) {
// save listen address
try {
s_httpAddress = CNetworkAddress(argv[i + 1], kDefaultPort + 1);
ARG->m_httpAddress = CNetworkAddress(argv[i + 1],
kDefaultPort + 1);
}
catch (XSocketAddress& e) {
LOG((CLOG_PRINT "%s: %s" BYE,
pname, e.what(), pname));
ARG->m_pname, e.what(), ARG->m_pname));
bye(kExitArgs);
}
++i;
@@ -414,36 +392,36 @@ parse(int argc, const char** argv)
else if (isArg(i, argc, argv, "-n", "--name", 1)) {
// save screen name
s_name = argv[++i];
ARG->m_name = argv[++i];
}
else if (isArg(i, argc, argv, "-c", "--config", 1)) {
// save configuration file path
s_configFile = argv[++i];
ARG->m_configFile = argv[++i];
}
else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
// not a daemon
s_daemon = false;
ARG->m_daemon = false;
}
else if (isArg(i, argc, argv, NULL, "--daemon")) {
// daemonize
s_daemon = true;
ARG->m_daemon = true;
}
else if (isArg(i, argc, argv, "-1", "--no-restart")) {
// don't try to restart
s_restartable = false;
ARG->m_restartable = false;
}
else if (isArg(i, argc, argv, NULL, "--restart")) {
// try to restart
s_restartable = true;
ARG->m_restartable = true;
}
else if (isArg(i, argc, argv, "-z", NULL)) {
s_backend = true;
ARG->m_backend = true;
}
else if (isArg(i, argc, argv, "-h", "--help")) {
@@ -464,7 +442,7 @@ parse(int argc, const char** argv)
else if (argv[i][0] == '-') {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
pname, argv[i], pname));
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
@@ -477,30 +455,30 @@ parse(int argc, const char** argv)
// no non-option arguments are allowed
if (i != argc) {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
pname, argv[i], pname));
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
// increase default filter level for daemon. the user must
// explicitly request another level for a daemon.
if (s_daemon && s_logFilter == NULL) {
if (ARG->m_daemon && ARG->m_logFilter == NULL) {
#if WINDOWS_LIKE
if (CPlatform::isWindows95Family()) {
if (CArchMiscWindows::isWindows95Family()) {
// windows 95 has no place for logging so avoid showing
// the log console window.
s_logFilter = "FATAL";
ARG->m_logFilter = "FATAL";
}
else
#endif
{
s_logFilter = "NOTE";
ARG->m_logFilter = "NOTE";
}
}
// set log filter
if (!CLog::setFilter(s_logFilter)) {
if (!CLOG->setFilter(ARG->m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
pname, s_logFilter, pname));
ARG->m_pname, ARG->m_logFilter, ARG->m_pname));
bye(kExitArgs);
}
}
@@ -518,14 +496,14 @@ loadConfig(const char* pathname, bool require)
if (!configStream) {
throw XConfigRead("cannot open file");
}
configStream >> s_config;
configStream >> ARG->m_config;
LOG((CLOG_DEBUG "configuration read successfully"));
return true;
}
catch (XConfigRead& e) {
if (require) {
LOG((CLOG_PRINT "%s: cannot read configuration '%s': %s",
pname, pathname, e.what()));
ARG->m_pname, pathname, e.what()));
bye(kExitConfig);
}
else {
@@ -541,36 +519,46 @@ void
loadConfig()
{
// load the config file, if specified
if (s_configFile != NULL) {
if (ARG->m_configFile != NULL) {
// require the user specified file to load correctly
loadConfig(s_configFile, true);
loadConfig(ARG->m_configFile, true);
}
// load the default configuration if no explicit file given
else {
// get the user's home directory. use the effective user id
// so a user can't get a setuid root program to load his file.
CPlatform platform;
bool loaded = false;
CString path = platform.getUserDirectory();
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
// complete path
path = platform.addPathComponent(path, USR_CONFIG_NAME);
path = ARCH->concatPath(path, USR_CONFIG_NAME);
// now try loading the user's configuration
loaded = loadConfig(path.c_str(), false);
}
if (!loaded) {
// try the system-wide config file
path = platform.getSystemDirectory();
path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = platform.addPathComponent(path, SYS_CONFIG_NAME);
path = ARCH->concatPath(path, SYS_CONFIG_NAME);
loadConfig(path.c_str(), false);
}
}
}
}
static
void
useSystemLog()
{
// redirect log messages
ILogOutputter* logger = new CSystemLogOutputter;
logger->open(DAEMON_NAME);
CLOG->insert(new CStopLogOutputter);
CLOG->insert(logger);
}
//
// platform dependent entry points
//
@@ -581,24 +569,41 @@ loadConfig()
static bool s_hasImportantLogMessages = false;
static
//
// CMessageBoxOutputter
//
// This class writes severe log messages to a message box
//
class CMessageBoxOutputter : public ILogOutputter {
public:
CMessageBoxOutputter() { }
virtual ~CMessageBoxOutputter() { }
// ILogOutputter overrides
virtual void open(const char*) { }
virtual void close() { }
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const { return ""; }
};
bool
logMessageBox(int priority, const char* msg)
CMessageBoxOutputter::write(ELevel level, const char* message)
{
// note any important messages the user may need to know about
if (priority <= CLog::kWARNING) {
if (level <= CLog::kWARNING) {
s_hasImportantLogMessages = true;
}
// FATAL and PRINT messages get a dialog box if not running as
// backend. if we're running as a backend the user will have
// a chance to see the messages when we exit.
if (!s_backend && priority <= CLog::kFATAL) {
MessageBox(NULL, msg, pname, MB_OK | MB_ICONWARNING);
return true;
if (!ARG->m_backend && level <= CLog::kFATAL) {
MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING);
return false;
}
else {
return false;
return true;
}
}
@@ -606,7 +611,7 @@ static
void
byeThrow(int x)
{
throw CWin32Platform::CDaemonFailed(x);
CArchMiscWindows::daemonFailed(x);
}
static
@@ -618,10 +623,9 @@ daemonStop(void)
static
int
daemonStartup(IPlatform* iplatform, int argc, const char** argv)
daemonStartup(int argc, const char** argv)
{
// get platform pointer
CWin32Platform* platform = static_cast<CWin32Platform*>(iplatform);
useSystemLog();
// catch errors that would normally exit
bye = &byeThrow;
@@ -630,38 +634,38 @@ daemonStartup(IPlatform* iplatform, int argc, const char** argv)
parse(argc, argv);
// cannot run as backend if running as a service
s_backend = false;
ARG->m_backend = false;
// load configuration
loadConfig();
// run as a service
return platform->runDaemon(realMain, daemonStop);
return CArchMiscWindows::runDaemon(realMain, daemonStop);
}
static
int
daemonStartup95(IPlatform*, int, const char**)
daemonStartup95(int, const char**)
{
return realMain(NULL);
useSystemLog();
return realMain();
}
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
{
CPlatform platform;
CArch arch;
CLOG;
CArgs args;
// save instance
CMSWindowsScreen::init(instance);
// get program name
pname = platform.getBasename(__argv[0]);
// initialize network library
CNetwork::init();
ARG->m_pname = ARCH->getBasename(__argv[0]);
// send PRINT and FATAL output to a message box
CLog::setOutputter(&logMessageBox);
CLOG->insert(new CMessageBoxOutputter);
// windows NT family starts services using no command line options.
// since i'm not sure how to tell the difference between that and
@@ -669,13 +673,14 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// arguments and we're on NT then we're being invoked as a service.
// users on NT can use `--daemon' or `--no-daemon' to force us out
// of the service code path.
if (__argc <= 1 && !CWin32Platform::isWindows95Family()) {
int result = platform.daemonize(DAEMON_NAME, &daemonStartup);
if (result == -1) {
LOG((CLOG_CRIT "failed to start as a service" BYE, pname));
if (__argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
try {
return ARCH->daemonize(DAEMON_NAME, &daemonStartup);
}
catch (XArchDaemon&) {
LOG((CLOG_CRIT "failed to start as a service" BYE, ARG->m_pname));
return kExitFailed;
}
return result;
}
// parse command line
@@ -686,38 +691,36 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// daemonize if requested
int result;
if (s_daemon) {
// redirect log messages
platform.installDaemonLogger(DAEMON_NAME);
if (ARG->m_daemon) {
// start as a daemon
if (CWin32Platform::isWindows95Family()) {
result = platform.daemonize(DAEMON_NAME, &daemonStartup95);
if (result == -1) {
LOG((CLOG_CRIT "failed to start as a service" BYE, pname));
if (CArchMiscWindows::isWindows95Family()) {
try {
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
}
catch (XArchDaemon&) {
LOG((CLOG_CRIT "failed to start as a service" BYE, ARG->m_pname));
result = kExitFailed;
}
}
else {
// cannot start a service from the command line so just
// run normally (except with log messages redirected).
result = realMain(NULL);
useSystemLog();
result = realMain();
}
}
else {
// run
result = realMain(NULL);
result = realMain();
}
CNetwork::cleanup();
// let user examine any messages if we're running as a backend
// by putting up a dialog box before exiting.
if (s_backend && s_hasImportantLogMessages) {
if (ARG->m_backend && s_hasImportantLogMessages) {
char msg[1024];
msg[0] = '\0';
LoadString(instance, IDS_FAILED, msg, sizeof(msg) / sizeof(msg[0]));
MessageBox(NULL, msg, pname, MB_OK | MB_ICONWARNING);
MessageBox(NULL, msg, ARG->m_pname, MB_OK | MB_ICONWARNING);
}
return result;
@@ -727,21 +730,21 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
static
int
daemonStartup(IPlatform*, int, const char**)
daemonStartup(int, const char**)
{
return realMain(NULL);
useSystemLog();
return realMain();
}
int
main(int argc, char** argv)
{
CPlatform platform;
CArch arch;
CLOG;
CArgs args;
// get program name
pname = platform.getBasename(argv[0]);
// initialize network library
CNetwork::init();
ARG->m_pname = ARCH->getBasename(argv[0]);
// parse command line
parse(argc, const_cast<const char**>(argv));
@@ -751,19 +754,19 @@ main(int argc, char** argv)
// daemonize if requested
int result;
if (s_daemon) {
result = platform.daemonize(DAEMON_NAME, &daemonStartup);
if (result == -1) {
if (ARG->m_daemon) {
try {
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup);
}
catch (XArchDaemon&) {
LOG((CLOG_CRIT "failed to daemonize"));
return kExitFailed;
result = kExitFailed;
}
}
else {
result = realMain(NULL);
result = realMain();
}
CNetwork::cleanup();
return result;
}

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -70,7 +70,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\..\lib\common" /I "..\..\lib\arch" /I "..\..\lib\base" /I "..\..\lib\mt" /I "..\..\lib\io" /I "..\..\lib\http" /I "..\..\lib\net" /I "..\..\lib\synergy" /I "..\..\lib\platform" /I "..\..\lib\server" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32