diff --git a/code/nel/include/nel/misc/cmd_args.h b/code/nel/include/nel/misc/cmd_args.h index 25195b64d..3fb87e0c0 100644 --- a/code/nel/include/nel/misc/cmd_args.h +++ b/code/nel/include/nel/misc/cmd_args.h @@ -118,6 +118,7 @@ public: /// Returns program name or path passed as first parameter to parse() method std::string getProgramName() const { return _ProgramName; } std::string getProgramPath() const { return _ProgramPath; } + std::string getStartupPath() const { return _StartupPath; } /// Set or get description to display in help void setDescription(const std::string &description) { _Description = description; } @@ -129,6 +130,7 @@ public: protected: std::string _ProgramName; // filename of the program std::string _ProgramPath; // full path of the program + std::string _StartupPath; // initial startup path std::string _Description; // description of the program std::string _Version; // version of the program diff --git a/code/nel/src/misc/cmd_args.cpp b/code/nel/src/misc/cmd_args.cpp index 11464b222..85239e8ff 100644 --- a/code/nel/src/misc/cmd_args.cpp +++ b/code/nel/src/misc/cmd_args.cpp @@ -264,6 +264,9 @@ bool CCmdArgs::parse(const std::vector &argv) _ProgramName = CFile::getFilename(argv.front()); _ProgramPath = CPath::makePathAbsolute(CPath::standardizePath(CFile::getPath(argv.front())), CPath::getCurrentPath(), true); + // current path + _StartupPath = CPath::standardizePath(CPath::getCurrentPath()); + // set process name for logs CLog::setProcessName(_ProgramName); diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index b40734b73..decd52dbf 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -765,26 +765,34 @@ bool launchProgram(const std::string &programName, const std::string &arguments, CloseHandle( pi.hThread ); } -#elif defined(NL_OS_MAC) - // we need to open bundles with "open" command - std::string command = NLMISC::toString("open \"%s\"", programName.c_str()); - - // append arguments if any - if (!arguments.empty()) - { - command += NLMISC::toString(" --args %s", arguments.c_str()); - } - - int res = system(command.c_str()); - - if (!res) return true; - - if (log) - { - nlwarning ("LAUNCH: Failed launched '%s' with arg '%s' return code %d", programName.c_str(), arguments.c_str(), res); - } #else +#ifdef NL_OS_MAC + // special OS X case with bundles + if (toLower(programName).find(".app") != std::string::npos) + { + // we need to open bundles with "open" command + std::string command = NLMISC::toString("open \"%s\"", programName.c_str()); + + // append arguments if any + if (!arguments.empty()) + { + command += NLMISC::toString(" --args %s", arguments.c_str()); + } + + int res = system(command.c_str()); + + if (!res) return true; + + if (log) + { + nlwarning ("LAUNCH: Failed launched '%s' with arg '%s' return code %d", programName.c_str(), arguments.c_str(), res); + } + + return false; + } +#endif + static bool firstLaunchProgram = true; if (firstLaunchProgram) { @@ -1025,6 +1033,7 @@ std::string expandEnvironmentVariables(const std::string &s) { // value not found found = false; + nlwarning("Environment variable '%s' not found, won't be replaced", name.c_str()); } } diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index 41477db32..ee47fd494 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -1789,18 +1789,18 @@ std::string CFileContainer::getApplicationDirectory(const std::string &appName, if (appPath.empty()) { #ifdef NL_OS_WINDOWS - wchar_t buffer[MAX_PATH]; + char buffer[MAX_PATH]; #ifdef CSIDL_LOCAL_APPDATA if (local) { - SHGetSpecialFolderPathW(NULL, buffer, CSIDL_LOCAL_APPDATA, TRUE); + SHGetSpecialFolderPathA(NULL, buffer, CSIDL_LOCAL_APPDATA, TRUE); } else #endif { - SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, TRUE); + SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, TRUE); } - appPath = CPath::standardizePath(ucstring((ucchar*)buffer).toUtf8()); + appPath = CPath::standardizePath(buffer); #elif defined(NL_OS_MAC) appPath = CPath::standardizePath(getenv("HOME")); appPath += "/Library/Application Support/"; diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/login_main.xml b/code/ryzom/client/data/gamedev/interfaces_v3/login_main.xml index 432bb998b..f74967f41 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/login_main.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/login_main.xml @@ -303,7 +303,7 @@ on_enter="leave_modal" options="no_bordure" mouse_pos="false" exit_key_pushed="t fontsize="12" shadow="true" hardtext="uiOnChecking" /> + fontsize="12" shadow="true" multi_line="true" multi_line_space="0" case_mode="%case_normal"/> @@ -419,7 +419,7 @@ on_enter="leave_modal" options="no_bordure" mouse_pos="false" exit_key_pushed="t + fontsize="12" shadow="true" multi_line="true" multi_line_space="0" case_mode="%case_normal"/> @@ -572,7 +572,7 @@ on_enter="leave_modal" options="no_bordure" mouse_pos="false" exit_key_pushed="t + fontsize="12" shadow="true" multi_line="true" multi_line_space="0" case_mode="%case_normal"/> diff --git a/code/ryzom/client/src/CMakeLists.txt b/code/ryzom/client/src/CMakeLists.txt index 035445faf..4f91cfed8 100644 --- a/code/ryzom/client/src/CMakeLists.txt +++ b/code/ryzom/client/src/CMakeLists.txt @@ -160,8 +160,6 @@ IF(WITH_RYZOM_CLIENT) ${CURL_LIBRARIES} ) - ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) - IF(NOT APPLE AND NOT WIN32) TARGET_LINK_LIBRARIES(ryzom_client ${X11_LIBRARIES}) ENDIF() diff --git a/code/ryzom/client/src/client.cpp b/code/ryzom/client/src/client.cpp index 641305d0c..e899771b2 100644 --- a/code/ryzom/client/src/client.cpp +++ b/code/ryzom/client/src/client.cpp @@ -205,7 +205,7 @@ int main(int argc, char **argv) LoginShardId = std::numeric_limits::max(); // if client_default.cfg is not in current directory, use application default directory - if (!CFile::isExists("client_default.cfg")) + if (Args.haveArg("c") || !CFile::isExists("client_default.cfg")) { std::string currentPath = CPath::getApplicationDirectory("Ryzom"); diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 007157d9a..ac5314ac4 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -25,6 +25,7 @@ #include "nel/misc/config_file.h" #include "nel/misc/bit_mem_stream.h" #include "nel/misc/i18n.h" +#include "nel/misc/cmd_args.h" // Client. #include "client_cfg.h" #include "entities.h" @@ -256,6 +257,8 @@ extern string Cookie; extern string FSAddr; #endif +extern NLMISC::CCmdArgs Args; + ///////////// // METHODS // ///////////// @@ -2202,24 +2205,26 @@ bool CClientConfig::getDefaultConfigLocation(std::string& p_name) const #ifdef NL_OS_MAC // on mac, client_default.cfg should be searched in .app/Contents/Resources/ - defaultConfigPath = CPath::standardizePath(getAppBundlePath() + "/Contents/Resources/"); -#elif defined(NL_OS_UNIX) - // if RYZOM_ETC_PREFIX is defined, client_default.cfg might be over there - defaultConfigPath = CPath::standardizePath(getRyzomEtcPrefix()); + defaultConfigPath = getAppBundlePath() + "/Contents/Resources/"; #else - // some other prefix here :) -#endif // NL_OS_UNIX + // unders Windows or Linux, search client_default.cfg is same directory as executable + defaultConfigPath = Args.getProgramPath(); +#endif // look in the current working directory first if (CFile::isExists(defaultConfigFileName)) p_name = defaultConfigFileName; - // if not in working directory, check using prefix path + // look in startup directory + else if (CFile::isExists(Args.getStartupPath() + defaultConfigFileName)) + p_name = Args.getStartupPath() + defaultConfigFileName; + + // look in prefix path else if (CFile::isExists(defaultConfigPath + defaultConfigFileName)) p_name = defaultConfigPath + defaultConfigFileName; // if some client_default.cfg was found return true - if(p_name.size()) + if (p_name.size()) return true; return false; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 828506c2d..c0df71a43 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -661,6 +661,9 @@ static void addPaths(IProgressCallback &progress, const std::vector // current directory has priority everywhere directoryPrefixes.push_back(CPath::standardizePath(CPath::getCurrentPath())); + // startup directory + directoryPrefixes.push_back(Args.getStartupPath()); + #if defined(NL_OS_WINDOWS) // check in same directory as executable directoryPrefixes.push_back(Args.getProgramPath()); diff --git a/code/ryzom/client/src/interface_v3/action_handler_base.cpp b/code/ryzom/client/src/interface_v3/action_handler_base.cpp index f44dc986b..fcb66b1bc 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_base.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_base.cpp @@ -311,8 +311,7 @@ class CAHMilkoMenuDoResetInterface : public IActionHandler virtual void execute (CCtrlBase * /* pCaller */, const string& Params) { // get param - string mode; - fromString(getParam(Params, "mode"), mode); + string mode = getParam(Params, "mode"); // run procedure vector v; diff --git a/code/ryzom/client/src/login.cpp b/code/ryzom/client/src/login.cpp index 72d59e61f..b4dc7ff42 100644 --- a/code/ryzom/client/src/login.cpp +++ b/code/ryzom/client/src/login.cpp @@ -2192,7 +2192,6 @@ void initDataScan() pPM->startScanDataThread(); NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SCREEN")->setValue32(UI_VARIABLES_SCREEN_DATASCAN); NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DATASCAN_RUNNING")->setValue32(1); - } // *************************************************************************** diff --git a/code/ryzom/client/src/login_patch.cpp b/code/ryzom/client/src/login_patch.cpp index c8be10781..0c4abc207 100644 --- a/code/ryzom/client/src/login_patch.cpp +++ b/code/ryzom/client/src/login_patch.cpp @@ -892,6 +892,13 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool #ifdef NL_OS_WINDOWS fprintf(fp, "start \"\" \"%s\" %%1 %%2 %%3\n", CPath::standardizeDosPath(RyzomFilename).c_str()); #else + // wait until client is not in memory + fprintf(fp, "until ! pgrep %s > /dev/null; do sleep 1; done\n", CFile::getFilename(RyzomFilename).c_str()); + + // be sure file is executable + fprintf(fp, "chmod +x \"%s\"\n", RyzomFilename.c_str()); + + // launch new client fprintf(fp, "\"%s\" $1 $2 $3\n", RyzomFilename.c_str()); #endif } @@ -945,11 +952,7 @@ void CPatchManager::executeBatchFile() arguments += " " + toString(LoginShardId); } - if (launchProgram(batchFilename, arguments, false)) - { - exit(0); - } - else + if (!launchProgram(batchFilename, arguments, false)) { // error occurs during the launch string str = toString("Can't execute '%s': code=%d %s (error code 30)", batchFilename.c_str(), errno, strerror(errno)); @@ -1015,12 +1018,12 @@ float CPatchManager::getCurrentFileProgress() const // **************************************************************************** void CPatchManager::setRWAccess (const string &filename, bool bThrowException) { - ucstring s = CI18N::get("uiSetAttrib") + " " + filename; + ucstring s = CI18N::get("uiSetAttrib") + " " + CFile::getFilename(filename); setState(true, s); if (!NLMISC::CFile::setRWAccess(filename) && bThrowException) { - s = CI18N::get("uiAttribErr") + " " + filename + " (" + toString(errno) + "," + strerror(errno) + ")"; + s = CI18N::get("uiAttribErr") + " " + CFile::getFilename(filename) + " (" + toString(errno) + "," + strerror(errno) + ")"; setState(true, s); throw Exception (s.toString()); } @@ -1029,7 +1032,7 @@ void CPatchManager::setRWAccess (const string &filename, bool bThrowException) // **************************************************************************** string CPatchManager::deleteFile (const string &filename, bool bThrowException, bool bWarning) { - ucstring s = CI18N::get("uiDelFile") + " " + filename; + ucstring s = CI18N::get("uiDelFile") + " " + CFile::getFilename(filename); setState(true, s); if (!NLMISC::CFile::fileExists(filename)) @@ -1041,7 +1044,7 @@ string CPatchManager::deleteFile (const string &filename, bool bThrowException, if (!NLMISC::CFile::deleteFile(filename)) { - s = CI18N::get("uiDelErr") + " " + filename + " (" + toString(errno) + "," + strerror(errno) + ")"; + s = CI18N::get("uiDelErr") + " " + CFile::getFilename(filename) + " (" + toString(errno) + "," + strerror(errno) + ")"; if(bWarning) setState(true, s); if(bThrowException) @@ -1269,7 +1272,7 @@ void CPatchManager::downloadFileWithCurl (const string &source, const string &de try { #ifdef USE_CURL - ucstring s = CI18N::get("uiDLWithCurl") + " " + dest; + ucstring s = CI18N::get("uiDLWithCurl") + " " + CFile::getFilename(dest); setState(true, s); // user agent = nel_launcher @@ -1776,10 +1779,19 @@ int CPatchManager::downloadProgressFunc(void *foo, double t, double d, double ul // **************************************************************************** int CPatchManager::validateProgress(void *foo, double t, double d, double /* ultotal */, double /* ulnow */) { + static std::vector units; + + if (units.empty()) + { + units.push_back("B"); // there is no translation for byte unit... + units.push_back(CI18N::get("uiKb").toUtf8()); + units.push_back(CI18N::get("uiMb").toUtf8()); + } + CPatchManager *pPM = CPatchManager::getInstance(); double pour1 = t!=0.0?d*100.0/t:0.0; - ucstring sTranslate = CI18N::get("uiLoginGetFile") + toString(" %s : %s / %s (%5.02f %%)", NLMISC::CFile::getFilename(pPM->CurrentFile).c_str(), - NLMISC::bytesToHumanReadable((uint64)d).c_str(), NLMISC::bytesToHumanReadable((uint64)t).c_str(), pour1); + ucstring sTranslate = CI18N::get("uiLoginGetFile") + ucstring::makeFromUtf8(toString(" %s : %s / %s (%5.02f %%)", NLMISC::CFile::getFilename(pPM->CurrentFile).c_str(), + NLMISC::bytesToHumanReadableUnits((uint64)d, units).c_str(), NLMISC::bytesToHumanReadableUnits((uint64)t, units).c_str(), pour1)); pPM->setState(false, sTranslate); if (foo) { @@ -2791,49 +2803,8 @@ void CPatchThread::xDeltaPatch(const string &patch, const string &src, const str // Launching xdelta /* - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory( &si, sizeof(si) ); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - si.cb = sizeof(si); - - ZeroMemory( &pi, sizeof(pi) ); - // Start the child process. string strCmdLine = "xdelta patch " + patch + " " + src + " " + out; - - if( !CreateProcess( NULL, // No module name (use command line). - (char*)strCmdLine.c_str(), // Command line. - NULL, // Process handle not inheritable. - NULL, // Thread handle not inheritable. - FALSE, // Set handle inheritance to FALSE. - 0, // No creation flags. - NULL, // Use parent's environment block. - NULL, // Use parent's starting directory. - &si, // Pointer to STARTUPINFO structure. - &pi ) // Pointer to PROCESS_INFORMATION structure. - ) - { - // error occurs during the launch - string str = toString("Can't execute '%s'", strCmdLine.c_str()); - throw Exception (str); - } - - // Wait for the process to terminate - DWORD dwTimeout = 1000 * 300; // 5 min = 300 s - DWORD nRetWait = WaitForSingleObject(pi.hProcess, dwTimeout); - - if (nRetWait == WAIT_TIMEOUT) - { - string str = toString("Time Out After %d s", dwTimeout/1000); - throw Exception (str); - } - - // Close process and thread handles. - CloseHandle( pi.hProcess ); - CloseHandle( pi.hThread ); */ } @@ -3170,44 +3141,13 @@ bool CPatchManager::extract(const std::string& patchPath, stopFun(); } -#ifdef NL_OS_WINDOWS - // normal quit - // Launch the batch file - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory( &si, sizeof(si) ); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; // SW_SHOW - - si.cb = sizeof(si); - - ZeroMemory( &pi, sizeof(pi) ); - - // Start the child process. - string strCmdLine; - strCmdLine = updateBatchFilename; - //onFileInstallFinished(); - - if( !CreateProcess( NULL, // No module name (use command line). - (LPSTR)strCmdLine.c_str(), // Command line. - NULL, // Process handle not inheritable. - NULL, // Thread handle not inheritable. - FALSE, // Set handle inheritance to FALSE. - 0, // No creation flags. - NULL, // Use parent's environment block. - NULL, // Use parent's starting directory. - &si, // Pointer to STARTUPINFO structure. - &pi ) // Pointer to PROCESS_INFORMATION structure. - ) + if (!launchProgram(updateBatchFilename, "", false)) { // error occurs during the launch string str = toString("Can't execute '%s': code=%d %s (error code 30)", updateBatchFilename.c_str(), errno, strerror(errno)); throw Exception (str); } -#else - // TODO for Linux and Mac OS -#endif + return true; } @@ -3497,4 +3437,3 @@ void CInstallThread::run() pPM->reboot(); // do not reboot just run the extract .bat } -