/* PIP - Platform Independent Primitives Initialization Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "piinit.h" #include "piincludes_p.h" #ifndef MICRO_PIP # include "pidir.h" # include "piobject.h" # include "piprocess.h" # include "piresourcesstorage.h" # include "pisignals.h" # include "pisysteminfo.h" # include "pitime.h" # ifdef ESP_PLATFORM # include "esp_system.h" # endif # ifdef WINDOWS # include extern FILETIME __pi_ftjan1970; extern PINtQueryTimerResolution getTimerResolutionAddr; extern PINtSetTimerResolution setTimerResolutionAddr; void __PISetTimerResolution() { if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL) return; ULONG _max(0), _min(0), _cur(0); // printf("getTimerResolution ...\n"); LONG q = getTimerResolutionAddr(&_max, &_min, &_cur); // printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur); if (q == 0) setTimerResolutionAddr(_min, TRUE, &_cur); // printf("setTimerResolution %lu\n", cur); } # else # include # include # include # ifdef BLACKBERRY # include # else # include # endif # endif # ifdef MAC_OS # include # include # include extern clock_serv_t __pi_mac_clock; # endif # ifdef PIP_ICU # define U_NOEXCEPT # include # include # endif # ifdef HAS_LOCALE static locale_t currentLocale_t = 0; # endif PRIVATE_DEFINITION_START(PIInit) # ifdef WINDOWS HMODULE ntlib; ULONG prev_res; # endif bool delete_locs; PRIVATE_DEFINITION_END(PIInit) void __sighandler__(PISignals::Signal s) { // piCout << Hex << int(s); if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) piMSleep(10); if (s == PISignals::UserDefined1) dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID())); } PIInit::PIInit() { PISystemInfo * sinfo = PISystemInfo::instance(); sinfo->execDateTime = PIDateTime::current(); # ifndef ANDROID PISignals::setSlot(__sighandler__); PISignals::grabSignals(PISignals::UserDefined1); # ifndef WINDOWS PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput); sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); sigprocmask(SIG_BLOCK, &ss, 0); pthread_sigmask(SIG_BLOCK, &ss, 0); signal(SIGPIPE, SIG_IGN); PIStringList ifpathes; ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig") << PIStringAscii("/usr/bin/ifconfig") << PIStringAscii("/usr/sbin/ifconfig"); for (const auto & i: ifpathes) { if (fileExists(i)) { sinfo->ifconfigPath = i; break; } } # else // WINDOWS // OS version DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion); // WinSock inint WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // Timers init SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0}; SystemTimeToFileTime(&jan1970, &__pi_ftjan1970); LARGE_INTEGER pf; pf.QuadPart = -1; if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart; if (__pi_perf_freq == 0) __pi_perf_freq = -1; // Sleep precision init PRIVATE->ntlib = LoadLibraryA("ntdll.dll"); if (PRIVATE->ntlib) { getTimerResolutionAddr = (PINtQueryTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtQueryTimerResolution"); setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution"); __PISetTimerResolution(); } # endif // WINDOWS # ifdef HAS_LOCALE // std::cout << "has locale" << std::endl; if (currentLocale_t != 0) { freelocale(currentLocale_t); currentLocale_t = 0; } currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, "C"), 0); setlocale(LC_CTYPE, "en_US.UTF-8"); # else // HAS_LOCALE setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); # endif // HAS_LOCALE # endif // ANDROID PRIVATE->delete_locs = false; __syslocname__ = __sysoemname__ = 0; __utf8name__ = const_cast("UTF-8"); # ifdef PIP_ICU UErrorCode e((UErrorCode)0); u_init(&e); # ifdef WINDOWS PRIVATE->delete_locs = true; CPINFOEX cpinfo; int l = 0; GetCPInfoEx(CP_OEMCP, 0, &cpinfo); for (l = 0; l < MAX_PATH; ++l) if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') break; __sysoemname__ = new char[256]; piZeroMemory(__sysoemname__, 256); memcpy(__sysoemname__, "ibm-", 4); memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l); # else /*PIString en(getenv("LANG")); if (!en.isEmpty()) en = en.mid(en.find(".") + 1); PIByteArray enba = en.toByteArray(); memcpy(__syslocname__, enba.data(), enba.size_s());*/ # endif // piCout << __syslocname__; // piCout << __sysoemname__; # else // PIP_ICU # ifdef WINDOWS __syslocname__ = (char *)CP_ACP; __sysoemname__ = (char *)CP_OEMCP; __utf8name__ = (char *)CP_UTF8; # endif # endif // PIP_ICU # ifdef MAC_OS host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); # endif char cbuff[1024]; piZeroMemory(cbuff, 1024); if (gethostname(cbuff, 1023) == 0) { sinfo->hostname = cbuff; } # ifdef WINDOWS SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); sinfo->processorsCount = sysinfo.dwNumberOfProcessors; switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: sinfo->architecture = PIStringAscii("x86_64"); break; case PROCESSOR_ARCHITECTURE_ARM: sinfo->architecture = PIStringAscii("arm"); break; case PROCESSOR_ARCHITECTURE_IA64: sinfo->architecture = PIStringAscii("Intel Itanium-based"); break; case PROCESSOR_ARCHITECTURE_INTEL: sinfo->architecture = PIStringAscii("x86"); break; case PROCESSOR_ARCHITECTURE_UNKNOWN: default: sinfo->architecture = PIStringAscii("unknown"); break; } int argc_(0); wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_); if (argc_ > 0 && argv_ != 0) sinfo->execCommand = argv_[0]; LocalFree(argv_); piZeroMemory(cbuff, 1024); ulong unlen = 1023; if (GetUserNameA(cbuff, &unlen) != 0) sinfo->user = cbuff; # else // WINDOWS sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN))); passwd * ps = getpwuid(getuid()); if (ps) sinfo->user = ps->pw_name; else { piZeroMemory(cbuff, 1024); char * l = getlogin(); if (l) sinfo->user = l; } struct utsname uns; if (uname(&uns) == 0) { sinfo->OS_version = uns.release; sinfo->architecture = uns.machine; } # endif // WINDOWS # ifdef ESP_PLATFORM esp_chip_info_t chip_info; esp_chip_info(&chip_info); sinfo->processorsCount = chip_info.cores; sinfo->architecture = "Xtensa LX6"; // printf("silicon revision %d, ", chip_info.revision); sinfo->OS_version = esp_get_idf_version(); # endif sinfo->OS_name = # ifdef WINDOWS PIStringAscii("Windows"); # elif defined(QNX) PIStringAscii("QNX"); # elif defined(MAC_OS) PIStringAscii("MacOS"); # elif defined(ANDROID) PIStringAscii("Android"); # elif defined(FREE_BSD) PIStringAscii("FreeBSD"); # elif defined(FREERTOS) PIStringAscii("FreeRTOS"); # elif defined(MICRO_PIP) PIStringAscii("MicroPIP"); # else uns.sysname; # endif } PIInit::~PIInit() { PIResourcesStorage::instance()->clear(); # ifdef WINDOWS WSACleanup(); if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib); PRIVATE->ntlib = 0; # endif # ifdef MAC_OS mach_port_deallocate(mach_task_self(), __pi_mac_clock); # endif if (PRIVATE->delete_locs) { if (__syslocname__) delete __syslocname__; if (__sysoemname__) delete __sysoemname__; } # ifdef PIP_ICU u_cleanup(); # endif } bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) { switch (o) { case boICU: return # ifdef PIP_ICU true; # else false; # endif case boUSB: return # ifdef PIP_USB true; # else false; # endif case boCrypt: return # ifdef PIP_CRYPT true; # else false; # endif case boIntrospection: return # ifdef PIP_INTROSPECTION true; # else false; # endif case boFFTW: return # ifdef PIP_FFTW true; # else false; # endif case boCompress: return # ifdef PIP_COMPRESS true; # else false; # endif case boOpenCL: return # ifdef PIP_OPENCL true; # else false; # endif case boCloud: return # ifdef PIP_CLOUD true; # else false; # endif case boConsole: return # ifdef PIP_CONSOLE true; # else false; # endif default: return false; } return false; } PIStringList PIInit::buildOptions() { PIStringList ret; if (isBuildOptionEnabled(boICU)) ret << "ICU"; if (isBuildOptionEnabled(boUSB)) ret << "USB"; if (isBuildOptionEnabled(boCrypt)) ret << "Crypt"; if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection"; if (isBuildOptionEnabled(boFFTW)) ret << "FFTW"; if (isBuildOptionEnabled(boCompress)) ret << "Compress"; if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL"; if (isBuildOptionEnabled(boCloud)) ret << "Cloud"; if (isBuildOptionEnabled(boConsole)) ret << "Console"; return ret; } bool PIInit::fileExists(const PIString & p) { FILE * f = fopen(p.data(), "r"); if (f == 0) return false; fclose(f); return true; } int __PIInit_Initializer__::count_(0); PIInit * __PIInit_Initializer__::__instance__(0); __PIInit_Initializer__::__PIInit_Initializer__() { count_++; if (count_ > 1) return; // piCout << "create PIInit"; __instance__ = new PIInit(); } __PIInit_Initializer__::~__PIInit_Initializer__() { count_--; if (count_ > 0) return; // piCout << "delete PIInit"; if (__instance__ != 0) { delete __instance__; __instance__ = 0; } } #endif // MICRO_PIP