13 #include <sys/types.h>
18 #include "GmshConfig.h"
22 #if defined(HAVE_ZIPPER)
29 #if defined(__APPLE__)
30 #include <sys/sysctl.h>
31 #include <mach-o/dyld.h>
34 #if defined(__linux__) && !defined(BUILD_ANDROID)
35 #include <sys/sysinfo.h>
38 #if !defined(WIN32) || defined(__CYGWIN__)
41 #include <sys/resource.h>
53 #include <sys/timeb.h>
59 #if defined(WIN32) && !defined(__CYGWIN__)
63 static unsigned int utf8decode(
const char *p,
const char *end,
int *len)
65 static unsigned short cp1252[32] = {
66 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
67 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
68 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
69 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178};
70 unsigned char c = *(
unsigned char *)p;
77 return cp1252[
c - 0x80];
82 if((end && p + 1 >= end) || (p[1] & 0xc0) != 0x80)
goto FAIL;
85 return ((p[0] & 0x1f) << 6) + ((p[1] & 0x3f));
88 if(((
unsigned char *)p)[1] < 0xa0)
goto FAIL;
93 if((end && p + 2 >= end) || (p[2] & 0xc0) != 0x80)
goto FAIL;
95 return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + ((p[2] & 0x3f));
98 if(((
unsigned char *)p)[1] < 0x90)
goto FAIL;
103 if((end && p + 3 >= end) || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)
106 return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) +
107 ((p[2] & 0x3f) << 6) + ((p[3] & 0x3f));
110 if(((
unsigned char *)p)[1] > 0x8f)
goto FAIL;
120 static unsigned int utf8toUtf16(
const char *src,
unsigned int srclen,
121 unsigned short *dst,
unsigned int dstlen)
124 const char *e = src + srclen;
125 unsigned int count = 0;
137 unsigned int ucs = utf8decode(p, e, &len);
144 if(count + 2 >= dstlen) {
149 dst[count] = (((ucs - 0x10000u) >> 10) & 0x3ff) | 0xd800;
150 dst[++count] = (ucs & 0x3ff) | 0xdc00;
153 if(++count == dstlen) {
164 unsigned int ucs = utf8decode(p, e, &len);
166 if(ucs >= 0x10000) ++count;
173 static unsigned int utf8FromUtf16(
char *dst,
unsigned int dstlen,
174 const wchar_t *src,
unsigned int srclen)
177 unsigned int count = 0;
188 if(count >= dstlen) {
193 else if(ucs < 0x800U) {
194 if(count + 2 >= dstlen) {
199 dst[count++] = 0xc0 | (ucs >> 6);
200 dst[count++] = 0x80 | (ucs & 0x3F);
202 else if(ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
203 src[i] >= 0xdc00 && src[i] <= 0xdfff) {
205 unsigned int ucs2 = src[i++];
206 ucs = 0x10000U + ((ucs & 0x3ff) << 10) + (ucs2 & 0x3ff);
208 if(count + 4 >= dstlen) {
213 dst[count++] = 0xf0 | (ucs >> 18);
214 dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
215 dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
216 dst[count++] = 0x80 | (ucs & 0x3F);
220 if(count + 3 >= dstlen) {
225 dst[count++] = 0xe0 | (ucs >> 12);
226 dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
227 dst[count++] = 0x80 | (ucs & 0x3F);
233 unsigned int ucs = src[i++];
237 else if(ucs < 0x800U) {
240 else if(ucs >= 0xd800 && ucs <= 0xdbff && i < srclen - 1 &&
241 src[i + 1] >= 0xdc00 && src[i + 1] <= 0xdfff) {
253 static wchar_t *wbuf[3] = {
nullptr,
nullptr,
nullptr};
255 static void setwbuf(
int i,
const char *
f)
264 size_t l = strlen(
f);
265 unsigned int wn = utf8toUtf16(
f, (
unsigned int)l,
nullptr, 0) + 1;
266 wbuf[i] = (
wchar_t *)realloc(wbuf[i],
sizeof(
wchar_t) * wn);
267 wn = utf8toUtf16(
f, (
unsigned)l, (
unsigned short *)wbuf[i], wn);
273 FILE *
Fopen(
const char *
f,
const char *mode)
275 #if defined(WIN32) && !defined(__CYGWIN__)
278 return _wfopen(wbuf[0], wbuf[1]);
280 return fopen(
f, mode);
286 #if defined(WIN32) && !defined(__CYGWIN__)
287 setwbuf(0, var.c_str());
288 const wchar_t *wtmp = _wgetenv(wbuf[0]);
291 utf8FromUtf16(tmp, MAX_PATH, wtmp, wcslen(wtmp));
294 if(!strcmp(tmp,
"/") || strstr(tmp,
"%") || strstr(tmp,
"$"))
297 return std::string(tmp);
299 const char *tmp = getenv(var.c_str());
301 return std::string(tmp);
307 #if defined(WIN32) && !defined(__CYGWIN__)
308 setwbuf(0, (var +
"=" + val).c_str());
311 setenv(var.c_str(), val.c_str(), 1);
317 #if defined(WIN32) && !defined(__CYGWIN__)
318 Sleep((
long)(1.e3 * s));
320 usleep((
long)(1.e6 * s));
326 #if defined(WIN32) && !defined(__CYGWIN__)
327 FILETIME creation, exit, kernel, user;
328 if(GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user)) {
329 *s = 1.e-7 * 4294967296. * (double)user.dwHighDateTime +
330 1.e-7 * (
double)user.dwLowDateTime;
332 PROCESS_MEMORY_COUNTERS info;
333 GetProcessMemoryInfo(GetCurrentProcess(), &info,
sizeof(info));
334 *mem = (long)info.PeakWorkingSetSize;
336 static struct rusage r;
337 getrusage(RUSAGE_SELF, &r);
338 *s = (double)r.ru_utime.tv_sec + 1.e-6 * (
double)r.ru_utime.tv_usec;
339 #if defined(__APPLE__)
340 *mem = (long)r.ru_maxrss;
342 *mem = (
long)(r.ru_maxrss * 1024L);
349 #if !defined(WIN32) || defined(__CYGWIN__)
350 static struct rlimit r;
352 getrlimit(RLIMIT_STACK, &r);
357 if(r.rlim_cur < 16 * 1024 * 1024) {
358 Msg::Info(
"Increasing process stack size (%d kB < 16 MB)",
360 r.rlim_cur = r.rlim_max;
361 setrlimit(RLIMIT_STACK, &r);
377 #if defined(__APPLE__)
378 int name[] = {CTL_HW, HW_MEMSIZE};
380 size_t len =
sizeof(value);
381 if(sysctl(name, 2, &value, &len,
nullptr, 0) != -1)
382 ram = value / (1024 * 1024);
384 MEMORYSTATUSEX status;
385 status.dwLength =
sizeof(status);
386 GlobalMemoryStatusEx(&status);
387 ram = status.ullTotalPhys / ((double)1024 * 1024);
388 #elif defined(BUILD_ANDROID)
390 #elif defined(__linux__)
391 struct sysinfo infos;
392 if(sysinfo(&infos) != -1)
394 infos.totalram * (
unsigned long)infos.mem_unit / ((double)1024 * 1024);
402 auto t = std::chrono::steady_clock::now();
403 return std::chrono::duration<double>(t.time_since_epoch()).count();
416 #if defined(WIN32) && !defined(__CYGWIN__)
425 std::string name =
"";
426 #if defined(WIN32) && !defined(__CYGWIN__)
427 wchar_t src[MAX_PATH];
428 unsigned long size = GetModuleFileNameW(
nullptr, src, MAX_PATH);
431 utf8FromUtf16(dst, MAX_PATH, src, size);
432 name = std::string(dst);
434 #elif defined(__APPLE__)
436 uint32_t size =
sizeof(path);
437 if(_NSGetExecutablePath(path, &size) == 0) {
439 if(realpath(path, real)) {
440 name = std::string(real);
443 #elif defined(__linux__)
445 int n = readlink(
"/proc/self/exe", path,
sizeof(path));
446 if(n > 0 && n < (
int)
sizeof(path)) {
448 name = std::string(path);
456 #if defined(WIN32) && !defined(__CYGWIN__)
457 setwbuf(0, fileName.c_str());
458 wchar_t path[MAX_PATH];
459 unsigned long size = GetFullPathNameW(wbuf[0], MAX_PATH, path,
nullptr);
462 utf8FromUtf16(dst, MAX_PATH, path, size);
463 return std::string(dst);
467 if(realpath(fileName.c_str(), path))
return path;
475 gethostname(host,
sizeof(host));
476 return std::string(host);
481 #if defined(WIN32) && !defined(__CYGWIN__)
482 setwbuf(0, fileName.c_str());
483 return _wunlink(wbuf[0]);
485 return unlink(fileName.c_str());
491 #if defined(WIN32) && !defined(__CYGWIN__)
493 setwbuf(0, fileName.c_str());
494 int ret = _wstat(wbuf[0], &buf);
497 int ret = stat(fileName.c_str(), &buf);
504 #if defined(WIN32) && !defined(__CYGWIN__)
505 setwbuf(0, dirName.c_str());
506 if(_wmkdir(wbuf[0]))
return 0;
508 if(mkdir(dirName.c_str(), 0777))
return 0;
515 size_t lastp = fullPath.find_last_of(
'/');
516 if(lastp == std::string::npos)
return;
517 std::string dirname = std::string(fullPath, 0, lastp);
519 while(cur != std::string::npos) {
520 cur = dirname.find(
'/', cur + 1);
527 #if defined(WIN32) && !defined(__CYGWIN__)
528 HANDLE hProc = OpenProcess(PROCESS_TERMINATE,
FALSE, pid);
529 if(!TerminateProcess(hProc, 0)) {
534 if(kill(pid, 9))
return 0;
544 bool isPython = (split[2] ==
".py" || split[2] ==
".PY");
545 bool isOctave = (split[2] ==
".m" || split[2] ==
".M");
546 bool isExe = (split[2] ==
".exe" || split[2] ==
".EXE");
548 if(isPython || isOctave || isExe) {
550 Msg::Error(
"Unable to open file '%s'", exe.c_str());
557 command.append(
"\"" + exe +
"\"");
558 if(argsOrCommand.size()) command.append(
" ");
560 command.append(argsOrCommand);
562 #if defined(WIN32) && !defined(__CYGWIN__)
563 if(isPython || isOctave) {
564 Msg::Info(
"Shell opening '%s' with arguments '%s'", exe.c_str(),
565 argsOrCommand.c_str());
567 setwbuf(1, exe.c_str());
568 setwbuf(2, argsOrCommand.c_str());
569 ShellExecuteW(
nullptr, wbuf[0], wbuf[1], wbuf[2],
nullptr, 0);
573 PROCESS_INFORMATION prInfo;
574 memset(&suInfo, 0,
sizeof(suInfo));
575 suInfo.cb =
sizeof(suInfo);
576 Msg::Info(
"Calling '%s'", command.c_str());
577 setwbuf(0, command.c_str());
579 CreateProcessW(
nullptr, wbuf[0],
nullptr,
nullptr,
FALSE,
580 NORMAL_PRIORITY_CLASS,
nullptr,
nullptr, &suInfo, &prInfo);
582 WaitForSingleObject(prInfo.hProcess, INFINITE);
584 CloseHandle(prInfo.hProcess);
585 CloseHandle(prInfo.hThread);
590 DWORD dwCreationFlags;
592 dwCreationFlags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS;
594 dwCreationFlags = NORMAL_PRIORITY_CLASS;
596 CreateProcessW(
nullptr, wbuf[0],
nullptr,
nullptr,
FALSE,
597 dwCreationFlags,
nullptr,
nullptr, &suInfo, &prInfo);
603 std::string cmd(command);
604 if(isPython || isOctave || isExe) {
605 if(access(exe.c_str(), X_OK)) {
607 Msg::Info(
"Script '%s' is not executable: running with `%s'",
613 Msg::Info(
"Script '%s' is not executable: running with `%s'",
619 Msg::Warning(
"File '%s' is not executable", exe.c_str());
621 else if(split[0].empty()) {
626 if(!system(
nullptr)) {
627 Msg::Error(
"Could not find /bin/sh: aborting system call");
630 if(!blocking) cmd +=
" &";
632 return system(cmd.c_str());
644 #if defined(WIN32) && !defined(__CYGWIN__)
649 if(!AttachConsole(ATTACH_PARENT_PROCESS))
return;
652 intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
653 if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE) {
654 int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
655 if(hConHandle >= 0) {
656 FILE *fp = _fdopen(hConHandle,
"w");
659 setvbuf(stdout,
nullptr, _IONBF, 0);
665 intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
666 if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE) {
667 int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
668 if(hConHandle >= 0) {
669 FILE *fp = _fdopen(hConHandle,
"r");
672 setvbuf(stdin,
nullptr, _IONBF, 0);
678 intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
679 if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE) {
680 int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
681 if(hConHandle >= 0) {
682 FILE *fp = _fdopen(hConHandle,
"w");
685 setvbuf(stderr,
nullptr, _IONBF, 0);
692 std::ios::sync_with_stdio();
696 void UnzipFile(
const std::string &fileName,
const std::string &prependDir)
698 #if defined(HAVE_ZIPPER)
699 std::string dir = prependDir;
700 if(dir.size() && dir[dir.size() - 1] !=
'/' && dir[dir.size() - 1] !=
'\\')
703 ziputils::unzipper zipFile;
704 zipFile.open(fileName.c_str());
705 std::vector<std::string> dirnames = zipFile.getFolders();
706 for(
auto it = dirnames.begin(); it != dirnames.end(); it++) {
707 std::string folder = dir + *it;
708 Msg::Info(
"Creating folder `%s'", folder.c_str());
711 std::vector<std::string> filenames = zipFile.getFilenames();
712 for(
auto it = filenames.begin(); it != filenames.end(); it++) {
713 zipFile.openEntry(it->c_str());
714 std::string name = dir + *it;
715 Msg::Info(
"Extracting file `%s'", name.c_str());
717 ofs.open(name.c_str());
723 Msg::Error(
"Could not create file `%s'", name.c_str());
726 Msg::Error(
"Gmsh must be compiled with Zipper support to extract zip files");