From: Christian P. <cp...@us...> - 2004-12-31 03:23:08
|
Update of /cvsroot/pclasses/pclasses2/src/System In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22434/src/System Added Files: Process.common.cpp Process.posix.cpp ProcessIO.cpp Log Message: Added ProcessIO and Process class (compiles but untested). --- NEW FILE: ProcessIO.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/System/ProcessIO.h" namespace P { namespace System { ProcessIO::ProcessIO(const Pipe& in, const Pipe& out, const Pipe& err) throw(IO::IOError) : _in(in), _out(out), _err(err) { } ProcessIO::~ProcessIO() throw() { } void ProcessIO::close() throw(IO::IOError) { _in.close(); _out.close(); _err.close(); } void ProcessIO::closeWrite() throw(IO::IOError) { if(_in.valid()) _in.close(); } void ProcessIO::closeRead() throw(IO::IOError) { if(_out.valid()) _out.close(); } void ProcessIO::closeErr() throw(IO::IOError) { if(_err.valid()) _err.close(); } size_t ProcessIO::write(const char* buffer, size_t count) throw(IO::IOError) { return _in.write(buffer,count); } size_t ProcessIO::read(char* buffer, size_t count) throw(IO::IOError) { return _out.read(buffer,count); } size_t ProcessIO::readErr(char* buffer, size_t count) throw(IO::IOError) { return _err.read(buffer,count); } } // !namespace System } // !namespace P --- NEW FILE: Process.posix.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/System/Process.h" #include "pclasses/System/Directory.h" #include "pclasses/System/FileInfo.h" #include "pclasses/System/File.h" #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <string> namespace P { namespace System { void Process::start(int mode) throw(IO::IOError,SystemError,LogicError) { if(_state != Stopped) throw LogicError("Process is already running", P_SOURCEINFO); // test if file is existent FileInfo info = File::stat(_program); int ret; int infds[2] = { -1, -1 }; int outfds[2] = { -1, -1 }; int errfds[2] = { -1, -1 }; // save program dir, name and args std::string dir = _workDir.utf8(); std::string program = _program.utf8(); ArgList args = _args; // shall we redirect StdIn ? if(mode & RedirectStdIn) { ret = pipe(infds); if(ret == -1) throw IO::IOError(errno, "Could not create pipe", P_SOURCEINFO); } if(mode & RedirectStdOut) { ret = pipe(outfds); if(ret == -1) { close(infds[0]); close(infds[1]); throw IO::IOError(errno, "Could not create pipe", P_SOURCEINFO); } } if(mode & RedirectStdErr) { ret = pipe(errfds); if(ret == -1) { close(infds[0]); close(infds[1]); close(outfds[0]); close(outfds[1]); throw IO::IOError(errno, "Could not create pipe", P_SOURCEINFO); } } pid_t child = fork(); // fork failed if(child == -1) { close(infds[0]); close(infds[1]); close(outfds[0]); close(outfds[1]); close(errfds[0]); close(errfds[1]); throw SystemError(errno, "Could not start process", P_SOURCEINFO); } // child process else if(child == 0) { //close(0); close(1); close(2); if(mode & RedirectStdIn) { close(infds[1]); ret = dup2(infds[0], 0); close(infds[0]); if(ret == -1) _exit(127); } else if(!(mode & InheritStdIn)) close(0); if(mode & RedirectStdOut) { close(outfds[0]); ret = dup2(outfds[1], 1); close(outfds[1]); if(ret == -1) _exit(127); } else if(!(mode & InheritStdOut)) close(1); if(mode & RedirectStdErr) { close(outfds[0]); ret = dup2(errfds[1], 2); close(errfds[1]); if(ret == -1) _exit(127); } else if(!(mode & InheritStdErr)) close(2); if(!dir.empty()) Directory::change(dir); const char* argv[256]; int argc = 0; argv[argc++] = program.c_str(); for(ArgList::const_iterator argi = args.begin(); argi != args.end() && argc < 256; argi++) { argv[argc++] = (*argi).utf8().c_str(); } argv[argc] = 0; // exec binary, does not return except on error execve(_program.utf8().c_str(), (char**)argv, environ); _exit(127); } if(mode & RedirectStdIn) close(infds[0]); if(mode & RedirectStdOut) close(outfds[1]); if(mode & RedirectStdErr) close(errfds[1]); _handle = (unsigned long)child; if(mode) { _procIO = new ProcessIO(Pipe(infds[1],false), Pipe(outfds[0],true), Pipe(errfds[0],true)); } close(infds[1]); close(outfds[0]); close(errfds[0]); _state = Running; } void Process::stop() throw(SystemError) { int ret = ::kill((pid_t)_handle, SIGTERM); if(ret == -1) throw SystemError(errno, "Could not stop process", P_SOURCEINFO); } void Process::kill() throw(SystemError) { int ret = ::kill((pid_t)_handle, SIGKILL); if(ret == -1) throw SystemError(errno, "Could not kill process", P_SOURCEINFO); } bool Process::tryWait(int& exitCode) throw(SystemError) { int status = 0; pid_t pid = waitpid((pid_t)_handle, &status, WNOHANG|WUNTRACED); if(pid == -1) throw SystemError(errno, "Could not wait for process", P_SOURCEINFO); else if(pid == 0) return false; if(WIFEXITED(status) || WIFSIGNALED(status)) { exitCode = WIFEXITED(status) ? WEXITSTATUS(status) : 127; _state = Stopped; _handle = (unsigned long)-1; delete _procIO; _procIO = 0; return true; } return false; } int Process::wait() throw(SystemError) { int status = 0; Process_wait: pid_t pid = waitpid((pid_t)_handle, &status, WUNTRACED); if(pid == -1) { if(errno == EINTR) goto Process_wait; throw SystemError(errno, "Could not wait for process", P_SOURCEINFO); } _state = Stopped; _handle = (unsigned long)-1; delete _procIO; _procIO = 0; return WIFEXITED(status) ? WEXITSTATUS(status) : 127; } } // !namespace System } // !namespace P --- NEW FILE: Process.common.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/System/Process.h" namespace P { namespace System { Process::Process(const Unicode::String& program, const ArgList& args) : _handle((unsigned long)-1), _procIO(0), _state(Stopped), _program(program), _args(args) { } Process::~Process() throw() { } Process::State Process::state() const { return _state; } void Process::setArgs(const ArgList& args) { _args = args; } void Process::addArg(const Unicode::String& arg) { _args.push_back(arg); } void Process::clearArgs() { _args.clear(); } void Process::setWorkDir(const Unicode::String& dir) { _workDir = dir; } const Unicode::String& Process::workDir() const { return _workDir; } ProcessIO& Process::processIO() const throw(LogicError) { if(_procIO) return *_procIO; throw LogicError("Process does not have I/O channels", P_SOURCEINFO); } } // !namespace System } // !namespace P |