37 #include <sys/utime.h>
42 #include <sys/select.h>
53 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
58 #include <sys/types.h>
63 #define _access access
78 void my_aux_sighandler(
int) {}
87 tcgetattr(0, &oldtio);
92 tcgetattr(0, &curtio);
93 curtio.c_lflag &= ~(ICANON | ECHO);
94 tcsetattr(0, TCSANOW, &curtio);
96 struct pollfd pfds[1];
100 pfds[0].events = POLLIN;
101 const int ret = poll(pfds, 1, 0);
104 tcsetattr(0, TCSANOW, &oldtio);
124 static std::mutex cs;
125 std::lock_guard<std::mutex> lock(cs);
131 char* org_tz = getenv(
"TZ");
132 if (org_tz)
os::strcpy(tz,
sizeof(tz), org_tz);
152 #endif // HAVE_TIMEGM
157 #include <mrpt/version.h>
169 const char* source_date_epoch = MRPT_SOURCE_DATE_EPOCH;
172 unsigned long epoch = strtoul(source_date_epoch, &endptr, 10);
175 (epoch == std::numeric_limits<unsigned long>::max() || epoch == 0)) ||
176 (errno != 0 && epoch == 0)))
185 struct tm* build_time = gmtime(&
now);
186 const int year = build_time->tm_year + 1900;
187 const int month = build_time->tm_mon + 1;
188 const int day = build_time->tm_mday;
191 "%i-%02i-%02i %02i:%02i:%02i UTC", year, month, day,
192 build_time->tm_hour, build_time->tm_min, build_time->tm_sec);
203 char* buf, [[maybe_unused]]
size_t bufSize,
const char*
format,
210 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
212 result = ::vsprintf_s(buf, bufSize,
format, ap);
226 char* buf, [[maybe_unused]]
size_t bufSize,
const char*
format,
227 va_list args) noexcept
229 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
231 return ::vsprintf_s(buf, bufSize,
format, args);
242 char* buf,
size_t bufSize,
const char*
format, va_list args) noexcept
244 #if defined(_MSC_VER)
245 #if (_MSC_VER >= 1400)
247 return ::vsnprintf_s(buf, bufSize, _TRUNCATE,
format, args);
260 FILE*
os::fopen(
const std::string& fileName,
const char* mode) noexcept
262 return fopen(fileName.c_str(), mode);
268 FILE*
os::fopen(
const char* fileName,
const char* mode) noexcept
270 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
273 if (0 != ::fopen_s(&f, fileName, mode))
288 if (!f)
THROW_EXCEPTION(
"Trying to close a nullptr 'FILE*' descriptor");
296 char* dest, [[maybe_unused]]
size_t destSize,
const char* source) noexcept
298 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
299 ::strcat_s(dest, destSize, source);
310 char* dest, [[maybe_unused]]
size_t destSize,
const char* source) noexcept
312 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
313 ::strcpy_s(dest, destSize, source);
325 return ::strcmp(str1, str2);
334 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
337 return ::strcmpi(str1, str2);
340 return ::strcasecmp(str1, str2);
347 int os::_strncmp(
const char* str1,
const char* str2,
size_t count) noexcept
349 return ::strncmp(str1, str2, count);
355 int os::_strnicmp(
const char* str1,
const char* str2,
size_t count) noexcept
357 #if defined(_MSC_VER)
360 return ::strncasecmp(str1, str2, count);
368 void* dest, [[maybe_unused]]
size_t destSize,
const void* src,
369 size_t copyCount) noexcept
371 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
372 ::memcpy_s(dest, destSize, src, copyCount);
390 tcgetattr(STDIN_FILENO, &oldt);
392 newt.c_lflag &= ~(ICANON | ECHO);
393 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
395 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
406 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
407 return ::_kbhit() != 0;
425 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
427 result = ::vfprintf_s(fil, frm, ap);
431 result = ::vfprintf(fil, frm, ap);
443 std::cout << msg << std::endl;
453 int ret = ::system(
"cls");
455 int ret = ::system(
"clear");
458 cerr <<
"[mrpt::system::clearConsole] Error invoking 'clear screen' "
468 return (int64_t)::strtol(nptr, endptr, base);
470 return (int64_t)::strtoll(nptr, endptr, base);
480 return (uint64_t)::strtoul(nptr, endptr, base);
482 return (uint64_t)::strtoull(nptr, endptr, base);
488 static const int TS_NORMAL = 0;
489 static const int TS_BLUE = 1;
490 static const int TS_GREEN = 2;
491 static const int TS_RED = 4;
493 static int normal_attributes = -1;
495 GetStdHandle(changeStdErr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
496 fflush(changeStdErr ? stderr : stdout);
498 if (normal_attributes < 0)
500 CONSOLE_SCREEN_BUFFER_INFO info;
501 GetConsoleScreenBufferInfo(hstdout, &info);
502 normal_attributes = info.wAttributes;
505 SetConsoleTextAttribute(
508 color == TS_NORMAL ? normal_attributes
509 : ((color & TS_BLUE ? FOREGROUND_BLUE : 0) |
510 (color & TS_GREEN ? FOREGROUND_GREEN : 0) |
511 (color & TS_RED ? FOREGROUND_RED : 0) |
512 FOREGROUND_INTENSITY)));
515 FILE* f = changeStdErr ? stdout : stderr;
516 const int fd = changeStdErr ? STDOUT_FILENO : STDERR_FILENO;
519 if (!isatty(fd))
return;
522 if (color == last_color)
return;
525 static const uint8_t ansi_tab[] = {30, 34, 32, 36, 31, 35, 33, 37};
528 if (color != TS_NORMAL)
529 code = ansi_tab[color & (TS_BLUE | TS_GREEN | TS_RED)];
535 " Mobile Robot Programming Toolkit (MRPT) "
537 " https://www.mrpt.org/ "
542 " Copyright (c) 2005-%Y, Individual contributors, see AUTHORS file "
544 " See: https://www.mrpt.org/Authors - All rights reserved. "
547 " Released under BSD License. See details in https://www.mrpt.org/License "
553 static bool sLicenseTextReady =
false;
554 static std::string sLicenseText;
556 if (!sLicenseTextReady)
563 timeinfo = localtime(&rawtime);
567 sLicenseText = std::string(buf);
568 sLicenseTextReady =
true;
577 DWORD e = GetLastError();
578 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, e, 0, str,
sizeof(str), NULL);
595 PROCESS_INFORMATION PI;
596 memset(&SI, 0,
sizeof(STARTUPINFOA));
597 SI.cb =
sizeof(STARTUPINFOA);
599 NULL, (LPSTR)command.c_str(), NULL, NULL,
true, 0, NULL, NULL, &SI,
603 WaitForSingleObject(PI.hProcess, INFINITE);
614 return 0 == ::system(command.c_str());
620 #include <mrpt/mrpt_paths_config.h>
623 static bool mrpt_shared_first_call =
true;
624 static std::string found_mrpt_shared_dir;
626 if (mrpt_shared_first_call)
628 mrpt_shared_first_call =
false;
630 for (
int attempt = 0;; attempt++)
636 dir = string(MRPT_SOURCE_BASE_DIRECTORY) +
637 string(
"/share/mrpt/");
640 dir = string(MRPT_INSTALL_PREFIX_DIRECTORY) +
641 string(
"/share/mrpt/");
647 GetModuleFileNameA(
nullptr, curExe,
sizeof(curExe));
650 std::string(curExe)) +
657 found_mrpt_shared_dir =
".";
661 found_mrpt_shared_dir =
dir;
663 if (!found_mrpt_shared_dir.empty())
break;
667 return found_mrpt_shared_dir;
671 const std::string& command, std::string* output ,
672 const std::string& mode )
686 if (!(in = popen(command.c_str(), mode.c_str())))
688 sout <<
"Popen Execution failed!" << endl;
689 *output = sout.str();
695 while (fgets(buff,
sizeof(buff), in) !=
nullptr)
701 exit_code = pclose(in);
707 HANDLE g_hChildStd_IN_Rd = NULL;
708 HANDLE g_hChildStd_IN_Wr = NULL;
709 HANDLE g_hChildStd_OUT_Rd = NULL;
710 HANDLE g_hChildStd_OUT_Wr = NULL;
712 HANDLE g_hInputFile = NULL;
713 SECURITY_ATTRIBUTES saAttr;
715 saAttr.nLength =
sizeof(SECURITY_ATTRIBUTES);
716 saAttr.bInheritHandle = TRUE;
717 saAttr.lpSecurityDescriptor = NULL;
719 if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
724 if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
729 if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
734 if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
738 PROCESS_INFORMATION piProcInfo;
739 STARTUPINFOA siStartInfo;
740 BOOL bSuccess = FALSE;
744 ZeroMemory(&piProcInfo,
sizeof(PROCESS_INFORMATION));
750 ZeroMemory(&siStartInfo,
sizeof(STARTUPINFO));
751 siStartInfo.cb =
sizeof(STARTUPINFO);
752 siStartInfo.hStdError = g_hChildStd_OUT_Wr;
753 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
754 siStartInfo.hStdInput = g_hChildStd_IN_Rd;
755 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
758 bSuccess = CreateProcessA(
760 (LPSTR)command.c_str(),
781 DWORD dwAvailable = 0;
783 g_hChildStd_OUT_Rd, NULL, NULL, NULL, &dwAvailable, NULL);
787 g_hChildStd_OUT_Rd, chBuf,
sizeof(chBuf), &dwRead, NULL);
788 if (!bSuccess || dwRead == 0)
break;
789 sout.write(chBuf, dwRead);
794 if (GetExitCodeProcess(piProcInfo.hProcess, &exitval))
796 if (exitval != STILL_ACTIVE)
806 CloseHandle(piProcInfo.hProcess);
807 CloseHandle(piProcInfo.hThread);
809 catch (std::string& errStr)
818 *output = sout.str();
827 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
828 void* handle =
nullptr;
830 #ifdef MRPT_OS_WINDOWS
850 loadedModules_mtx.lock();
851 auto lstCopy = loadedModules;
852 loadedModules_mtx.unlock();
856 catch (
const std::exception& e)
858 std::cerr <<
"[~ModulesRegistry] Exception: "
869 const std::string& moduleFileName,
873 std::lock_guard<std::mutex> lck(md.loadedModules_mtx);
877 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
878 void* handle = dlopen(moduleFileName.c_str(), RTLD_LAZY);
879 #elif defined(MRPT_OS_WINDOWS)
880 HMODULE handle = LoadLibraryA(moduleFileName.c_str());
882 void* handle =
nullptr;
883 sError =
"Unsupported OS";
889 md.loadedModules[moduleFileName].handle = handle;
893 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
895 "Error loading '%s':\n%s\n", moduleFileName.c_str(), dlerror());
896 #elif defined(MRPT_OS_WINDOWS)
898 "Error loading '%s':\nWindows error: %u\n", moduleFileName.c_str(),
903 outErrorMsgs.value().get() += sError;
910 const std::string& moduleFileName,
914 std::lock_guard<std::mutex> lck(md.loadedModules_mtx);
918 const auto it = md.loadedModules.find(moduleFileName);
919 if (it == md.loadedModules.end())
921 sError =
"Module filename '" + moduleFileName +
922 "' not found in previous calls to loadPluginModule().";
926 #if defined(MRPT_OS_LINUX) || defined(MRPT_OS_APPLE)
927 if (0 != dlclose(it->second.handle))
930 "Error unloading '%s':\n%s\n", moduleFileName.c_str(),
933 #elif defined(MRPT_OS_WINDOWS)
934 if (!FreeLibrary(it->second.handle))
937 "Error unloading '%s':\nWindows error: %u\n",
938 moduleFileName.c_str(), GetLastError());
946 outErrorMsgs.value().get() += sError;
953 md.loadedModules.erase(it);
959 const std::string& moduleFileNames,
962 std::vector<std::string> lstModules;
966 for (
const auto& sLib : lstModules)
973 const std::string& moduleFileNames,
976 std::vector<std::string> lstModules;
980 for (
const auto& sLib : lstModules)