
From: Stanislav Visnovsky <visnov@novell.com> The Process class is a general-purpose implementation for wrapping a process invocation. Locating it to the library instead of a specific agent allows to use it from other binaries (tty-wrapper in particular) --- core/agent-process/src/Makefile.am | 4 +- core/agent-process/src/Process.cc | 249 ------------------------- core/agent-process/src/Process.h | 156 ---------------- core/agent-process/src/ProcessAgent.cc | 2 +- core/liby2util-r/src/Makefile.am | 3 +- core/liby2util-r/src/Process.cc | 249 +++++++++++++++++++++++++ core/liby2util-r/src/include/y2util/Process.h | 156 ++++++++++++++++ 7 files changed, 409 insertions(+), 410 deletions(-) delete mode 100644 core/agent-process/src/Process.cc delete mode 100644 core/agent-process/src/Process.h create mode 100644 core/liby2util-r/src/Process.cc create mode 100644 core/liby2util-r/src/include/y2util/Process.h diff --git a/core/agent-process/src/Makefile.am b/core/agent-process/src/Makefile.am index 76f8a05..ca7f778 100644 --- a/core/agent-process/src/Makefile.am +++ b/core/agent-process/src/Makefile.am @@ -9,9 +9,7 @@ noinst_LTLIBRARIES = liby2ag_process.la liby2ag_process_la_SOURCES = \ ProcessAgent.cc \ - ProcessAgent.h \ - Process.cc \ - Process.h + ProcessAgent.h liby2ag_process_la_LDFLAGS = -version-info 2:0 liby2ag_process_la_LIBADD = @AGENT_LIBADD@ diff --git a/core/agent-process/src/Process.cc b/core/agent-process/src/Process.cc deleted file mode 100644 index 7c33863..0000000 --- a/core/agent-process/src/Process.cc +++ /dev/null @@ -1,249 +0,0 @@ -/* ProcessAgent.cc - * - * ------------------------------------------------------------------------------ - * Copyright (c) 2008 Novell, Inc. All Rights Reserved. - * - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of version 2 of the GNU General Public License as published by the - * Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you may find - * current contact information at www.novell.com. - * ------------------------------------------------------------------------------ - * - * Implementation of class Process. - * - * Authors: Ladislav Slezák <lslezak@novell.com> - * - * $Id: ProcessAgent.cc 27914 2006-02-13 14:32:08Z locilka $ - */ - -#include "Process.h" - -#include <signal.h> -#include <fcntl.h> -#include <errno.h> -#include <cstring> -#include <y2util/Y2SLog.h> - - -/** - * Destructor - */ -Process::~Process() -{ - if (running()) - { - MIL << "Terminating running process '" << getpid() << "'..." << std::endl; - kill(); - } -} - -// send a signal -bool Process::kill(int sig) -{ - if (getpid() > 0) - { - return ::kill(getpid(), sig) == 0; - } - - return false; -} - -// send SIGKILL -bool Process::kill() -{ - return ExternalProgram::kill(); -} - -void Process::BufferNewStdoutLines () -{ - const std::string new_output = receiveUpto('\n'); - stdout_buffer += new_output; -} - -// read a line from stdout -std::string Process::readLine() -{ - BufferNewStdoutLines(); - - return GetLineFromBuffer(stdout_buffer); -} - -// return whether stdout buffer contains any (finished) line -bool Process::anyLineInStdout() -{ - BufferNewStdoutLines(); - - return IsAnyLineInBuffer(stdout_buffer); -} - -void Process::readStdoutToBuffer() -{ - const size_t b_size = 4096; - char buffer[b_size]; - size_t read; - - do - { - read = receive(buffer, b_size); - stdout_buffer.append(buffer, read); - } - while(read == b_size); -} - -// read stdout and return the data -std::string Process::read() -{ - readStdoutToBuffer(); - - std::string ret(stdout_buffer); - - stdout_buffer.clear(); - - return ret; -} - -// read data from a fd to a buffer -void Process::readStderrToBuffer() -{ - if (!stderr_output) - { - ERR << "stderr output is not open!" << std::endl; - return; - } - - const int b_size = 4096; - char buffer[b_size]; - int len; - - do - { - len = ::fread(buffer, 1, b_size, stderr_output); - - if (len > 0) - { - stderr_buffer.append(buffer, len); - } - } - while(len == b_size); -} - -// cut off the first line from a buffer and return it -std::string Process::GetLineFromBuffer(std::string &buffer) -{ - // find end of the first line - std::string::size_type line_pos = buffer.find("\n"); - - // a line found? - if (line_pos != std::string::npos) - { - // remove the line from bufer and return it - std::string ret(buffer, 0, line_pos + 1); - buffer.erase(0, line_pos + 1); - - return ret; - } - - // no new line, return empty string - return std::string(); -} - -// returns whether the buffer is empty -bool Process::IsAnyLineInBuffer(const std::string &buffer) -{ - return buffer.empty(); -} - -// read a line from stderr -std::string Process::readErrLine() -{ - readStderrToBuffer(); - - return GetLineFromBuffer(stderr_buffer); -} - -// read data from stderr -std::string Process::readErr() -{ - // read from stderr to the buffer - readStderrToBuffer(); - - // return the buffer and clear it - std::string ret(stderr_buffer); - - stderr_buffer.clear(); - - return ret; -} - -// set the filedscriptor to unblocked mode -void UnblockFD(int fd) -{ - // get the current flags - int flags = ::fcntl(fd,F_GETFL); - - if (flags == -1) - { - ERR << strerror(errno) << std::endl; return; - } - - // set the non-blocking flag - flags = flags | O_NONBLOCK; - - // set the updated flags - flags = ::fcntl(fd,F_SETFL,flags); - - if (flags == -1) - { - ERR << strerror(errno) << std::endl; return; - } -} - -// create a pipe for stderr output -int Process::create_stderr_pipes() -{ - int stderr_pipes[2]; - - // create a pair of pipes - if (pipe(stderr_pipes) != 0) - { - // return current stderr - return 2; - } - - // set the stderr pipe to non-blocking mode - UnblockFD(stderr_pipes[0]); - - stderr_output = ::fdopen(stderr_pipes[0], "r"); - - // return fd for writing - return stderr_pipes[1]; -} - -int Process::closeAll() -{ - if (!stderr_output) - { - // close stderr pipe - ::fclose(stderr_output); - - stderr_output = NULL; - } - - return ExternalProgram::close(); -} - -FILE* Process::errorFile() -{ - return stderr_output; -} - diff --git a/core/agent-process/src/Process.h b/core/agent-process/src/Process.h deleted file mode 100644 index 904b80f..0000000 --- a/core/agent-process/src/Process.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Process.h - * - * ------------------------------------------------------------------------------ - * Copyright (c) 2008 Novell, Inc. All Rights Reserved. - * - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of version 2 of the GNU General Public License as published by the - * Free Software Foundation. - * - * 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, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you may find - * current contact information at www.novell.com. - * ------------------------------------------------------------------------------ - * - * Class Process - * - * Authors: Ladislav Slezák <lslezak@novell.com> - * - * $Id: Process.h 57029 2009-04-29 11:04:19Z lslezak $ - */ - -#ifndef Process_h -#define Process_h - -#include <y2util/ExternalProgram.h> - -/** - * @short Execute a program and give access to its io - * An object of this class encapsulates the execution of - * an external program. It starts the program using fork - * and some exec.. call, gives you access to the program's - * stdio/stderr and closes the program after use. - */ -class Process: public ExternalProgram -{ - -private: - - std::string stdout_buffer; // buffer for stdout - std::string stderr_buffer; // buffer for stderr - - FILE *stderr_output; - -private: - - // disable copy ctor and operator= - Process(const Process&); - Process& operator=(const Process&); - - // create a pipe for stderr, return the end for writing - int create_stderr_pipes(); - - // a helper function - std::string GetLineFromBuffer(std::string &buffer); - - // a helper function - // reads the new stdout lines and adds them to stdout buffer - void BufferNewStdoutLines(); - - // checks emptines of the stdout buffer - bool IsAnyLineInBuffer(const std::string &buffer); - -public: - - /** - * Start the external program by using the shell <tt>/bin/sh<tt> - * with the option <tt>-c</tt>. You can use io direction symbols < and >. - * @param commandline a shell commandline that is appended to - * <tt>/bin/sh -c</tt>. - * @param default_locale whether to set LC_ALL=C before starting - * @param use_pty start the process in a terminal - */ - Process(const std::string &commandline, bool use_pty = false, bool default_locale = false, bool pty_trans = true) - : ExternalProgram(commandline, Stderr_To_FileDesc, - use_pty, create_stderr_pipes(), default_locale, "", pty_trans), stderr_output(NULL) - {} - - /** - * Start an external program by giving the arguments as an arry of char *pointers. - * If environment is provided, variables will be added to the childs environment, - * overwriting existing ones. - */ - - Process(const char *const *argv, const Environment &environment, bool use_pty = false, bool default_locale = false, bool pty_trans = true) - : ExternalProgram(argv, environment, Stderr_To_FileDesc, - use_pty, create_stderr_pipes(), default_locale, "", pty_trans) - {} - - - ~Process(); - - /** - * Send a signal - */ - bool kill(int sig); - - /** - * Send SIGKILL - */ - bool kill(); - - /** - * Read a line from stdout - */ - std::string readLine(); - - /** - * Read characters from stdout (not line oriented) - */ - std::string read(); - - /** - * Read a line from stderr - */ - std::string readErrLine(); - - /** - * Read characters from stderr (not line oriented) - */ - std::string readErr(); - - /** - * Close all input/output filedescriptors - */ - int closeAll(); - - /** - * Read stdout to the internal buffer (can unblock the process) - */ - void readStdoutToBuffer(); - - /** - * Read stderr to the internal buffer (can unblock the process) - */ - void readStderrToBuffer(); - - /** - * Read whether there are some buffered lines - */ - bool anyLineInStdout(); - - /** - * Return the stderror stream - */ - FILE* errorFile(); - -}; - -#endif // Process_h diff --git a/core/agent-process/src/ProcessAgent.cc b/core/agent-process/src/ProcessAgent.cc index 5628d41..a82cddd 100644 --- a/core/agent-process/src/ProcessAgent.cc +++ b/core/agent-process/src/ProcessAgent.cc @@ -27,7 +27,7 @@ */ #include "ProcessAgent.h" -#include "Process.h" +#include <y2util/Process.h> #include <y2util/ExternalProgram.h> diff --git a/core/liby2util-r/src/Makefile.am b/core/liby2util-r/src/Makefile.am index b9dd3d4..9e1bd24 100644 --- a/core/liby2util-r/src/Makefile.am +++ b/core/liby2util-r/src/Makefile.am @@ -23,7 +23,8 @@ liby2util_la_SOURCES = \ miniini.cc \ stringutil.cc \ y2log.cc \ - y2changes.cc + y2changes.cc \ + Process.cc liby2util_la_LDFLAGS = -version-info 4:0:0 diff --git a/core/liby2util-r/src/Process.cc b/core/liby2util-r/src/Process.cc new file mode 100644 index 0000000..39cfe27 --- /dev/null +++ b/core/liby2util-r/src/Process.cc @@ -0,0 +1,249 @@ +/* ProcessAgent.cc + * + * ------------------------------------------------------------------------------ + * Copyright (c) 2008 Novell, Inc. All Rights Reserved. + * + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of version 2 of the GNU General Public License as published by the + * Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may find + * current contact information at www.novell.com. + * ------------------------------------------------------------------------------ + * + * Implementation of class Process. + * + * Authors: Ladislav Slezák <lslezak@novell.com> + * + * $Id: ProcessAgent.cc 27914 2006-02-13 14:32:08Z locilka $ + */ + +#include "y2util/Process.h" + +#include <signal.h> +#include <fcntl.h> +#include <errno.h> +#include <cstring> +#include <y2util/Y2SLog.h> + + +/** + * Destructor + */ +Process::~Process() +{ + if (running()) + { + MIL << "Terminating running process '" << getpid() << "'..." << std::endl; + kill(); + } +} + +// send a signal +bool Process::kill(int sig) +{ + if (getpid() > 0) + { + return ::kill(getpid(), sig) == 0; + } + + return false; +} + +// send SIGKILL +bool Process::kill() +{ + return ExternalProgram::kill(); +} + +void Process::BufferNewStdoutLines () +{ + const std::string new_output = receiveUpto('\n'); + stdout_buffer += new_output; +} + +// read a line from stdout +std::string Process::readLine() +{ + BufferNewStdoutLines(); + + return GetLineFromBuffer(stdout_buffer); +} + +// return whether stdout buffer contains any (finished) line +bool Process::anyLineInStdout() +{ + BufferNewStdoutLines(); + + return IsAnyLineInBuffer(stdout_buffer); +} + +void Process::readStdoutToBuffer() +{ + const size_t b_size = 4096; + char buffer[b_size]; + size_t read; + + do + { + read = receive(buffer, b_size); + stdout_buffer.append(buffer, read); + } + while(read == b_size); +} + +// read stdout and return the data +std::string Process::read() +{ + readStdoutToBuffer(); + + std::string ret(stdout_buffer); + + stdout_buffer.clear(); + + return ret; +} + +// read data from a fd to a buffer +void Process::readStderrToBuffer() +{ + if (!stderr_output) + { + ERR << "stderr output is not open!" << std::endl; + return; + } + + const int b_size = 4096; + char buffer[b_size]; + int len; + + do + { + len = ::fread(buffer, 1, b_size, stderr_output); + + if (len > 0) + { + stderr_buffer.append(buffer, len); + } + } + while(len == b_size); +} + +// cut off the first line from a buffer and return it +std::string Process::GetLineFromBuffer(std::string &buffer) +{ + // find end of the first line + std::string::size_type line_pos = buffer.find("\n"); + + // a line found? + if (line_pos != std::string::npos) + { + // remove the line from bufer and return it + std::string ret(buffer, 0, line_pos + 1); + buffer.erase(0, line_pos + 1); + + return ret; + } + + // no new line, return empty string + return std::string(); +} + +// returns whether the buffer is empty +bool Process::IsAnyLineInBuffer(const std::string &buffer) +{ + return buffer.empty(); +} + +// read a line from stderr +std::string Process::readErrLine() +{ + readStderrToBuffer(); + + return GetLineFromBuffer(stderr_buffer); +} + +// read data from stderr +std::string Process::readErr() +{ + // read from stderr to the buffer + readStderrToBuffer(); + + // return the buffer and clear it + std::string ret(stderr_buffer); + + stderr_buffer.clear(); + + return ret; +} + +// set the filedscriptor to unblocked mode +void UnblockFD(int fd) +{ + // get the current flags + int flags = ::fcntl(fd,F_GETFL); + + if (flags == -1) + { + ERR << strerror(errno) << std::endl; return; + } + + // set the non-blocking flag + flags = flags | O_NONBLOCK; + + // set the updated flags + flags = ::fcntl(fd,F_SETFL,flags); + + if (flags == -1) + { + ERR << strerror(errno) << std::endl; return; + } +} + +// create a pipe for stderr output +int Process::create_stderr_pipes() +{ + int stderr_pipes[2]; + + // create a pair of pipes + if (pipe(stderr_pipes) != 0) + { + // return current stderr + return 2; + } + + // set the stderr pipe to non-blocking mode + UnblockFD(stderr_pipes[0]); + + stderr_output = ::fdopen(stderr_pipes[0], "r"); + + // return fd for writing + return stderr_pipes[1]; +} + +int Process::closeAll() +{ + if (!stderr_output) + { + // close stderr pipe + ::fclose(stderr_output); + + stderr_output = NULL; + } + + return ExternalProgram::close(); +} + +FILE* Process::errorFile() +{ + return stderr_output; +} + diff --git a/core/liby2util-r/src/include/y2util/Process.h b/core/liby2util-r/src/include/y2util/Process.h new file mode 100644 index 0000000..904b80f --- /dev/null +++ b/core/liby2util-r/src/include/y2util/Process.h @@ -0,0 +1,156 @@ +/* Process.h + * + * ------------------------------------------------------------------------------ + * Copyright (c) 2008 Novell, Inc. All Rights Reserved. + * + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of version 2 of the GNU General Public License as published by the + * Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may find + * current contact information at www.novell.com. + * ------------------------------------------------------------------------------ + * + * Class Process + * + * Authors: Ladislav Slezák <lslezak@novell.com> + * + * $Id: Process.h 57029 2009-04-29 11:04:19Z lslezak $ + */ + +#ifndef Process_h +#define Process_h + +#include <y2util/ExternalProgram.h> + +/** + * @short Execute a program and give access to its io + * An object of this class encapsulates the execution of + * an external program. It starts the program using fork + * and some exec.. call, gives you access to the program's + * stdio/stderr and closes the program after use. + */ +class Process: public ExternalProgram +{ + +private: + + std::string stdout_buffer; // buffer for stdout + std::string stderr_buffer; // buffer for stderr + + FILE *stderr_output; + +private: + + // disable copy ctor and operator= + Process(const Process&); + Process& operator=(const Process&); + + // create a pipe for stderr, return the end for writing + int create_stderr_pipes(); + + // a helper function + std::string GetLineFromBuffer(std::string &buffer); + + // a helper function + // reads the new stdout lines and adds them to stdout buffer + void BufferNewStdoutLines(); + + // checks emptines of the stdout buffer + bool IsAnyLineInBuffer(const std::string &buffer); + +public: + + /** + * Start the external program by using the shell <tt>/bin/sh<tt> + * with the option <tt>-c</tt>. You can use io direction symbols < and >. + * @param commandline a shell commandline that is appended to + * <tt>/bin/sh -c</tt>. + * @param default_locale whether to set LC_ALL=C before starting + * @param use_pty start the process in a terminal + */ + Process(const std::string &commandline, bool use_pty = false, bool default_locale = false, bool pty_trans = true) + : ExternalProgram(commandline, Stderr_To_FileDesc, + use_pty, create_stderr_pipes(), default_locale, "", pty_trans), stderr_output(NULL) + {} + + /** + * Start an external program by giving the arguments as an arry of char *pointers. + * If environment is provided, variables will be added to the childs environment, + * overwriting existing ones. + */ + + Process(const char *const *argv, const Environment &environment, bool use_pty = false, bool default_locale = false, bool pty_trans = true) + : ExternalProgram(argv, environment, Stderr_To_FileDesc, + use_pty, create_stderr_pipes(), default_locale, "", pty_trans) + {} + + + ~Process(); + + /** + * Send a signal + */ + bool kill(int sig); + + /** + * Send SIGKILL + */ + bool kill(); + + /** + * Read a line from stdout + */ + std::string readLine(); + + /** + * Read characters from stdout (not line oriented) + */ + std::string read(); + + /** + * Read a line from stderr + */ + std::string readErrLine(); + + /** + * Read characters from stderr (not line oriented) + */ + std::string readErr(); + + /** + * Close all input/output filedescriptors + */ + int closeAll(); + + /** + * Read stdout to the internal buffer (can unblock the process) + */ + void readStdoutToBuffer(); + + /** + * Read stderr to the internal buffer (can unblock the process) + */ + void readStderrToBuffer(); + + /** + * Read whether there are some buffered lines + */ + bool anyLineInStdout(); + + /** + * Return the stderror stream + */ + FILE* errorFile(); + +}; + +#endif // Process_h -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org