icedb  version 0.5.1
Snow particle scattering database API
os_functions.cpp
Go to the documentation of this file.
1 #if defined(_WIN32)
2 #define _BIND_TO_CURRENT_VCLIBS_VERSION 1
3 #include <Windows.h>
4 #include <ShlObj.h>
5 #include <TlHelp32.h>
6 #include <Psapi.h>
7 #pragma comment(lib, "Psapi")
8 #pragma comment(lib, "Ws2_32")
9 #pragma comment(lib, "Advapi32")
10 #pragma comment(lib, "Shell32")
11 #elif defined(__unix__) || defined(__APPLE__)
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/user.h>
15 #include <sys/sysctl.h>
16 #include <pwd.h>
17 #include <dlfcn.h>
18 #ifdef __unix__
19 #include <link.h> // not on mac
20 #endif
21 #include <dirent.h>
22 #endif
23 #ifdef __APPLE__
24 #include <mach-o/dyld.h>
25 #endif
26 #include <mutex>
27 #include <thread>
28 #include <ctime>
29 #include <iostream>
30 #include <stdio.h>
31 #include <algorithm>
32 #include <cstdlib>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36 #include <map>
37 #include <memory>
38 #include "../icedb/error.h"
39 #include "../icedb/error_context.h"
40 #include "../icedb/misc/os_functions.h"
41 #include "../icedb/misc/os_functions.hpp"
42 //#include "../icedb/dlls/dlls.h"
43 //#include "../icedb/misc/mem.h"
44 #include "../icedb/util.h"
45 
46 namespace icedb {
47  namespace os_functions {
48  namespace vars {
49  std::mutex m_sys_names;
50  std::string hostname, username,
53  pluginDir;
54  bool _consoleTerminated = false;
55  // First element is name, second is path. Gets locked with m_sys_names.
56  std::vector<std::pair<std::string, std::string> > loadedModulesList;
58  bool doWaitOnExit = false;
60  std::map<std::string, std::string> mmods;
61  }
62  namespace win {
63 #ifdef _WIN32
64  BOOL WINAPI _CloseHandlerRoutine(DWORD dwCtrlType) {
65  // Helps gracefully close console
67  return false;
68  }
69 
70  std::string convertStr(const LPTSTR instr)
71  {
72 #ifdef UNICODE
73  size_t origsize = wcslen(instr) + 1;
74 
75  const size_t newsize = origsize * 4;
76  size_t convertedChars = 0;
77  std::unique_ptr<char[]> nstring(new char[newsize]);
78  wcstombs_s(&convertedChars, nstring.get(), origsize, instr, _TRUNCATE);
79  // Destination string was always null-terminated!
80  std::string res(nstring.get());
81 #else
82  std::string res(instr);
83 #endif
84  return std::move(res);
85  }
86 
87  std::string convertStr(const PWSTR instr)
88  {
89  size_t origsize = wcslen(instr) + 1;
90 
91  const size_t newsize = origsize * 4;
92  size_t convertedChars = 0;
93  std::unique_ptr<char[]> nstring(new char[newsize]);
94  //char nstring[newsize];
95  wcstombs_s(&convertedChars, nstring.get(), origsize, instr, _TRUNCATE);
96  // Destination string was always null-terminated!
97  std::string res(nstring.get());
98 
99  return std::move(res);
100  }
101 
102  HMODULE GetCurrentModule()
103  {
111  HMODULE hModule = NULL;
112  GetModuleHandleEx(
113  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
114  (LPCTSTR)GetCurrentModule,
115  &hModule);
116 
117  return hModule;
118  }
119 
120  std::string GetModulePath(HMODULE mod)
121  {
122  std::string out;
123  bool freeAtEnd = false;
124  if (!mod)
125  {
126  mod = GetCurrentModule();
127  if (!mod) return std::move(out);
128  freeAtEnd = true;
129  }
130  const DWORD nSize = MAX_PATH * 4;
131  TCHAR filename[nSize];
132  DWORD sz = GetModuleFileName(mod, filename, nSize);
133  out = convertStr(filename);
134  if (freeAtEnd)
135  FreeLibrary(mod);
136  return std::move(out);
137  }
138 
139  bool getPathWIN32(DWORD pid, std::string &modPath, std::string &filename)
140  {
141  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
142  if (NULL == h) return false;
143  CloseHandle(h);
144  // Get parent process name
145  h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
146  //| PROCESS_VM_READ
147  , FALSE, pid);
148  if (NULL == h) return false;
149  TCHAR szModName[MAX_PATH];
150  DWORD success = 0;
151  DWORD sz = sizeof(szModName) / sizeof(TCHAR);
152  success = QueryFullProcessImageName(h, 0, szModName, &sz);
153  //success = GetModuleFileNameEx(h,NULL,szModName,sizeof(szModName) / sizeof(TCHAR));
154 
155  modPath = convertStr(szModName); // See previous function
156  size_t lp = modPath.find_last_of("/\\");
157  if (lp == std::string::npos) filename = modPath;
158  else if (lp < modPath.size()-1) filename = modPath.substr(lp + 1);
159  else filename = modPath;
160 
161  CloseHandle(h);
162  if (!success)
163  {
165  const size_t mxErrorMsg = 500;
166  char es[mxErrorMsg] = "";
167  success = GetLastError();
168  snprintf(es, mxErrorMsg, "%d", success);
169  ICEDB_error_context_add_string2(err, "WinError", es);
170  return false;
171  }
172  return true;
173  }
174 
175  bool IsAppRunningAsAdminMode()
176  {
177  BOOL fIsRunAsAdmin = FALSE;
178  DWORD dwError = ERROR_SUCCESS;
179  PSID pAdministratorsGroup = NULL;
180 
181  // Allocate and initialize a SID of the administrators group.
182  SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
183  if (!AllocateAndInitializeSid(
184  &NtAuthority,
185  2,
186  SECURITY_BUILTIN_DOMAIN_RID,
187  DOMAIN_ALIAS_RID_ADMINS,
188  0, 0, 0, 0, 0, 0,
189  &pAdministratorsGroup))
190  {
191  dwError = GetLastError();
192  goto Cleanup;
193  }
194 
195  // Determine whether the SID of administrators group is enabled in
196  // the primary access token of the process.
197  if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin))
198  {
199  dwError = GetLastError();
200  goto Cleanup;
201  }
202 
203  Cleanup:
204  // Centralized cleanup for all allocated resources.
205  if (pAdministratorsGroup)
206  {
207  FreeSid(pAdministratorsGroup);
208  pAdministratorsGroup = NULL;
209  }
210 
211  // Throw the error if something failed in the function.
212  if (ERROR_SUCCESS != dwError)
213  {
215  const size_t mxErrorMsg = 500;
216  char es[mxErrorMsg] = "";
217  snprintf(es, mxErrorMsg, "%d", dwError);
218  ICEDB_error_context_add_string2(err, "WinError", es);
219  return false;
220  }
221 
222  if (fIsRunAsAdmin) return true;
223  return false;
224  }
225 #endif
226  }
227  namespace unix {
228 #if defined(__linux__) || defined(__unix__)
229  int moduleCallback(dl_phdr_info *info, size_t sz, void* data)
231  {
232  std::string name(info->dlpi_name);
233  if (!name.size()) return 0;
234  vars::mmods[name] = name;
235  return 0;
236  }
237 #endif
238 #if defined(__unix__) || defined(__APPLE__)
239  bool dirExists(const char *p) {
240  DIR *d = NULL;
241  d = opendir(p);
242  bool res = (d) ? true : false;
243  if (d) closedir(d);
244  return res;
245  }
246 #endif
247 #if defined(__APPLE__) || defined(__linux__) || defined(__unix__)
248  std::string GetModulePath(void *addr)
249  {
250  std::string out;
251  Dl_info info;
252  void *addrb = addr;
253  if (!addrb) addrb = (void*)GetModulePath;
254  if (dladdr(addrb, &info))
255  {
256  out = std::string(info.dli_fname);
257  }
258  if (!out.size()) {
260  }
261  return out;
262  }
263 #endif
264  }
266  using namespace icedb::os_functions::vars;
267  std::lock_guard<std::mutex> lock(m_sys_names);
268  // Because of the mutex lock, all of the getlogin functions are safe.
269  if (username.size()) return true;
270 
271  // Username
272 #if defined(ICEDB_OS_WINDOWS)
273  BOOL res = false;
274  const DWORD clen = 256;
275  DWORD len = clen;
276  TCHAR hname[clen];
277  res = GetUserName(hname, &len);
278  if (res) username = win::convertStr(hname);
279  else goto funcErrorOS;
280 
281  res = GetComputerName(hname, &len);
282  if (res) hostname = win::convertStr(hname);
283  else goto funcErrorOS;
284 
285  HRESULT resl = false;
286  wchar_t* happname = nullptr;
287  res = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &happname);
288  if (resl == S_OK) appConfigDir = win::convertStr(happname);
289  else goto funcErrorOS;
290 
291  wchar_t* hhomename = nullptr;
292  res = SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &hhomename);
293  if (resl == S_OK) homeDir = win::convertStr(hhomename);
294  else goto funcErrorOS;
295 
296  goto done;
297  funcErrorOS:
298  DWORD errn = GetLastError();
300  const char* osname = ICEDB_error_getOSname();
301  ICEDB_error_context_add_string2(err, "OS_id", osname);
302  char errns[50];
303  snprintf(errns, 50, "%d", errn);
304  ICEDB_error_context_add_string2(err, "OS_errno", errns);
305  if (!username.size()) ICEDB_error_context_add_string2(err, "OS_func", "GetUserName");
306  else if (!hostname.size()) ICEDB_error_context_add_string2(err, "OS_func", "GetComputerName");
307  else if (!appConfigDir.size()) ICEDB_error_context_add_string2(err, "OS_func", "SHGetKnownFolderPath app config dir");
308  else if (!homeDir.size()) ICEDB_error_context_add_string2(err, "OS_func", "SHGetKnownFolderPath profile dir");
309  done:
310  if (happname) CoTaskMemFree(static_cast<void*>(happname));
311  if (hhomename) CoTaskMemFree(static_cast<void*>(hhomename));
312 
313 #elif defined(__unix__) || defined(__APPLE__)
314  const size_t len = 65536;
315  char hname[len];
316  int res = 0;
317  char* envres = NULL;
318 
319  if ((envres = getenv("USER"))) username = std::string(envres);
320  else if ((envres = getenv("LOGNAME"))) username = std::string(envres);
321  if (!username.size()) {
322 #if defined(_POSIX_C_SOURCE)
323 #if _POSIX_C_SOURCE >= 199506L
324  res = getlogin_r(hname, len); // getlogin and getlogin_r have problems. Avoid.
325  if (!res) username = std::string(hname);
326 #else
327  if ((envres = getlogin())) username = std::string(envres);
328 #endif
329  // Has getpwuid_r
330  if (!username.size()) {
331  uid_t uid = geteuid();
332  struct passwd* ps = (passwd*) ICEDB_malloc(sizeof(passwd));
333  struct passwd** pres; // A pointer to the result (or NULL on failure) is stored here.
334  res = getpwuid_r(uid, ps, hname, len, pres);
335  if ((res == 0) && pres) {
336  username = std::string(ps->pw_name);
337  }
338 
339  ICEDB_free(ps);
340  }
341 #else
342  // May have getpwuid
343  uid_t uid = geteuid();
344  struct passwd* ps = getpwuid(uid);
345  if (ps) username = std::string(ps->pw_name);
346 #endif
347  }
348 
349  // Hostname
350  res = gethostname(hname, len); // May be empty
351  if (hname[0]) hostname = std::string(hname);
352 
353  // Home dir
354  if ((envres = getenv("HOME"))) homeDir = std::string(envres);
355  if (!homeDir.size())
356  {
357 #if defined(_POSIX_C_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
358  struct passwd pw, *pwp;
359  int res = getpwuid_r(geteuid(), &pw, hname, len, &pwp);
360  if (res == 0) {
361  const char *homedir = pw.pw_dir;
362  homeDir = std::string(homedir);
363  }
364 #else
365  struct passwd* ps = getpwuid(geteuid());
366  if (ps) homeDir = std::string(ps->pw_dir);
367 #endif
368  }
369  if (!homeDir.size()) goto funcErrorOS;
370 
371  // App config dir
372  if ((envres = getenv("XDG_CONFIG_HOME"))) appConfigDir = std::string(envres);
373  else {
375  appConfigDir.append("/.config");
376  }
377 
378  goto done;
379  funcErrorOS:
380  {
382  const char* osname = ICEDB_error_getOSname();
383  ICEDB_error_context_add_string2(err, "OS_id", osname);
384  if (!username.size()) ICEDB_error_context_add_string2(err, "OS_func", "getlogin_r");
385  else if (!hostname.size()) ICEDB_error_context_add_string2(err, "OS_func", "gethostname");
386  else if (!appConfigDir.size()) ICEDB_error_context_add_string2(err, "OS_func", "getEnviron app config dir");
387  else if (!homeDir.size()) ICEDB_error_context_add_string2(err, "OS_func", "getEnviron profile dir");
388  }
389  done:
390 
391 #endif
393  const char* cosname = ICEDB_error_getOSname();
394  ICEDB_error_context_add_string2(ctxerr, "OS_id", cosname);
395  return false;
396  }
397  }
398 }
399 using namespace icedb::os_functions::vars;
400 
401 bool ICEDB_pidExists(int pid, bool &res)
402 {
403  // Function needed because Qt is insufficient, and Windows / Unix have
404  // different methods of ascertaining this.
405 #if defined(ICEDB_OS_WINDOWS)
406  HANDLE h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
407  if (h)
408  {
409  DWORD code = 0;
410  if (GetExitCodeProcess(h, &code))
411  {
412  CloseHandle(h);
413  if (code == STILL_ACTIVE)
414  {
415  res = true;
416  return true;
417  }
418  else {
419  res = false;
420  return true;
421  }
422  }
423  else {
424  CloseHandle(h);
425  res = false;
426  return true;
427  }
428  CloseHandle(h);
429  res = true;
430  return true;
431  }
432  return false;
433 #elif defined(ICEDB_OS_LINUX)
434  // Need to check existence of directory /proc/pid
435  std::ostringstream pname;
436  pname << "/proc/" << pid;
437  if (icedb::os_functions::unix::dirExists(pname.str().c_str())) {
438  res = true;
439  return true;
440  }
441  res = false;
442  return true;
443 #elif defined(__FreeBSD__) || defined (__APPLE__)
444  // Works for both freebsd and mac os
445  res = false;
446  int mib[4];
447  size_t len;
448  struct kinfo_proc kp;
449 
450  /* Fill out the first three components of the mib */
451  len = 4;
452  sysctlnametomib("kern.proc.pid", mib, &len);
453  mib[3] = pid;
454  len = sizeof(kp);
455  int sres = sysctl(mib, 4, &kp, &len, NULL, 0);
456  if (sres == -1) {
457  // Either the pid does not exist, or some other error
458  if (errno == ENOENT) {
459  res = false; return true;
460  }
462  const char* osname = ICEDB_error_getOSname();
463  ICEDB_error_context_add_string2(err, "OS_id", osname);
464  const int buflen = 200;
465  char strerrbuf[buflen] = "\0";
466  snprintf(strerrbuf, buflen, "%d", errno);
467  ICEDB_error_context_add_string2(err, "errno", strerrbuf);
468 
469  // strerror_r will always yield a null-terminated string.
470  //int ebufres = strerror_r(err, strerrbuf, buflen);
471  }
472  else if ((sres == 0) && (len > 0)) res = true;
473  return true;
474 #endif
476  const char* osname = ICEDB_error_getOSname();
477  ICEDB_error_context_add_string2(err, "OS_id", osname);
478  return false;
479 }
480 
482 #if defined(__unix__)
483  return (int)getpid();
484 #elif defined(ICEDB_OS_WINDOWS)
485  DWORD pid = 0;
487  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
488  if (NULL == h) return false;
489  PROCESSENTRY32 pe = { 0 };
490  pe.dwSize = sizeof(PROCESSENTRY32);
491  pid = GetCurrentProcessId();
492  CloseHandle(h);
493  return (int)pid;
494 #endif
496  const char* osname = ICEDB_error_getOSname();
497  ICEDB_error_context_add_string2(err, "OS_id", osname);
498  return -1;
499 }
500 
501 int ICEDB_getPPID(int pid) {
502 #if defined(__unix__)
503  return (int)getppid();
504 #elif defined(ICEDB_OS_WINDOWS)
505  DWORD Dpid = pid, ppid = 0;
506  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
507  if (NULL == h) return false;
508  PROCESSENTRY32 pe = { 0 };
509  pe.dwSize = sizeof(PROCESSENTRY32);
510  if (!pid) Dpid = GetCurrentProcessId();
511  if (Process32First(h, &pe)) {
512  do {
513  if (pe.th32ProcessID == Dpid) {
514  ppid = pe.th32ParentProcessID;
515  //printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID);
516  }
517  } while (Process32Next(h, &pe));
518  }
519 
520  //std::cout << "Pid " << pid << "\nPPID " << ppid << std::endl;
521  CloseHandle(h);
522  return (int)ppid;
523 #endif
525  const char* osname = ICEDB_error_getOSname();
526  ICEDB_error_context_add_string2(err, "OS_id", osname);
527  return -1;
528 }
529 
531 #if defined(ICEDB_OS_WINDOWS)
532  // Get pid and parent pid. Duplicated getPID and getPPID, but combines the calls.
533  DWORD pid = 0, ppid = 0;
534  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
535  if (NULL == h) return false;
536  PROCESSENTRY32 pe = { 0 };
537  pe.dwSize = sizeof(PROCESSENTRY32);
538  pid = GetCurrentProcessId();
539  if (Process32First(h, &pe)) {
540  do {
541  if (pe.th32ProcessID == pid) {
542  ppid = pe.th32ParentProcessID;
543  }
544  } while (Process32Next(h, &pe));
545  }
546  CloseHandle(h);
547 
548  // Get parent process name
549  std::string filepath, filename;
550  icedb::os_functions::win::getPathWIN32(ppid, filepath, filename);
551 
552  //std::cout << filename.string() << std::endl;
553  // If run from cmd, no need to wait
554  if (filename == "cmd.exe") return false;
555  // Cygwin
556  if (filename == "bash.exe") return false;
557  if (filename == "tcsh.exe") return false;
558  // Don't need these due to end return. Just for reference.
559  //if (filename == "devenv.exe") return true;
560  //if (filename == "explorer.exe") return true;
561  return true;
562 #endif
563  return false;
564 }
565 void ICEDB_waitOnExitSet(bool val) {
566  std::lock_guard<std::mutex> lock(m_sys_names);
568  doWaitOnExit = val;
569 }
571  std::lock_guard<std::mutex> lock(m_sys_names);
575  }
576  return doWaitOnExit;
577 }
578 
579 const char* ICEDB_getUserName() {
581  return username.c_str();
582 }
583 const char* ICEDB_getHostName() {
585  return hostname.c_str();
586 }
587 const char* ICEDB_getAppConfigDir() {
589  return appConfigDir.c_str();
590 }
591 const char* ICEDB_getHomeDir() {
593  return homeDir.c_str();
594 }
595 
597  if (!p) return;
598  if (p->sz) {
599  for (int i = 0; i < p->sz; ++i) {
600  ICEDB_free((void*)p->modules[i]);
601  p->modules[i] = nullptr;
602  }
603  }
604  ICEDB_free(p->modules);
605  ICEDB_free(p);
606 }
609 
610 #if defined(_WIN32)
611  HANDLE h = NULL, snapshot = NULL;
612  h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
613  std::shared_ptr<MODULEENTRY32> mod(new MODULEENTRY32);
614  if (!h || h == INVALID_HANDLE_VALUE) goto err;
615  snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
616  if (!snapshot || snapshot == INVALID_HANDLE_VALUE) goto err;
617  mod->dwSize = sizeof(MODULEENTRY32); // Annoying requirement
618  if (!Module32First(snapshot, mod.get())) goto err;
619  do {
620  std::string modName = icedb::os_functions::win::convertStr(mod->szModule);
621  std::string modPath = icedb::os_functions::win::convertStr(mod->szExePath);
622  icedb::os_functions::vars::mmods[modName] = modPath;
623  } while (Module32Next(snapshot, mod.get()));
624 
625  goto done;
626  err:
628  const char* cosname = ICEDB_error_getOSname();
629  ICEDB_error_context_add_string2(ctxerr, "OS_id", cosname);
630  if (!h || h == INVALID_HANDLE_VALUE)
631  ICEDB_error_context_add_string2(ctxerr, "Description", "Error in getting handle for process!");
632  else if (!snapshot || snapshot == INVALID_HANDLE_VALUE)
633  ICEDB_error_context_add_string2(ctxerr, "Description", "Cannot get handle snapshot!");
634  else ICEDB_error_context_add_string2(ctxerr, "Description", "Cannot list first modle!");
635  done:
636 
637  if (snapshot && snapshot != INVALID_HANDLE_VALUE) CloseHandle(snapshot);
638  if (h && h != INVALID_HANDLE_VALUE) CloseHandle(h);
639 #elif defined(__linux__) || defined(__unix__)
640  if (pid != icedb::os_functions::getPID()) {
642  const char* cosname = ICEDB_error_getOSname();
643  ICEDB_error_context_add_string2(ctxerr, "OS_id", cosname);
644  ICEDB_error_context_add_string2(ctxerr, "Description", "This function only works for the pid of the main process.");
645  return NULL;
646  }
647  if (!moduleCallbackBuffer.size()) {
648  dl_iterate_phdr(icedb::os_functions::unix::moduleCallback, NULL);
649  }
650 #elif defined(__APPLE__)
651  uint32_t count = _dyld_image_count();
652  for (uint32_t i=0; i<count; ++i) {
653  std::string modName(_dyld_get_image_name(i));
654  char cmodPath[2048];
655  char *ccmodPath = realpath(modName.c_str(), NULL);
656  if (ccmodPath != NULL) {
657  strncpy(cmodPath,ccmodPath,2048);
658  free(ccmodPath);
659  }
660  std::string modPath(ccmodPath);
661  icedb::os_functions::vars::mmods[modPath] = modPath;
662  }
663 #else
664 #endif
665  // Convert the map to the resultant structure.
667  char **nmods = (char**)ICEDB_malloc(p->sz*sizeof (char**));
668  size_t i = 0;
669  for (auto &s : mmods) {
670  nmods[i] = ICEDB_COMPAT_strdup_s(s.second.c_str(), s.second.size());
671  ++i;
672  }
673  p->modules = const_cast<const char**>(nmods);
674  return p;
675 }
676 
677 char* ICEDB_findModuleByFunc(void* ptr, size_t sz, char* res) {
684  std::string modpath;
685 #if defined(_WIN32)
686  BOOL success = false;
687  if (ptr)
688  {
689  DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
690  LPCTSTR lpModuleName = (LPCTSTR)ptr;
691  HMODULE mod;
692  success = GetModuleHandleEx(flags, lpModuleName, &mod);
693  if (!success) return nullptr;
694  modpath = icedb::os_functions::win::GetModulePath(mod);
695  FreeLibrary(mod);
696  } else modpath = icedb::os_functions::win::GetModulePath(NULL);
697 #elif defined(__unix__) || defined(__APPLE__)
698  modpath = icedb::os_functions::unix::GetModulePath(ptr);
699 #else
701 #endif
702  ICEDB_COMPAT_strncpy_s(res, sz, modpath.c_str(), modpath.size());
703  return res;
704 }
705 
707 #if defined(_WIN32)
708  libPath = icedb::os_functions::win::GetModulePath(NULL);
709 #elif defined(__unix__) || defined(__APPLE__)
710  libPath = icedb::os_functions::unix::GetModulePath((void*)ICEDB_getLibDirI);
711 #endif
712  libDir = libPath.substr(0, libPath.find_last_of("/\\"));
713 }
714 char* ICEDB_getLibDir(size_t sz, char* res) {
716  ICEDB_COMPAT_strncpy_s(res, sz, libDir.c_str(), libDir.size());
717  return res;
718 }
719 const char* ICEDB_getLibDirC() {
721  return libDir.c_str();
722 }
724  std::string &appd = appDir;
725 #if defined(_WIN32)
726  DWORD pid = (DWORD)ICEDB_getPID(); // int always fits in DWORD
727  std::string filename;
728  icedb::os_functions::win::getPathWIN32(pid, appPath, filename);
729  appd = appPath.substr(0, appPath.find_last_of("/\\"));
730 #elif defined(__APPLE__)
731  char exePath[PATH_MAX];
732  uint32_t len = sizeof(exePath);
733  if (_NSGetExecutablePath(exePath, &len) != 0) {
734  exePath[0] = '\0'; // buffer too small (!)
735  }
736  else {
737  // resolve symlinks, ., .. if possible
738  char *canonicalPath = realpath(exePath, NULL);
739  if (canonicalPath != NULL) {
740  strncpy(exePath, canonicalPath, len);
741  free(canonicalPath);
742  }
743  }
744  appPath = std::string(exePath);
745  appd = appPath.substr(0, appPath.find_last_of("/\\"));
746 #elif defined(__linux__)
747  char exePath[PATH_MAX];
748  ssize_t len = ::readlink("/proc/self/exe", exePath, sizeof(exePath));
749  if (len == -1 || len == sizeof(exePath)) len = 0;
750  exePath[len] = '\0';
751  appPath = std::string(exePath);
752  appd = appPath.substr(0, appPath.find_last_of("/\\"));
753 #elif defined(__unix__)
754  char exePath[2048];
755  int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1;
756  size_t len = sizeof(exePath);
757  if (sysctl(mib, 4, exePath, &len, NULL, 0) != 0)
758  exePath[0] = '\0';
759  appPath = std::string(exePath);
760  appd = appPath.substr(0, appPath.find_last_of("/\\"));
761 #else
763 #endif
764 }
765 char* ICEDB_getAppDir(size_t sz, char* res) {
767  ICEDB_COMPAT_strncpy_s(res, sz, appDir.c_str(), appDir.size());
768  return res;
769 }
770 const char* ICEDB_getAppDirC() {
772  return appDir.c_str();
773 }
775  std::string &cwd = CWD;
776 #if defined(_WIN32)
777  DWORD sz = GetCurrentDirectory(0, NULL);
778  LPTSTR cd = new TCHAR[sz];
779  DWORD result = GetCurrentDirectory(2500, cd);
780  cwd = std::string(cd);
781  delete[] cd;
782 #else
783  char ccwd[4096];
784  char* res = getcwd(ccwd, 4096);
785  if (!res) {
788 
789  return ;
790  }
791  cwd = std::string(ccwd);
792 #endif
793 }
794 char* ICEDB_getCWD(size_t ssz, char* res) {
795  ICEDB_getCWDI();
796  ICEDB_COMPAT_strncpy_s(res, ssz, CWD.c_str(), CWD.size());
797  return res;
798 }
799 const char* ICEDB_getCWDC() {
800  ICEDB_getCWDI();
801  return CWD.c_str();
802 }
803 
804 char* ICEDB_getLibPath(size_t sz, char* res) {
806  ICEDB_COMPAT_strncpy_s(res, sz, libPath.c_str(), libPath.size());
807  return res;
808 }
809 const char* ICEDB_getLibPathC() {
811  return libPath.c_str();
812 }
813 char* ICEDB_getAppPath(size_t sz, char* res) {
815  ICEDB_COMPAT_strncpy_s(res, sz, appPath.c_str(), appPath.size());
816  return res;
817 }
818 const char* ICEDB_getAppPathC() {
819  ICEDB_getAppDirI();
820  return appPath.c_str();
821 }
822 
825  pluginDir = libDir + "/icedb-plugins";
826 }
827 char* ICEDB_getPluginDir(size_t sz, char* res) {
829  ICEDB_COMPAT_strncpy_s(res, sz, pluginDir.c_str(), pluginDir.size());
830  return res;
831 }
832 const char* ICEDB_getPluginDirC() {
834  return pluginDir.c_str();
835 }
836 
848 void ICEDB_libEntry(int, char**) {
849 #ifdef _WIN32
850  // Get PID
851  DWORD pid = 0;
852  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
853  if (NULL == h) return;
854  PROCESSENTRY32 pe = { 0 };
855  pe.dwSize = sizeof(PROCESSENTRY32);
856  pid = GetCurrentProcessId();
857  CloseHandle(h);
858 
859  // Get parent process name
860  h = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
861  //| PROCESS_VM_READ
862  , FALSE, pid);
863  if (NULL == h) return;
864  TCHAR szModName[600];
865  DWORD success = 0;
866  DWORD sz = sizeof(szModName) / sizeof(TCHAR);
867  success = QueryFullProcessImageName(h, 0, szModName, &sz);
868 
869  // Set Console Title
870  SetConsoleTitle(szModName);
871 
872 
873  // Also, set the window closing routine
874  // This allows for the user to click the X (or press ctrl-c)
875  // without causing a fault.
876  // The fault is because the window closes before the atexit
877  // functions can write output.
878  SetConsoleCtrlHandler(icedb::os_functions::win::_CloseHandlerRoutine, true);
879  CloseHandle(h);
880 #endif
881 
882 
883  // Set appexit
884  atexit(ICEDB_libExit);
885  // Static registration of i/o objects
886 
887  // Load the appropriate filesystem plugin
888  //std::string pDir(ICEDB_getPluginDirC());
889  //const size_t mangledNameSz = 200;
890  //char mangledName[mangledNameSz] = "";
891 #if defined(_WIN32)
892  //ICEDB_dll_name_mangle_simple("fs-win", mangledName, mangledNameSz);
893 #else
894  //ICEDB_dll_name_mangle_simple("fs-posix", mangledName, mangledNameSz);
895 #endif
896  //std::string testP = pDir + "/" + std::string(mangledName);
897  //ICEDB_load_plugin(testP.c_str());
898 
899 
900  // Query the filesystem to load the remaining plugins
901 
902 }
903 
905  using namespace std;
906  if (_consoleTerminated) return;
907  if (ICEDB_waitOnExitGet())
908  {
909  cerr << endl << "Program terminated. Press return to exit." << endl;
910  //std::getchar();
911  // Ignore to the end of file
912 //#ifdef max
913 //#undef max
914 //#endif
915  cin.clear();
916  //cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
917  std::string ln;
918  std::getline(cin, ln);
919  }
920 }
921 
922 void ICEDB_writeDebugString(const char* c) {
923 #ifdef _WIN32
924  OutputDebugStringA(c);
925 #else
926  // Just write to CERR
927  ICEDB_COMPAT_fprintf_s(stderr, "%s", c);
928 #endif
929 }
930 
931 
932 
933 
934 
935 namespace icedb {
936  namespace os_functions {
937 
938  bool pidExists(int pid) { bool res = false; ICEDB_pidExists(pid, res); return res; }
939  int getPID() { return ICEDB_getPID(); }
940  int getPPID(int pid) { return ICEDB_getPPID(pid); }
941  void libEntry(int argc, char** argv) { ICEDB_libEntry(argc, argv); }
942  void waitOnExit(bool val) { ICEDB_waitOnExitSet(val); }
943  bool waitOnExit() { return ICEDB_waitOnExitGet(); }
944  const char* getUserName() { return ICEDB_getUserName(); }
945  const char* getHostName() { return ICEDB_getHostName(); }
946  const char* getAppConfigDir() { return ICEDB_getAppConfigDir(); }
947  const char* getHomeDir() { return ICEDB_getHomeDir(); }
948  const char* getLibDir() { ICEDB_getLibDirI(); return libDir.c_str(); }
949  const char* getAppDir() { ICEDB_getAppDirI(); return appDir.c_str(); }
950  const char* getPluginDir() { ICEDB_getPluginDirI(); return pluginDir.c_str(); }
951  const char* getLibPath() { ICEDB_getLibDirI(); return libPath.c_str(); }
952  const char* getAppPath() { ICEDB_getAppDirI(); return appPath.c_str(); }
953  const char* getCWD() { ICEDB_getCWDI(); return CWD.c_str(); }
954  }
955 }
956 
std::map< std::string, std::string > mmods
const char * ICEDB_getCWDC()
#define ICEDB_DEBUG_RAISE_EXCEPTION()
Definition: defs.h:151
const char * ICEDB_getAppPathC()
const char ** modules
Definition: os_functions.h:25
const char * getHomeDir()
std::string moduleCallbackBuffer
void free(T *obj)
Definition: util.hpp:21
int getPPID(int pid)
char * ICEDB_getLibPath(size_t sz, char *res)
const char * getUserName()
const char * ICEDB_getLibPathC()
bool ICEDB_waitOnExitGet()
ICEDB_SYMBOL_SHARED void ICEDB_free(void *obj)
Free memory region. Should not be double-freed.
Definition: util.cpp:97
bool doWaitOnExit
Private flag that determines if the app waits for the user to press &#39;Enter&#39; to terminate it at the en...
const char * getAppConfigDir()
const char * ICEDB_getAppConfigDir()
STL namespace.
void ICEDB_getPluginDirI()
Unimplemented function path.
Definition: errorCodes.h:18
int ICEDB_getPID()
char * ICEDB_getAppPath(size_t sz, char *res)
const char * ICEDB_getAppDirC()
DL_ICEDB ICEDB_error_getOSname_f ICEDB_error_getOSname
Definition: error.cpp:210
void ICEDB_free_enumModulesRes(ICEDB_enumModulesRes *p)
bool ICEDB_waitOnExitGetDefault()
char * ICEDB_getPluginDir(size_t sz, char *res)
int ICEDB_getPPID(int pid)
void ICEDB_getLibDirI()
bool pidExists(int pid)
ICEDB_BEGIN_DECL_C ICEDB_SYMBOL_SHARED size_t ICEDB_COMPAT_strncpy_s(char *dest, size_t destSz, const char *src, size_t srcSz)
Definition: util.cpp:14
const char * getPluginDir()
char * ICEDB_getAppDir(size_t sz, char *res)
char * ICEDB_getLibDir(size_t sz, char *res)
const char * getLibDir()
const char * ICEDB_getPluginDirC()
ICEDB_SYMBOL_SHARED char * ICEDB_COMPAT_strdup_s(const char *src, size_t srcSz)
Definition: util.cpp:42
const char * getAppPath()
void ICEDB_getCWDI()
const char * ICEDB_getUserName()
const char * getHostName()
ICEDB_SYMBOL_SHARED void * ICEDB_malloc(size_t numBytes)
Allocate memory in bytes. Generally this is just malloced, but a custom allocator may be substituted...
Definition: util.cpp:90
char * ICEDB_getCWD(size_t ssz, char *res)
std::vector< std::pair< std::string, std::string > > loadedModulesList
void ICEDB_writeDebugString(const char *c)
const char * ICEDB_getHostName()
const char * getAppDir()
void ICEDB_getAppDirI()
const char * getLibPath()
bool ICEDB_pidExists(int pid, bool &res)
void waitOnExit(bool val)
const char * getCWD()
Error returned by an os subsystem (general)
Definition: errorCodes.h:17
char * ICEDB_findModuleByFunc(void *ptr, size_t sz, char *res)
void ICEDB_libEntry(int, char **)
Entry function that gets called when a debugged application first loads.
#define ICEDB_error_context_add_string2
Definition: error_context.h:63
ICEDB_enumModulesRes * ICEDB_enumModules(int pid)
void ICEDB_libExit()
void libEntry(int argc, char **argv)
const char * ICEDB_getLibDirC()
#define ICEDB_error_context_create(x)
Definition: error_context.h:35
void ICEDB_waitOnExitSet(bool val)
const char * ICEDB_getHomeDir()
#define ICEDB_COMPAT_fprintf_s
Definition: util.h:26