/* PIP - Platform Independent Primitives Process Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIP_FREERTOS #include "piincludes_p.h" #include "piprocess.h" #ifndef WINDOWS # include # include #endif #ifdef MAC_OS # include #endif PRIVATE_DEFINITION_START(PIProcess) #ifdef WINDOWS STARTUPINFOA si; PROCESS_INFORMATION pi; #else pid_t pid; #endif FILE * tf_in, * tf_out, * tf_err; PRIVATE_DEFINITION_END(PIProcess) PIProcess::PIProcess(): PIThread() { exit_code = -1; #ifdef WINDOWS PRIVATE->pi.dwProcessId = 0; #else PRIVATE->pid = 0; #endif is_exec = false; g_in = g_out = g_err = false; t_in = t_out = t_err = false; PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0; 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) piMinSleep(); //cout << "exec end" << endl; } void PIProcess::startProc(bool detached) { //cout << "run" << endl; PIString str; /// arguments convertion #ifdef WINDOWS int as = 0; piForeachC (PIString & i, args) as += i.lengthAscii() + 3; char * a = new char[as]; memset(a, ' ', as - 1); as = 0; for (int i = 0; i < args.size_s(); ++i) { str = args[i]; a[as] = '"'; memcpy(&(a[as + 1]), str.data(), str.lengthAscii()); a[as + str.lengthAscii() + 1] = '"'; as += str.lengthAscii() + 3; } a[as - 1] = 0; //piCout << a; #else //piCout << "#" << args; char * a[args.size_s() + 1]; for (int i = 0; i < args.size_s(); ++i) { str = args[i]; //piCout << i << str << str.size() << str.lengthAscii() << str.lengthAscii() << str.lengthAscii(); a[i] = new char[str.lengthAscii() + 1]; memcpy(a[i], str.data(), str.lengthAscii()); a[i][str.lengthAscii()] = 0; } 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]; e[i] = new char[str.lengthAscii() + 1]; memcpy(e[i], str.data(), str.lengthAscii()); e[i][str.lengthAscii()] = 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.openTemporary(PIIODevice::ReadWrite); t_in = true; } if (f_out.path().isEmpty()) { f_out.openTemporary(PIIODevice::ReadWrite); t_out = true; } if (f_err.path().isEmpty()) { f_err.openTemporary(PIIODevice::ReadWrite); t_err = true; } str = args.front(); is_exec = true; if (!detached) execStarted(str); #ifndef WINDOWS int pid_ = fork(); if (!detached) PRIVATE->pid = pid_; if (pid_ == 0) { #endif PRIVATE->tf_in = PRIVATE->tf_out = PRIVATE->tf_err = 0; //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; //cout << f_out.path() << endl; if (g_in) PRIVATE->tf_in = freopen(f_in.path().data(), "r", stdin); if (g_out) PRIVATE->tf_out = freopen(f_out.path().data(), "w", stdout); if (g_err) PRIVATE->tf_err = freopen(f_err.path().data(), "w", stderr); #ifndef WINDOWS if (!wd.isEmpty()) if (!chdir(wd.data())) piCoutObj << "Error while set working directory"; #endif #ifdef WINDOWS GetStartupInfoA(&(PRIVATE->si)); memset(&(PRIVATE->pi), 0, sizeof(PRIVATE->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 detached ? DETACHED_PROCESS/*CREATE_NEW_CONSOLE*/ : 0, // Creation flags 0,//e, // Use environment wd.isEmpty() ? 0 : wd.data(), // Use working directory &(PRIVATE->si), // Pointer to STARTUPINFO structure &(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure { if (!detached) WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE); CloseHandle(PRIVATE->pi.hThread); CloseHandle(PRIVATE->pi.hProcess); } else piCoutObj << "\"CreateProcess\" error, " << errorString(); #else //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; if (execve(str.data(), a, e) < 0) piCoutObj << "\"execve" << str << args << "\" error :" << errorString(); } else { piMinSleep; //cout << "wait" << endl; if (!detached) { wait(&exit_code); pid_ = 0; if (!detached) PRIVATE->pid = pid_; //cout << "wait done" << endl; } } #endif if (!detached) execFinished(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 } void PIProcess::terminate() { #ifdef WINDOWS if (is_exec) if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return; PRIVATE->pi.dwProcessId = 0; #else if (is_exec) kill(PRIVATE->pid, SIGKILL); PRIVATE->pid = 0; #endif } void PIProcess::execIndependent(const PIString & program, const PIStringList & args_) { PIProcess p; p.args << program << args_; p.startProc(true); } int PIProcess::pID() const { #ifdef WINDOWS return PRIVATE->pi.dwProcessId; #else return PRIVATE->pid; #endif } int PIProcess::currentPID() { #ifdef WINDOWS return GetCurrentProcessId(); #else return getpid(); #endif } PIStringList PIProcess::currentEnvironment() { PIStringList l; int i = 0; while (environ[i] != 0) { l << environ[i]; ++i; } return l; } void PIProcess::run() { startProc(false); } 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; } PIString PIProcess::getEnvironmentVariable(const PIString & variable) { PIStringList env_ = currentEnvironment(); PIString s, v; for (int i = 0; i < env_.size_s(); ++i) { s = env_[i]; v = s.left(s.find("=")).trimmed(); if (v == variable) { return s.right(s.size() - 1 - s.find("=")).trimmed(); } } return PIString(); } #endif // PIP_FREERTOS