| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <log4cxx/logstring.h> |
| #include <log4cxx/helpers/system.h> |
| #include <log4cxx/helpers/filesystempath.h> |
| |
| #include <log4cxx/helpers/transcoder.h> |
| #include <log4cxx/helpers/pool.h> |
| #include <log4cxx/helpers/properties.h> |
| #include <log4cxx/helpers/loglog.h> |
| #include <log4cxx/helpers/stringhelper.h> |
| #include <apr_file_io.h> |
| #include <apr_user.h> |
| #include <apr_env.h> |
| |
| #ifdef _WIN32 |
| #include <windows.h> |
| #elif __APPLE__ |
| #include <mach-o/dyld.h> |
| #elif (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) |
| #include <unistd.h> // getpid |
| #endif |
| #include <sstream> |
| |
| using namespace LOG4CXX_NS; |
| using namespace LOG4CXX_NS::helpers; |
| |
| |
| LogString System::getProperty(const LogString& lkey) |
| { |
| if (lkey.empty()) |
| { |
| throw IllegalArgumentException(LOG4CXX_STR("key is empty")); |
| } |
| |
| LogString rv; |
| |
| if (lkey == LOG4CXX_STR("java.io.tmpdir")) |
| { |
| Pool p; |
| const char* dir = NULL; |
| apr_status_t stat = apr_temp_dir_get(&dir, p.getAPRPool()); |
| |
| if (stat == APR_SUCCESS) |
| { |
| Transcoder::decode(dir, rv); |
| } |
| |
| return rv; |
| } |
| |
| if (lkey == LOG4CXX_STR("user.dir")) |
| { |
| Pool p; |
| char* dir = NULL; |
| apr_status_t stat = apr_filepath_get(&dir, APR_FILEPATH_NATIVE, |
| p.getAPRPool()); |
| |
| if (stat == APR_SUCCESS) |
| { |
| Transcoder::decode(dir, rv); |
| } |
| |
| return rv; |
| } |
| |
| #if APR_HAS_USER |
| |
| if (lkey == LOG4CXX_STR("user.home") || lkey == LOG4CXX_STR("user.name")) |
| { |
| Pool pool; |
| apr_uid_t userid; |
| apr_gid_t groupid; |
| apr_pool_t* p = pool.getAPRPool(); |
| apr_status_t stat = apr_uid_current(&userid, &groupid, p); |
| |
| if (stat == APR_SUCCESS) |
| { |
| char* username = NULL; |
| stat = apr_uid_name_get(&username, userid, p); |
| |
| if (stat == APR_SUCCESS) |
| { |
| if (lkey == LOG4CXX_STR("user.name")) |
| { |
| Transcoder::decode(username, rv); |
| } |
| else |
| { |
| char* dirname = NULL; |
| stat = apr_uid_homepath_get(&dirname, username, p); |
| |
| if (stat == APR_SUCCESS) |
| { |
| Transcoder::decode(dirname, rv); |
| } |
| } |
| } |
| } |
| |
| return rv; |
| } |
| |
| #endif |
| |
| LOG4CXX_ENCODE_CHAR(key, lkey); |
| Pool p; |
| char* value = NULL; |
| apr_status_t stat = apr_env_get(&value, key.c_str(), |
| p.getAPRPool()); |
| |
| if (stat == APR_SUCCESS) |
| { |
| Transcoder::decode((const char*) value, rv); |
| } |
| |
| return rv; |
| } |
| |
| void System::addProgramFilePathComponents(Properties& props) |
| { |
| // Find the executable file name |
| static const int bufSize = 4096; |
| char buf[bufSize+1] = {0}, pathSepar = '/'; |
| #if defined(_WIN32) |
| if (0 == GetModuleFileName(NULL, buf, bufSize)) |
| { |
| Pool p; |
| LogString lsErrorCode; |
| StringHelper::toString((int)GetLastError(), p, lsErrorCode); |
| LogLog::warn(LOG4CXX_STR("GetModuleFileName error ") + lsErrorCode); |
| return; |
| } |
| pathSepar = '\\'; |
| #elif defined(__APPLE__) |
| uint32_t bufCount = bufSize; |
| if (0 != _NSGetExecutablePath(buf, &bufCount)) |
| { |
| LogLog::warn(LOG4CXX_STR("_NSGetExecutablePath failed")); |
| return; |
| } |
| #elif (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) |
| int bufCount = 0; |
| std::ostringstream exeLink; |
| exeLink << "/proc/" << getpid() << "/exe"; |
| if ((bufCount = readlink(exeLink.str().c_str(), buf, bufSize)) <= 0) |
| { |
| LOG4CXX_DECODE_CHAR(lsExeLink, exeLink.str()); |
| LogLog::warn(LOG4CXX_STR("Failed to read ") + lsExeLink); |
| return; |
| } |
| if (bufSize < bufCount) |
| buf[bufSize] = 0; |
| else |
| buf[bufCount] = 0; |
| #else |
| LogLog::warn(LOG4CXX_STR("Unable to determine the name of the executable file on this system")); |
| return; |
| #endif |
| |
| // Add the path to the properties |
| std::string programFileName(buf); |
| if (programFileName.empty()) |
| { |
| LogLog::warn(LOG4CXX_STR("Current executable's file name is empty")); |
| return; |
| } |
| |
| LOG4CXX_DECODE_CHAR(lsProgramFileName, programFileName); |
| LogString prefix{ LOG4CXX_STR("PROGRAM_FILE_PATH") }; |
| props.setProperty(prefix, lsProgramFileName); |
| |
| #if LOG4CXX_HAS_FILESYSTEM_PATH |
| // Add the path components to the properties |
| prefix += '.'; |
| FilesystemPath programPath(programFileName); |
| #if LOG4CXX_LOGCHAR_IS_WCHAR |
| auto root_name = programPath.root_name().wstring(); |
| if (!root_name.empty()) |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_NAME"), root_name); |
| auto root_directory = programPath.root_directory().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_DIRECTORY"),root_directory); |
| auto root_path = programPath.root_path().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_PATH"), root_path); |
| auto relative_path = programPath.relative_path().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("RELATIVE_PATH"), relative_path); |
| auto parent_path = programPath.parent_path().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("PARENT_PATH"), parent_path); |
| auto filename = programPath.filename().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("FILENAME"), filename); |
| auto stem = programPath.stem().wstring(); |
| props.setProperty(prefix + LOG4CXX_STR("STEM"), stem); |
| auto extension = programPath.extension().wstring(); |
| if (!extension.empty()) |
| props.setProperty(prefix + LOG4CXX_STR("EXTENSION"), extension); |
| #else |
| LOG4CXX_DECODE_CHAR(root_name, programPath.root_name().string()); |
| if (!root_name.empty()) |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_NAME"), root_name); |
| LOG4CXX_DECODE_CHAR(root_directory, programPath.root_directory().string()); |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_DIRECTORY"),root_directory); |
| LOG4CXX_DECODE_CHAR(root_path, programPath.root_path().string()); |
| props.setProperty(prefix + LOG4CXX_STR("ROOT_PATH"), root_path); |
| LOG4CXX_DECODE_CHAR(relative_path, programPath.relative_path().string()); |
| props.setProperty(prefix + LOG4CXX_STR("RELATIVE_PATH"), relative_path); |
| LOG4CXX_DECODE_CHAR(parent_path, programPath.parent_path().string()); |
| props.setProperty(prefix + LOG4CXX_STR("PARENT_PATH"), parent_path); |
| LOG4CXX_DECODE_CHAR(filename, programPath.filename().string()); |
| props.setProperty(prefix + LOG4CXX_STR("FILENAME"), filename); |
| LOG4CXX_DECODE_CHAR(stem, programPath.stem().string()); |
| props.setProperty(prefix + LOG4CXX_STR("STEM"), stem); |
| LOG4CXX_DECODE_CHAR(extension, programPath.extension().string()); |
| if (!extension.empty()) |
| props.setProperty(prefix + LOG4CXX_STR("EXTENSION"), extension); |
| #endif |
| #endif // LOG4CXX_HAS_FILESYSTEM_PATH |
| } |