ultimatepp/uppsrc/ide/Core/Host.cpp
cxl 6ec31865a7 Win32: Support for bin git
git-svn-id: svn://ultimatepp.org/upp/trunk@15577 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-12-10 21:27:30 +00:00

404 lines
7.7 KiB
C++

#include "Core.h"
#define LLOG(x)
#include <plugin/bz2/bz2.h>
LocalHost::LocalHost()
{
}
String LocalHost::GetEnvironment()
{
return environment;
}
String LocalHost::GetHostPath(const String& path)
{
return path;
}
String LocalHost::GetLocalPath(const String& path)
{
return path;
}
String LocalHost::NormalizePath(const String& path)
{
return ::NormalizePath(path);
}
String LocalHost::NormalizeExecutablePath(const String& path)
{
return NormalizeExePath(path);
}
Vector<Host::FileInfo> LocalHost::GetFileInfo(const Vector<String>& path)
{
Vector<FileInfo> fi;
for(int i = 0; i < path.GetCount(); i++) {
FindFile ff(path[i]);
FileInfo& f = fi.Add();
if(ff) {
(Time&)f = ff.GetLastWriteTime();
f.length = ff.IsFile() ? (int)ff.GetLength() : -1;
}
else {
(Time&)f = Time::Low();
f.length = Null;
}
}
return fi;
}
void LocalHost::DeleteFile(const Vector<String>& path)
{
for(int i = 0; i < path.GetCount(); i++)
::DeleteFile(path[i]);
}
void LocalHost::DeleteFolderDeep(const String& folder)
{
::DeleteFolderDeep(folder);
}
void LocalHost::ChDir(const String& path)
{
#ifdef PLATFORM_WIN32
SetCurrentDirectory(path);
#endif
#ifdef PLATFORM_POSIX
IGNORE_RESULT( chdir(path) );
#endif
if(cmdout)
*cmdout << "cd \"" << GetHostPath(path) << "\"\n";
}
void LocalHost::DoDir(const String& dir)
{
if(dir.GetLength() > 3) {
DoDir(GetFileFolder(dir));
*cmdout << "mkdir \"" << dir << "\"\n";
}
}
bool LocalHost::RealizeDir(const String& path)
{
bool realized = RealizeDirectory(path);
if(cmdout)
DoDir(path);
return realized;
}
bool LocalHost::SaveFile(const String& path, const String& data)
{
return ::SaveFile(path, data);
}
String LocalHost::LoadFile(const String& path)
{
return ::LoadFile(path);
}
int LocalHost::Execute(const char *cmdline)
{
if(cmdout)
*cmdout << cmdline << '\n';
PutVerbose(cmdline);
int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), NULL, environment, false);
PutVerbose(Format("Exitcode: %d", q));
return q;
}
int LocalHost::ExecuteWithInput(const char *cmdline, bool noconvert)
{
if(cmdout)
*cmdout << cmdline << '\n';
PutVerbose(cmdline);
int q = IdeConsoleExecuteWithInput(FindCommand(exedirs, cmdline), NULL, environment, false, noconvert);
PutVerbose(Format("Exitcode: %d", q));
return q;
}
int LocalHost::Execute(const char *cmdline, Stream& out, bool noconvert)
{
PutVerbose(cmdline);
int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), &out, environment, true, noconvert);
PutVerbose(Format("Exitcode: %d", q));
return q;
}
int LocalHost::AllocSlot()
{
return IdeConsoleAllocSlot();
}
bool LocalHost::Run(const char *cmdline, int slot, String key, int blitz_count)
{
return IdeConsoleRun(FindCommand(exedirs, cmdline), NULL, environment, false, slot, key, blitz_count);
}
bool LocalHost::Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count)
{
return IdeConsoleRun(FindCommand(exedirs, cmdline), &out, environment, true, slot, key, blitz_count);
}
bool LocalHost::Wait()
{
return IdeConsoleWait();
}
bool LocalHost::Wait(int slot)
{
return IdeConsoleWait(slot);
}
void LocalHost::OnFinish(Event<> cb)
{
IdeConsoleOnFinish(cb);
}
One<AProcess> LocalHost::StartProcess(const char *cmdline)
{
try {
PutVerbose(cmdline);
One<AProcess> p;
if(p.Create<LocalProcess>().Start(FindCommand(exedirs, cmdline), environment))
return p;
}
catch(...) {
}
return NULL;
}
#ifdef PLATFORM_POSIX
//#BLITZ_APPROVE
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
static Vector<int>& sPid()
{
static Vector<int> q;
return q;
}
void sCleanZombies(int signal_number)
{
Vector<int>& pid = sPid();
int i = 0;
while(i < pid.GetCount())
if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0)
pid.Remove(i);
else
i++;
}
#endif
#ifdef PLATFORM_WIN32
String HostConsole = "powershell.exe";
#else
String HostConsole = "/usr/bin/xterm -e";
#endif
void LocalHost::Launch(const char *_cmdline, bool console)
{
String cmdline = FindCommand(exedirs, _cmdline);
PutVerbose(cmdline);
#ifdef PLATFORM_WIN32
if(console)
cmdline = GetExeFilePath() + " ! " + cmdline;
PROCESS_INFORMATION pi;
STARTUPINFOW si;
ZeroMemory(&si, sizeof(STARTUPINFOW));
si.cb = sizeof(STARTUPINFOW);
if(Win32CreateProcess(cmdline, ~environment, si, pi, NULL)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
PutConsole("Unable to launch " + String(_cmdline));
#endif
#ifdef PLATFORM_POSIX
String script = ConfigFile("console-script-" + AsString(getpid()));
if(console) {
FileStream out(script, FileStream::CREATE, 0777);
out << "#!/bin/sh\n"
<< cmdline << '\n'
#ifndef PLATFORM_COCOA
<< "echo \"<--- Finished, press [ENTER] to close the window --->\"\nread dummy\n"
#endif
;
}
#ifdef PLATFORM_COCOA
if(console)
cmdline = "/usr/bin/open " + script;
#else
String lc;
static const char *term[] = {
"/usr/bin/mate-terminal -x",
"/usr/bin/gnome-terminal --window -x",
"/usr/bin/konsole -e",
"/usr/bin/lxterminal -e",
"/usr/bin/xterm -e",
};
int ii = 0;
for(;;) { // If (pre)defined terminal emulator is not available, try to find one
int c = HostConsole.FindFirstOf(" ");
lc = c < 0 ? HostConsole : HostConsole.Left(c);
if(ii >= __countof(term) || FileExists(lc))
break;
HostConsole = term[ii++];
}
if(FileExists(lc))
{
if(console)
cmdline = HostConsole + " sh " + script;
}
else
if(HostConsole.GetCount())
PutConsole("Warning: Terminal '" + lc + "' not found, executing in background.");
#endif
Buffer<char> cmd_buf(strlen(cmdline) + 1);
Vector<char *> args;
PutVerbose(cmdline);
char *o = cmd_buf;
const char *s = cmdline;
while(*s) {
char *arg = o;
while((byte)*s > ' ') {
if(*s == '\"') {
s++;
while(*s) {
if(*s == '\"') {
s++;
break;
}
*o++ = *s++;
}
}
else
*o++ = *s++;
}
while(*s && (byte)*s <= ' ')
s++;
if(o > arg) {
*o++ = '\0';
args.Add(arg);
}
}
args.Add(NULL);
ONCELOCK {
struct sigaction sigchld_action;
memset(&sigchld_action, 0, sizeof(sigchld_action));
sigchld_action.sa_handler = sCleanZombies;
sigaction(SIGCHLD, &sigchld_action, NULL);
}
pid_t pid = fork();
if(pid == 0)
{
const char *from = environment;
Vector<const char *> env;
while(*from) {
env.Add(from);
from += strlen(from) + 1;
}
env.Add(NULL);
const char **envp = env.Begin();
execve(args[0], args, (char *const *)envp);
abort();
}
LLOG("Launch pid: " << pid);
sPid().Add(pid);
#endif
}
void LocalHost::AddFlags(Index<String>& cfg)
{
if(HasPlatformFlag(cfg))
return;
#if defined(PLATFORM_WIN32)
cfg.Add("WIN32");
#endif
#ifdef PLATFORM_POSIX
cfg.Add("POSIX");
#endif
#ifdef PLATFORM_LINUX
cfg.Add("LINUX");
#endif
#ifdef PLATFORM_ANDROID
cfg.Add("ANDROID");
#endif
#ifdef PLATFORM_BSD
cfg.Add("BSD");
#endif
#ifdef PLATFORM_OSX
cfg.Add("OSX");
#endif
#ifdef PLATFORM_FREEBSD
cfg.Add("FREEBSD");
#endif
#ifdef PLATFORM_OPENBSD
cfg.Add("OPENBSD");
#endif
#ifdef PLATFORM_NETBSD
cfg.Add("NETBSD");
#endif
#ifdef PLATFORM_DRAGONFLY
cfg.Add("DRAGONFLY");
#endif
#ifdef PLATFORM_SOLARIS
cfg.Add("SOLARIS");
#endif
#ifdef PLATFORM_OSX11
cfg.Add("OSX11");
#endif
}
const Vector<String>& LocalHost::GetExecutablesDirs() const
{
return exedirs;
}
bool LocalHost::HasPlatformFlag(const Index<String>& cfg)
{
static const Index<String> platformFlags = {
"WIN32", "POSIX", "LINUX", "ANDROID",
"BSD", "FREEBSD", "OPENBSD", "NETBSD",
"DRAGONFLY", "SOLARIS", "OSX11", "OSX"
};
for(const String& flag : cfg)
if(platformFlags.Find(flag) >= 0)
return true;
return false;
}
#if 0
static bool IsSamePath(const char *a, const char *b, int count) {
for(; --count >= 0; a++, b++)
if(a != b && ToLower(*a) != ToLower(*b) && !((*a == '\\' || *a == '/') && (*b == '\\' || *b == '/')))
return false;
return true;
}
#endif