Files
pip/piprocess.cpp

200 lines
5.3 KiB
C++

/*
PIP - Platform Independent Primitives
Process
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piprocess.h"
PIProcess::PIProcess(): PIThread() {
exit_code = -1;
#ifdef WINDOWS
pi.dwProcessId = 0;
#else
pid = 0;
#endif
is_exec = false;
g_in = g_out = g_err = false;
t_in = t_out = t_err = false;
env = PIProcess::currentEnvironment();
}
PIProcess::~PIProcess() {
if (t_in) f_in.remove();
if (t_out) f_out.remove();
if (t_err) f_err.remove();
}
void PIProcess::exec_() {
is_exec = false;
startOnce();
//cout << "exec wait" << endl;
while (!is_exec)
msleep(1);
//cout << "exec end" << endl;
}
void PIProcess::run() {
//cout << "run" << endl;
string str;
/// arguments convertion
as = 0;
#ifdef WINDOWS
//args.pop_front();
piForeachC (PIString & i, args)
as += i.lengthAscii() + 1;
char * a = new char[as];
memset(a, ' ', as - 1);
as = 0;
for (int i = 0; i < args.size_s(); ++i) {
str = args[i].stdString();
memcpy(&a[as], str.c_str(), str.size());
as += str.length() + 1;
}
a[as - 1] = 0;
#else
char * a[args.size_s() + 1];
for (int i = 0; i < args.size_s(); ++i) {
str = args[i].stdString();
a[i] = new char[str.size() + 1];
memcpy(a[i], str.c_str(), str.size());
a[i][str.size()] = 0;
//cout << a[i] << endl;
}
a[args.size_s()] = 0;
#endif
/// environment convertion
char ** e = new char*[env.size_s() + 1];
for (int i = 0; i < env.size_s(); ++i) {
str = env[i].stdString();
e[i] = new char[str.size() + 1];
memcpy(e[i], str.c_str(), str.size());
e[i][str.size()] = 0;
//cout << e[i] << endl;
}
e[env.size_s()] = 0;
/// files for stdin/out/err
t_in = t_out = t_err = false;
if (f_in.path().isEmpty()) {
f_in = PIFile::openTemporary(PIIODevice::ReadWrite);
t_in = true;
}
//f_in.open(PIIODevice::ReadWrite); f_in.close();
if (f_out.path().isEmpty()) {
f_out = PIFile::openTemporary(PIIODevice::ReadWrite);
t_out = true;
}
//f_out.open(PIIODevice::WriteOnly); f_out.close();
if (f_err.path().isEmpty()) {
f_err = PIFile::openTemporary(PIIODevice::ReadWrite);
t_err = true;
}
//f_err.open(PIIODevice::WriteOnly); f_err.close();
str = args.front().stdString();
is_exec = true;
execStarted(PIString(str));
#ifndef WINDOWS
pid = fork();
if (pid == 0) {
#endif
tf_in = tf_out = tf_err = 0;
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
//cout << f_out.path() << endl;
if (g_in) tf_in = freopen(f_in.path().data(), "r", stdin);
if (g_out) tf_out = freopen(f_out.path().data(), "w", stdout);
if (g_err) tf_err = freopen(f_err.path().data(), "w", stderr);
#ifndef WINDOWS
if (!wd.isEmpty()) as = chdir(wd.data());
#endif
#ifdef WINDOWS
GetStartupInfoA(&si);
memset(&pi, 0, sizeof(pi));
if(CreateProcessA(0, // No module name (use command line)
a, // Command line
0, // Process handle not inheritable
0, // Thread handle not inheritable
false, // Set handle inheritance to FALSE
0, // No creation flags
0,//e, // Use environment
wd.isEmpty() ? 0 : wd.data(), // Use working directory
&si, // Pointer to STARTUPINFO structure
&pi)) // Pointer to PROCESS_INFORMATION structure
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
} else
piCoutObj << "[PIProcess] \"CreateProcess\" error, " << errorString();
#else
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
if (execve(str.c_str(), a, e) < 0)
piCoutObj << "[PIProcess] \"execve\" error, " << errorString();
} else {
msleep(1);
//cout << "wait" << endl;
wait(&exit_code);
/*if (tf_in != 0) fclose(tf_in);
if (tf_out != 0) fclose(tf_out);
if (tf_err != 0) fclose(tf_err);*/
pid = 0;
//cout << "wait done" << endl;
}
#endif
execFinished(PIString(str), exit_code);
is_exec = false;
for (int i = 0; i < env.size_s(); ++i)
delete e[i];
delete e;
#ifdef WINDOWS
delete a;
#else
for (int i = 0; i < args.size_s(); ++i)
delete a[i];
#endif
//cout << "end " << tf_in << ", " << tf_out << ", " << tf_err << endl;
}
void PIProcess::removeEnvironmentVariable(const PIString & variable) {
PIString s;
for (int i = 0; i < env.size_s(); ++i) {
s = env[i];
if (s.left(s.find("=")).trimmed() == variable) {
env.remove(i);
--i;
}
}
}
void PIProcess::setEnvironmentVariable(const PIString & variable, const PIString & value) {
PIString s, v;
for (int i = 0; i < env.size_s(); ++i) {
s = env[i];
v = s.left(s.find("=")).trimmed();
if (v == variable) {
env[i] = v + "=" + value;
return;
}
}
env << variable + "=" + value;
}