Author: mvidner Date: Fri Feb 25 17:15:43 2011 New Revision: 63488 URL: http://svn.opensuse.org/viewcvs/yast?rev=63488&view=rev Log: Move Process library class to lib2util-r. 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) (it was using it anyway but this is slightly cleaner --mvidner) From: Stanislav Visnovsky <visnov@novell.com> http://lists.opensuse.org/yast-devel/2011-02/msg00168.html patch: 03, 04 Added: trunk/core/liby2util-r/src/Process.cc trunk/core/liby2util-r/src/include/y2util/Process.h Removed: trunk/core/agent-process/src/Process.cc trunk/core/agent-process/src/Process.h Modified: trunk/core/agent-process/src/Makefile.am trunk/core/agent-process/src/ProcessAgent.cc trunk/core/base/tools/tty_wrapper/Makefile.am trunk/core/base/tools/tty_wrapper/tty_wrapper.cc trunk/core/liby2util-r/src/Makefile.am Modified: trunk/core/agent-process/src/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/Makefile.am?rev=63488&r1=63487&r2=63488&view=diff ============================================================================== --- trunk/core/agent-process/src/Makefile.am (original) +++ trunk/core/agent-process/src/Makefile.am Fri Feb 25 17:15:43 2011 @@ -9,9 +9,7 @@ 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@ Modified: trunk/core/agent-process/src/ProcessAgent.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/ProcessAgent.cc?rev=63488&r1=63487&r2=63488&view=diff ============================================================================== --- trunk/core/agent-process/src/ProcessAgent.cc (original) +++ trunk/core/agent-process/src/ProcessAgent.cc Fri Feb 25 17:15:43 2011 @@ -27,7 +27,7 @@ */ #include "ProcessAgent.h" -#include "Process.h" +#include <y2util/Process.h> #include <y2util/ExternalProgram.h> Modified: trunk/core/base/tools/tty_wrapper/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/base/tools/tty_wrapper/Makefile.am?rev=63488&r1=63487&r2=63488&view=diff ============================================================================== --- trunk/core/base/tools/tty_wrapper/Makefile.am (original) +++ trunk/core/base/tools/tty_wrapper/Makefile.am Fri Feb 25 17:15:43 2011 @@ -8,7 +8,8 @@ tty_wrapper_SOURCES = tty_wrapper.cc -tty_wrapper_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/agent-process/src +tty_wrapper_CPPFLAGS = $(AM_CPPFLAGS) -tty_wrapper_LDADD = $(top_builddir)/agent-process/src/libpy2ag_process.la +tty_wrapper_LDADD = -ly2util +tty_wrapper_LDFLAGS = -L$(srcdir)/../../../liby2util-r/src -L$(libdir) Modified: trunk/core/base/tools/tty_wrapper/tty_wrapper.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/base/tools/tty_wrapper/tty_wrapper.cc?rev=63488&r1=63487&r2=63488&view=diff ============================================================================== --- trunk/core/base/tools/tty_wrapper/tty_wrapper.cc (original) +++ trunk/core/base/tools/tty_wrapper/tty_wrapper.cc Fri Feb 25 17:15:43 2011 @@ -30,7 +30,7 @@ */ -#include "Process.h" +#include <y2util/Process.h> #include <iostream> extern "C" @@ -40,7 +40,6 @@ #include <errno.h> } - // use atomic type in signal handler static sig_atomic_t finish = false; Modified: trunk/core/liby2util-r/src/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/Makefile.am?rev=63488&r1=63487&r2=63488&view=diff ============================================================================== --- trunk/core/liby2util-r/src/Makefile.am (original) +++ trunk/core/liby2util-r/src/Makefile.am Fri Feb 25 17:15:43 2011 @@ -23,7 +23,8 @@ miniini.cc \ stringutil.cc \ y2log.cc \ - y2changes.cc + y2changes.cc \ + Process.cc liby2util_la_LDFLAGS = -version-info 4:0:0 Added: trunk/core/liby2util-r/src/Process.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/Process.cc?rev=63488&view=auto ============================================================================== --- trunk/core/liby2util-r/src/Process.cc (added) +++ trunk/core/liby2util-r/src/Process.cc Fri Feb 25 17:15:43 2011 @@ -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; +} + Added: trunk/core/liby2util-r/src/include/y2util/Process.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/liby2util-r/src/include/y2util/Process.h?rev=63488&view=auto ============================================================================== --- trunk/core/liby2util-r/src/include/y2util/Process.h (added) +++ trunk/core/liby2util-r/src/include/y2util/Process.h Fri Feb 25 17:15:43 2011 @@ -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 -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org