Newer
Older
// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to the public mailing list <gmsh@geuz.org>.
// This file contains a bunch of functions that depend on OS-dependent
// features and/or system calls
// these are available on all OSes
#include <stdlib.h>

Christophe Geuzaine
committed
#include "StringUtils.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <iostream>
#include <fstream>
#endif
#if defined(__APPLE__)
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN -1
#endif

Christophe Geuzaine
committed
#include "GmshMessage.h"
{
#if !defined(WIN32)
return getenv(var);
#else
const char *tmp = getenv(var);
// Don't accept top dir or anything partially expanded like
// c:\Documents and Settings\%USERPROFILE%, etc.
if(!tmp || !strcmp(tmp, "/") || strstr(tmp, "%") || strstr(tmp, "$"))
return 0;
else
return tmp;
#endif
}
const void SetEnvironmentVar(const char *var, const char *val)
{
#if !defined(WIN32)
setenv(var, val, 1);
#else
_putenv((std::string(var) + "=" + std::string(val)).c_str());
#endif
}
#if !defined(WIN32) || defined(__CYGWIN__)
struct timeval tp;
gettimeofday(&tp, (struct timezone *)0);
double t = (double)tp.tv_sec + 1.e-6 * (double)tp.tv_usec;
return t;
#else
double t = 1.e-7 * 4294967296. * (double)ft.dwHighDateTime +
1.e-7 * (double)ft.dwLowDateTime;
#endif
#if !defined(WIN32) || defined(__CYGWIN__)
usleep((long)(1.e6 * s));
#else
#endif
{
#if !defined(WIN32) || defined(__CYGWIN__)
static struct rusage r;
getrusage(RUSAGE_SELF, &r);
*s = (double)r.ru_utime.tv_sec + 1.e-6 * (double)r.ru_utime.tv_usec;
*mem = (long)r.ru_maxrss;
#else
*mem = (long)(r.ru_maxrss * 1024L);
#endif
#else
FILETIME creation, exit, kernel, user;
if(GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user)){
*s = 1.e-7 * 4294967296. * (double)user.dwHighDateTime +
1.e-7 * (double)user.dwLowDateTime;
}
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
*mem = (long)info.PeakWorkingSetSize;
}
void CheckResources()
{
#if !defined (WIN32) || defined(__CYGWIN__)
static struct rlimit r;
getrlimit(RLIMIT_STACK, &r);
// Try to get at least 16 MB of stack. Running with too small a stack
// can cause crashes in the recursive calls (e.g. for tet
// classification in 3D Delaunay)
if(r.rlim_cur < 16 * 1024 * 1024){
Msg::Info("Increasing process stack size (%d kB < 16 MB)", r.rlim_cur / 1024);
r.rlim_cur = r.rlim_max;
setrlimit(RLIMIT_STACK, &r);
}
#endif
}
double Cpu()
{
long mem = 0;
double s = 0.;
GetResources(&s, &mem);
return s;
}
long GetMemoryUsage()
{
long mem = 0;
double s = 0.;
GetResources(&s, &mem);
return mem;
}
int GetProcessId()
{
#if !defined(WIN32) || defined(__CYGWIN__)
return getpid();
#else
return _getpid();
#endif
}
std::string GetHostName()
{
char host[256];
gethostname(host, sizeof(host));
return std::string(host);
}
int UnlinkFile(const std::string &fileName)
int StatFile(const std::string &fileName)
{
#if !defined(WIN32) || defined(__CYGWIN__)
struct stat buf;

Christophe Geuzaine
committed
int ret = stat(fileName.c_str(), &buf);
// could get file modification time from buf

Christophe Geuzaine
committed
return ret;

Christophe Geuzaine
committed
int CreateDirectory(const std::string &dirName)
{
#if !defined(WIN32) || defined(__CYGWIN__)
if(mkdir(dirName.c_str(), 0777))
return 0;
#else
if(_mkdir(dirName.c_str()))
return 0;
#endif
return 1;
}
int KillProcess(int pid)
{
#if !defined(WIN32) || defined(__CYGWIN__)
#else
HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if(!TerminateProcess(hProc, 0)){
CloseHandle(hProc);
return 0;
}
#endif
return 1;
}
int SystemCall(const std::string &command, bool blocking)
// separate (potential) executable from arguments
std::string exe, args;
std::string::size_type pos = command.find_first_of(" ");
if(pos != std::string::npos){
exe = command.substr(0, pos);
args = command.substr(pos, command.size() - pos);
}

Christophe Geuzaine
committed
else
exe = command;
// get executable extension
std::vector<std::string> split = SplitFileName(exe);
// do we try to run a .py script or a .exe?
bool isPython = (split[2] == ".py" || split[2] == ".PY");
bool isExe = (split[2] == ".exe" || split[2] == ".EXE");
if(isPython || isExe){
if(StatFile(exe)){
Msg::Error("Unable to open file '%s'", exe.c_str());
return 1;
}

Christophe Geuzaine
committed
#if defined(WIN32)
Msg::Info("Shell opening '%s' with arguments '%s'", exe.c_str(),
args.c_str());
(char*)args.c_str(), NULL, 0);
STARTUPINFO suInfo;
PROCESS_INFORMATION prInfo;
memset(&suInfo, 0, sizeof(suInfo));
suInfo.cb = sizeof(suInfo);
Msg::Info("Calling '%s'", command.c_str());
if(blocking){
CreateProcess(NULL, (char*)command.c_str(), NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL,
&suInfo, &prInfo);
// wait until child process exits.
WaitForSingleObject(prInfo.hProcess, INFINITE);
// close process and thread handles.
CloseHandle(prInfo.hProcess);
CloseHandle(prInfo.hThread);
}
else{
// DETACHED_PROCESS removes the console (useful if the program to launch
// is a console-mode exe)
CreateProcess(NULL, (char*)command.c_str(), NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS|DETACHED_PROCESS, NULL, NULL,
&suInfo, &prInfo);
}

Christophe Geuzaine
committed
std::string cmd(command);

Christophe Geuzaine
committed
if(access(exe.c_str(), X_OK)){
if(isPython){
Msg::Info("Script '%s' is not executable: running with python", exe.c_str());
cmd = "python " + cmd;
}
else
Msg::Warning("File '%s' is not executable", exe.c_str());

Christophe Geuzaine
committed
}
else if(split[0].empty()){
// workaround if pwd is not in PATH
cmd = "./" + cmd;
}

Christophe Geuzaine
committed
}
Msg::Error("Could not find /bin/sh: aborting system call");
{
char path[1024];
#if defined(WIN32)
if(!_getcwd(path, sizeof(path))) return "";
#else
if(!getcwd(path, sizeof(path))) return "";
// match the convention of SplitFileName that delivers directory path
// ending with a directory separator
#if defined(WIN32)
str.append("\\");
#else
str.append("/");
#endif
return str;
}
void RedirectIOToConsole()
{
#if defined(WIN32) && !defined(__CYGWIN__)
// Win32 GUI apps do not write to the DOS console; make it work again by
// attaching to parent console, which allows to use the DOS shell to work with
// Gmsh on the command line (without this hack, you need to either use a
// better shell (e.g. bash), or compile a /subsystem:console version
if(!AttachConsole(ATTACH_PARENT_PROCESS)) return;
// redirect unbuffered stdout, stdin and stderr to the console
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
{
intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
if(lStdHandle != INVALID_HANDLE_VALUE){
int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if(hConHandle >= 0){
FILE *fp = _fdopen(hConHandle, "w");
if(fp){
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}
}
}
}
{
intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
if(lStdHandle != INVALID_HANDLE_VALUE){
int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if(hConHandle >= 0){
FILE *fp = _fdopen(hConHandle, "r");
if(fp){
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
}
}
}
}
{
intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
if(lStdHandle != INVALID_HANDLE_VALUE){
int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if(hConHandle >= 0){
FILE *fp = _fdopen(hConHandle, "w");
if(fp){
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
}
}
}
}
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console
// as well
std::ios::sync_with_stdio();
#endif
}