446 lines
11 KiB
C++
446 lines
11 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Initialization
|
|
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piincludes_p.h"
|
|
#include "piinit.h"
|
|
#include "pitime.h"
|
|
#include "pisignals.h"
|
|
#include "piobject.h"
|
|
#include "pisysteminfo.h"
|
|
#include "piresourcesstorage.h"
|
|
#include "pidir.h"
|
|
#ifndef FREERTOS
|
|
# include "piprocess.h"
|
|
#endif
|
|
#ifdef ESP_PLATFORM
|
|
# include "esp_system.h"
|
|
#endif
|
|
#ifdef WINDOWS
|
|
# include <winsock2.h>
|
|
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 <pwd.h>
|
|
# ifndef FREERTOS
|
|
# include <sys/utsname.h>
|
|
# endif
|
|
# include <pthread.h>
|
|
# ifdef BLACKBERRY
|
|
# include <signal.h>
|
|
# else
|
|
# include <csignal>
|
|
# endif
|
|
#endif
|
|
#ifdef MAC_OS
|
|
# include <mach/mach_traps.h>
|
|
# include <mach/mach.h>
|
|
# include <mach/clock.h>
|
|
//# include <crt_externs.h>
|
|
extern clock_serv_t __pi_mac_clock;
|
|
#endif
|
|
#ifdef PIP_ICU
|
|
# define U_NOEXCEPT
|
|
# include <unicode/uclean.h>
|
|
# include <unicode/ucnv.h>
|
|
#endif
|
|
/*
|
|
#ifdef WINDOWS
|
|
# include <conio.h>
|
|
# include <io.h>
|
|
# include <windows.h>
|
|
# include <wincon.h>
|
|
#else
|
|
# include <fcntl.h>
|
|
# include <sys/ioctl.h>
|
|
# include <pthread.h>
|
|
#endif*/
|
|
|
|
|
|
#ifdef HAS_LOCALE
|
|
static locale_t currentLocale_t = 0;
|
|
#endif
|
|
|
|
PRIVATE_DEFINITION_START(PIInit)
|
|
#ifdef WINDOWS
|
|
HMODULE ntlib;
|
|
ULONG prev_res;
|
|
#endif
|
|
PRIVATE_DEFINITION_END(PIInit)
|
|
|
|
#ifndef FREERTOS
|
|
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()));
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef ANDROID
|
|
void android_thread_exit_handler(int sig) {
|
|
pthread_exit(0);
|
|
}
|
|
#endif
|
|
|
|
|
|
PIInit::PIInit() {
|
|
file_charset = 0;
|
|
PISystemInfo * sinfo = PISystemInfo::instance();
|
|
sinfo->execDateTime = PIDateTime::current();
|
|
setFileCharset("UTF-8");
|
|
#ifndef FREERTOS
|
|
#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");
|
|
piForeachC (PIString & i, ifpathes)
|
|
if (fileExists(i)) {
|
|
sinfo->ifconfigPath = i;
|
|
piBreak;
|
|
}
|
|
# else
|
|
// 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 = LoadLibrary("ntdll.dll");
|
|
if (PRIVATE->ntlib) {
|
|
getTimerResolutionAddr = (PINtQueryTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtQueryTimerResolution");
|
|
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
|
|
__PISetTimerResolution();
|
|
}
|
|
/*if (setTimerResolution) setTimerResolutionAddr(1, TRUE, &(PRIVATE->prev_res));*/
|
|
# endif
|
|
//piDebug = true;
|
|
# ifdef HAS_LOCALE
|
|
//cout << "has locale" << endl;
|
|
if (currentLocale_t != 0) {
|
|
freelocale(currentLocale_t);
|
|
currentLocale_t = 0;
|
|
}
|
|
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
|
|
# else
|
|
setlocale(LC_ALL, "");
|
|
setlocale(LC_NUMERIC, "C");
|
|
# endif
|
|
#else
|
|
struct sigaction actions;
|
|
memset(&actions, 0, sizeof(actions));
|
|
sigemptyset(&actions.sa_mask);
|
|
actions.sa_flags = 0;
|
|
actions.sa_handler = android_thread_exit_handler;
|
|
sigaction(SIGTERM, &actions, 0);
|
|
#endif
|
|
#ifdef PIP_ICU
|
|
__syslocname__ = __sysoemname__ = 0;
|
|
//__syslocname__ = new char[256];
|
|
//memset(__syslocname__, 0, 256);
|
|
UErrorCode e((UErrorCode)0);
|
|
u_init(&e);
|
|
# ifdef WINDOWS
|
|
CPINFOEX cpinfo;
|
|
int l = 0;
|
|
/*GetCPInfoEx(CP_ACP, 0, &cpinfo);
|
|
for (l = 0; l < MAX_PATH; ++l)
|
|
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ')
|
|
break;
|
|
memcpy(__syslocname__, "windows-", 8);
|
|
memcpy(&(__syslocname__[8]), cpinfo.CodePageName, l);*/
|
|
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];
|
|
memset(__sysoemname__, 0, 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__;
|
|
#endif
|
|
#ifdef MAC_OS
|
|
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
|
|
#endif
|
|
char cbuff[1024];
|
|
memset(cbuff, 0, 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_);
|
|
memset(cbuff, 0, 1024);
|
|
ulong unlen = 1023;
|
|
if (GetUserName(cbuff, &unlen) != 0)
|
|
sinfo->user = cbuff;
|
|
#else
|
|
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
|
|
passwd * ps = getpwuid(getuid());
|
|
if (ps)
|
|
sinfo->user = ps->pw_name;
|
|
else {
|
|
memset(cbuff, 0, 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
|
|
#endif
|
|
#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");
|
|
#else
|
|
# ifdef QNX
|
|
PIStringAscii("QNX");
|
|
# else
|
|
# ifdef MAC_OS
|
|
PIStringAscii("MacOS");
|
|
# else
|
|
# ifdef ANDROID
|
|
PIStringAscii("Android");
|
|
# else
|
|
# ifdef FREE_BSD
|
|
PIStringAscii("FreeBSD");
|
|
# else
|
|
# ifdef FREERTOS
|
|
PIStringAscii("FreeRTOS");
|
|
# else
|
|
uns.sysname;
|
|
# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
#endif
|
|
}
|
|
|
|
|
|
PIInit::~PIInit() {
|
|
if (file_charset) delete file_charset;
|
|
file_charset = 0;
|
|
PIResourcesStorage::instance()->clear();
|
|
#ifdef WINDOWS
|
|
WSACleanup();
|
|
//if (setTimerResolution) setTimerResolutionAddr(PRIVATE->prev_res, TRUE, &(PRIVATE->prev_res));
|
|
if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib);
|
|
PRIVATE->ntlib = 0;
|
|
#endif
|
|
#ifdef MAC_OS
|
|
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
|
|
#endif
|
|
#ifdef PIP_ICU
|
|
if (__syslocname__) delete __syslocname__;
|
|
if (__sysoemname__) delete __sysoemname__;
|
|
u_cleanup();
|
|
#endif
|
|
//if (currentLocale_t != 0) freelocale(currentLocale_t);
|
|
}
|
|
|
|
|
|
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
|
|
switch (o) {
|
|
case ICU: return
|
|
#ifdef PIP_ICU
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case USB: return
|
|
#ifdef PIP_USB
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case STL: return
|
|
#ifdef PIP_CONTAINERS_STL
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case Crypt: return
|
|
#ifdef PIP_CRYPT
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case IntrospectionContainers: return
|
|
#ifdef PIP_INTROSPECTION_CONTAINERS
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case IntrospectionThreads: return
|
|
#ifdef PIP_INTROSPECTION_THREADS
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case FFTW: return
|
|
#ifdef PIP_FFTW
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case Compress: return
|
|
#ifdef PIP_COMPRESS
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
case OpenCL: return
|
|
#ifdef PIP_OPENCL
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
default: return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
PIStringList PIInit::buildOptions() {
|
|
PIStringList ret;
|
|
if (isBuildOptionEnabled(ICU)) ret << "ICU";
|
|
if (isBuildOptionEnabled(USB)) ret << "USB";
|
|
if (isBuildOptionEnabled(STL)) ret << "STL";
|
|
if (isBuildOptionEnabled(Crypt)) ret << "Crypt";
|
|
if (isBuildOptionEnabled(IntrospectionContainers)) ret << "IntrospectionContainers";
|
|
if (isBuildOptionEnabled(IntrospectionThreads)) ret << "IntrospectionThreads";
|
|
if (isBuildOptionEnabled(FFTW)) ret << "FFTW";
|
|
if (isBuildOptionEnabled(Compress)) ret << "Compress";
|
|
if (isBuildOptionEnabled(OpenCL)) ret << "OpenCL";
|
|
return ret;
|
|
}
|
|
|
|
|
|
void PIInit::setFileCharset(const char *charset) {
|
|
if (file_charset) delete file_charset;
|
|
file_charset = 0;
|
|
if (charset) {
|
|
file_charset = new char[1024];
|
|
memset(file_charset, 0, 1024);
|
|
strcpy(file_charset, charset);
|
|
}
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
}
|