9 #define _CRT_SECURE_NO_WARNINGS
19#include <mach/vm_statistics.h>
21#include <mach/host_info.h>
22#include <mach/task_info.h>
23#include <mach/thread_act.h>
24#include <sys/sysctl.h>
31#include <condition_variable>
66 std::map<std::string, utils::Semaphore*>::iterator si;
81 std::map<std::string, utils::Event*>::iterator ei;
96 std::map<std::string, utils::Mutex*>::iterator mi;
145 return "String info";
147 return "Binary info";
149 return "Message info";
151 return "Unknown type";
156 if ((
stricmp(typeName,
"string") == 0) || (
stricmp(typeName,
"text") == 0))
158 else if (
stricmp(typeName,
"time") == 0)
160 else if ((
stricmp(typeName,
"integer") == 0) || (
stricmp(typeName,
"int") == 0))
162 else if ((
stricmp(typeName,
"float") == 0) || (
stricmp(typeName,
"double") == 0))
164 else if (
stricmp(typeName,
"binary") == 0)
166 else if (
stricmp(typeName,
"message") == 0)
168 else if (
stricmp(typeName,
"string info") == 0)
170 else if (
stricmp(typeName,
"binary info") == 0)
172 else if (
stricmp(typeName,
"message info") == 0)
255 return (
char*)
this+
sizeof(
LogEntry);
264 if (avail < (int32)len)
266 memcpy((
char*)
this+
sizeof(
LogEntry), text, len);
267 *((
char*)
this+
sizeof(
LogEntry)+len) = 0;
273 const char* text =
getText(len);
275 "{ \"time\": %llu, \"level\": %u, \"source\": %u, \"subject\": %u, \"type\": %u, \"text\": \"%s\" }",
281 const char* text =
getText(len);
283 "<entry time=\"%llu\" level=\"%u\" source=\"%u\" subject=\"%u\" type=\"%u\" text=\"%s\" />\n",
335 va_start(args, formatstring);
348 entry->
level = level;
359 std::cout << strline;
383 va_start(args, formatstring);
396 entry->
level = level;
417 static int macos_pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *abs_timeout)
427 while ((rv = pthread_mutex_trylock(mutex)) == EBUSY) {
429 gettimeofday(&now, NULL);
430 if (now.tv_sec > abs_timeout->tv_sec ||
431 (now.tv_sec == abs_timeout->tv_sec &&
432 (
long)(now.tv_usec) * 1000L >= abs_timeout->tv_nsec))
434 struct timespec nap = { 0, 1000000 };
435 nanosleep(&nap, NULL);
448 if (gettimeofday(&now, NULL) != 0)
451 timeout.tv_sec = now.tv_sec + (ms / 1000);
452 int64 us = (int64)(now.tv_usec) + ((ms % 1000)*1000);
453 while (us >= 1000000) {
457 timeout.tv_nsec = (long)(us * 1000);
463 if ( gettimeofday(&tv, NULL))
465 return (tv.tv_usec + tv.tv_sec * 1000000LL);
472 VOID CALLBACK
DrumBeatCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) {
473 DrumBeatInfo* info = (DrumBeatInfo*) lpParameter;
475 if (!info->id || !info->createdTime || !info->started || !func)
478 if (!info->func(info->id, info->count))
519 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
520 dispatch_source_t timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
522 info->
handle = timer_source;
525 struct sigevent timer_event;
532 timer_event.sigev_notify = SIGEV_THREAD;
533 timer_event.sigev_notify_attributes = NULL;
535 timer_event.sigev_value.sival_ptr = (
void *)info;
536 int ret = timer_create(CLOCK_REALTIME, &timer_event, &info->
handle);
565 uint64 intervalNs = (uint64)info->
interval * 1000000;
566 dispatch_source_set_timer(info->
handle, dispatch_time(DISPATCH_TIME_NOW, (int64_t)intervalNs), intervalNs, 0);
568 dispatch_source_set_event_handler(info->
handle, ^{
570 if (!inf->func(inf->id, inf->count))
571 StopDrumBeat(inf->id);
573 dispatch_resume(info->
handle);
577 struct itimerspec newtv;
579 newtv.it_interval.tv_sec = p / 1000000;
580 newtv.it_interval.tv_nsec = (p % 1000000)*1000;
581 newtv.it_value.tv_sec = p / 1000000;
582 newtv.it_value.tv_nsec = (p % 1000000)*1000;
584 int ret = timer_settime(info->
handle, 0, &newtv, NULL);
605 DeleteTimerQueueTimer(NULL, info->
handle, NULL);
611 dispatch_suspend(info->
handle);
615 struct itimerspec newtv;
616 memset(&newtv, 0,
sizeof(itimerspec));
617 int ret = timer_settime(info->
handle, 0, &newtv, NULL);
649 dispatch_source_cancel(info->
handle);
651 dispatch_resume(info->
handle);
652 dispatch_release(info->
handle);
657 timer_delete(info->
handle);
671bool EnterMutex(
const char* name, uint32 ms,
bool autocreate) {
688 mutex =
new Mutex(name);
700 mutex =
new Mutex(name);
708 return (mutex->
enter(ms));
721 return (i->second->leave());
770 semaphore = i->second;
783 semaphore = i->second;
809 semaphore = i->second;
822 semaphore = i->second;
823 return (semaphore->
wait(ms));
845 semaphore = i->second;
854 semaphore = i->second;
855 return (semaphore->
signal());
903 event =
new Event(name);
915 event =
new Event(name);
936 return (i->second->signal());
999 #if defined(__GNUC__) || defined(__clang__)
1026 (*g_cancelSafeSet)[
this] =
true;
1052 mutex =
new pthread_mutex_t;
1053 pthread_mutexattr_t attr;
1054 pthread_mutexattr_init(&attr);
1055 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1056 pthread_mutex_init(
mutex, &attr);
1064 pthread_mutexattr_destroy(&attr);
1077 mutex = ::CreateMutex(NULL,
FALSE, this->name);
1091 mutex = (pthread_mutex_t*) data;
1098 mutex = (pthread_mutex_t*) data;
1099 pthread_mutexattr_t attr;
1100 pthread_mutexattr_init(&attr);
1101 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1102 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1103 pthread_mutex_init(
mutex, &attr);
1104 pthread_mutexattr_destroy(&attr);
1111bool CloseMutexHandle(HANDLE mutex) {
1117 __except (EXCEPTION_EXECUTE_HANDLER) {
1138 CloseMutexHandle(
mutex);
1143 pthread_mutex_destroy(
mutex);
1149 pthread_mutex_destroy(
mutex);
1161 reply = WaitForSingleObject(
mutex, INFINITE);
1166 if (reply == WAIT_OBJECT_0 || reply == WAIT_ABANDONED) {
1174 else if (reply == WAIT_FAILED && GetLastError() == ERROR_INVALID_HANDLE) {
1192 int prevCancelState = 0;
1194 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &prevCancelState);
1195 int error = pthread_mutex_lock(
mutex);
1200 if (cs &&
count == 0)
1207 pthread_setcancelstate(prevCancelState, NULL);
1222 reply = WaitForSingleObject(
mutex, timeout);
1224 if (reply == WAIT_OBJECT_0 || reply == WAIT_ABANDONED) {
1240 if (reply == WAIT_TIMEOUT) {
1241 LogPrint(0,
LOG_SYSTEM, 0,
"[%u]Mutex enter timeout[%p](%s) - currently held by %u, count %u, total %u",
1246 else if (reply == WAIT_FAILED) {
1247 DWORD mtxErr = GetLastError();
1248 if (mtxErr == ERROR_INVALID_HANDLE)
1250 char* msg =
new char[2048];
1251 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1252 NULL, mtxErr, 0, msg, 2048, NULL);
1254 LogPrint(0,
LOG_SYSTEM, 0,
"[%u]Mutex enter failed[%p](%s): %s - currently held by %u, count %u, total %u",
1260 LogPrint(0,
LOG_SYSTEM,0,
"[%u]Mutex enter error[%p](%s): %d - currently held by %u, count %u, total %u",
1270 int prevCancelState = 0;
1272 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &prevCancelState);
1274 int error = macos_pthread_mutex_timedlock(
mutex, &ts);
1276 int error = pthread_mutex_timedlock(
mutex, &ts);
1280 if (cs &&
count == 0)
1291 pthread_setcancelstate(prevCancelState, NULL);
1293 if (error == EINVAL) {
1295 errorMsg ? errorMsg :
"-", error, timeout, (uint64)(ts.tv_sec), (int64)(ts.tv_nsec));
1299 LogPrint(0,
LOG_SYSTEM,0,
"Mutex enter timeout %u: '%s' (%d) [%p] - held by %u", timeout, errorMsg ? errorMsg :
"-", error,
this,
osid);
1335 uint32 osid2 =
osid;
1343 if (ReleaseMutex(
mutex) != 0) {
1368 if (pthread_mutex_unlock(
mutex) != 0)
1374 pthread_setcancelstate(restoreState, NULL);
1416 semaphore_impl = dispatch_semaphore_create(0);
1441 snprintf(shmemname,
sizeof(shmemname),
"Semaphore_%s",
name);
1446 pthread_mutex_t* m = (pthread_mutex_t*)data;
1447 pthread_mutexattr_t attr;
1448 pthread_mutexattr_init(&attr);
1449 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1450 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1451 pthread_mutex_init(m, &attr);
1452 pthread_mutexattr_destroy(&attr);
1453 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1454 pthread_condattr_t cattr;
1455 pthread_condattr_init(&cattr);
1456 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
1457 pthread_cond_init(c, &cattr);
1458 pthread_condattr_destroy(&cattr);
1459 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1463 semaphore_impl = data;
1467 semaphore = sem_open(this->name, O_CREAT, 0666, 1);
1487 dispatch_release((dispatch_semaphore_t)semaphore_impl);
1488 semaphore_impl = NULL;
1491 if (semaphore_impl) {
1493 semaphore_impl = NULL;
1509 snprintf(semname,
sizeof(semname),
"/Semaphore_%s",
name);
1510 sem_unlink(semname);
1519 return (WaitForSingleObject(
semaphore, INFINITE) == WAIT_OBJECT_0);
1523 return dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_impl, DISPATCH_TIME_FOREVER) == 0;
1525 char* data = (
char*)semaphore_impl;
1526 if (!data)
return false;
1527 pthread_mutex_t* m = (pthread_mutex_t*)data;
1528 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1529 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1530 pthread_mutex_lock(m);
1532 pthread_cond_wait(c, m);
1534 pthread_mutex_unlock(m);
1546 return (WaitForSingleObject(
semaphore, timeout) == WAIT_OBJECT_0);
1550 dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout * 1000000);
1551 return dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_impl, when) == 0;
1554 char* data = (
char*)semaphore_impl;
1555 if (!data)
return false;
1556 pthread_mutex_t* m = (pthread_mutex_t*)data;
1557 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1558 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1559 pthread_mutex_lock(m);
1563 int r = pthread_cond_timedwait(c, m, &t);
1564 if (r == ETIMEDOUT) {
1565 pthread_mutex_unlock(m);
1569 pthread_mutex_unlock(m);
1574 pthread_mutex_unlock(m);
1588 return (ReleaseSemaphore(
1595 return dispatch_semaphore_signal((dispatch_semaphore_t)semaphore_impl) != 0;
1597 char* data = (
char*)semaphore_impl;
1598 if (!data)
return false;
1599 pthread_mutex_t* m = (pthread_mutex_t*)data;
1600 pthread_cond_t* c = (pthread_cond_t*)(data +
sizeof(pthread_mutex_t));
1601 uint32* cnt = (uint32*)(data +
sizeof(pthread_mutex_t) +
sizeof(pthread_cond_t));
1602 pthread_mutex_lock(m);
1604 pthread_cond_signal(c);
1605 pthread_mutex_unlock(m);
1640 event = CreateEvent(
1646 event =
new pthread_cond_t;
1647 pthread_cond_init(
event, NULL);
1649 mutex =
new pthread_mutex_t;
1650 pthread_mutex_init(
mutex, NULL);
1660 event = CreateEvent(
1668 mutex = (pthread_mutex_t*) data;
1669 event = (pthread_cond_t*) (data +
sizeof(pthread_mutex_t));
1675 mutex = (pthread_mutex_t*) data;
1676 pthread_mutexattr_t attr;
1677 pthread_mutexattr_init(&attr);
1678 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1679 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1680 pthread_mutex_init(
mutex, &attr);
1681 pthread_mutexattr_destroy(&attr);
1683 event = (pthread_cond_t*) (data +
sizeof(pthread_mutex_t));
1684 pthread_condattr_t cattr;
1685 pthread_condattr_init(&cattr);
1686 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
1688 pthread_cond_init(
event, &cattr);
1689 pthread_mutexattr_destroy(&attr);
1704 pthread_cond_destroy(
event);
1706 pthread_mutex_destroy(
mutex);
1710 pthread_cond_destroy(
event);
1711 pthread_mutex_destroy(
mutex);
1722 return (WaitForSingleObject(
event, INFINITE) == WAIT_OBJECT_0);
1724 pthread_mutex_lock(
mutex);
1726 pthread_mutex_unlock(
mutex);
1733 return (WaitForSingleObject(
event, timeout) == WAIT_OBJECT_0);
1735 pthread_mutex_lock(
mutex);
1738 int r = pthread_cond_timedwait(
event,
mutex, &t);
1739 pthread_mutex_unlock(
mutex);
1746 if (!SetEvent(
event))
1752 pthread_mutex_lock(
mutex);
1753 int r = pthread_cond_broadcast(
event);
1754 pthread_mutex_unlock(
mutex);
1786 timers =
new std::map<uint32, Timer*>;
1790 (*timers)[globalID] =
this;
1798 std::map<uint32, TimerSchedule*>::iterator it = schedules.begin();
1799 std::map<uint32, TimerSchedule*>::iterator itEnd = schedules.end();
1805 std::list<TimerSchedule*>::iterator it2 = oldSchedules.begin();
1806 std::list<TimerSchedule*>::iterator it2End = oldSchedules.end();
1807 while (it2 != it2End)
1809 oldSchedules.clear();
1816 if (schedules[
id]) {
1825 schedule->
start = start;
1826 schedule->
end = end;
1828 schedules[id] = schedule;
1831 uint32 firstDelay = 0;
1832 if (start && (start > now))
1833 firstDelay = (uint32)(start - now)/1000;
1837 if (!CreateTimerQueueTimer(&schedule->
handle, NULL,
TimerCallback, schedule, firstDelay, interval, WT_EXECUTEINTIMERTHREAD)) {
1838 schedules[id] = NULL;
1845 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1846 dispatch_source_t timer_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
1847 if (!timer_source) {
1848 schedules[id] = NULL;
1853 schedule->
handle = timer_source;
1854 uint64 firstDelayNs = (uint64)firstDelay * 1000000;
1855 uint64 intervalNs = (uint64)interval * 1000000;
1856 dispatch_source_set_timer(timer_source, dispatch_time(DISPATCH_TIME_NOW, (int64_t)firstDelayNs), intervalNs, 0);
1857 dispatch_source_set_event_handler(timer_source, ^{
1867 dispatch_resume(timer_source);
1869 struct sigaction sa;
1870 struct sigevent timer_event;
1872 sigemptyset(&sa.sa_mask);
1873 sa.sa_flags = SA_SIGINFO;
1875 sigaction(SIGRTMIN, &sa, NULL);
1877 timer_event.sigev_notify = SIGEV_SIGNAL;
1878 timer_event.sigev_signo = SIGRTMIN;
1879 timer_event.sigev_value.sival_ptr = (
void *)schedule;
1880 if (timer_create(CLOCK_REALTIME, &timer_event, &schedule->
handle) != 0) {
1881 schedules[id] = NULL;
1887 struct itimerspec newtv;
1890 uint64 period = interval * 1000;
1891 newtv.it_value.tv_sec = firstDelay / 1000000;
1892 newtv.it_value.tv_nsec = (firstDelay % 1000000)*1000;
1893 newtv.it_interval.tv_sec = period / 1000000;
1894 newtv.it_interval.tv_nsec = (period % 1000000)*1000;
1896 if (timer_settime(schedule->
handle, 0, &newtv, NULL) != 0) {
1897 timer_delete(schedule->
handle);
1898 schedules[id] = NULL;
1903 sigemptyset(&allsigs);
1920 schedules[id] = NULL;
1923 DeleteTimerQueueTimer(NULL, schedule->
handle, NULL);
1926 dispatch_source_cancel(schedule->
handle);
1927 dispatch_release(schedule->
handle);
1929 timer_delete(schedule->
handle);
1933 oldSchedules.push_back(schedule);
1947 trigger->
id = schedule->
id;
1950 triggers.push(trigger);
1953 if ( schedule->
end && ((int32)(schedule->
end - trigger->
time) < (int32)schedule->
interval))
1966 while (!triggers.size()) {
1968 if ( (timeleft = (int32)timeout -
GetTimeAgeMS(start)) <= 0)
1970 semaphore.wait((uint32)timeleft);
1974 trigger = triggers.front();
1977 time = trigger->
time;
1984 void CALLBACK
TimerCallback(PVOID arg, BOOLEAN TimerOrWaitFired) {
2021 if (!timer->
addTimer(1, 1000, now+50000, now+10000000)) {
2026 if (!timer->
addTimer(2, 2000, now+55000, now+15000000)) {
2031 if (!timer->
addTimer(3, 3000, now+60000, now+20000000)) {
2038 uint32 triggers = 0;
2039 double totalLatencyUs = 0;
2043 for (uint32 n = 0; n < 60; n++) {
2047 totalLatencyUs += (double)(now - time);
2048 unittest::detail(
"Timer %u triggered %.3f ms ago",
id, (now - time) / 1000.0);
2059 if (triggers == 0) {
2066 unittest::metric(
"avg_trigger_latency", totalLatencyUs / (
double)triggers,
"us",
false);
2083 if (pipe(inPipe) != 0) {
unittest::fail(
"pipe() failed");
return false; }
2084 pid_t child = fork();
2085 if (child < 0) {
unittest::fail(
"fork() failed"); close(inPipe[0]); close(inPipe[1]);
return false; }
2087 dup2(inPipe[0], STDIN_FILENO);
2088 close(inPipe[0]); close(inPipe[1]);
2089 execl(
"/bin/sh",
"sh",
"-c",
"read x", (
char*)NULL);
2093 uint32 pid = (uint32)child;
2095 bool detected =
false;
2096 for (
int i = 0; i < 40 && !detected; i++) {
2097 if (!
ProbeProcessWait(pid, info)) {
unittest::fail(
"ProbeProcessWait returned false"); kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false; }
2102 unittest::fail(
"stdin-blocked child not detected (alive=%d waitingStdin=%d waitExact=%d)",
2104 kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false;
2106#if defined(__linux__)
2107 if (!info.
waitExact) {
unittest::fail(
"Linux should report waitExact"); kill(child, SIGKILL); close(inPipe[1]); waitpid(child, NULL, 0);
return false; }
2109 kill(child, SIGKILL);
2111 waitpid(child, NULL, 0);
2113 unittest::progress(55,
"spawn CPU-busy child, expect no stdin-wait + growing cpuTimeMs");
2114 uint32 pid2 =
NewProcessEx(
"i=0; while [ $i -lt 100000000 ]; do i=$((i+1)); done",
2115 NULL, NULL, NULL,
true,
false,
true, SIGKILL,
true);
2116 if (!pid2) {
unittest::fail(
"NewProcessEx(busy loop) failed");
return false; }
2125 if (busyFlagged) {
unittest::fail(
"busy child wrongly flagged waitingStdin");
return false; }
2136 uint32 slotCount = 350;
2138 char* bitField =
new char[bitFieldSize];
2147 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: false", loc);
2153 unittest::fail(
"GetFirstFreeBitLoc failed: %u, expected: 0", loc);
2158 unittest::fail(
"GetFirstFreeBitLocN failed: %u, expected: 0", loc);
2172 unittest::fail(
"GetFirstFreeBitLoc 2 failed: %u, expected: 0", loc);
2177 unittest::fail(
"GetFirstFreeBitLocN 2 failed: %u, expected: 0", loc);
2184 unittest::fail(
"GetFirstFreeBitLocN 3 failed: %u, expected: 11", loc);
2189 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 10", loc);
2208 unittest::fail(
"GetFirstFreeBitLoc 4 failed: %u, expected: 1", loc);
2213 unittest::fail(
"GetFirstFreeBitLocN 5 failed: %u, expected: 11", loc);
2218 unittest::fail(
"GetFirstFreeBitLocN 6 failed: %u, expected: 11", loc);
2223 unittest::fail(
"GetFirstFreeBitLocN 7 failed: %u, expected: 150", loc);
2228 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 149", loc);
2242 unittest::fail(
"GetFirstFreeBitLoc 8 failed: %u, expected: 1", loc);
2247 unittest::fail(
"GetFirstFreeBitLocN 9 failed: %u, expected: 11", loc);
2252 unittest::fail(
"GetFirstFreeBitLocN 10 failed: %u, expected: 11", loc);
2257 unittest::fail(
"GetFirstFreeBitLocN 11 failed: %u, expected: 250", loc);
2262 unittest::fail(
"GetFirstFreeBitLocN 12 failed: %u, expected: false", loc);
2268 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2282 unittest::fail(
"GetFirstFreeBitLoc 13 failed: %u, expected: 1", loc);
2287 unittest::fail(
"GetFirstFreeBitLocN 14 failed: %u, expected: 11", loc);
2292 unittest::fail(
"GetFirstFreeBitLocN 15 failed: %u, expected: 11", loc);
2297 unittest::fail(
"GetFirstFreeBitLocN 16 failed: %u, expected: 11", loc);
2302 unittest::fail(
"GetFirstFreeBitLocN 17 failed: %u, expected: 250", loc);
2307 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2320 unittest::fail(
"GetFirstFreeBitLoc 18 failed: %u, expected: 1", loc);
2325 unittest::fail(
"GetFirstFreeBitLocN 19 failed: %u, expected: 11", loc);
2330 unittest::fail(
"GetFirstFreeBitLocN 20 failed: %u, expected: 11", loc);
2335 unittest::fail(
"GetFirstFreeBitLocN 21 failed: %u, expected: 250", loc);
2340 unittest::fail(
"GetFirstFreeBitLocN 22 failed: %u, expected: 250", loc);
2345 unittest::fail(
"GetFirstFreeBitLocN 23 failed: %u, expected: false", loc);
2350 unittest::fail(
"GetLastOccupiedBitLoc: loc %u, expected: 249", loc);
2377 hMapFile = CreateFileMapping(
2378 INVALID_HANDLE_VALUE,
2381 (uint32)((size >> 32) & 0xffffffff),
2382 (uint32)(size & 0xffffffff),
2393 bool alreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS);
2395 if (hMapFile == NULL) {
2401 pBuf = (
char*) MapViewOfFile(hMapFile,
2402 FILE_MAP_ALL_ACCESS,
2406 int error = GetLastError();
2407 CloseHandle(hMapFile);
2416 if (force && alreadyExisted)
2417 memset(pBuf, 0, (
size_t)size);
2422 (*SharedMemoryFileHandleMap)[pBuf] = hMapFile;
2431 int fd = open(memname, O_CREAT | O_RDWR, 0666);
2433 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't create shared memory: '%s' (err: %d)...", memname, errno);
2437 if (ftruncate(fd, size) == -1) {
2438 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't truncate shared memory: '%s' size: %u (%d) (err: %d)...", memname, size, fd, errno);
2443 char* pBuf = (
char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2444 if (pBuf == MAP_FAILED) {
2445 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't map created shared memory: '%s' (err: %d)...", memname, errno);
2452 (*SharedMemoryFileHandleMap)[pBuf] = std::string(memname);
2459 int fd = shm_open(memname, O_CREAT | O_RDWR, 0666);
2461 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't create shared memory: '%s' (err: %d)...", memname, errno);
2465 if (ftruncate(fd, size) == -1) {
2466 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't truncate shared memory: '%s' size: %u (%d) (err: %d)...", memname, size, fd, errno);
2471 char* pBuf = (
char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2472 if (pBuf == MAP_FAILED) {
2473 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't map created shared memory: '%s' (err: %d)...", memname, errno);
2480 (*SharedMemoryFileHandleMap)[pBuf] = memname;
2498 hMapFile = OpenFileMapping(
2499 FILE_MAP_ALL_ACCESS,
2503 if (hMapFile == NULL) {
2509 pBuf = (
char*) MapViewOfFile(hMapFile,
2510 FILE_MAP_ALL_ACCESS,
2517 CloseHandle(hMapFile);
2525 (*SharedMemoryFileHandleMap)[pBuf] = hMapFile;
2532 int fd = open(memname, O_RDWR);
2538 uint64 memSize = size;
2545 if (fstat(fd, &st) == -1 || st.st_size <= 0) {
2550 memSize = (uint64) st.st_size;
2552 pBuf = (
char*)mmap(NULL, memSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2553 if (pBuf == MAP_FAILED) {
2560 (*SharedMemoryFileHandleMap)[pBuf] = std::string(memname);
2567 int fd = shm_open(memname, O_RDWR, 0666);
2573 uint64 memSize = size;
2579 if (fstat(fd, &st) == -1 || st.st_size <= 0) {
2580 LogPrint(0,
LOG_SYSTEM,0,
"Couldn't stat opened shared memory: '%s' (err: %d)...", memname, errno);
2585 memSize = (uint64) st.st_size;
2587 pBuf = (
char*)mmap(NULL, memSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2588 if (pBuf == MAP_FAILED) {
2595 (*SharedMemoryFileHandleMap)[pBuf] = memname;
2608 UnmapViewOfFile(data);
2644 const char* p = name;
2645 while ((p = strstr(p, portstr)) != NULL) {
2646 bool leftOK = (p == name) || !isdigit((
unsigned char)*(p - 1));
2647 char after = *(p + plen);
2648 bool rightOK = (after ==
'\0') || !isdigit((
unsigned char)after);
2649 if (leftOK && rightOK)
2656static uint32
ClearSegmentsIn(
const char* dir,
const char* prefix,
const char* portstr,
size_t plen) {
2660 size_t preflen = strlen(prefix);
2662 while ((e =
readdir(d)) != NULL) {
2663 if (strncmp(e->
d_name, prefix, preflen) != 0)
2667 std::string path = std::string(dir) +
"/" + e->
d_name;
2668 if (unlink(path.c_str()) == 0)
2683 snprintf(portstr,
sizeof(portstr),
"%u", port);
2684 size_t plen = strlen(portstr);
2690 count +=
ClearSegmentsIn(
"/dev/shm",
"sem.Semaphore_", portstr, plen);
2693 LogPrint(0,
LOG_SYSTEM, 1,
"Cleared %u stale shared segment(s) for port %u...", count, port);
2704 uint8 *data = (uint8*)&rval;
2705 data[0] = (uint8)(*input >> 56);
2706 data[1] = (uint8)(*input >> 48);
2707 data[2] = (uint8)(*input >> 40);
2708 data[3] = (uint8)(*input >> 32);
2709 data[4] = (uint8)(*input >> 24);
2710 data[5] = (uint8)(*input >> 16);
2711 data[6] = (uint8)(*input >> 8);
2712 data[7] = (uint8)(*input >> 0);
2724 return ((bitsize + 31) >> 5) << 2;
2728 memset(bitfield, 255, bytesize);
2734 uint32* data = (uint32*)bitfield;
2735 uint32* src = (uint32*)data;
2747 const int32 words = (int32)(bytesize >> 2);
2748 while (src - data < words && *src == 0)
2750 if (src - data >= words)
2753 _BitScanForward((DWORD*)&index, *src);
2755 index = ffsl(*src) - 1;
2757 index = ffsl(*src) - 1;
2760 loc = ((uint32)(src-data)*32) + index;
2766 uint32* data = (uint32*)bitfield;
2767 uint32* src = (uint32*)data;
2773 uint32 foundBlock = 0;
2776 const int32 words = (int32)(bytesize >> 2);
2778 while (src - data < words && *src == 0)
2780 if (src - data >= words)
2783 _BitScanForward((DWORD*)&index, *src);
2785 index = ffsl(*src) - 1;
2787 index = ffsl(*src) - 1;
2789 loc = ((uint32)(src - data) * 32) + index;
2802 if ((l >> 5) >= (bytesize >> 2))
2805 uint32* word = (uint32*)bitfield + (l >> 5);
2808 val = (_bittest((
long*)word, n) != 0);
2810 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2812 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2820 if (foundBlock >= num)
2822 if (index % 32 == 0) {
2827 while ((num - foundBlock > 31) && (src - data < words) && (*src ==
MAXVALUINT32)) {
2832 if (src - data >= words)
2834 if ((num - foundBlock > 15) && (*(uint16*)src ==
MAXVALUINT16)) {
2838 if ((num - foundBlock > 7) && (*((
unsigned char*)src+2) == 255)) {
2844 else if ((num - foundBlock > 7) && (*(
unsigned char*)src == 255)) {
2850 if (foundBlock >= num)
2857 if (index % 32 == 0)
2863 if ((l >> 5) >= (bytesize >> 2))
2866 uint32* word = (uint32*)bitfield + (l >> 5);
2869 val = (_bittest((
long*)word, n) != 0);
2871 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2873 val = (bit)((*word & (
static_cast<uint32
>(1) << n)) != 0);
2878 src += (uint32)(index / 32);
2879 if (src - data >= words)
2888bool SetBit(uint32 loc, bit value,
char* bitfield, uint32 bytesize) {
2889 if ((loc + 7) >> 3 > bytesize)
2891 uint32* data = (uint32*)bitfield;
2892 uint32* src = (uint32*)data;
2901 _bittestandset((
long*)src, n);
2903 _bittestandreset((
long*)src, n);
2920bool SetBitN(uint32 loc, uint32 num, bit value,
char* bitfield, uint32 bytesize) {
2921 if ((loc + 7) >> 3 > bytesize)
2923 uint32* data = (uint32*)bitfield;
2924 uint32* src = (uint32*)data;
2931 for (uint32 i = 0; i < num; i++) {
2933 while (num - i > 31) {
2943 *((
unsigned char*)src + 2) = (value ? 255 : 0);
2948 else if (num - i > 7) {
2949 *(
unsigned char*)src = (value ? 255 : 0);
2958 _bittestandset((
long*)src, n);
2960 _bittestandreset((
long*)src, n);
2983bool GetBit(uint32 loc,
const char* bitfield, uint32 bytesize, bit& val) {
2984 if ((loc + 7) >> 3 > bytesize)
2986 uint32* data = (uint32*)bitfield;
2987 uint32* src = (uint32*)data;
2995 val = (_bittest((
long*)src, n) != 0);
2997 uint32 mask =
static_cast<uint32
>( 1 << n ) ;
2998 val = (bit)(mask & *src);
3000 uint32 mask =
static_cast<uint32
>(1 << n);
3001 val = (bit)(mask & *src);
3009 uint32* data = (uint32*)bitfield;
3010 uint32* src = (uint32*)(bitfield + bytesize - 4);
3014 while ((*src == 0xFFFFFFFF)) {
3021 _BitScanReverse((DWORD*)&index, ~(*src));
3023 index = 31 - __builtin_clz(~(*src));
3025 index = 31 - __builtin_clz(~(*src));
3027 loc = ((uint32)(src - data) * 32) + index;
3035 str.reserve(bytesize * 9);
3038 for(i = 0; i < bytesize; i++) {
3039 for(j = 0; j < 8; j++) {
3041 str.push_back((bitfield[i] & (1 << j)) ?
'_' :
'0');
3054 uint32 strSize = (uint32)str.size();
3059 return StringFormat(
"%s [%u]: %s\n", title, size, str.c_str());
3068 while (loc < strSize-1) {
3069 str2 += str.substr(loc, 36) +
"\n";
3073 str2 += str.substr(loc) +
"\n";
3083 return InterlockedIncrement((LONG*)&v);
3086 __sync_add_and_fetch(&v, 1);
3093 return InterlockedIncrement64((LONGLONG*)&v);
3096 __sync_add_and_fetch(&v, 1);
3103 return InterlockedDecrement((LONG*)&v);
3106 __sync_add_and_fetch(&v, -1);
3113 return InterlockedDecrement64((LONGLONG*)&v);
3116 __sync_add_and_fetch(&v, -1);
3132 std::string tracePrint;
3135 std::list<std::string>::iterator i = trace.begin(), e = trace.end();
3139 if ((++line > startLine) && (!endLine || (line <= endLine)))
3140 tracePrint +=
" -" + (*i) +
"\n";
3147 std::list<std::string> trace;
3176 size = backtrace(array, 200);
3177 strings = backtrace_symbols(array, size);
3178 for (i = 0; i < size; i++)
3179 trace.push_back(strings[i]);
3194 (LPTHREAD_START_ROUTINE) func,
3199 if (thread != NULL) {
3200 osID = ::GetThreadId(thread);
3207 pthread_attr_t attr;
3208 pthread_attr_init(&attr);
3210 pthread_attr_setschedpolicy(&attr, SCHED_RR);
3211 pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
3215 if ((res=pthread_create(&thread, &attr, func, args)) != 0)
3218 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
3219 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
3222 pthread_threadid_np(thread, &tid);
3225 osID = (uint32) thread;
3235 int res = WaitForSingleObject(hThread, 0);
3236 if (res != WAIT_OBJECT_0)
3249 return (pthread_kill(hThread, 0) != 0);
3262 return (pthread_kill(hThread, 0) != 0);
3275 CloseHandle(hThread);
3277 pthread_join(hThread, NULL);
3294 if (WaitForSingleObject(hThread, 0) != WAIT_OBJECT_0)
3296 CloseHandle(hThread);
3297 #elif defined __APPLE__
3298 if (pthread_kill(hThread, 0) == 0)
3300 pthread_join(hThread, NULL);
3302 if (pthread_tryjoin_np(hThread, NULL) != 0)
3313 int res = WaitForSingleObject(hThread, timeoutMS ? timeoutMS : INFINITE);
3314 if(res != WAIT_OBJECT_0)
3324 return (pthread_join(hThread, NULL) == 0);
3332 while (pthread_kill(hThread, 0) == 0) {
3333 if (waited >= timeoutMS)
3339 pthread_join(hThread, NULL);
3345 if (pthread_timedjoin_np(hThread, NULL, &ts) != 0)
3351 if (pthread_join(hThread, NULL) != 0)
3368 char* msg =
new char[2048];
3369 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
3370 NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
3376 CloseHandle(hThread);
3382 pthread_cancel(hThread);
3383 if (pthread_join(hThread, NULL) != 0)
3401 sigaddset(set, SIGINT);
3402 sigaddset(set, SIGTERM);
3403 sigaddset(set, SIGHUP);
3404 sigaddset(set, SIGUSR2);
3418 if (sigwait(&set, &sig) != 0)
3441 return (pthread_sigmask(SIG_BLOCK, &set, NULL) == 0);
3460 pthread_sigmask(SIG_BLOCK, &set, NULL);
3486 return (SuspendThread(hThread) >= 0);
3488 return (pthread_kill(hThread, SIGSTOP) == 0);
3496 while ( (count = ResumeThread(hThread)) > 1);
3497 return (count == 1);
3499 return (pthread_kill(hThread, SIGCONT) == 0);
3510 tid = ::GetCurrentThreadId();
3515 pthread_threadid_np(pthread_self(), &
id);
3518 tid = (uint32) pthread_self();
3526 tid = ::GetCurrentThreadId();
3531 if (pthread_threadid_np(pthread_self(), &
id) != 0)
3535 int id = syscall(SYS_gettid);
3549 thread = pthread_self();
3557 if (!GetExitCodeThread(hThread, &code))
3559 return (code == STILL_ACTIVE);
3572 return (pthread_kill(hThread, 0) == 0);
3579 return (pthread_kill(hThread, 0) == 0);
3588 #if defined RUSAGE_THREAD
3602 uint64 cpuTicks = 0;
3603 LARGE_INTEGER perfFreq;
3604 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3606 if (!QueryThreadCycleTime(hThread, &cpuTicks))
3608 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3621 mach_port_t machThread = pthread_mach_thread_np(hThread);
3622 if (machThread == MACH_PORT_NULL)
3624 thread_basic_info_data_t info;
3625 mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
3626 if (thread_info(machThread, THREAD_BASIC_INFO, (thread_info_t)&info, &infoCount) != KERN_SUCCESS)
3628 ticks = (uint64)info.user_time.seconds * 1000000 + info.user_time.microseconds
3629 + (uint64)info.system_time.seconds * 1000000 + info.system_time.microseconds;
3633 if (pthread_getcpuclockid(hThread, &cid) != 0)
3636 if (clock_gettime(cid, &ts) != -1 ) {
3637 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3652 uint64 cpuTicks = 0;
3653 LARGE_INTEGER perfFreq;
3654 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3658 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3670 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != -1 ) {
3671 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3694 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS,
FALSE, osProcID);
3700 uint64 cpuTicks = 0;
3701 LARGE_INTEGER perfFreq;
3702 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3704 if (!QueryProcessCycleTime(hProcess, &cpuTicks))
3706 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3719 if ((pid_t)osProcID != getpid())
3722 if (getrusage(RUSAGE_SELF, &ru) != 0)
3724 ticks = ((uint64)ru.ru_utime.tv_sec * 1000000) + (uint64)ru.ru_utime.tv_usec
3725 + ((uint64)ru.ru_stime.tv_sec * 1000000) + (uint64)ru.ru_stime.tv_usec;
3729 if (clock_getcpuclockid(osProcID, &clockid) != 0)
3732 if (clock_gettime(clockid, &ts) != -1 ) {
3733 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3761 uint64 cpuTicks = 0;
3762 LARGE_INTEGER perfFreq;
3763 if (!QueryPerformanceFrequency(&perfFreq) || !perfFreq.QuadPart)
3765 if (!QueryProcessCycleTime(::GetCurrentProcess(), &cpuTicks))
3767 ticks = cpuTicks / (perfFreq.QuadPart / 1000000);
3780 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != -1 ) {
3781 ticks = ((uint64)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
3801bool GetProcAndOSCPUUsage(
double& procPercentUse,
double& osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks) {
3803 return GetProcAndOSCPUUsage(0, procPercentUse, osPercentUse, prevOSTicks, prevOSIdleTicks, prevProcTicks);
3805 return GetProcAndOSCPUUsage(getpid(), procPercentUse, osPercentUse, prevOSTicks, prevOSIdleTicks, prevProcTicks);
3810bool GetProcAndOSCPUUsage(uint32 osProcID,
double& procPercentUse,
double& osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks) {
3811 procPercentUse = osPercentUse = 0;
3813 uint64 totalTicks, kernelTicks, userTicks, idleTicks, procTotalTicks, procUserTicks, procKernelTicks;
3816 FILETIME idleTime, kernelTime, userTime;
3817 if (!GetSystemTimes(&idleTime, &kernelTime, &userTime))
3820 idleTicks = FileTimeToUint64(idleTime);
3821 kernelTicks = FileTimeToUint64(kernelTime);
3822 userTicks = FileTimeToUint64(userTime);
3823 totalTicks = kernelTicks + userTicks;
3825 FILETIME procCreationTime, procExitTime, procKernelTime, procUserTime;
3828 if (!GetProcessTimes(GetCurrentProcess(), &procCreationTime, &procExitTime, &procKernelTime, &procUserTime))
3832 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS,
FALSE, osProcID);
3836 if (!GetProcessTimes(hProcess, &procCreationTime, &procExitTime, &procKernelTime, &procUserTime))
3840 procKernelTicks = FileTimeToUint64(procKernelTime);
3841 procUserTicks = FileTimeToUint64(procUserTime);
3842 procTotalTicks = procKernelTicks + procUserTicks;
3847 host_cpu_load_info_data_t cpuInfo;
3848 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
3849 if (host_statistics64(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpuInfo, &count) != KERN_SUCCESS)
3853 long ticksPerSec = sysconf(_SC_CLK_TCK);
3854 uint64 usPerTick = (ticksPerSec > 0) ? (1000000 / ticksPerSec) : 10000;
3855 totalTicks = ((uint64)cpuInfo.cpu_ticks[CPU_STATE_USER] + cpuInfo.cpu_ticks[CPU_STATE_SYSTEM] + cpuInfo.cpu_ticks[CPU_STATE_IDLE] + cpuInfo.cpu_ticks[CPU_STATE_NICE]) * usPerTick;
3856 idleTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_IDLE] * usPerTick;
3857 if (osProcID == 0 || osProcID == (uint32)getpid()) {
3858 task_thread_times_info_data_t threadTimes;
3859 count = TASK_THREAD_TIMES_INFO_COUNT;
3860 if (task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&threadTimes, &count) == KERN_SUCCESS)
3861 procTotalTicks = (uint64)threadTimes.user_time.seconds * 1000000 + threadTimes.user_time.microseconds + (uint64)threadTimes.system_time.seconds * 1000000 + threadTimes.system_time.microseconds;
3869 std::string statLine, procStatLine;
3870 std::ifstream statFile (
"/proc/stat");
3871 std::ifstream procStatFile (
StringFormat(
"/proc/%d/stat", osProcID).c_str());
3872 if (statFile.is_open())
3873 getline (statFile, statLine);
3877 if (procStatFile.is_open())
3878 getline (procStatFile, procStatLine);
3882 if (!statLine.length() || !procStatLine.length())
3887 int retval = sscanf(statLine.c_str(),
"cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
3888 &fields[0], &fields[1], &fields[2], &fields[3], &fields[4],
3889 &fields[5], &fields[6], &fields[7], &fields[8], &fields[9]);
3891 for (
int i=0; i<10; i++)
3892 totalTicks += fields[i];
3893 idleTicks = fields[3];
3895 uint64 utime_ticks, stime_ticks, cutime_ticks, cstime_ticks;
3896 retval = sscanf(procStatLine.c_str(),
"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu %llu %llu",
3897 &utime_ticks, &stime_ticks, &cutime_ticks, &cstime_ticks);
3899 procTotalTicks = utime_ticks + stime_ticks + cutime_ticks + cstime_ticks;
3902 uint64 totalTicksSinceLastTime = totalTicks - prevOSTicks;
3903 uint64 idleTicksSinceLastTime = idleTicks - prevOSIdleTicks;
3904 uint64 procTicksSinceLastTime = procTotalTicks - prevProcTicks;
3906 osPercentUse = 1.0f-((totalTicksSinceLastTime > 0) ? ((double)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3907 procPercentUse = ((totalTicksSinceLastTime > 0) ? ((double)procTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3912 prevOSTicks = totalTicks;
3913 prevOSIdleTicks = idleTicks;
3914 prevProcTicks = procTotalTicks;
3922 static uint64 PreviousTotalTicks = 0;
3923 static uint64 PreviousIdleTicks = 0;
3925 uint64 totalTicks, kernelTicks, userTicks, idleTicks;
3929 FILETIME idleTime, kernelTime, userTime;
3930 if (!GetSystemTimes(&idleTime, &kernelTime, &userTime))
3933 idleTicks = FileTimeToUint64(idleTime);
3934 kernelTicks = FileTimeToUint64(kernelTime);
3935 userTicks = FileTimeToUint64(userTime);
3936 totalTicks = kernelTicks + userTicks;
3939 host_cpu_load_info_data_t cpuInfo;
3940 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
3941 if (host_statistics64(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpuInfo, &count) != KERN_SUCCESS)
3943 totalTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_USER] + cpuInfo.cpu_ticks[CPU_STATE_SYSTEM] + cpuInfo.cpu_ticks[CPU_STATE_IDLE] + cpuInfo.cpu_ticks[CPU_STATE_NICE];
3944 idleTicks = (uint64)cpuInfo.cpu_ticks[CPU_STATE_IDLE];
3946 std::string statLine;
3947 std::ifstream statFile(
"/proc/stat");
3948 if (!statFile.is_open() || !getline(statFile, statLine) || !statLine.length())
3952 if (sscanf(statLine.c_str(),
"cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
3953 &fields[0], &fields[1], &fields[2], &fields[3], &fields[4],
3954 &fields[5], &fields[6], &fields[7], &fields[8], &fields[9]) < 10)
3957 for (
int i = 0; i < 10; i++)
3958 totalTicks += fields[i];
3959 idleTicks = fields[3];
3962 uint64 totalTicksSinceLastTime = totalTicks - PreviousTotalTicks;
3963 uint64 idleTicksSinceLastTime = idleTicks - PreviousIdleTicks;
3965 percentUse = 1.0f-((totalTicksSinceLastTime > 0) ? ((double)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
3970 PreviousTotalTicks = totalTicks;
3971 PreviousIdleTicks = idleTicks;
3982 struct sched_param sched;
3985 policy = SCHED_OTHER;
3987 policy = sched_getscheduler(0);
3991 if (pthread_getschedparam(hThread, &policy, &sched) != 0)
4004 struct sched_param sched;
4005 memset(&sched, 0,
sizeof(
struct sched_param));
4007 policy = SCHED_FIFO;
4011 int res = pthread_setschedparam(hThread, policy, &sched);
4023 val = THREAD_PRIORITY_NORMAL;
4025 val = THREAD_PRIORITY_TIME_CRITICAL;
4027 val = THREAD_PRIORITY_HIGHEST;
4029 val = THREAD_PRIORITY_ABOVE_NORMAL;
4031 val = THREAD_PRIORITY_NORMAL;
4033 val = THREAD_PRIORITY_BELOW_NORMAL;
4035 val = THREAD_PRIORITY_LOWEST;
4037 val = THREAD_PRIORITY_IDLE;
4070 case THREAD_PRIORITY_TIME_CRITICAL:
4072 case THREAD_PRIORITY_HIGHEST:
4074 case THREAD_PRIORITY_ABOVE_NORMAL:
4076 case THREAD_PRIORITY_NORMAL:
4078 case THREAD_PRIORITY_BELOW_NORMAL:
4080 case THREAD_PRIORITY_LOWEST:
4111 const HWND hDesktop = GetDesktopWindow();
4113 if (!GetWindowRect(hDesktop, &desktop))
4118 width = (uint32)desktop.right;
4119 height = (uint32)desktop.bottom;
4130 char* oldName =
new char[1024];
4131 if (!GetConsoleTitle(oldName, 1024)) {
4135 char* newName =
StringFormat(size,
"%s - %s", name, oldName);
4136 bool res = (SetConsoleTitle(name) != 0);
4142 return (SetConsoleTitle(name) != 0);
4150 char* consoleName =
new char[1024];
4151 if (!GetConsoleTitle(consoleName, 1024)) {
4152 delete [] consoleName;
4155 HWND handle = FindWindow(NULL, consoleName);
4157 delete [] consoleName;
4161 if (!GetWindowRect(handle, &wRect)) {
4162 delete [] consoleName;
4166 int conX = (x<0) ? wRect.left : x;
4167 int conY = (y<0) ? wRect.top : y;
4168 int conW = (w<0) ? wRect.right - wRect.left : w;
4169 int conH = (h<0) ? wRect.bottom - wRect.top : h;
4171 bool res = (MoveWindow(handle, conX, conY, conW, conH,
true) != 0);
4172 delete [] consoleName;
4187 return (uint32)GetCurrentProcessId();
4189 return (uint32)getpid();
4194int RunOSCommand(
const char* cmdline,
const char* initdir, uint32 timeout, std::string& stdoutString, std::string& stderrString) {
4195 if (!cmdline || !strlen(cmdline))
4199 HANDLE g_hChildStd_OUT_Rd = NULL;
4200 HANDLE g_hChildStd_OUT_Wr = NULL;
4201 HANDLE g_hChildStd_ERR_Rd = NULL;
4202 HANDLE g_hChildStd_ERR_Wr = NULL;
4204 SECURITY_ATTRIBUTES sa;
4206 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
4207 sa.bInheritHandle =
TRUE;
4208 sa.lpSecurityDescriptor = NULL;
4210 if ( ! CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0) ) {
4214 if ( ! SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0) ){
4218 if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0) ) {
4222 if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ){
4225 PROCESS_INFORMATION piProcInfo;
4226 STARTUPINFO siStartInfo;
4227 bool bSuccess =
FALSE;
4230 ZeroMemory( &piProcInfo,
sizeof(PROCESS_INFORMATION) );
4234 ZeroMemory( &siStartInfo,
sizeof(STARTUPINFO) );
4235 siStartInfo.cb =
sizeof(STARTUPINFO);
4236 siStartInfo.hStdError = g_hChildStd_ERR_Wr;
4237 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
4238 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
4244 bSuccess = (CreateProcess(NULL,
4254 CloseHandle(g_hChildStd_ERR_Wr);
4255 CloseHandle(g_hChildStd_OUT_Wr);
4267 bSuccess=(ReadFile( g_hChildStd_OUT_Rd, chBuf,
PROCBUFSIZE, &dwRead, NULL) != 0);
4268 if( ! bSuccess || dwRead == 0 )
break;
4269 std::string s(chBuf, dwRead);
4275 bSuccess=(ReadFile( g_hChildStd_ERR_Rd, chBuf,
PROCBUFSIZE, &dwRead, NULL) != 0);
4276 if( ! bSuccess || dwRead == 0 )
break;
4277 std::string s(chBuf, dwRead);
4284 if (GetExitCodeProcess(piProcInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
4285 TerminateProcess(piProcInfo.hProcess, 1);
4287 CloseHandle(g_hChildStd_ERR_Rd);
4288 CloseHandle(g_hChildStd_OUT_Rd);
4289 CloseHandle(piProcInfo.hProcess);
4290 CloseHandle(piProcInfo.hThread);
4295 FILE* runfile = popen(cmdline,
"r");
4296 if (runfile == NULL)
4303 char* buffer =
new char[size+1];
4305 res = fread(buffer, 1, size, runfile);
4307 status = pclose(runfile);
4308 exitcode = WEXITSTATUS(status);
4314 stdoutString += buffer;
4315 }
while (res = fread(buffer, 1, size, runfile));
4317 status = pclose(runfile);
4318 exitcode = WEXITSTATUS(status);
4387uint32
NewProcess(
const char* cmdline,
const char* initdir,
const char* title, int16 x, int16 y, int16 w, int16 h) {
4389 if (!cmdline || !strlen(cmdline))
4396 ghJob = CreateJobObject(NULL, NULL);
4398 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
4400 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
4401 SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli,
sizeof(jeli));
4407 ZeroMemory(&(pData->procInfo),
sizeof(pData->procInfo));
4408 ZeroMemory(&(pData->si),
sizeof(pData->si));
4409 pData->si.cb =
sizeof(pData->si);
4410 pData->si.wShowWindow = SW_SHOWNOACTIVATE;
4412 if ( (x>=0) && (y>=0) && (w>=0) && (h>=0) ) {
4413 pData->si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEPOSITION | STARTF_USESIZE;
4416 pData->si.dwXSize = w;
4417 pData->si.dwYSize = h;
4420 pData->si.dwFlags = STARTF_USESHOWWINDOW;
4425 char* titleCopy = NULL;
4427 size_t tlen = strlen(title);
4428 titleCopy =
new char[tlen + 1];
4429 memcpy(titleCopy, title, tlen + 1);
4430 pData->si.lpTitle = titleCopy;
4433 size_t clen = strlen(cmdline);
4434 char* cmd =
new char[clen + 1];
4435 memcpy(cmd, cmdline, clen + 1);
4439 int res = CreateProcess(NULL, cmd, NULL, NULL,
TRUE, CREATE_NEW_CONSOLE, NULL, initdir, &pData->si, &pData->procInfo);
4440 delete [] titleCopy;
4443 char* msg =
new char[2048];
4444 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
4445 NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
4454 AssignProcessToJobObject(ghJob, pData->procInfo.hProcess);
4457 return pData->procInfo.dwProcessId;
4477 pid_t ppid_before_fork = getpid();
4485 else if (pid == 0) {
4487 if ( initdir && (chdir(initdir) != 0) ) {
4488 LogPrint(0,
LOG_SYSTEM,0,
"Could not run process '%s' from starup dir '%s'\n", cmdline, initdir);
4493 int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
4494 if (r == -1) { perror(0); exit(1); }
4497 if (getppid() != ppid_before_fork)
4501 execvp(argv[0],argv);
4526 if (GetExitCodeProcess(pData->procInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
4531 CloseHandle(pData->procInfo.hProcess);
4532 CloseHandle(pData->procInfo.hThread);
4533 if (pData->hOutRead) CloseHandle(pData->hOutRead);
4534 if (pData->hErrRead) CloseHandle(pData->hErrRead);
4535 if (pData->hInWrite) CloseHandle(pData->hInWrite);
4536 if (pData->hJob) CloseHandle(pData->hJob);
4538 returncode = exitcode;
4544 HANDLE hproc = OpenProcess(NULL,
false, (DWORD)proc);
4547 if (GetExitCodeProcess(hproc, &exitcode) && (exitcode == STILL_ACTIVE)) {
4558 int res = waitpid(proc, &status, WNOHANG);
4570 returncode = WEXITSTATUS(status);
4574 else if (res == 0) {
4581#if !defined(WINDOWS)
4609 TerminateProcess(pData->procInfo.hProcess, 1);
4610 CloseHandle(pData->procInfo.hProcess);
4611 CloseHandle(pData->procInfo.hThread);
4612 if (pData->hOutRead) CloseHandle(pData->hOutRead);
4613 if (pData->hErrRead) CloseHandle(pData->hErrRead);
4614 if (pData->hInWrite) CloseHandle(pData->hInWrite);
4615 if (pData->hJob) CloseHandle(pData->hJob);
4621 HANDLE hproc = OpenProcess(NULL, NULL, (DWORD)proc);
4624 if (TerminateProcess(hproc, 1) == 0) {
4634 bool ok = (kill(proc, SIGKILL) == 0);
4675 out.alive =
false; out.waitExact =
false; out.waitingStdin =
false; out.cpuTimeMs = 0;
4676 if (!pid)
return false;
4677 HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, (DWORD)pid);
4678 if (!h)
return true;
4680 if (GetExitCodeProcess(h, &code) && code == STILL_ACTIVE)
4684 bool haveTreeCpu =
false;
4685 ProcessData* pd = NULL;
4690 if (pd && pd->hJob) {
4691 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION jbai;
4692 ZeroMemory(&jbai,
sizeof(jbai));
4694 if (QueryInformationJobObject(pd->hJob, JobObjectBasicAccountingInformation,
4695 &jbai,
sizeof(jbai), &retLen)) {
4699 out.cpuTimeMs = (uint64)((jbai.TotalUserTime.QuadPart +
4700 jbai.TotalKernelTime.QuadPart) / 10000ULL);
4705 FILETIME ct, et, kt, ut;
4706 if (GetProcessTimes(h, &ct, &et, &kt, &ut)) {
4707 ULARGE_INTEGER k, u;
4708 k.LowPart = kt.dwLowDateTime; k.HighPart = kt.dwHighDateTime;
4709 u.LowPart = ut.dwLowDateTime; u.HighPart = ut.dwHighDateTime;
4710 out.cpuTimeMs = (uint64)((k.QuadPart + u.QuadPart) / 10000ULL);
4732 uint64 firstCpu = out.cpuTimeMs;
4734 uint64 secondCpu = firstCpu;
4735 if (pd && pd->hJob) {
4736 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION j2;
4737 ZeroMemory(&j2,
sizeof(j2));
4739 if (QueryInformationJobObject(pd->hJob, JobObjectBasicAccountingInformation,
4740 &j2,
sizeof(j2), &rl))
4741 secondCpu = (uint64)((j2.TotalUserTime.QuadPart +
4742 j2.TotalKernelTime.QuadPart) / 10000ULL);
4744 FILETIME c2, e2, k2, u2;
4745 if (GetProcessTimes(h, &c2, &e2, &k2, &u2)) {
4746 ULARGE_INTEGER k, u;
4747 k.LowPart = k2.dwLowDateTime; k.HighPart = k2.dwHighDateTime;
4748 u.LowPart = u2.dwLowDateTime; u.HighPart = u2.dwHighDateTime;
4749 secondCpu = (uint64)((k.QuadPart + u.QuadPart) / 10000ULL);
4753 out.cpuTimeMs = secondCpu;
4759 out.waitingStdin = (secondCpu == firstCpu);
4764#elif defined(__APPLE__)
4769 out.alive =
false; out.waitExact =
false; out.waitingStdin =
false; out.cpuTimeMs = 0;
4770 if (!pid)
return false;
4771 if (kill((pid_t)pid, 0) != 0 && errno == ESRCH)
return true;
4773 struct proc_taskinfo ti;
4774 if (proc_pidinfo((
int)pid, PROC_PIDTASKINFO, 0, &ti,
sizeof(ti)) == (
int)
sizeof(ti))
4775 out.cpuTimeMs = (uint64)((ti.pti_total_user + ti.pti_total_system) / 1000000ULL);
4777 int n = proc_pidinfo((
int)pid, PROC_PIDLISTTHREADS, 0, tids,
sizeof(tids));
4778 if (n <= 0)
return true;
4779 int count = n / (int)
sizeof(uint64_t);
4780 bool allWaiting = (count > 0);
4781 for (
int i = 0; i < count; i++) {
4782 struct proc_threadinfo th;
4783 if (proc_pidinfo((
int)pid, PROC_PIDTHREADINFO, tids[i], &th,
sizeof(th)) != (
int)
sizeof(th)
4784 || th.pth_run_state != TH_STATE_WAITING) {
4785 allWaiting =
false;
break;
4789 struct pipe_fdinfo pfd;
4790 if (proc_pidfdinfo((
int)pid, 0, PROC_PIDFDPIPEINFO, &pfd,
sizeof(pfd)) == (
int)
sizeof(pfd))
4791 out.waitingStdin =
true;
4800#if defined(__x86_64__)
4801 static const long PPW_SYS_read = 0;
4802#elif defined(__aarch64__)
4803 static const long PPW_SYS_read = 63;
4805 static const long PPW_SYS_read = -1;
4808 static bool ppwReadStat(
const char* path,
char& state,
long& pgrp, uint64& cpuTicks) {
4809 FILE* f = fopen(path,
"r");
4810 if (!f)
return false;
4812 size_t len = fread(buf, 1,
sizeof(buf) - 1, f);
4814 if (!len)
return false;
4816 const char* p = strrchr(buf,
')');
4817 if (!p)
return false;
4819 long ppid = 0;
unsigned long ut = 0, st = 0;
4822 if (sscanf(p,
" %c %ld %ld %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu",
4823 &st_c, &ppid, &pgrp, &ut, &st) != 5)
4826 cpuTicks = (uint64)ut + (uint64)st;
4831 static int ppwSyscallIsStdinRead(
const char* path) {
4832 FILE* f = fopen(path,
"r");
4835 size_t len = fread(buf, 1,
sizeof(buf) - 1, f);
4837 if (!len)
return -1;
4839 long nr = 0;
unsigned long arg0 = 0;
4840 if (sscanf(buf,
"%ld %lx", &nr, &arg0) < 1)
4842 if (PPW_SYS_read < 0)
return -1;
4843 return (nr == PPW_SYS_read && arg0 == 0) ? 1 : 0;
4849 if (!pid)
return false;
4851 snprintf(path,
sizeof(path),
"/proc/%u/stat", pid);
4852 char state = 0;
long pgid = 0; uint64 ticks = 0;
4853 if (!ppwReadStat(path, state, pgid, ticks))
return true;
4854 if (state ==
'Z' || state ==
'X')
return true;
4856 long tck = sysconf(_SC_CLK_TCK);
4857 if (tck <= 0) tck = 100;
4858 uint64 totalTicks = 0;
4859 bool sawUnreadable =
false, sawStdinRead =
false;
4865 while ((de =
readdir(proc)) != NULL) {
4866 if (de->
d_name[0] <
'0' || de->
d_name[0] >
'9')
continue;
4867 unsigned long p = strtoul(de->
d_name, NULL, 10);
4868 char pstate = 0;
long ppgrp = 0; uint64 pticks = 0;
4869 snprintf(path,
sizeof(path),
"/proc/%lu/stat", p);
4870 if (!ppwReadStat(path, pstate, ppgrp, pticks))
continue;
4871 if (ppgrp != pgid && (uint32)p != pid)
continue;
4872 totalTicks += pticks;
4875 snprintf(tdir,
sizeof(tdir),
"/proc/%lu/task", p);
4877 if (!tasks) { sawUnreadable =
true;
continue; }
4879 while ((te =
readdir(tasks)) != NULL) {
4880 if (te->
d_name[0] <
'0' || te->
d_name[0] >
'9')
continue;
4881 char tpath[352];
char tstate = 0;
long tpgrp = 0; uint64 tt = 0;
4882 snprintf(tpath,
sizeof(tpath),
"%s/%s/stat", tdir, te->
d_name);
4883 if (ppwReadStat(tpath, tstate, tpgrp, tt) && tstate !=
'S')
4885 snprintf(tpath,
sizeof(tpath),
"%s/%s/syscall", tdir, te->
d_name);
4886 int r = ppwSyscallIsStdinRead(tpath);
4887 if (r < 0) sawUnreadable =
true;
4888 else if (r == 1) sawStdinRead =
true;
4893 }
else sawUnreadable =
true;
4894 out.
cpuTimeMs = totalTicks * 1000ULL / (uint64)tck;
4896 else if (!sawUnreadable) out.
waitExact =
true;
4914 const std::map<std::string, std::string>*
env;
4929 pid_t ppid_before_fork = getpid();
4930 (void)ppid_before_fork;
4932 const char* shArgv[4] = {
"sh",
"-c", r.
cmdline, NULL };
4945 int devnull = open(
"/dev/null", O_WRONLY);
4947 dup2(devnull, STDOUT_FILENO);
4948 dup2(devnull, STDERR_FILENO);
4963 std::map<std::string, std::string>::const_iterator ei = r.
env->begin();
4964 while (ei != r.
env->end()) { setenv(ei->first.c_str(), ei->second.c_str(), 1); ei++; }
4973 if (getppid() != ppid_before_fork)
4975 pid_t self = getpid();
4976 pid_t nanny = fork();
4983 EV_SET(&ev, ppid_before_fork, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL);
4984 if (kevent(kq, &ev, 1, NULL, 0, NULL) != -1) {
4986 kevent(kq, NULL, 0, &out, 1, NULL);
4989 kill(-self, SIGKILL);
4996 if (pres == -1) { perror(0); _exit(1); }
4998 if (getppid() != ppid_before_fork)
5020 std::unique_lock<std::mutex> lock(
gLaunchMx);
5035 std::unique_lock<std::mutex> lock(
gLaunchMx);
5052uint32
NewProcessEx(
const char* cmdline,
const char* initdir,
const char* title,
5053 const std::map<std::string, std::string>* env,
5054 bool captureOutput,
bool ignoreOutput,
bool newProcessGroup,
5055 int posixParentDeathSig,
bool posixUseShell) {
5056 if (!cmdline || !strlen(cmdline))
5061 (void)posixParentDeathSig; (void)posixUseShell;
5064 ghJob = CreateJobObject(NULL, NULL);
5066 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
5067 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
5068 SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli,
sizeof(jeli));
5073 ZeroMemory(&(pData->procInfo),
sizeof(pData->procInfo));
5074 ZeroMemory(&(pData->si),
sizeof(pData->si));
5075 pData->si.cb =
sizeof(pData->si);
5076 pData->si.wShowWindow = SW_SHOWNOACTIVATE;
5077 pData->si.dwFlags = STARTF_USESHOWWINDOW;
5081 HANDLE hOutWrite = NULL, hErrWrite = NULL, hNull = NULL, hInRead = NULL;
5082 SECURITY_ATTRIBUTES sa;
5083 ZeroMemory(&sa,
sizeof(sa));
5084 sa.nLength =
sizeof(sa);
5085 sa.bInheritHandle =
TRUE;
5086 sa.lpSecurityDescriptor = NULL;
5088 if (captureOutput) {
5090 if ( !CreatePipe(&pData->hOutRead, &hOutWrite, &sa, 0) ||
5091 !CreatePipe(&pData->hErrRead, &hErrWrite, &sa, 0) ) {
5092 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5093 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5094 if (hOutWrite) CloseHandle(hOutWrite);
5095 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5099 SetHandleInformation(pData->hOutRead, HANDLE_FLAG_INHERIT, 0);
5100 SetHandleInformation(pData->hErrRead, HANDLE_FLAG_INHERIT, 0);
5109 if (!CreatePipe(&hInRead, &pData->hInWrite, &sa, 0)) {
5110 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create stdin pipe for '%s'", cmdline);
5111 CloseHandle(pData->hOutRead); CloseHandle(hOutWrite);
5112 CloseHandle(pData->hErrRead); CloseHandle(hErrWrite);
5116 SetHandleInformation(pData->hInWrite, HANDLE_FLAG_INHERIT, 0);
5117 pData->si.dwFlags |= STARTF_USESTDHANDLES;
5118 pData->si.hStdOutput = hOutWrite;
5119 pData->si.hStdError = hErrWrite;
5120 pData->si.hStdInput = hInRead;
5122 else if (ignoreOutput) {
5123 hNull = CreateFile(
"NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
5124 &sa, OPEN_EXISTING, 0, NULL);
5125 if (hNull != INVALID_HANDLE_VALUE) {
5126 pData->si.dwFlags |= STARTF_USESTDHANDLES;
5127 pData->si.hStdOutput = hNull;
5128 pData->si.hStdError = hNull;
5129 pData->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
5135 char* envBlock = NULL;
5136 if (env && env->size()) {
5137 std::map<std::string, std::string> merged;
5138 LPCH parentEnv = GetEnvironmentStrings();
5140 for (LPCH p = parentEnv; *p; ) {
5141 std::string entry = p;
5142 size_t eq = entry.find(
'=');
5143 if (eq != std::string::npos && eq > 0)
5144 merged[entry.substr(0, eq)] = entry.substr(eq + 1);
5145 p += entry.size() + 1;
5147 FreeEnvironmentStrings(parentEnv);
5149 std::map<std::string, std::string>::const_iterator ei = env->begin();
5150 while (ei != env->end()) { merged[ei->first] = ei->second; ei++; }
5152 std::map<std::string, std::string>::iterator mi = merged.begin();
5153 while (mi != merged.end()) { total += mi->first.size() + 1 + mi->second.size() + 1; mi++; }
5154 envBlock =
new char[total];
5156 for (mi = merged.begin(); mi != merged.end(); mi++) {
5157 std::string kv = mi->first +
"=" + mi->second;
5158 memcpy(envBlock + off, kv.c_str(), kv.size() + 1);
5159 off += kv.size() + 1;
5164 DWORD flags = CREATE_NEW_CONSOLE;
5165 if (newProcessGroup)
5166 flags |= CREATE_NEW_PROCESS_GROUP;
5173 char* titleCopy = NULL;
5175 size_t tlen = strlen(title);
5176 titleCopy =
new char[tlen + 1];
5177 memcpy(titleCopy, title, tlen + 1);
5178 pData->si.lpTitle = titleCopy;
5180 size_t clen = strlen(cmdline);
5181 char* cmd =
new char[clen + 1];
5182 memcpy(cmd, cmdline, clen + 1);
5184 int res = CreateProcess(NULL, cmd, NULL, NULL,
TRUE, flags, envBlock, initdir, &pData->si, &pData->procInfo);
5186 delete [] titleCopy;
5188 if (envBlock)
delete [] envBlock;
5193 if (hOutWrite) CloseHandle(hOutWrite);
5194 if (hErrWrite) CloseHandle(hErrWrite);
5195 if (hInRead) CloseHandle(hInRead);
5196 if (hNull) CloseHandle(hNull);
5200 int length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, msg,
sizeof(msg), NULL);
5202 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: error creating process: %s\n%s", msg, cmdline);
5203 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5204 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5205 if (pData->hInWrite) CloseHandle(pData->hInWrite);
5212 AssignProcessToJobObject(ghJob, pData->procInfo.hProcess);
5219 pData->hJob = CreateJobObject(NULL, NULL);
5221 if (!AssignProcessToJobObject(pData->hJob, pData->procInfo.hProcess)) {
5222 CloseHandle(pData->hJob);
5227 return pData->procInfo.dwProcessId;
5237 (void)title; (void)ignoreOutput;
5242 int outPipe[2] = { -1, -1 }, errPipe[2] = { -1, -1 };
5243 if (captureOutput) {
5244 if (pipe(outPipe) != 0) {
5245 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5248 if (pipe(errPipe) != 0) {
5249 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessEx: could not create output pipes for '%s'", cmdline);
5250 close(outPipe[0]); close(outPipe[1]);
5257 if (!posixUseShell) {
5260 if (captureOutput) { close(outPipe[0]); close(outPipe[1]); close(errPipe[0]); close(errPipe[1]); }
5274 req.
pid = -1; req.
done =
false;
5281 if (captureOutput) { close(outPipe[0]); close(outPipe[1]); close(errPipe[0]); close(errPipe[1]); }
5286 if (captureOutput) {
5289 fcntl(outPipe[0], F_SETFL, fcntl(outPipe[0], F_GETFL, 0) | O_NONBLOCK);
5290 fcntl(errPipe[0], F_SETFL, fcntl(errPipe[0], F_GETFL, 0) | O_NONBLOCK);
5292 pData->
outFD = outPipe[0];
5293 pData->
errFD = errPipe[0];
5303 if (!data || !len)
return false;
5308 if (!pData->hInWrite)
return false;
5310 while (written < len) {
5312 if (!WriteFile(pData->hInWrite, data + written, (DWORD)(len - written), &n, NULL) || !n) {
5317 written += (uint32)n;
5325 (void)proc; (void)data; (void)len;
5337 if (!pData->hInWrite)
return false;
5338 CloseHandle(pData->hInWrite);
5339 pData->hInWrite = NULL;
5353 HANDLE handles[2] = { pData->hOutRead, pData->hErrRead };
5354 std::string* targets[2] = { &out, &err };
5356 for (
int n = 0; n < 2; n++) {
5357 if (!handles[n])
continue;
5360 while (PeekNamedPipe(handles[n], NULL, 0, NULL, &avail, NULL) && avail) {
5361 DWORD toRead = avail <
sizeof(buf) ? avail : (DWORD)
sizeof(buf);
5363 if (!ReadFile(handles[n], buf, toRead, &got, NULL) || !got)
break;
5364 targets[n]->append(buf, got);
5377 std::string* targets[2] = { &out, &err };
5379 for (
int n = 0; n < 2; n++) {
5380 if (fds[n] < 0)
continue;
5382 while ((got = read(fds[n], buf,
sizeof(buf))) > 0)
5383 targets[n]->append(buf, (
size_t)got);
5394#if !defined(WINDOWS)
5406 const std::map<std::string, std::string>* env,
5407 uint16 cols, uint16 rows) {
5410 (void)cmdline; (void)initdir; (void)env; (void)cols; (void)rows;
5414 if (!cmdline || !*cmdline)
return 0;
5416 int master = posix_openpt(O_RDWR | O_NOCTTY);
5418 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessTerminal: posix_openpt failed (%d) for '%s'", errno, cmdline);
5421 if (grantpt(master) != 0 || unlockpt(master) != 0) {
5422 LogPrint(0,
LOG_SYSTEM, 0,
"NewProcessTerminal: grantpt/unlockpt failed (%d) for '%s'", errno, cmdline);
5426 char slaveName[256];
5427 #if defined(__APPLE__)
5428 const char* sn = ptsname(master);
5429 if (!sn) { close(master);
return 0; }
5430 strncpy(slaveName, sn,
sizeof(slaveName) - 1);
5431 slaveName[
sizeof(slaveName) - 1] = 0;
5433 if (ptsname_r(master, slaveName,
sizeof(slaveName)) != 0) { close(master);
return 0; }
5436 memset(&ws, 0,
sizeof(ws));
5437 ws.ws_col = cols ? cols : 80;
5438 ws.ws_row = rows ? rows : 25;
5439 ioctl(master, TIOCSWINSZ, &ws);
5442 if (pid < 0) { close(master);
return 0; }
5448 int slave = open(slaveName, O_RDWR);
5449 if (slave < 0) _exit(127);
5451 ioctl(slave, TIOCSCTTY, 0);
5453 dup2(slave, STDIN_FILENO);
5454 dup2(slave, STDOUT_FILENO);
5455 dup2(slave, STDERR_FILENO);
5456 if (slave > STDERR_FILENO) close(slave);
5457 if (initdir && *initdir && chdir(initdir) != 0) _exit(126);
5459 std::map<std::string, std::string>::const_iterator ei = env->begin();
5460 while (ei != env->end()) { setenv(ei->first.c_str(), ei->second.c_str(), 1); ei++; }
5462 execl(
"/bin/sh",
"sh",
"-c", cmdline, (
char*)NULL);
5466 fcntl(master, F_SETFL, fcntl(master, F_GETFL, 0) | O_NONBLOCK);
5469 (*TerminalMasterMap)[(uint32)pid] = master;
5477 (void)proc; (void)out;
5484 ssize_t got = read(fd, buf,
sizeof(buf));
5485 if (got > 0) { out.append(buf, (
size_t)got);
continue; }
5486 if (got == 0) { eofOut =
true;
break; }
5487 if (errno == EINTR)
continue;
5488 if (errno == EAGAIN || errno == EWOULDBLOCK)
break;
5501 (void)proc; (void)data; (void)len;
5504 if (!data || !len)
return false;
5508 while (written < len) {
5509 ssize_t n = write(fd, data + written, len - written);
5511 if (errno == EINTR)
continue;
5512 if (errno == EAGAIN || errno == EWOULDBLOCK) {
Sleep(2);
continue; }
5515 written += (uint32)n;
5523 (void)proc; (void)cols; (void)rows;
5529 memset(&ws, 0,
sizeof(ws));
5530 ws.ws_col = cols ? cols : 80;
5531 ws.ws_row = rows ? rows : 25;
5532 if (ioctl(fd, TIOCSWINSZ, &ws) != 0)
return false;
5533 kill(-(pid_t)proc, SIGWINCH);
5555 return (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, (DWORD)proc) != 0);
5557 return (kill((pid_t)proc, sig) == 0);
5567 if (WaitForSingleObject(pData->procInfo.hProcess, timeout) == WAIT_OBJECT_0) {
5568 if (GetExitCodeProcess(pData->procInfo.hProcess, &exitcode) && (exitcode == STILL_ACTIVE)) {
5573 CloseHandle(pData->procInfo.hProcess);
5574 CloseHandle(pData->procInfo.hThread);
5575 if (pData->hOutRead) CloseHandle(pData->hOutRead);
5576 if (pData->hErrRead) CloseHandle(pData->hErrRead);
5577 if (pData->hInWrite) CloseHandle(pData->hInWrite);
5578 if (pData->hJob) CloseHandle(pData->hJob);
5580 returncode = exitcode;
5587 HANDLE hproc = OpenProcess(NULL, NULL, (DWORD)proc);
5591 if (WaitForSingleObject(hproc, timeout) == WAIT_OBJECT_0) {
5592 if (GetExitCodeProcess(hproc, &exitcode) && (exitcode == STILL_ACTIVE)) {
5597 returncode = exitcode;
5641 for (n=1; n<argc; n++) {
5644 val = strchr(argv[n],
'=');
5683 if (p1 == std::string::npos) {
5684 if (p2 == std::string::npos)
5689 else if (p2 == std::string::npos)
5706 if (p1 == std::string::npos) {
5707 if (p2 == std::string::npos)
5712 else if (p2 == std::string::npos)
5739 std::map<std::string, std::string>::const_iterator it =
5755 FreeLibrary(handle);
5769 std::string realLibName;
5771 realLibName = filename;
5775 int32 filenameStart;
5776 if ( (filenameStart = realLibName.find_last_of(
'/') == std::string::npos ))
5782 realLibName.insert(filenameStart,
"lib");
5784 if (!filenameStart) {
5786 realLibName.insert(0,
"./");
5788 realLibName.insert(0, path);
5798 std::string errorText;
5805 if (handle == NULL) {
5807 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5808 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5809 (LPTSTR)&lpMsgBuf, 0, NULL);
5810 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find or load debug library '%sDebug': %s", filename, lpMsgBuf);
5811 LocalFree(lpMsgBuf);
5815 handle = LoadLibrary(filename);
5816 if (handle == NULL) {
5818 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5819 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5820 (LPTSTR) &lpMsgBuf, 0, NULL);
5821 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find or load library '%s': %s", filename, lpMsgBuf);
5822 LocalFree(lpMsgBuf);
5828 const char* dlErrorText;
5835 std::string debugName = realLibName;
5838 handle = dlopen(debugName.c_str(), RTLD_NOW | RTLD_GLOBAL);
5840 dlErrorText = dlerror();
5842 if (dlErrorText && strlen(dlErrorText) &&
5843 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, debugName.c_str())))
5844 errorText = dlErrorText;
5848 if (!handle && !errorText.size()) {
5851 dlErrorText = dlerror();
5853 if (dlErrorText && strlen(dlErrorText) &&
5854 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, realLibName.c_str())))
5855 errorText = dlErrorText;
5859 if (!handle && !errorText.size() && !strchr(filename,
'/')) {
5862 handle = dlopen(realLibName.c_str(), RTLD_NOW | RTLD_GLOBAL);
5864 dlErrorText = dlerror();
5866 if (dlErrorText && strlen(dlErrorText) &&
5867 !(strstr(dlErrorText,
"No such file") && strstr(dlErrorText, realLibName.c_str())))
5868 errorText = dlErrorText;
5872 if (handle == NULL) {
5873 if (errorText.size())
5874 LogPrint(0,
LOG_SYSTEM, 0,
"Could not load library file '%s': %s", realLibName.c_str(), errorText.c_str());
5886 if (!strlen(funcName))
5897 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5898 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5899 (LPTSTR) &lpMsgBuf, 0, NULL);
5900 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find library function: %s: %s", funcName, lpMsgBuf);
5902 LocalFree(lpMsgBuf);
5910 if (errmsg != NULL) {
5911 LogPrint(0,
LOG_SYSTEM, 0,
"Could not find library function: %s: %s", (
char*) funcName, (
char*) errmsg);
5920 if (!lib->
load(libName)) {
5938 char* name =
new char[1024];
5969 std::string outString, errString;
5970 if (!
RunOSCommand(
"uname -n", NULL, 1000, outString, errString)) {
5986 HANDLE hProcess = GetCurrentProcess();
5987 PROCESS_MEMORY_COUNTERS pmc;
5988 if (hProcess == NULL)
5990 if ( GetProcessMemoryInfo( hProcess, &pmc,
sizeof(pmc)) != 0)
5991 return (uint64)pmc.WorkingSetSize;
5995 struct task_basic_info_64 info;
5996 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
5997 if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t)&info, &count) == KERN_SUCCESS)
5998 return (uint64)info.resident_size;
6004 if ( (fp = fopen(
"/proc/self/statm",
"r" )) == NULL )
6006 if ( fscanf( fp,
"%*s%ld", &rss ) != 1 ) {
6011 return (uint64)rss * (uint64)sysconf( _SC_PAGESIZE);
6018 HANDLE hProcess = GetCurrentProcess();
6019 PROCESS_MEMORY_COUNTERS pmc;
6020 if (hProcess == NULL)
6022 if ( GetProcessMemoryInfo( hProcess, &pmc,
sizeof(pmc)) != 0)
6023 return (uint64)pmc.PeakWorkingSetSize;
6028 struct rusage usage;
6029 getrusage(RUSAGE_SELF, &usage);
6030 return (uint64)usage.ru_maxrss;
6033 struct rusage usage;
6034 getrusage( RUSAGE_SELF, &usage );
6035 return ((uint64)usage.ru_maxrss) * 1024L;
6057 SYSTEM_INFO siSysInfo;
6058 GetSystemInfo(&siSysInfo);
6059 return (uint16) siSysInfo.dwNumberOfProcessors;
6062 size_t len =
sizeof(ncpu);
6063 if (sysctlbyname(
"hw.ncpu", &ncpu, &len, NULL, 0) == 0 && ncpu > 0)
6064 return (uint16)(ncpu > 65535 ? 65535 : ncpu);
6067 long n = sysconf(_SC_NPROCESSORS_ONLN);
6069 return (uint16)(n > 65535 ? 65535 : (uint16)n);
6076 SYSTEM_INFO siSysInfo;
6077 GetSystemInfo(&siSysInfo);
6078 switch(siSysInfo.wProcessorArchitecture) {
6079 case PROCESSOR_ARCHITECTURE_AMD64:
6081 case PROCESSOR_ARCHITECTURE_IA64:
6083 case PROCESSOR_ARCHITECTURE_INTEL:
6089 #if defined(__x86_64__)
6091 #elif defined(__i386__)
6093 #elif defined(__aarch64__)
6099 #if defined(__x86_64__)
6101 #elif defined(__i386__)
6103 #elif defined(__aarch64__)
6135 size_t len =
sizeof(freq);
6136 if (sysctlbyname(
"hw.cpufrequency", &freq, &len, NULL, 0) == 0)
6141 std::ifstream cpuinfo(
"/proc/cpuinfo");
6143 while (cpuinfo && getline(cpuinfo, line)) {
6144 if (line.compare(0, 7,
"cpu MHz") == 0) {
6145 size_t colon = line.find(
':');
6146 if (colon != std::string::npos) {
6148 if (sscanf(line.c_str() + colon + 1,
"%lf", &mhz) == 1 && mhz > 0)
6149 return (uint64)(mhz * 1000000.0);
6160 MEMORYSTATUS memstat;
6161 GlobalMemoryStatus(&memstat);
6162 return (uint64)memstat.dwTotalPhys;
6166 size_t len =
sizeof(memsize);
6167 if (sysctlbyname(
"hw.memsize", &memsize, &len, NULL, 0) == 0)
6171 struct sysinfo info;
6172 if (sysinfo(&info) == 0)
6173 return info.totalram;
6183 MEMORYSTATUSEX memstat;
6184 memset(&memstat, 0,
sizeof(MEMORYSTATUSEX));
6185 memstat.dwLength =
sizeof(MEMORYSTATUSEX);
6186 if (!GlobalMemoryStatusEx(&memstat)) {
6187 int a = GetLastError();
6190 totalRAM = (uint64)memstat.ullTotalPhys;
6191 freeRAM = (uint64)memstat.ullAvailPhys;
6196 size_t len =
sizeof(memsize);
6197 if (sysctlbyname(
"hw.memsize", &memsize, &len, NULL, 0) != 0)
6200 vm_statistics64_data_t vm_stat;
6201 mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
6202 if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &count) != KERN_SUCCESS)
6204 vm_size_t page_size;
6205 if (host_page_size(mach_host_self(), &page_size) != KERN_SUCCESS)
6207 freeRAM = (uint64)vm_stat.free_count * (uint64)page_size;
6210 struct sysinfo info;
6211 if (sysinfo(&info) == 0) {
6212 totalRAM = info.totalram;
6213 freeRAM = info.freeram;
6225 SYSTEM_INFO siSysInfo;
6226 GetSystemInfo(&siSysInfo);
6228 switch(siSysInfo.wProcessorArchitecture) {
6229 case PROCESSOR_ARCHITECTURE_UNKNOWN:
6231 case PROCESSOR_ARCHITECTURE_INTEL:
6232 switch(siSysInfo.wProcessorLevel) {
6258 case PROCESSOR_ARCHITECTURE_MIPS:
6261 case PROCESSOR_ARCHITECTURE_ALPHA:
6264 case PROCESSOR_ARCHITECTURE_PPC:
6267 case PROCESSOR_ARCHITECTURE_IA64:
6270 case PROCESSOR_ARCHITECTURE_AMD64:
6284 if (strlen(
OSName) == 0) {
6320 BOOL bOsVersionInfoEx;
6325 ZeroMemory(&osvi,
sizeof(OSVERSIONINFO));
6326 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
6328 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
6330 osvi.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
6331 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
6335 major = osvi.dwMajorVersion;
6336 minor = osvi.dwMinorVersion;
6337 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6341 OSVERSIONINFOEX osvi;
6342 BOOL bOsVersionInfoEx;
6347 ZeroMemory(&osvi,
sizeof(OSVERSIONINFOEX));
6348 osvi.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
6350 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
6352 osvi.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
6353 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
6357 switch (osvi.dwPlatformId)
6360 case VER_PLATFORM_WIN32_NT:
6364 if( osvi.dwMajorVersion == 4 &&
6365 lstrcmpi( osvi.szCSDVersion,
"Service Pack 6" ) == 0 )
6371 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
6372 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
6373 0, KEY_QUERY_VALUE, &hKey );
6374 if( lRet == ERROR_SUCCESS ) {
6377 build = osvi.dwBuildNumber & 0xFFFF;
6381 major = (uint16)osvi.dwMajorVersion;
6382 minor = (uint16)osvi.dwMinorVersion;
6383 build = (uint16)osvi.dwBuildNumber & 0xFFFF;
6384 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6387 RegCloseKey( hKey );
6391 major = (uint16)osvi.dwMajorVersion;
6392 minor = (uint16)osvi.dwMinorVersion;
6393 build = (uint16)osvi.dwBuildNumber & 0xFFFF;
6395 if (strlen((
char*)osvi.szCSDVersion) < textSize)
6462char*
Int2Ascii(int64 value,
char* result, uint16 size, uint8 base) {
6463 if (base < 2 || base > 36) {
6468 char* ptr = result, *ptr1 = result, tmp_char;
6474 *ptr++ =
"zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
6489char*
Uint2Ascii(uint64 value,
char* result, uint16 size, uint8 base) {
6490 if (base < 2 || base > 36) {
6495 char* ptr = result, *ptr1 = result, tmp_char;
6501 *ptr++ =
"zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
6514 size = (len * 2) + 4;
6515 unsigned char* result =
new unsigned char[size];
6519 const char* src = ascii;
6520 for (uint32 n = 0; n < len; n++) {
6527 size = (len * 2) + 2;
6532bool GetSocketError(
int error,
char* errorString, uint16 errorStringMaxSize,
bool* isRecoverable) {
6534 if (errorStringMaxSize < 128)
6539 if (error == WSANOTINITIALISED) {
6540 utils::strcpyavail(errorString,
"Cannot initialize WinSock!", errorStringMaxSize,
true);
6541 *isRecoverable =
false;
6543 else if (error == WSAENETDOWN) {
6544 utils::strcpyavail(errorString,
"The network subsystem or the associated service provider has failed", errorStringMaxSize,
true);
6545 *isRecoverable =
false;
6547 else if (error == WSAEAFNOSUPPORT) {
6548 utils::strcpyavail(errorString,
"The specified address family is not supported", errorStringMaxSize,
true);
6549 *isRecoverable =
false;
6551 else if (error == WSAEINPROGRESS) {
6552 utils::strcpyavail(errorString,
"A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function", errorStringMaxSize,
true);
6553 *isRecoverable =
true;
6555 else if (error == WSAEMFILE) {
6556 utils::strcpyavail(errorString,
"No more socket descriptors are available", errorStringMaxSize,
true);
6557 *isRecoverable =
false;
6559 else if (error == WSAENOBUFS) {
6560 utils::strcpyavail(errorString,
"No buffer space is available. The socket cannot be created", errorStringMaxSize,
true);
6561 *isRecoverable =
false;
6563 else if (error == WSAEPROTONOSUPPORT) {
6564 utils::strcpyavail(errorString,
"The specified protocol is not supported", errorStringMaxSize,
true);
6565 *isRecoverable =
false;
6567 else if (error == WSAEPROTOTYPE) {
6568 utils::strcpyavail(errorString,
"The specified protocol is the wrong type for this socket", errorStringMaxSize,
true);
6569 *isRecoverable =
false;
6571 else if (error == WSAESOCKTNOSUPPORT) {
6572 utils::strcpyavail(errorString,
"The specified socket type is not supported in this address family", errorStringMaxSize,
true);
6573 *isRecoverable =
false;
6575 else if (error == WSAEADDRINUSE) {
6576 utils::strcpyavail(errorString,
"The socket's local address is already in use and the socket was not marked to allow address reuse with SO_REUSEADDR. This error usually occurs during execution of the bind function, but could be delayed until this function if the bind was to a partially wildcard address (involving ADDR_ANY) and if a specific address needs to be committed at the time of this function", errorStringMaxSize,
true);
6577 *isRecoverable =
false;
6579 else if (error == WSAEINVAL) {
6580 utils::strcpyavail(errorString,
"The socket has not been bound with bind", errorStringMaxSize,
true);
6581 *isRecoverable =
false;
6583 else if (error == WSAEISCONN) {
6584 utils::strcpyavail(errorString,
"The socket is already connected", errorStringMaxSize,
true);
6585 *isRecoverable =
false;
6587 else if (error == WSAENOTSOCK) {
6588 utils::strcpyavail(errorString,
"The descriptor is not a socket", errorStringMaxSize,
true);
6589 *isRecoverable =
false;
6591 else if (error == WSAEOPNOTSUPP) {
6592 utils::strcpyavail(errorString,
"The referenced socket is not of a type that supports the listen operation", errorStringMaxSize,
true);
6593 *isRecoverable =
false;
6595 else if (error == WSAEADDRNOTAVAIL) {
6596 utils::strcpyavail(errorString,
"The specified address is not a valid address for this machine", errorStringMaxSize,
true);
6597 *isRecoverable =
false;
6599 else if (error == WSAEFAULT) {
6600 utils::strcpyavail(errorString,
"The name or namelen parameter is not a valid part of the user address space", errorStringMaxSize,
true);
6601 *isRecoverable =
false;
6603 else if (error == WSAEMFILE) {
6604 utils::strcpyavail(errorString,
"The queue is nonempty upon entry to accept and there are no descriptors available", errorStringMaxSize,
true);
6605 *isRecoverable =
false;
6608 utils::strcpyavail(errorString,
"The socket is marked as nonblocking and no connections are present to be accepted", errorStringMaxSize,
true);
6609 *isRecoverable =
false;
6611 else if (error == WSAETIMEDOUT) {
6612 utils::strcpyavail(errorString,
"Attempt to connect timed out without establishing a connection", errorStringMaxSize,
true);
6613 *isRecoverable =
false;
6615 else if (error == WSAENETUNREACH) {
6616 utils::strcpyavail(errorString,
"The network cannot be reached from this host at this time", errorStringMaxSize,
true);
6617 *isRecoverable =
false;
6619 else if (error == WSAEISCONN) {
6620 utils::strcpyavail(errorString,
"The socket is already connected (connection-oriented sockets only)", errorStringMaxSize,
true);
6621 *isRecoverable =
false;
6623 else if (error == WSAECONNREFUSED) {
6624 utils::strcpyavail(errorString,
"The attempt to connect was forcefully rejected", errorStringMaxSize,
true);
6625 *isRecoverable =
false;
6627 else if (error == WSAEAFNOSUPPORT) {
6628 utils::strcpyavail(errorString,
"Addresses in the specified family cannot be used with this socket", errorStringMaxSize,
true);
6629 *isRecoverable =
false;
6631 else if (error == WSAEADDRNOTAVAIL) {
6632 utils::strcpyavail(errorString,
"The remote address is not a valid address (such as ADDR_ANY)", errorStringMaxSize,
true);
6633 *isRecoverable =
false;
6635 else if (error == WSAEALREADY) {
6636 utils::strcpyavail(errorString,
"A nonblocking connect call is in progress on the specified socket", errorStringMaxSize,
true);
6637 *isRecoverable =
false;
6639 else if (error == WSAECONNRESET) {
6641 *isRecoverable =
false;
6643 else if (error == WSAECONNABORTED) {
6644 utils::strcpyavail(errorString,
"Software caused connection abort", errorStringMaxSize,
true);
6645 *isRecoverable =
false;
6648 snprintf(errorString, errorStringMaxSize,
"TCP error with no description: %d", error);
6649 *isRecoverable =
false;
6655 utils::strcpyavail(errorString,
"Cannot initialise socket", errorStringMaxSize,
true);
6656 *isRecoverable =
false;
6660 *isRecoverable =
false;
6670 int err = WSAGetLastError();
6681 DWORD error = GetLastError();
6682 uint32 len = FormatMessage(
6683 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
6684 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
6685 (LPTSTR) &lpMsgBuf, 0, NULL);
6686 std::string str = (
char*)lpMsgBuf;
6687 LocalFree(lpMsgBuf);
6717 ldiv_t d = ldiv(timeout*1000, 1000000);
6723 return( select(maxfd, NULL, &wds, NULL, &tv) > 0);
6749 ldiv_t d = ldiv(timeout*1000, 1000000);
6756 int ret = select(maxfd, &rdds, NULL, NULL, &tv);
6764 #if defined(WINDOWS)
6765 unsigned long parm = 1;
6766 ioctlsocket(s, FIONBIO, &parm);
6768 long parm = fcntl(s, F_GETFL);
6770 fcntl(s, F_SETFL, parm);
6776 #if defined(WINDOWS)
6777 unsigned long parm = 0;
6778 ioctlsocket(s, FIONBIO, &parm);
6780 long parm = fcntl(s, F_GETFL);
6781 parm &= ~O_NONBLOCK;
6782 fcntl(s, F_SETFL, parm);
6789 if ( (name == NULL) || (strlen(name) == 0) )
6805 struct addrinfo hints, *res;
6807 const char *cause = NULL;
6809 memset(&hints, 0,
sizeof(hints));
6812 hints.ai_family = AF_INET;
6813 hints.ai_socktype = SOCK_STREAM;
6814 hints.ai_protocol = IPPROTO_TCP;
6816 error = getaddrinfo(name, NULL, &hints, &res);
6818 __except (EXCEPTION_CONTINUE_EXECUTION) {
6823 memcpy(&address, res->ai_addr->sa_data + 2,
sizeof(address));
6833 struct addrinfo hints, *res;
6835 const char *cause = NULL;
6837 memset(&hints, 0,
sizeof(hints));
6839 hints.ai_family = PF_UNSPEC;
6840 hints.ai_socktype = SOCK_STREAM;
6841 error = getaddrinfo(name, NULL, &hints, &res);
6843 memcpy(&address, res->ai_addr->sa_data+2, 4);
6853 bool IsNetworkInitialised =
false;
6854 bool CheckNetworkInit() {
6855 if (IsNetworkInitialised)
return true;
6857 if (WSAStartup(MAKEWORD(1,1), &info) != 0) {
6861 IsNetworkInitialised =
true;
6868 struct hostent *pHost;
6870 unsigned char* addrChars = (
unsigned char*)&address;
6872 char* addrString =
new char[20];
6873 snprintf(addrString, 20,
"%u.%u.%u.%u", addrChars[0], addrChars[1], addrChars[2], addrChars[3]);
6876 pHost = gethostbyname(addrString);
6877 delete [] addrString;
6878 if (pHost == NULL) {
6881 if (strlen(pHost->h_name) > maxSize-1) {
6889 pHost = gethostbyname(addrString);
6890 delete [] addrString;
6894 if (strlen(pHost->h_name) > maxSize-1)
6901 pHost =
new struct hostent;
6904 gethostbyname_r(addrString, pHost, bf, 2000, &pHost, &er);
6905 delete [] addrString;
6911 if (strlen(pHost->h_name) > maxSize-1)
6923 char* name =
new char[256];
6929 std::string sname = name;
6937 if (gethostname(name, maxSize) == 0)
6998 for (uint32 i=0; i<c; i++) {
6999 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) )
7000 address = interfaces[i].
mac;
7002 delete [] interfaces;
7003 return (address != 0);
7011 uint64* addresses =
new uint64[c];
7013 for (uint32 i=0; i<c; i++) {
7014 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) )
7015 addresses[p++] = interfaces[i].
mac;
7032 if ((addresses == NULL) || (count == 0)) {
7033 delete [] addresses;
7038 for (n=0; n<count; n++) {
7039 if (addresses[n] == address) {
7040 delete [] addresses;
7044 delete [] addresses;
7052 if ((addresses == NULL) || (count == 0)) {
7053 delete [] addresses;
7058 bool localhostPresent =
false;
7059 for (n=0; n<count; n++) {
7061 if (addresses[n] != 0) {
7062 address = addresses[n];
7063 delete [] addresses;
7068 localhostPresent =
true;
7070 delete [] addresses;
7072 if (localhostPresent) {
7083 uint32 maxSize = 128;
7084 uint32* addresses =
new uint32[maxSize];
7089 char* szHostName =
new char[255];
7091 bool canAskHost =
true;
7092 if( gethostname(szHostName, 255) != 0 ) {
7095 if (err == WSANOTINITIALISED) {
7097 if (WSAStartup(MAKEWORD(1,1), &info) != 0) {
7098 delete [] szHostName;
7102 if( gethostname(szHostName, 255) != 0 )
7113 struct hostent * pHost;
7116 #if !defined(WINDOWS) && !defined(Darwin)
7122 char* hostBuf = NULL;
7123 struct hostent* hostAlloc = NULL;
7130 pHost = gethostbyname(szHostName);
7134 pHost = gethostbyname(szHostName);
7139 hostAlloc =
new struct hostent;
7140 hostBuf =
new char[2000];
7142 struct hostent* hres = NULL;
7143 int res = gethostbyname_r(szHostName, hostAlloc, hostBuf, 2000, &hres, &er);
7150 if ((res != 0) || (hres == NULL))
7157 for( i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
7160 memcpy(&addr, ((
unsigned char*)pHost->h_addr_list[i]),
sizeof(uint32));
7162 for (j=0; j<count; j++) {
7163 if (addresses[j] == addr) {
7169 addresses[count++] = addr;
7187 for (i=0; i<c; i++) {
7189 if ( (interfaces[i].address != 0) && (interfaces[i].address !=
LOCALHOSTIP) ) {
7190 for (j=0; j<count; j++) {
7191 if (addresses[j] == interfaces[i].address) {
7197 addresses[count++] = interfaces[i].
address;
7200 delete [] interfaces;
7201 delete [] szHostName;
7208 uint32 maxSize = 128;
7221 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
7224 ULONG family = AF_INET;
7226 LPVOID lpMsgBuf = NULL;
7228 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
7229 ULONG outBufLen = 0;
7230 ULONG Iterations = 0;
7232 PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
7233 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
7234 PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
7235 PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
7236 IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
7237 IP_ADAPTER_PREFIX *pPrefix = NULL;
7244 pAddresses = (IP_ADAPTER_ADDRESSES *)
MALLOC(outBufLen);
7245 if (pAddresses == NULL)
7249 GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
7251 if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
7260 }
while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < 10));
7263 if (dwRetVal == NO_ERROR) {
7265 pCurrAddresses = pAddresses;
7266 while (pCurrAddresses) {
7267 if ( (pCurrAddresses->OperStatus == IfOperStatusUp) && (pCurrAddresses->IfIndex != 0)) {
7270 pUnicast = pCurrAddresses->FirstUnicastAddress;
7271 if (pUnicast != NULL) {
7272 for (i = 0; pUnicast != NULL; i++) {
7273 addr = *(uint32*)(((
unsigned char*) ((
SOCKADDR*)(pUnicast->Address.lpSockaddr))->sa_data) + 2);
7275 interfaces[count].
address = addr;
7276 interfaces[count].
mac = 0;
7277 if (pCurrAddresses->PhysicalAddressLength == 6)
7278 memcpy(&(interfaces[count].mac), &(pCurrAddresses->PhysicalAddress), 6);
7279 WideCharToMultiByte( CP_ACP, 0, pCurrAddresses->Description, -1, interfaces[count].
name,
MAXKEYNAMELEN, NULL, NULL );
7280 WideCharToMultiByte( CP_ACP, 0, pCurrAddresses->FriendlyName, -1, interfaces[count].
friendlyName,
MAXKEYNAMELEN, NULL, NULL );
7283 pUnicast = pUnicast->Next;
7288 pCurrAddresses = pCurrAddresses->Next;
7299 struct sockaddr_in *saptr = NULL;
7300 struct if_nameindex *iflist = NULL, *listsave = NULL;
7303 if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
7308 iflist = listsave = if_nameindex();
7310 if (iflist == NULL) {
7318 for(; iflist->if_index != 0; iflist++) {
7320 strncpy(ifreq.ifr_name, iflist->if_name, IF_NAMESIZE);
7322 if(ioctl(sock, SIOCGIFADDR, &ifreq) != 0) {
7327 saptr = (
struct sockaddr_in *)&ifreq.ifr_addr;
7330 memcpy(&(interfaces[count].address), &(saptr->sin_addr.s_addr),
sizeof(uint32));
7333 interfaces[count].
mac = 0;
7336 interfaces[count].
mac = 0;
7337 ioctl(sock, SIOCGIFHWADDR, &ifreq);
7338 memcpy(&(interfaces[count].mac), &(ifreq.ifr_hwaddr.sa_data), 6);
7343 if_freenameindex(listsave);
7355 struct sockaddr_in addr;
7356 addr.sin_family= AF_INET;
7357 addr.sin_addr.s_addr=INADDR_ANY;
7358 bool result =
false;
7360 nextPort = lastPort + 1;
7361 while (nextPort < lastPort + 1000) {
7362 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==
INVALID_SOCKET)
7369 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char *) &one,
sizeof(one));
7381 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,
sizeof(one));
7384 addr.sin_port=htons(nextPort);
7400 printf(
"Testing Utils...\n\n");
7402 char hostname[1024];
7404 printf(
"Error GetLocalHostname\n");
7407 printf(
"Local Hostname: '%s'\n\n", hostname);
7410 unsigned char* addrChars = (
unsigned char*) &addr;
7412 printf(
"Error GetLocalIPAddress\n");
7415 printf(
"Local IP Address: %u.%u.%u.%u\n\n", addrChars[0], addrChars[1], addrChars[2], addrChars[3]);
7419 if (addresses == NULL) {
7420 printf(
"Error GetLocalIPAddresses\n");
7424 for (n=0; n<count; n++) {
7425 addrChars = (
unsigned char*) &addresses[n];
7426 printf(
"Local IP Address[%u]: %u.%u.%u.%u (%u,%u)\n\n", n, addrChars[0], addrChars[1], addrChars[2], addrChars[3], addresses[n],
LOCALHOSTIP);
7428 delete [] addresses;
7431 for (n=0; n<count; n++) {
7432 addrChars = (
unsigned char*) &(interfaces[n]);
7433 printf(
"Local Interface[%u] %s: %u.%u.%u.%u (%llX)\n\n", n, interfaces[n].name,
7434 addrChars[0], addrChars[1], addrChars[2], addrChars[3], interfaces[n].mac);
7436 delete [] interfaces;
7441void PrintBinary(
void* p, uint32 size,
bool asInt,
const char* title) {
7443 printf(
"--- %s %u ---\n", title, size);
7445 for (uint32 n=0; n<size; n++) {
7446 c = *(((
unsigned char*)p)+n);
7448 printf(
"[%u] ", (
unsigned int)c);
7451 if ( (n > 0) && ((n+1)%10 == 0) )
7476const char*
stristr(
const char *str,
const char *substr, uint32 len) {
7477 if (!str || !substr)
return NULL;
7478 uint32 sslen = (uint32)strlen(substr);
7479 if (sslen == 0)
return (
const char*)str;
7482 for (; *str; str++, n++) {
7487 while ((*a++ | 32) == (*b++ | 32)) {
7490 if (len && (++m > len))
7497uint32
strcpyavail(
char* dst,
const char* src, uint32 maxlen,
bool copyAvailable) {
7498 if ( !dst || ! src || !maxlen )
7500 uint32 len = (uint32)strlen(src);
7501 if (len > maxlen-1) {
7505 memcpy(dst, src, maxlen-1);
7511 memcpy(dst, src, len+1);
7519 for (len = 0; len < size; len++) {
7521 if (str[len] == 13) {
7522 crSize = ( (len < size-1) && (str[len+1] == 10 ) ) ? 2 : 1;
7526 if (str[len] == 10) {
7537 std::string str = text;
7540 std::string::iterator i = str.begin(), e = str.end();
7544 std::transform(i, e, i, ::tolower);
7549 std::string str = text;
7550 std::transform(str.begin(), str.end(), str.begin(), ::toupper);
7555 std::string str = text;
7556 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
7562 std::vector<std::string>::iterator i = lines.begin(), e = lines.end();
7572 uint32 len = (uint32)strlen(text);
7573 if (!len)
return "";
7578 uint32 s = 0, p = 0;
7580 while ( ((text[s] ==
'\n') || (text[s] ==
'\r')) && (s < len))
7583 while ((text[p] <= 32) && (p < len))
7585 std::string indentString = std::string(text+s, p-s);
7586 std::string str = text;
7594 uint32 begin = 0, end = (uint32)strlen(text);
7597 while ((begin < end) && (text[begin] <= 32) || (text[begin] ==
'\"') || (text[begin] ==
'\''))
7601 while ((end > begin) && (text[end-1] <= 32) || (text[end-1] ==
'\"') || (text[end-1] ==
'\''))
7603 return std::string(text+begin, end-begin);
7612 uint32 begin = 0, end = (uint32)strlen(text);
7615 while ((text[begin] <= 32) && (begin < end))
7617 while ((end > begin) && (text[end-1] <= 32))
7619 return std::string(text+begin, end-begin);
7625std::multimap<std::string, std::string>
TextMultiMapSplit(
const char* text,
const char* outersplit,
const char* innersplit) {
7626 std::multimap<std::string, std::string> result;
7627 typedef std::pair <std::string, std::string> Map_String_Pair;
7629 if (!text || !outersplit || !innersplit)
7632 const char* pstr = text, *lstr = text;
7633 const char* src = text;
7635 while (pstr = strstr(src, outersplit)) {
7636 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7638 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr-src).c_str()),
TextTrim(std::string(lstr+1, pstr-lstr-1).c_str())));
7642 pstr = src + strlen(src);
7643 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7645 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr-src).c_str()),
TextTrim(std::string(lstr+1, pstr-lstr-1).c_str())));
7652std::map<std::string, std::string>
TextMapSplit(
const char* text,
const char* outersplit,
const char* innersplit) {
7653 std::map<std::string, std::string> result;
7654 typedef std::pair <std::string, std::string> Map_String_Pair;
7656 if (!text || !outersplit || !innersplit)
7659 const char* pstr = text, *lstr = text;
7660 const char* src = text;
7662 while (pstr = strstr(src, outersplit)) {
7663 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7665 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr - src).c_str()),
TextTrim(std::string(lstr + 1, pstr - lstr - 1).c_str())));
7669 pstr = src + strlen(src);
7670 if ((lstr = strstr(src, innersplit)) && (lstr < pstr)) {
7672 result.insert(Map_String_Pair(
TextTrim(std::string(src, lstr - src).c_str()),
TextTrim(std::string(lstr + 1, pstr - lstr - 1).c_str())));
7680 uint32 size = (uint32)args.size();
7684 char** argv =
new char*[size+1];
7686 std::vector<std::string>::iterator i = args.begin(), e = args.end();
7688 argv[c] =
new char[(*i).length()+1];
7689 strcpy(argv[c], (*i).c_str());
7700 uint32 size = (uint32)args.size();
7704 wchar_t** argv =
new wchar_t*[size+1];
7706 std::vector<std::string>::iterator i = args.begin(), e = args.end();
7708 argv[c] =
new wchar_t[(*i).length()+1];
7709 mbstowcs(argv[c], (*i).c_str(), (*i).length() + 1);
7719 for (uint32 n=0; n<(uint32)argc; n++)
7727 bool insideQuotes =
false;
7728 bool lastWasWhiteSpace =
false;
7729 std::vector<std::string> vect;
7730 std::string arg, val, str;
7733 uint32 len = (uint32)strlen(cmdline);
7735 bool keepQuotes =
false;
7737 for (uint32 n=0; n<len; n++) {
7740 if (!insideQuotes) {
7741 if (!lastWasWhiteSpace) {
7743 vect.push_back(str);
7749 lastWasWhiteSpace =
true;
7755 else if (ch ==
'"') {
7756 insideQuotes = !insideQuotes;
7759 lastWasWhiteSpace =
false;
7763 lastWasWhiteSpace =
false;
7767 if (str.length() > 0) {
7768 vect.push_back(str);
7776 if (!text || !strlen(text))
7777 return std::vector<std::string>();
7779 if (strstr(text,
"\r\n"))
7781 else if (strstr(text,
"\n\r"))
7783 else if (strstr(text,
"\n"))
7785 else if (strstr(text,
"\r"))
7788 std::vector<std::string> result;
7789 result.push_back(text);
7794 if (!text || !strlen(text))
7795 return std::vector<std::string>();
7798 std::vector<std::string> result;
7799 uint32 s = 0, n = 0, len = (uint32)strlen(text);
7802 if (text[n] == 13) {
7804 result.push_back(
"");
7806 str = std::string(text + s, n - s);
7807 result.push_back(
TextTrim(str.c_str()));
7809 if ((n < len - 1) && (text[n + 1] == 10))
7815 else if (text[n] == 10) {
7817 result.push_back(
"");
7819 str = std::string(text + s, n - s);
7820 result.push_back(
TextTrim(str.c_str()));
7822 if ((n < len - 1) && (text[n + 1] == 13))
7828 else if ((n-s < maxLineLength) && (text[n] == 32)) {
7831 else if (n - s >= maxLineLength) {
7833 result.push_back(
"");
7839 str = std::string(text + s, p);
7840 result.push_back(
TextTrim(str.c_str()));
7846 str = std::string(text + s, maxLineLength);
7847 result.push_back(
TextTrim(str.c_str()));
7856 str = std::string(text + s, n - s);
7857 result.push_back(
TextTrim(str.c_str()));
7871std::string
TextJoin(std::vector<std::string> &list,
const char* split, uint32 start, uint32 count) {
7872 std::ostringstream o;
7873 std::vector<std::string>::iterator i = list.begin(), e = list.end();
7874 uint32 l = 0, c = 0;
7876 if (!count || ((l >= start) && (c < count))) {
7877 if (c++) o << split;
7886std::string
TextJoin(std::list<std::string> &list,
const char* split, uint32 start, uint32 count) {
7887 std::ostringstream o;
7888 std::list<std::string>::iterator i = list.begin(), e = list.end();
7889 uint32 l = 0, c = 0;
7891 if (!count || ((l >= start) && (c < count))) {
7892 if (c++) o << split;
7901std::string
TextJoin(std::map<std::string, std::string> &map,
const char* innersplit,
const char* outersplit,
bool keyquotes,
bool valquotes) {
7902 std::ostringstream o;
7903 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7906 if (c++) o << outersplit;
7907 if (keyquotes && valquotes)
7908 o <<
"\"" << i->first <<
"\"" << innersplit <<
"\"" << i->second <<
"\"";
7910 o << i->first << innersplit <<
"\"" << i->second <<
"\"";
7912 o << i->first << innersplit << i->second;
7919 std::ostringstream o;
7920 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7934std::string
TextJoinXML(std::map<std::string, std::string> &map,
const char* innernodeName,
const char* outernodeName) {
7935 if (!innernodeName || !strlen(innernodeName))
7937 std::ostringstream o;
7938 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
7939 if (outernodeName && strlen(outernodeName))
7940 o <<
"<" << outernodeName <<
">\n";
7945 if (outernodeName && strlen(outernodeName))
7946 o <<
"</" << outernodeName <<
">\n";
7952std::vector<std::string>
TextListSplit(
const char* text,
const char* split,
bool keepEmpty,
bool autoTrim) {
7953 std::vector<std::string> result;
7954 if (!text || !split)
7957 uint32 splitLen = (uint32)strlen(split);
7958 const char* pstr = text;
7959 const char* src = text;
7961 while (pstr = strstr(src, split)) {
7962 if (pstr - src || keepEmpty) {
7964 result.push_back(
TextTrim(std::string(src, pstr - src).c_str()));
7966 result.push_back(std::string(src, pstr - src).c_str());
7968 src = pstr + splitLen;
7970 pstr = src + strlen(src);
7973 result.push_back(
TextTrim(std::string(src, pstr - src).c_str()));
7975 result.push_back(std::string(src, pstr - src).c_str());
7982 std::vector<std::string>::iterator i, e;
7983 for (i=vect.begin(), e=vect.end(); i!=e; i++) {
7984 if (allowEmpty || (*i).size()) {
7994 if (strlen(format) == 0) {
8000 va_start(args, format);
8011 int len = _vscprintf(format, orig_args) + 10;
8012 str = (
char*)malloc(len+1);
8014 len = vsnprintf(str, len, format, orig_args);
8016 len = _vsnprintf_s(str, len, len+1, format, orig_args);
8020 size = (uint32)strlen(str);
8027 int len = vasprintf(&str, format, orig_args);
8038 if (!dst || !maxsize)
8040 if (strlen(format) == 0) {
8047 va_start(args, format);
8051 if (len > maxsize) {
8068 if (strlen(format) == 0)
8074 va_start(args, format);
8086 if (!text.size() || !key.size())
8091 uint32 keylen = (uint32)key.size();
8093 while ( (p = text.find(key, p)) != std::string::npos) {
8094 text.replace(p, keylen, value);
8104 if (!text.size() || !map.size())
8109 std::map<std::string, std::string>::iterator it, itEnd;
8110 for (it = map.begin(), itEnd = map.end(); it != itEnd; ++it)
8137uint32
StringScriptReplace(std::string& text, std::string name, std::list<std::map<std::string, std::string> >& list) {
8138 if (!text.size() || !name.size())
8143 char* start =
new char[name.size() + 50];
8144 snprintf(start, name.size()+50,
"<!-- start:%s -->", name.c_str());
8145 char* end =
new char[name.size() + 50];
8146 snprintf(end, name.size()+50,
"<!-- end:%s -->", name.c_str());
8149 size_t a1 = text.find(start);
8150 if (a1 == std::string::npos) {
8155 size_t b1 = text.find(end);
8156 if (b1 == std::string::npos) {
8162 uint32 a2 = (uint32)(a1 + strlen(start));
8163 uint32 b2 = (uint32)(b1 + strlen(end));
8166 std::string section = text.substr(a2, b1-a2);
8170 std::list<std::map<std::string, std::string> >::iterator it, itEnd;
8171 for (it = list.begin(), itEnd = list.end(); it != itEnd; ++it) {
8177 text.replace(a1, b2-a1, result);
8186 unsigned char c = (
unsigned char) strtol(str, NULL, 16);
8194 unsigned char c = (
unsigned char) strtol(str, NULL, 10);
8202 float64 diff = a - b;
8203 if ((diff < std::numeric_limits<float64>::epsilon()) && (-diff < std::numeric_limits<float64>::epsilon()))
8212#define poly 0xEDB88320
8220int CRC32(
const char *addr, uint32 length, int32 crc) {
8222 for (; length>0; length--) {
8223 crc = crc ^ *addr++;
8224 for (i=0; i<8; i++) {
8226 crc = (crc >> 1) ^
poly;
8240 char* data =
ReadAFile(filename.c_str(), length,
false);
8241 if (!data || !length)
8243 std::string dataString = data;
8248char*
ReadAFile(
const char* dir,
const char* filename, uint32& length,
bool binary) {
8249 if (!dir || !filename || strlen(filename) == 0)
8252 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8253 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8254 char* res =
ReadAFile(fullname, length, binary);
8259char*
ReadAFile(
const char* filename, uint32& length,
bool binary) {
8260 if (!filename || strlen(filename) == 0)
8267 file = fopen(filename,
"rb");
8269 file = fopen(filename,
"r");
8275 fseek(file, 0, SEEK_END);
8276 length = ftell(file);
8277 fseek(file, 0, SEEK_SET);
8285 char* data =
new char[length+1];
8287 int res = (int)fread(data, 1, length, file);
8289 if ((res <= 0) || (res != length)) {
8290 int error = ferror(file);
8291 int eof = feof(file);
8295 LogPrint(0,0,0,
"File %s has no data", filename);
8302 length = (uint32)res;
8307bool WriteAFile(
const char* dir,
const char* filename,
const char* data, uint32 length,
bool binary) {
8308 if (!dir || !filename || strlen(filename) == 0)
8311 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8312 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8313 bool res =
WriteAFile(fullname, data, length, binary);
8318bool WriteAFile(
const char* filename,
const char* data, uint32 length,
bool binary) {
8319 if (!filename || strlen(filename) == 0)
8324 file = fopen(filename,
"wb");
8326 file = fopen(filename,
"w");
8330 int res = (int)fwrite(data, 1, length, file);
8332 return (res == length);
8335bool AppendToAFile(
const char* dir,
const char* filename,
const char* data, uint32 length,
bool binary) {
8336 if (!dir || !filename || strlen(filename) == 0)
8339 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8340 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8346bool AppendToAFile(
const char* filename,
const char* data, uint32 length,
bool binary) {
8347 if (!filename || strlen(filename) == 0)
8352 file = fopen(filename,
"ab");
8354 file = fopen(filename,
"a");
8358 int res = (int)fwrite(data, 1, length, file);
8360 return (res == length);
8364 if (!dir || !filename || strlen(filename) == 0)
8367 char* fullname =
new char[strlen(dir) + strlen(filename) + 5];
8368 snprintf(fullname, strlen(dir) + strlen(filename) + 5,
"%s/%s", dir, filename);
8379 if (!filename || strlen(filename) == 0)
8383 return (SetFileAttributes(filename, FILE_ATTRIBUTE_READONLY) != 0);
8385 return (SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL) != 0);
8388 return (chmod(filename,S_IREAD | S_IWRITE) != 0);
8390 return (chmod(filename,S_IREAD) == 0);
8392 return (chmod(filename,S_IWRITE) == 0);
8394 return (chmod(filename,0) == 0);
8398bool MoveAFile(
const char* oldfilename,
const char* newfilename,
bool force) {
8402 result = (MoveFileEx(oldfilename, newfilename, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0);
8404 result = (MoveFileEx(oldfilename, newfilename, MOVEFILE_COPY_ALLOWED) != 0);
8410 if (rename(oldfilename, newfilename) == 0)
8416 delete(newfilename);
8417 if (rename(oldfilename, newfilename) == 0)
8421 if (error == EXDEV) {
8422 if (
CopyAFile(newfilename, oldfilename)) {
8431bool MoveAFile(
const char* olddir,
const char* oldfilename,
const char* newdir,
const char* newfilename,
bool force) {
8432 if (!newdir || !newfilename || !strlen(newfilename) ||
8433 !olddir || !oldfilename || !strlen(oldfilename) )
8436 char* oldname =
new char[strlen(olddir) + strlen(oldfilename) + 5];
8437 snprintf(oldname, strlen(olddir) + strlen(oldfilename) + 5,
"%s/%s", olddir, oldfilename);
8438 char* newname =
new char[strlen(newdir) + strlen(newfilename) + 5];
8439 snprintf(newname, strlen(newdir) + strlen(newfilename) + 5,
"%s/%s", newdir, newfilename);
8440 bool res =
MoveAFile(newname, oldname, force);
8446bool CopyAFile(
const char* oldfilename,
const char* newfilename,
bool force) {
8449 return (CopyFile(oldfilename, newfilename,
FALSE) != 0);
8451 return (CopyFile(oldfilename, newfilename,
TRUE) != 0);
8459 char* data =
ReadAFile(oldfilename, size,
true);
8460 if (!data || !size) {
8470 if (!
WriteAFile(newfilename, data, size,
true)) {
8479bool CopyAFile(
const char* olddir,
const char* oldfilename,
const char* newdir,
const char* newfilename,
bool force) {
8480 if (!newdir || !newfilename || !strlen(newfilename) ||
8481 !olddir || !oldfilename || !strlen(oldfilename) )
8484 char* oldname =
new char[strlen(olddir) + strlen(oldfilename) + 5];
8485 snprintf(oldname, strlen(olddir) + strlen(oldfilename) + 5,
"%s/%s", olddir, oldfilename);
8486 char* newname =
new char[strlen(newdir) + strlen(newfilename) + 5];
8487 snprintf(newname, strlen(newdir) + strlen(newfilename) + 5,
"%s/%s", newdir, newfilename);
8488 bool res =
CopyAFile(newname, oldname, force);
8495 if (!dirname || strlen(dirname) == 0)
8508 if (CreateDirectory(dirname, NULL) != 0)
8513 if (mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
8521 if (!dirname || strlen(dirname) == 0)
8532 if (DeleteFile(dirname) != 0)
8538 if (DeleteFile(dirname) != 0)
8544 if (unlink(dirname) == 0)
8550 if (unlink(dirname) == 0)
8560 if (RemoveDirectory(dirname) != 0)
8566 if (RemoveDirectory(dirname) != 0)
8572 if (rmdir(dirname) == 0)
8578 if (rmdir(dirname) == 0)
8588 if (!dirname || strlen(dirname) == 0)
8597 for (uint32 n = 0; n<count; n++) {
8615 for (uint32 n=0; n<size; n++) {
8616 if (str[n] == find) {
8628 len2 = (int)strlen(str2);
8632 len1 = (int)strlen(str1);
8634 return (strcmp(str1, str2) == 0) ? str1 : 0;
8635 else if (len1 - len2 < 0)
8638 strp = (
char*)(str1 + len1 - len2);
8639 while(strp != str1) {
8640 if(*strp == *str2) {
8641 if(strncmp(strp,str2,len2)==0)
8653 len2 = (int)strlen(str2);
8657 len1 = (int)strlen(str1);
8659 return (
stricmp(str1, str2) == 0) ? str1 : 0;
8660 else if (len1 - len2 < 0)
8663 strp = (
char*)(str1 + len1 - len2);
8664 while(strp != str1) {
8665 if(*strp == *str2) {
8676 return (
laststristr(str, end) == str + strlen(str) - strlen(end));
8678 return (
laststrstr(str, end) == str + strlen(str) - strlen(end));
8683 return (
stristr(str, start) == str);
8685 return (strstr(str, start) == str);
8690 std::string name = filename;
8691 std::string::size_type p1 = name.find_last_of(
'/');
8692 std::string::size_type p2 = name.find_last_of(
'\\');
8693 if (p1 == std::string::npos) {
8694 if (p2 == std::string::npos)
8697 return name.substr(0, p2 + 1);
8699 else if (p2 == std::string::npos)
8700 return name.substr(0, p1 + 1);
8702 return name.substr(0, (p1 > p2) ? p1 + 1 : p2 + 1);
8706 std::string name = filename;
8707 std::string::size_type p1 = name.find_last_of(
'/');
8708 std::string::size_type p2 = name.find_last_of(
'\\');
8709 if (p1 == std::string::npos) {
8710 if (p2 == std::string::npos)
8713 return filename + p2 + 1;
8715 else if (p2 == std::string::npos)
8716 return filename + p1 + 1;
8718 return (p1 > p2) ? filename + p1 + 1 : filename + p2 + 1;
8723 char cCurrentPath[FILENAME_MAX];
8729 cCurrentPath[
sizeof(cCurrentPath) - 1] =
'\0';
8731 return cCurrentPath;
8734char*
GetFileList(
const char* dirname,
const char* ext, uint32& count,
bool fullpath, uint32 maxNameLen) {
8739 uint32 extlen = (ext == NULL) ? 0 : (uint32)strlen(ext);
8740 struct dirent* direntry = NULL;
8742 uint32 tempMaxCount = 50;
8743 uint32 len = (maxNameLen+1)*tempMaxCount;
8744 char* result =
new char[len];
8747 uint32 dirnamelen = (uint32)strlen(dirname);
8748 bool dirslash = (*(dirname + dirnamelen - 1) ==
'/') || (*(dirname + dirnamelen - 1) ==
'\\');
8756 if (direntry->
d_name[0] !=
'\0') {
8758 if ( !strcmp(direntry->
d_name,
".") || !strcmp(direntry->
d_name,
"..") ) {
8769 memset(dst+dirnamelen,
'/', 1);
8779 if (count >= tempMaxCount) {
8781 tmp =
new char[len*2];
8782 memcpy(tmp, result, len);
8806 struct stat statbuf;
8822 if ((fd = _open(filename, O_RDONLY)) == -1) {
8841 result = fstat(fd, &statbuf);
8852 info.
size = statbuf.st_size;
8853 info.
isDirectory = ((statbuf.st_mode & S_IFDIR) != 0);
8859 info.
isReadable = ((statbuf.st_mode & _S_IREAD) != 0);
8860 info.
isWritable = ((statbuf.st_mode & _S_IWRITE) != 0);
8861 info.
isExecutable = ((statbuf.st_mode & _S_IEXEC) != 0);
8863 info.
isReadable = ((statbuf.st_mode & S_IRUSR) != 0);
8864 info.
isWritable = ((statbuf.st_mode & S_IWUSR) != 0);
8865 info.
isExecutable = ((statbuf.st_mode & S_IXUSR) != 0);
8875 if (!ascii || (start >= end) || (!(len = (uint32)strlen(ascii))) ) {
8882 copy =
new char[end - start + 2];
8883 memcpy(copy, ascii + start,
8885 copy[end - start + 1] = 0;
8892 if (!ascii || (start > end))
return false;
8893 uint32 len = (uint32)strlen(ascii);
8894 uint32 stop = end ? end+1 : len;
8895 if (stop > len) stop = len;
8896 for (uint32 n=start; n<stop; n++) {
8897 if (( ascii[n] <
'0' || ascii[n] >
'9') && ascii[n] !=
'.')
8904 if (!ascii || (start > end))
return false;
8907 return _strtoi64(ascii + start, NULL, 10);
8909 return strtoll(ascii + start, NULL, 10);
8913 int64 val = _strtoi64(copy, NULL, 10);
8915 int64 val = strtoll(copy, NULL, 10);
8922 if (!ascii || (start > end))
return false;
8925 return _strtoui64(ascii + start, NULL, 10);
8927 return strtoull(ascii + start, NULL, 10);
8931 uint64 val = _strtoui64(copy, NULL, 10);
8933 uint64 val = strtoull(copy, NULL, 10);
8940 if (!ascii || (start > end))
return false;
8943 return _strtoui64(ascii + start, NULL, 16);
8945 return strtoull(ascii + start, NULL, 16);
8949 uint64 val = _strtoui64(copy, NULL, 16);
8951 uint64 val = strtoull(copy, NULL, 16);
8958 if (!ascii || (start > end))
return false;
8960 return (int32)strtol(ascii + start, NULL, 10);
8962 int32 val = (int32)strtol(copy, NULL, 10);
8968 if (!ascii || (start > end))
return false;
8970 return (uint32)strtoul(ascii + start, NULL, 10);
8972 uint32 val = (uint32)strtoul(copy, NULL, 10);
8978 if (!ascii || (start > end))
return false;
8980 return (uint32)strtoul(ascii + start, NULL, 16);
8982 uint32 val = (uint32)strtoul(copy, NULL, 16);
8988 if (!ascii || (start > end))
return false;
8990 return strtod(ascii + start, NULL);
8992 float64 val = strtod(copy, NULL);
8999 bool isEscaped =
false;
9000 char* tmp =
new char[5];
9002 std::ostringstream o;
9003 std::string::iterator c;
9004 for (c = str.begin(); c != str.end(); c++) {
9007 case '"': o <<
"\"";
break;
9008 case '\\': o <<
"\\";
break;
9009 case 'b': o <<
"\b";
break;
9010 case 'f': o <<
"\f";
break;
9011 case 'n': o <<
"\n";
break;
9012 case 'r': o <<
"\r";
break;
9013 case 't': o <<
"\t";
break;
9016 tmp[0] = (uint8)(*c++);
9017 tmp[1] = (uint8)(*c++);
9018 tmp[2] = (uint8)(*c++);
9019 tmp[3] = (uint8)(*c);
9020 o << (char) strtol(tmp, NULL, 16);
9028 case '\\': isEscaped =
true;
break;
9038 std::ostringstream o;
9039 std::string::iterator c;
9040 for (c = str.begin(); c != str.end(); c++) {
9042 case '"': o <<
"\\\"";
break;
9043 case '\\': o <<
"\\\\";
break;
9044 case '\b': o <<
"\\b";
break;
9045 case '\f': o <<
"\\f";
break;
9046 case '\n': o <<
"\\n";
break;
9047 case '\r': o <<
"\\r";
break;
9048 case '\t': o <<
"\\t";
break;
9050 if (
'\x00' <= *c && *c <=
'\x1f') {
9052 << std::hex << std::setw(4) << std::setfill(
'0') << (int)*c;
9114 srand( seedvalue ? seedvalue : (uint32)
GetTimeNow());
9121 double t = (1.0/((RAND_MAX + 1.0)*(RAND_MAX + 1.0)*(RAND_MAX + 1.0)));
9123 d = (rand () * ((RAND_MAX + 1.0) * (RAND_MAX + 1.0))
9124 + rand () * (RAND_MAX + 1.0)
9148 uint64 n = (uint64)(r/interval);
9149 double l = r - (n*interval);
9150 if (l >= (0.5*interval))
9151 return from + (n*interval);
9153 return from + ((n+1)*interval);
9157 return (int64)roundl(
RandomValue((
double)from, (
double)to));
9168 double mb = kb*1024;
9169 double gb = mb*1024;
9170 double tb = gb*1024;
9172 char *tmp =
new char[64];
9175 snprintf(tmp, 64,
"%.2f B", val);
9176 else if (val < 512*kb) {
9178 snprintf(tmp, 64,
"%.2f KB", val);
9180 else if (val < 512*mb) {
9182 snprintf(tmp, 64,
"%.2f MB", val);
9184 else if (val < 512*gb) {
9186 snprintf(tmp, 64,
"%.2f GB", val);
9190 snprintf(tmp, 64,
"%.2f TB", val);
9193 std::string result = tmp;
9205 double mb = kb*1024;
9206 double gb = mb*1024;
9207 double tb = gb*1024;
9209 char *tmp =
new char[64];
9210 char *end =
new char[64];
9213 double maximum = ((val1 > val2) ? val1 : val2);
9215 if (maximum < 512) {
9219 else if (maximum < 512*kb) {
9223 else if (maximum < 512*mb) {
9227 else if (maximum < 512*gb) {
9235 snprintf(tmp, 64,
"%.2f / %.2f %s", ((
double)val1)/val, ((
double)val2)/val, (
char*) end);
9237 std::string result = tmp;
9249 char *tmp =
new char[64];
9250 snprintf(tmp, 64,
"%s/sec", (
char*)
BytifySize(val).c_str());
9251 std::string result = tmp;
9261 char *tmp =
new char[64];
9262 snprintf(tmp, 64,
"%s/sec", (
char*)
BytifySizes(val1, val2).c_str());
9263 std::string result = tmp;
9277 HKEY hKeyRoot, hKey;
9278 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9280 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9281 if (err != ERROR_SUCCESS)
9284 DWORD dwType = REG_DWORD;
9286 DWORD dwSize =
sizeof(numVal);
9288 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)&numVal, &dwSize);
9290 if (err != ERROR_SUCCESS)
9296 HKEY hKeyRoot, hKey;
9297 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9299 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9300 if (err != ERROR_SUCCESS)
9303 DWORD dwType = REG_QWORD;
9305 DWORD dwSize =
sizeof(numVal);
9307 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)&numVal, &dwSize);
9309 if (err != ERROR_SUCCESS)
9315 HKEY hKeyRoot, hKey;
9316 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9318 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9319 if (err != ERROR_SUCCESS) {
9323 DWORD dwType = REG_SZ;
9324 DWORD dwSize = 4096;
9325 char* lszValue =
new char[dwSize];
9327 err = RegQueryValueEx(hKey, entry, NULL, &dwType, (LPBYTE)lszValue, &dwSize);
9329 if (err != ERROR_SUCCESS) {
9334 std::string val = lszValue;
9340 DWORD dwDisposition;
9341 HKEY hKeyRoot, hKey;
9342 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9344 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9345 if (err != ERROR_SUCCESS) {
9346 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9347 if (err != ERROR_SUCCESS)
9351 DWORD dwType = REG_DWORD;
9352 err = RegSetValueEx(hKey, entry, 0, dwType, (
const BYTE*)&value,
sizeof(value));
9354 return (err == ERROR_SUCCESS);
9358 DWORD dwDisposition;
9359 HKEY hKeyRoot, hKey;
9360 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9362 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9363 if (err != ERROR_SUCCESS) {
9364 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9365 if (err != ERROR_SUCCESS)
9369 DWORD dwType = REG_QWORD;
9370 err = RegSetValueEx(hKey, entry, 0, dwType, (
const BYTE*)&value,
sizeof(value));
9372 return (err == ERROR_SUCCESS);
9376 DWORD dwDisposition;
9377 HKEY hKeyRoot, hKey;
9378 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9380 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_WRITE | KEY_WOW64_64KEY, &hKey);
9381 if (err != ERROR_SUCCESS) {
9382 err = RegCreateKeyEx(hKeyRoot, keySubName.c_str(), 0, NULL, 0, KEY_WRITE | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
9383 if (err != ERROR_SUCCESS)
9387 DWORD dwType = REG_SZ;
9388 DWORD dwSize = 4096;
9390 err = RegSetValueEx(hKey, entry, 0, dwType, (LPBYTE)value, (DWORD)(strlen(value) + 1));
9392 return (err == ERROR_SUCCESS);
9396 HKEY hKeyRoot, hKey;
9397 std::string keySubName = GetRegistryKeyInfo(key, hKeyRoot);
9399 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_SET_VALUE | KEY_WOW64_64KEY, &hKey);
9400 if (err != ERROR_SUCCESS)
9404 err = RegDeleteValue(hKey, entry);
9405 return (err == ERROR_SUCCESS);
9412 std::string keySubName = GetRegistryKeyInfo(entry, hKeyRoot);
9413 uint32 err = RegDeleteKeyEx(hKeyRoot, keySubName.c_str(), KEY_WOW64_64KEY, 0);
9414 return (err == ERROR_SUCCESS);
9418 if (!key || !strlen(key))
9423 std::string keySubName = GetRegistryKeyInfo(root, hKeyRoot);
9424 uint32 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey);
9425 if (err != ERROR_SUCCESS)
9428 err = RegDeleteTree(hKey, key);
9429 return (err == ERROR_SUCCESS);
9441 DWORD dwDisposition;
9448 std::string keySubName = GetRegistryKeyInfo(entry, hKeyRoot);
9449 std::string keySubNewName = GetRegistryKeyInfo(newName, hKeyNewRoot);
9451 err = RegOpenKeyEx(hKeyRoot, keySubName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
9452 if (err != ERROR_SUCCESS)
9455 err = RegCreateKeyEx(hKeyNewRoot, keySubNewName.c_str(), 0, NULL, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKeyNew, &dwDisposition);
9456 if (err != ERROR_SUCCESS) {
9461 err = RegCopyTree(hKey, NULL, hKeyNew);
9464 RegCloseKey(hKeyNew);
9466 if (err != ERROR_SUCCESS) {
9467 RegDeleteKeyEx(hKeyNewRoot, keySubNewName.c_str(), KEY_WOW64_64KEY, 0);
9493std::string GetRegistryKeyInfo(
const char* key, HKEY &hKeyRoot) {
9496 if (path.size() < 2)
return false;
9497 if (
stristr(path.at(0).c_str(),
"HKEY_CLASSES_ROOT"))
9498 hKeyRoot = HKEY_CLASSES_ROOT;
9499 else if (
stristr(path.at(0).c_str(),
"HKEY_CURRENT_USER"))
9500 hKeyRoot = HKEY_CURRENT_USER;
9501 else if (
stristr(path.at(0).c_str(),
"HKEY_LOCAL_MACHINE"))
9502 hKeyRoot = HKEY_LOCAL_MACHINE;
9503 else if (
stristr(path.at(0).c_str(),
"HKEY_USERS"))
9504 hKeyRoot = HKEY_USERS;
9508std::string GetRegistryParentKeyInfo(
const char* key, HKEY &hKeyRoot) {
9511 if (path.size() < 2)
return false;
9512 if (
stristr(path.at(0).c_str(),
"HKEY_CLASSES_ROOT"))
9513 hKeyRoot = HKEY_CLASSES_ROOT;
9514 else if (
stristr(path.at(0).c_str(),
"HKEY_CURRENT_USER"))
9515 hKeyRoot = HKEY_CURRENT_USER;
9516 else if (
stristr(path.at(0).c_str(),
"HKEY_LOCAL_MACHINE"))
9517 hKeyRoot = HKEY_LOCAL_MACHINE;
9518 else if (
stristr(path.at(0).c_str(),
"HKEY_USERS"))
9519 hKeyRoot = HKEY_USERS;
9550 "Bitfield slot allocation: SetBit/SetBitN, first-free and last-occupied searches",
"util");
9552 "Timer scheduling and trigger delivery via waitForTimer",
"util");
9554 "ProbeProcessWait: stdin-blocked child detected, busy child not flagged, cpuTimeMs grows",
"util");
HTML/URL helper utilities: entity encoding/decoding, MIME type lookup and URL component parsing.
#define PROC_ERROR
Error state.
Object type ids used to tag and verify every binary structure in CMSDK memory.
#define DATAMESSAGEINFOID
Process-wide thread registry and lifecycle manager: the concurrency core of CMSDK.
Small, dependency-free unit test harness used by all CMSDK object tests.
Cross-platform utility toolbox for CMSDK: threading, synchronization, shared memory,...
#define thread_ret_val(ret)
#define THREAD_STATS_ADHOC
#define THREAD_FUNCTION_CALL
THREAD_RET(* THREAD_FUNCTION)(void *)
#define THREAD_STATS_AUTO
RAII guard whose single static instance triggers global utility cleanup at program exit.
CleanShutdown()
Default constructor; no side effects.
~CleanShutdown()
Destroys all lazily-created global utility maps via ClearUtilsMaps().
Callback interface for receiving log entries produced through LogSystem.
Process-wide singleton logging hub with per-topic verbosity/debug levels.
static bool SetLogFileOutput(const char *logfile, bool printOut=true)
Direct log output to a file.
static bool SetLogReceiver(LogReceiver *rec)
Register a receiver that gets every accepted LogEntry.
static bool LogSystemPrint(uint32 source, uint8 subject, uint8 level, const char *formatstring,...)
printf-style informational logging (usually invoked via the LogPrint macro).
static bool LogSystemDebug(uint32 source, uint8 subject, uint8 level, const char *formatstring,...)
printf-style debug logging (usually invoked via the LogDebug macro); same parameters as LogSystemPrin...
static LogSystem * LogSingleton
Lazily-created global instance used by all static functions.
static bool SetLogLevelDebug(uint8 level)
Set the debug level threshold for all topics.
static bool SetLogLevelVerbose(uint8 level)
Set the verbose (print) level threshold for all topics.
static bool Shutdown()
Terminate all managed threads, then destroy the singleton.
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
Singleton snapshot of the parsed process command line (set via SetCommandLine()).
static CommandLineInfo * CommandLineInfoSingleton
Auto-reset notification event (condition variable style), optionally named for cross-process use.
bool waitNext()
Block until the next signal() occurs.
Event()
Create an anonymous, process-local event.
bool signal()
Wake all threads currently waiting on this event.
Thin RAII wrapper around a dynamically loaded library (LoadLibrary / dlopen).
LibraryFunction getFunction(const char *funcName)
Resolve an exported function.
static std::string patchLibraryFilename(const char *filename, const char *path=NULL)
Normalize a library name into a platform filename (adds lib prefix / .dll, .so, .dylib suffix and opt...
bool load(const char *filename)
Load a library.
Recursive mutual-exclusion lock, optionally named for cross-process use.
Mutex()
Create an anonymous, process-local mutex.
void setCancelSafe(bool on)
Make this mutex cancellation-safe (POSIX only; no-op on Windows).
bool leave()
Release the mutex.
bool enter()
Block until the mutex is acquired.
Counting semaphore, optionally named for cross-process use.
Semaphore(uint32 maxCount=100)
Create an anonymous semaphore.
bool signal()
Increment (release) the semaphore, waking one waiter.
bool wait()
Block until the semaphore can be decremented.
Multiplexing timer: schedule many periodic timers and consume their expiries from one queue.
bool addTimer(uint32 id, uint32 interval, uint64 start=0, uint64 end=0)
Register a periodic timer.
static std::map< uint32, Timer * > * timers
Global registry mapping globalID to live Timer instances, used by the OS callbacks.
bool triggerTimer(uint32 id)
Manually inject an expiry for timer id, as if it had fired now.
bool waitForTimer(uint32 timeout, uint32 &id, uint64 &time)
Wait for the next expiry of any registered timer.
bool removeTimer(uint32 id)
Unregister a timer and cancel its OS timer.
uint64 FTime2PsyTime(uint64 t)
Convert an ftime-style value (ms since Unix epoch) to a PsyTime µs timestamp.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
std::string PrintTimeNowString(bool local=true, bool us=true, bool ms=true)
Format GetTimeNow().
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
bool UnitTest_Utils()
Aggregate self test for miscellaneous utils functionality.
int64 AtomicDecrement64(int64 volatile &v)
Atomically decrement a 64-bit value.
bool ResizeProcessTerminal(uint32 proc, uint16 cols, uint16 rows)
Resize the pseudo-terminal (TIOCSWINSZ + SIGWINCH to the child's group).
uint32 NewProcess(const char *cmdline, const char *initdir=NULL, const char *title=NULL, int16 x=-1, int16 y=-1, int16 w=-1, int16 h=-1)
Launch a detached child process.
bool SetSharedSystemInstance(uint32 inst)
Set the instance number used to namespace shared OS objects, allowing several independent CMSDK syste...
static std::map< uint32, ProcessData * > * ProcessInformationMap
uint32 GetThreadStatColAbility()
Report this platform's capability for per-thread CPU statistics collection.
void ReleaseProcessCapture(uint32 proc)
POSIX only: release the captured stdout/stderr read-pipes recorded for a child by NewProcessEx(captur...
bool WaitForThreadToFinish(ThreadHandle hThread, uint32 timeoutMS=0)
Join a thread.
bool SignalSemaphore(const char *name)
Signal a named global semaphore.
bool GetThreadPriority(ThreadHandle hThread, uint16 priority)
Query a thread's scheduling priority.
std::pair< std::string, Mutex * > SharedMemoryMutexMapPair
int FromOSPriority(int pri)
Map a native OS priority back to the CMSDK priority scale.
bool CloseProcessInput(uint32 proc)
Close a child's stdin, delivering EOF (T1.1 step 2.7c).
bool EndProcess(uint32 proc)
Forcibly terminate a child process.
std::pair< std::string, Semaphore * > SharedMemorySemaphoreMapPair
static Mutex * SharedMemorySemaphoreMapMutex
bool GetLastOccupiedBitLoc(const char *bitfield, uint32 bytesize, uint32 &loc)
Find the highest set (occupied) bit.
const char * laststrstr(const char *str1, const char *str2)
Find the last occurrence of str2 in str1.
std::pair< std::string, Event * > SharedMemoryEventMapPair
bool DestroyEvent(const char *name)
Destroy a named global event.
bool WaitForSemaphore(const char *name, uint32 ms, bool autocreate=true)
Wait on a named global semaphore.
static SharedMemoryFileHandleMapType * SharedMemoryFileHandleMap
bool TextStartsWith(const char *str, const char *start, bool caseSensitive=true)
Test whether str starts with start.
bool Sleep(uint32 ms)
Suspend the calling thread.
bool SetThreadPriority(ThreadHandle hThread, uint16 priority)
Set a thread's scheduling priority.
bool ReadProcessTerminal(uint32 proc, std::string &out, bool &eofOut)
Non-blocking read of the merged terminal stream.
bool GetProcAndOSCPUUsage(double &procPercentUse, double &osPercentUse, uint64 &prevOSTicks, uint64 &prevOSIdleTicks, uint64 &prevProcTicks)
Sample CPU usage of this process and of the whole OS since the previous call.
bool PauseThread(ThreadHandle hThread)
Suspend a thread's execution.
uint32 NewProcessTerminal(const char *cmdline, const char *initdir, const std::map< std::string, std::string > *env, uint16 cols=0, uint16 rows=0)
Launch a child on a new pseudo-terminal (POSIX: posix_openpt + fork; child setsid() + TIOCSCTTY so it...
static std::map< std::string, Event * > * SharedMemoryEventMap
bool MoveConsoleWindow(int32 x=-1, int32 y=-1, int32 w=-1, int32 h=-1)
Move/resize the console window.
bool WriteProcessTerminal(uint32 proc, const char *data, uint32 len)
Write bytes to the child's terminal input (its stdin).
bool IsThreadRunning(ThreadHandle hThread)
Check whether a thread is still alive.
bool CreateThread(THREAD_FUNCTION func, void *args, ThreadHandle &thread, uint32 &osID)
Start a new OS thread.
int32 AtomicDecrement32(int32 volatile &v)
Atomically decrement a 32-bit value.
uint32 NewProcessEx(const char *cmdline, const char *initdir, const char *title, const std::map< std::string, std::string > *env, bool captureOutput, bool ignoreOutput, bool newProcessGroup, int posixParentDeathSig=0, bool posixUseShell=false)
Launch a child with environment overrides and optional output capture.
static std::map< uint32, DrumBeatInfo > * DrumBeatMap
bool SignalThread(ThreadHandle hThread, int32 signal)
Send a signal to a thread (POSIX pthread_kill; limited emulation on Windows).
bool BlockShutdownSignals()
Block the graceful-shutdown signals (SIGINT, SIGTERM, SIGHUP) on the CALLING thread.
bool UnitTest_ProbeProcessWait()
char * OpenSharedMemorySegment(const char *name, uint64 size)
Open and map an existing named shared memory segment.
int64 AtomicIncrement64(int64 volatile &v)
Atomically increment a 64-bit value.
uint32 GetSharedSystemInstance()
Get the current shared-system instance number.
bool StopDrumBeat(uint32 id)
Stop a running drum beat without destroying it.
bool EnterMutex(const char *name, uint32 ms, bool autocreate=true)
Acquire a named global mutex, creating it on first use.
const char * laststristr(const char *str1, const char *str2)
Case-insensitive laststrstr().
bool ProbeProcessWait(uint32 pid, ProcessWaitInfo &out)
Probe whether a child process (group) appears blocked reading stdin (fd 0).
static Mutex * SharedMemoryMutexMapMutex
#define SharedMemoryFileHandleMapType
bool CreateDrumBeat(uint32 id, uint32 interval, DrumBeatFunc func, bool autostart=false)
Create a periodic timer ("drum beat") that calls func every interval ms.
bool ReapThread(ThreadHandle &hThread)
std::string PrintProgramTrace(uint32 startLine=0, uint32 endLine=0)
Format the current call stack as printable text.
uint8 GetProcessStatus(uint32 proc, int &returncode)
Poll a child started with NewProcess().
bool(* DrumBeatFunc)(uint32 id, uint32 count)
Callback invoked on every drum-beat tick.
static Mutex * SharedMemoryEventMapMutex
Semaphore * GetSemaphore(const char *name, bool autocreate=true)
Look up (and optionally create) a named semaphore in the global registry.
bool LeaveMutex(const char *name)
Release a named global mutex previously acquired with EnterMutex().
int RunOSCommand(const char *cmdline, const char *initdir, uint32 timeout, std::string &stdoutString, std::string &stderrString)
Run a command synchronously and capture its output.
char * CreateSharedMemorySegment(const char *name, uint64 size, bool force=false)
Create a named shared memory segment and map it into this process.
std::string PrintBitFieldString(const char *bitfield, uint32 bytesize, uint32 size, const char *title)
Like GetBitFieldAsString() but prefixed with title and formatted for printing.
std::string GetBitFieldAsString(const char *bitfield, uint32 bytesize, uint32 size)
Render the first size bits as a '0'/'1' string, for debugging.
uint8 WaitForProcess(uint32 proc, uint32 timeout, int &returncode)
Wait for a child to exit.
uint32 GetLocalProcessID()
Get the OS process id of the current process.
bool EndDrumBeat(uint32 id)
Destroy a drum beat and release its OS timer.
bool DestroySemaphore(const char *name)
Destroy a named global semaphore.
bool CloseSharedMemorySegment(char *data, uint64 size)
Unmap a segment previously created/opened here.
bool TerminateThread(ThreadHandle hThread)
Forcibly kill a thread.
bool GetFirstFreeBitLocN(const char *bitfield, uint32 bytesize, uint32 num, uint32 &loc)
Find the first run of num consecutive 0 bits.
bool StartSignalThread(ShutdownSignalCallback cb)
Start the dedicated signal-handling thread (POSIX only).
bool GetCurrentThreadUniqueID(uint32 &tid)
Get a process-unique id for the calling thread.
int32 AtomicIncrement32(int32 volatile &v)
Atomically increment a 32-bit value.
bool GetDesktopSize(uint32 &width, uint32 &height)
Get the primary desktop resolution.
bool CheckForThreadFinished(ThreadHandle hThread)
Non-blocking check whether a thread has terminated.
void(* ShutdownSignalCallback)(int sig, int count)
Callback invoked (on the dedicated signal thread) when a graceful-shutdown signal is caught.
bool DestroyMutex(const char *name)
Destroy a named global mutex and remove it from the registry.
bool ContinueThread(ThreadHandle hThread)
Resume a thread paused with PauseThread().
const char * stristr(const char *str, const char *substr, uint32 len=0)
Case-insensitive strstr.
void CloseProcessTerminal(uint32 proc)
Close the master side (terminal hangup: the child's foreground group gets SIGHUP and any blocked term...
std::list< std::string > GetProgramTrace()
Capture the current call stack.
uint64 hton64(const uint64_t *input)
Convert a 64-bit value from host to network byte order.
static uint16 SharedSystemInstance
static void TimerCallback(int sig, siginfo_t *siginfo, void *context)
POSIX signal-based timer callback trampoline (SIGEV_SIGNAL); routes the expiry into the owning Timer'...
void PrintBinary(void *p, uint32 size, bool asInt, const char *title)
Hex/decimal dump a memory region to stdout for debugging.
static std::map< std::string, Mutex * > * SharedMemoryMutexMap
bool GetFirstFreeBitLoc(const char *bitfield, uint32 bytesize, uint32 &loc)
Find the first 0 (free) bit.
bool SignalEvent(const char *name)
Signal a named global event.
bool WriteProcessInput(uint32 proc, const char *data, uint32 len)
Write to the stdin of a child launched with captureOutput=true (T1.1 step 2.7c).
bool GetCPUTicks(ThreadHandle hThread, uint64 &ticks)
Get accumulated CPU time of a specific thread.
bool GetNextLineEnd(const char *str, uint32 size, uint32 &len, uint32 &crSize)
Find the end of the current line.
bool GetBit(uint32 loc, const char *bitfield, uint32 bytesize, bit &val)
Read bit loc.
uint64 ntoh64(const uint64 *input)
Convert a 64-bit value from network to host byte order.
bool GetProcessCPUTicks(uint64 &ticks)
Get accumulated CPU time of the current process.
bool ReadProcessOutput(uint32 proc, std::string &out, std::string &err)
Read any pending captured stdout/stderr from a child launched with captureOutput=true.
int ToOSPriority(int pri)
Map a CMSDK priority value to the platform's native priority scale.
static std::map< std::string, Semaphore * > * SharedMemorySemaphoreMap
bool StopSignalThread()
Stop the dedicated signal thread and join it.
bool SendProcessBreak(uint32 proc, int sig)
Attempt a graceful stop: POSIX sends the given signal; Windows posts a CTRL_BREAK to the child's proc...
bool SetBitN(uint32 loc, uint32 num, bit value, char *bitfield, uint32 bytesize)
Set num consecutive bits starting at loc to value.
bool Reset32BitField(char *bitfield, uint32 bytesize)
Zero the whole bitfield, marking every bit as free.
bool StartDrumBeat(uint32 id)
Start (or resume) a previously created drum beat.
bool TextEndsWith(const char *str, const char *end, bool caseSensitive=true)
Test whether str ends with end.
bool UnitTest_Timer()
Self test for the Timer class.
bool SetBit(uint32 loc, bit value, char *bitfield, uint32 bytesize)
Set bit loc to value.
bool GetCurrentThread(ThreadHandle &thread)
Get the handle of the calling thread.
bool RenameConsoleWindow(const char *name, bool prepend=false)
Set the console window title.
bool TryReapThread(ThreadHandle &hThread)
bool UtilsTest()
Run the built-in self test of the utils module.
uint32 Calc32BitFieldSize(uint32 bitsize)
Compute the byte size needed for a bitfield of bitsize bits, rounded up to a 32-bit boundary.
uint32 TextReplaceCharsInPlace(char *str, uint32 size, char find, char replace)
Replace every occurrence of a character, in place.
uint32 strcpyavail(char *dst, const char *src, uint32 maxlen, bool copyAvailable)
Bounded strcpy that always NUL-terminates.
void ClearStaleSharedSegments(uint16 port)
Remove stale OS shared-memory/semaphore objects left by a crashed node on this port.
std::pair< uint32, ProcessData * > Proc_Pair
bool GetOSCPUUsage(double &percentUse)
Get the instantaneous total OS CPU usage.
bool GetCurrentThreadOSID(uint32 &tid)
Get the OS-level id of the calling thread (gettid / GetCurrentThreadId).
std::string EncodeHTML(std::string str)
Encode a plain string for safe embedding in HTML (e.g.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void metric(const char *name, double value, const char *unit="", bool higherIsBetter=true)
Record a performance metric.
void detail(const char *fmt,...)
Verbose-only indented diagnostic line (shown only when verbose=1).
void progress(int percent, const char *action)
Report progress with a short description of the current action.
bool SeedRandomValues(uint32 seedvalue=0)
Seed the pseudo-random generator.
int GetLastOSErrorNumber()
Get the last OS error number (errno / GetLastError()).
static THREAD_RET THREAD_FUNCTION_CALL SignalThreadMain(THREAD_ARG arg)
std::string GetLastOSErrorMessage()
Get the last OS error as human-readable text.
static bool AnyCancelSafeMutexes()
std::vector< std::string > TextListBreakLines(const char *text, uint32 maxLineLength=80)
Word-wrap text into lines no longer than maxLineLength.
int8 CompareFloats(float64 a, float64 b)
Compare two doubles with epsilon tolerance.
uint32 * GetLocalIPAddresses(uint32 &count)
List all local IPv4 addresses.
std::string EncodeJSON(std::string str)
Escape text for embedding as a JSON string value.
unsigned char * Ascii2UTF16LE(const char *ascii, uint32 len, uint32 &size)
Convert 8-bit ASCII text to UTF-16LE (used for Windows wide APIs and some protocols).
uint64 GetProcessMemoryUsage()
Current resident memory usage of this process.
char ** SplitCommandline(const char *cmdline, int &argc)
Split a command line into a malloc'ed argv array.
uint64 ReadRegistryQWORD(const char *key, const char *entry)
Read a 64-bit registry value.
static std::map< uint32, int > * TerminalMasterMap
std::string GetCommandLineArg(uint16 n)
Get the n-th positional command line item.
bool CreateADir(const char *dirname)
Create a directory (parents included where supported).
std::string BytifyRates(double val1, double val2)
Format two byte rates as "x / y" with matching units.
bool CopyAFile(const char *oldfilename, const char *newfilename, bool force=false)
Copy a file.
bool DeleteFilesInADir(const char *dirname, bool force)
Delete all files inside a directory, leaving the directory itself.
uint32 GetCommandLineArgCount()
Number of positional command line items (excluding the executable).
uint16 GetCPUArchitecture()
CPU architecture id.
char OSLocalHostName[1024]
char OSArchitectureName[1024]
std::string ReadAFileString(std::string filename)
Read an entire file into a std::string.
static uint32 g_shutdownSignalCount
char * StringFormatVA(uint32 &size, const char *format, va_list args)
va_list core used by the other StringFormat overloads.
std::string TextUppercase(const char *text)
Convert to upper case (ASCII/current locale).
int CRC32(const char *addr, uint32 length, int32 crc=0)
Compute (or continue) a CRC-32 checksum.
static pthread_mutex_t g_cancelSafeSetLock
bool WaitForSocketReadability(SOCKET s, int32 timeout)
Wait until a socket has data to read.
uint64 * GetLocalMACAddresses(uint32 &count)
List all local MAC addresses.
bool WaitForNextEvent(const char *name, uint32 ms, bool autocreate)
static volatile int g_cancelSafeCount
const char * GetSystemArchitecture()
Architecture name string, e.g.
std::string TextTrim(const char *text)
Strip leading and trailing whitespace.
std::string GetCommandLinePath()
Get the directory portion of the executable path.
bool HasCommandLineArg(const char *key, std::string &value)
Test for a 'key=value' argument without mutating the argument map.
bool SetSocketBlockingMode(SOCKET s)
Put a socket into blocking mode.
uint32 Ascii2Uint32(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 32-bit decimal integer from a substring.
uint64 GetCPUSpeed()
Nominal CPU clock speed.
wchar_t ** SplitCommandlineW(const char *cmdline, int &argc)
Wide-character variant of SplitCommandline() (for Windows APIs).
std::string TextVectorConcat(std::vector< std::string >, const char *sep, bool allowEmpty=true)
Concatenate vector entries with sep.
bool AppendToAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Append to a file, creating it if missing.
std::string TextIndent(const char *text, const char *indent)
Prefix every line of text with indent.
unsigned char Dec2Char(const char *str)
Parse up to three decimal digits into a byte.
char * GetFileList(const char *dirname, const char *ext, uint32 &count, bool fullpath, uint32 maxNameLen=256)
List files in a directory matching an extension.
bool GetNextAvailableLocalPort(uint16 lastPort, uint16 &nextPort)
Find the next free TCP port above lastPort.
static std::map< const void *, bool > * g_cancelSafeSet
bool MoveAFile(const char *oldfilename, const char *newfilename, bool force=false)
Move/rename a file.
uint32 StringMultiReplace(std::string &text, std::map< std::string, std::string > &map, bool onlyFirst)
Apply many key→value replacements in one pass.
std::vector< std::string > TextListSplit(const char *text, const char *split, bool keepEmpty=true, bool autoTrim=false)
Split text on a separator.
bool IsTextNumeric(const char *ascii, uint32 start=0, uint32 end=0)
Test whether a (sub)string is a valid number.
uint16 GetCPUCount()
Number of logical CPU cores.
char * Uint2Ascii(uint64 value, char *result, uint16 size, uint8 base)
Render an unsigned integer as text in an arbitrary base.
std::map< std::string, std::string > TextMapSplit(const char *text, const char *outersplit, const char *innersplit)
Split "k=v<sep>k=v..." text into a map (later duplicates overwrite earlier ones).
uint64 GetPeakProcessMemoryUsage()
Peak resident memory usage of this process.
bool DeleteCommandline(char **argv, int argc)
Free an argv array produced by SplitCommandline().
uint32 AsciiHex2Uint32(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 32-bit hexadecimal integer from a substring.
bool DeleteRegistryKey(const char *key)
Delete a (leaf) registry key.
bool GetLocalHostname(char *name, uint32 maxSize)
Local hostname into a caller buffer.
std::string TextUnindent(const char *text)
Remove one level of leading indentation from every line.
bool GetSystemOSVersion(uint16 &major, uint16 &minor, uint16 &build, char *text, uint16 textSize)
Detailed OS version.
uint32 StringScriptReplace(std::string &text, std::string name, std::list< std::map< std::string, std::string > > &list)
Expand a named repeating template block in text once per map in list, substituting each map's keys in...
std::string TextJoinXML(std::map< std::string, std::string > &map, const char *innernodeName, const char *outernodeName)
Serialize a map as XML, one innernodeName element per pair inside an outernodeName element.
bool SetCommandLine(int argc, char *argv[])
Parse and store the process command line for later retrieval by the Get/HasCommandLine* functions.
uint32 StringSingleReplace(std::string &text, std::string key, std::string value, bool onlyFirst)
Replace occurrences of key with value in text.
uint64 GetSystemMemorySize()
Total physical RAM installed.
uint32 ReadRegistryDWORD(const char *key, const char *entry)
Read a 32-bit registry value.
static bool TerminalMasterFind(uint32 proc, int &fd)
static ShutdownSignalCallback g_shutdownCallback
bool GetLocalMACAddress(uint64 &address)
Get the primary local MAC address.
bool WaitForSocketWriteability(SOCKET s, int32 timeout)
Wait until a socket can be written without blocking.
FileDetails GetFileDetails(const char *filename)
Stat a file.
double RandomValue()
Uniform random double in [0,1).
bool GetSocketError(int wsaError, char *errorString, uint16 errorStringMaxSize, bool *isRecoverable)
Translate a socket error code into text and classify it.
std::string GetCommandLineExecutableOnly()
Get just the executable filename without path.
static volatile sig_atomic_t g_signalThreadStop
std::multimap< std::string, std::string > TextMultiMapSplit(const char *text, const char *outersplit, const char *innersplit)
Split "k=v<sep>k=v..." text into a multimap (duplicate keys preserved).
bool RenameRegistryTree(const char *entry, const char *newName)
static bool ContainsPortToken(const char *name, const char *portstr, size_t plen)
bool GetLocalIPAddress(uint32 &address)
Get the primary local IPv4 address.
bool LookupHostname(uint32 address, char *name, uint32 maxSize)
Reverse-resolve an IPv4 address to a hostname.
char * TextSubstringCopy(const char *ascii, uint32 start, uint32 end)
Copy the substring [start,end) into a new NUL-terminated buffer.
bool LookupIPAddress(const char *name, uint32 &address)
Resolve a hostname to an IPv4 address.
static uint32 ClearSegmentsIn(const char *dir, const char *prefix, const char *portstr, size_t plen)
char * Int2Ascii(int64 value, char *result, uint16 size, uint8 base)
Render a signed integer as text in an arbitrary base.
std::string GetLocalHostnameString()
Local hostname as std::string.
static pid_t DoPosixForkExec(PosixLaunchRequest &r)
int32 Ascii2Int32(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 32-bit decimal integer from a substring.
bool DoesAFileExist(const char *filename)
Test whether a regular file exists.
NetworkInterfaces * GetLocalInterfaces(uint32 &count)
Enumerate local network interfaces with address, MAC and names.
std::string TextTrimQuotes(const char *text)
Strip a single pair of surrounding quotes if present.
unsigned char Hex2Char(const char *str)
Parse two hex digits into a byte.
bool DeleteAFile(const char *filename, bool force)
Delete a file.
bool ChangeAFileAttr(const char *filename, bool read, bool write)
Change read/write permission attributes of a file.
static bool MutexIsCancelSafe(const void *m)
std::string BytifySize(double val)
Format a byte count with binary units, e.g.
std::string GetCommandLineExecutable()
Get the full executable path as invoked.
bool StringFormatInto(char *dst, uint32 maxsize, const char *format,...)
printf into a caller-supplied buffer with truncation.
std::vector< std::string > TextListSplitLines(const char *text, bool keepEmpty=true, bool autoTrim=false)
Split text into lines, handling both \n and \r\n.
bool WriteAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Write (create/overwrite) a file.
std::string GetCurrentDir()
Current working directory.
std::string GetCommandLine()
Get the full original command line as one string.
static std::mutex gLaunchMx
bool CalcTimeout(struct timespec &timeout, uint32 ms)
static std::mutex gLaunchSerialMx
std::string ReadRegistryString(const char *key, const char *entry)
Read a string registry value.
std::vector< std::string > TextCommandlineSplit(const char *cmdline)
Split a command line into arguments, honouring quoting rules.
bool DoesADirExist(const char *dirname)
Test whether a directory exists.
static std::condition_variable gLaunchCv
bool DeleteRegistryEntry(const char *key, const char *entry)
Delete a single value from a key.
static bool gLauncherStarted
std::string StringFormat(const char *format,...)
printf into a std::string.
bool SetSocketNonBlockingMode(SOCKET s)
Put a socket into non-blocking mode.
bool DeleteADir(const char *dirname, bool force)
Delete a directory (recursively when force).
bool WriteRegistryQWORD(const char *key, const char *entry, uint64 value)
Write a 64-bit registry value.
char * ReadAFile(const char *filename, uint32 &length, bool binary=false)
Read an entire file into a new buffer.
static __thread int g_savedCancelState
uint64 Ascii2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit decimal integer from a substring.
uint64 AsciiHex2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit hexadecimal integer (with or without 0x) from a substring.
const char * GetFileBasename(const char *filename)
Filename portion of a path.
static PosixLaunchRequest * gLaunchReq
Library * OpenLibrary(const char *libName)
Load a library by name, applying platform filename conventions.
bool WriteRegistryString(const char *key, const char *entry, const char *value)
Write a string registry value.
static void DrumBeatCallback(union sigval p)
bool GetSystemMemoryUsage(uint64 &totalRAM, uint64 &freeRAM)
Query total and free physical memory.
static THREAD_RET THREAD_FUNCTION_CALL ProcessLauncherRun(THREAD_ARG)
int64 Ascii2Int64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 64-bit decimal integer from a substring.
static pid_t SubmitLaunchRequest(PosixLaunchRequest &req)
bool WriteRegistryDWORD(const char *key, const char *entry, uint32 value)
Write a 32-bit registry value (creates the key when needed).
std::string TextJoinJSON(std::map< std::string, std::string > &map)
Serialize a map as a JSON object (keys/values escaped).
bool CopyRegistryTree(const char *entry, const char *newName)
Recursively copy a registry subtree.
static bool g_signalThreadRunning
int(* LibraryFunction)()
Signature of a plain function exported from a dynamically loaded library.
bool DeleteRegistryTree(const char *root, const char *key)
Recursively delete a key and all subkeys.
std::string TextLowercase(const char *text)
Convert to lower case (ASCII/current locale).
std::string DecodeJSON(std::string str)
Unescape a JSON string value (\" \\ \n \t \uXXXX etc.).
std::string TextCapitalise(const char *text)
Capitalise the first letter of text.
const char * GetComputerName()
Get this machine's hostname.
std::string GetFilePath(const char *filename)
Directory portion of a path.
static void SignalShutdownSigset(sigset_t *set)
const char * GetSystemOSName()
OS name string, e.g.
std::string BytifySizes(double val1, double val2)
Format two byte counts as "x / y" with matching units.
bool IsLocalIPAddress(const char *addr)
Test whether a textual address refers to this machine (loopback or a local interface).
float64 Ascii2Float64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a 64-bit float from a substring (decimal point, not locale dependent).
std::string TextJoin(std::vector< std::string > &list, const char *split, uint32 start=0, uint32 count=0)
Join vector elements with split.
static pthread_t g_signalThread
int64 RandomInt(int64 from=0, int64 to=100)
Uniform random integer in [from,to].
std::string BytifyRate(double val)
Format a byte rate, e.g.
CleanShutdown CleanShutdownInstance
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
bool ClearUtilsMaps()
Free all lazily-allocated global registries (mutex/semaphore/event/shared-memory maps).
static bool Test_ProbeProcessWait()
uint32 CleanShutdownInstanceCount
void Register_Utils_Tests()
uint32 GetDataTypeID(const char *typeName)
Inverse of GetDataTypeName(): look up the numeric datatype id for a type name.
std::string GetDataTypeName(uint32 datatype)
Translate a CMSDK datatype id (e.g.
Wire/storage layout of one log record: fixed header immediately followed by the message text.
std::string toJSON()
Serialize the entry (header fields + text) as a JSON object string.
bool setText(char *text, uint32 len)
Copy len bytes of text into the payload area and update size.
const char * getText(uint32 &len)
Access the text payload stored after the header.
std::string toXML()
Serialize the entry as an XML fragment.
Bookkeeping record for one periodic "drum beat" timer.
Existence, type, permission and timestamp information for one file, as returned by GetFileDetails().
Description of one local network interface (IPv4 address, MAC and names).
char friendlyName[MAXKEYNAMELEN+1]
char name[MAXKEYNAMELEN+1]
const std::map< std::string, std::string > * env
POSIX capture bookkeeping for children started via NewProcessEx(captureOutput).
int errFD
Parent read-end of the child's stderr (-1 = not captured).
int outFD
Parent read-end of the child's stdout (-1 = not captured).
Snapshot from ProbeProcessWait(): is the child (group) alive, is it blocked reading stdin,...
uint64 cpuTimeMs
cumulative user+sys CPU across the process group, in ms
bool waitingStdin
blocked reading fd 0 (exact on Linux; best-effort composite elsewhere)
bool alive
process (or group) still exists
bool waitExact
true only when the OS reported the exact blocking syscall (Linux /proc/<pid>/syscall)
One scheduled entry inside a Timer: id, active window and platform timer handle.
A single timer expiry: which timer fired and when.