[yast-devel] yast2-core clean up and refactoring
This is a bunch of patches for yast2-core. Some are pure clean up, but there is also a removal of genericfrontend.cc and replacing it with non-generic scr and y2base binaries. -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> The binary is build here and also in base/ directory. Because of build sequence, base/ binary will win and overwrite this binary. --- core/scr/src/Makefile.am | 14 -------------- 1 files changed, 0 insertions(+), 14 deletions(-) diff --git a/core/scr/src/Makefile.am b/core/scr/src/Makefile.am index cd129ae..e913abc 100644 --- a/core/scr/src/Makefile.am +++ b/core/scr/src/Makefile.am @@ -5,20 +5,6 @@ AM_CXXFLAGS = -DY2LOG=\"scr\" -DSUSEVERSION=\"${SUSEVERSION}\" serversdir = $(execcompdir)/servers -servers_PROGRAMS = scr - -scr_SOURCES = \ - scr.cc - -scr_LDADD = ${AGENT_LIBADD} \ - $(top_builddir)/liby2/src/liby2.la - -scr_DEPENDENCIES = libpy2scr.la - -scr_LDFLAGS = \ - -Xlinker --whole-archive \ - libpy2scr.la \ - -Xlinker --no-whole-archive plugin_LTLIBRARIES = libpy2scr.la -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> --- core/scr/src/scr.cc | 14 -------------- 1 files changed, 0 insertions(+), 14 deletions(-) delete mode 100644 core/scr/src/scr.cc diff --git a/core/scr/src/scr.cc b/core/scr/src/scr.cc deleted file mode 100644 index 877a7c5..0000000 --- a/core/scr/src/scr.cc +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Basic setup for the standalone "scr" binary. - * - * Author: Stanislav Visnovsky <visnov@suse.cz> - */ - -#include "scr/SCR.h" -#include "ScriptingAgent.h" - -// register builtins -SCR scr_builtins; - -// create agent for SCR calls -ScriptingAgent agent; -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
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
From: Stanislav Visnovsky <visnov@novell.com> --- core/base/tools/tty_wrapper/Makefile.am | 5 +++-- core/base/tools/tty_wrapper/tty_wrapper.cc | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/base/tools/tty_wrapper/Makefile.am b/core/base/tools/tty_wrapper/Makefile.am index 07e34ce..848575b 100644 --- a/core/base/tools/tty_wrapper/Makefile.am +++ b/core/base/tools/tty_wrapper/Makefile.am @@ -8,7 +8,8 @@ ybin_PROGRAMS = tty_wrapper 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) diff --git a/core/base/tools/tty_wrapper/tty_wrapper.cc b/core/base/tools/tty_wrapper/tty_wrapper.cc index cf181dd..e6df324 100644 --- a/core/base/tools/tty_wrapper/tty_wrapper.cc +++ b/core/base/tools/tty_wrapper/tty_wrapper.cc @@ -30,7 +30,7 @@ */ -#include "Process.h" +#include <y2util/Process.h> #include <iostream> extern "C" @@ -40,7 +40,6 @@ extern "C" #include <errno.h> } - // use atomic type in signal handler static sig_atomic_t finish = false; -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> This patch removes generic frontend from liby2 and moves it to /y2base where actual binaries are build. It also splits parts of the code to single files to improve readability and allow sharing with the 'scr' binary. scr becomes very specialized and does not provide any fancy options (which are not used anyway) --- core/base/src/Makefile.am | 4 +- core/base/src/exitcodes.h | 31 ++ core/base/src/logger.cc | 85 +++ core/base/src/scr.cc | 97 ++++- core/base/src/signals.cc | 191 +++++++ core/base/src/signals.h | 22 + core/base/src/y2base.cc | 944 ++++++++++++++++++++++++++++++++- core/liby2/src/Makefile.am | 1 - core/liby2/src/genericfrontend.cc | 930 -------------------------------- core/liby2/src/include/y2/Makefile.am | 3 +- core/liby2/src/include/y2/exitcodes.h | 31 -- 11 files changed, 1351 insertions(+), 988 deletions(-) create mode 100644 core/base/src/exitcodes.h create mode 100644 core/base/src/logger.cc create mode 100644 core/base/src/signals.cc create mode 100644 core/base/src/signals.h delete mode 100644 core/liby2/src/genericfrontend.cc delete mode 100644 core/liby2/src/include/y2/exitcodes.h diff --git a/core/base/src/Makefile.am b/core/base/src/Makefile.am index d6eff40..e74e336 100644 --- a/core/base/src/Makefile.am +++ b/core/base/src/Makefile.am @@ -40,7 +40,9 @@ INCLUDES = ${AGENT_INCLUDES} \ -I$(srcdir)/../../scr/src scr_SOURCES = \ - scr.cc + scr.cc \ + logger.cc \ + signals.cc scr_LDADD = ${AGENT_LIBADD} diff --git a/core/base/src/exitcodes.h b/core/base/src/exitcodes.h new file mode 100644 index 0000000..a224093 --- /dev/null +++ b/core/base/src/exitcodes.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + + File: exitcodes.h + + Author: Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Stanislav Visnovsky <visnov@suse.cz> + +/-*/ +// -*- c++ -*- + +#ifndef exitcodes_h +#define exitcodes_h + +enum error_codes { + YAST_OK = 0, // process finished without errors + YAST_FEWARGUMENTS = 1, // too few arguments for the commandline + YAST_OPTIONERROR = 5, // error in provided arguments + YAST_CLIENTRESULT = 16 // client (YCP) returned special result, this is used as offset (or as generic error) +}; + +#endif // exitcodes_h diff --git a/core/base/src/logger.cc b/core/base/src/logger.cc new file mode 100644 index 0000000..9544aab --- /dev/null +++ b/core/base/src/logger.cc @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + + File: scr.cc, based on genericfrontend.cc + + Authors: Mathias Kettner <kettner@suse.de> + Arvin Schnell <arvin@suse.de> + Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Arvin Schnell <arvin@suse.de> + +/-*/ +#include <blocxx/BLOCXX_config.h> +#include <blocxx/Logger.hpp> +#include <blocxx/LogMessage.hpp> +#include <blocxx/LogAppender.hpp> + +#include <ycp/y2log.h> + +class YaSTLogger : public blocxx::LogAppender +{ +public: + virtual ~YaSTLogger() {}; + + /** + * Constructor. YaST will try to log every message level, + * because we filter on our own. + */ + YaSTLogger() : blocxx::LogAppender( + blocxx::LogAppender::ALL_COMPONENTS, + blocxx::LogAppender::ALL_CATEGORIES, + blocxx::LogAppender::STR_TTCC_MESSAGE_FORMAT + ) + {} + + /** + * The logging message processing. The method converts the + * Blocxx LogMessage into a YaST logger. Unfortunatelly, + * the log level can be received only as a string, so + * we have to do a conversion to loglevel_t used by YaST. + * + * @param m the message to be logged + */ + virtual void doProcessLogMessage(const blocxx::String & /*f*/, + const blocxx::LogMessage& m) const + { + loglevel_t level = LOG_DEBUG; + if (m.category == blocxx::Logger::STR_FATAL_CATEGORY + || m.category == blocxx::Logger::STR_ERROR_CATEGORY) + { + level = LOG_ERROR; + } else if (m.category == blocxx::Logger::STR_WARNING_CATEGORY) + { + level = LOG_WARNING; + } else if (m.category == blocxx::Logger::STR_INFO_CATEGORY) + { + level = LOG_MILESTONE; + } + + y2_logger(level,m.component.c_str () + ,m.filename,m.fileline,m.methodname,"%s", m.message.c_str ()); + } +}; + +// YaSTLogger redirection factory for BloCxx/LiMaL +struct logger_initializer +{ + logger_initializer() + { + blocxx::LogAppender::setDefaultLogAppender( + blocxx::LogAppenderRef(new YaSTLogger()) + ); + } +}; +static logger_initializer initialize_logger; + + diff --git a/core/base/src/scr.cc b/core/base/src/scr.cc index 877a7c5..e75f856 100644 --- a/core/base/src/scr.cc +++ b/core/base/src/scr.cc @@ -1,14 +1,101 @@ -/* - * Basic setup for the standalone "scr" binary. - * - * Author: Stanislav Visnovsky <visnov@suse.cz> - */ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + File: scr.cc, based on genericfrontend.cc + + Authors: Mathias Kettner <kettner@suse.de> + Arvin Schnell <arvin@suse.de> + Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Arvin Schnell <arvin@suse.de> + +/-*/ +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sstream> +#include <iomanip> +#include <string> +#include <sys/stat.h> + +#include <ycp/y2log.h> +#include <ycp/ExecutionEnvironment.h> +#include <scr/Y2AgentComponent.h> #include "scr/SCR.h" #include "ScriptingAgent.h" +#include <y2/Y2StdioComponent.h> + +#include "exitcodes.h" +#include "signals.h" + +using std::string; +ExecutionEnvironment ee; + +/// fallback name of the program +static const char *progname = "scr"; // register builtins SCR scr_builtins; // create agent for SCR calls ScriptingAgent agent; + +static void +print_help() +{ + fprintf (stderr, + "Usage: %s\n" + "Creates YaST2 SCR-based server reading input from stdin\n", + progname); +} + +int +main (int argc, char **argv) +{ + if (!argv[0]) + { + fprintf (stderr, "Missing argv[0]. It is a NULL pointer."); + exit (YAST_OPTIONERROR); + } + + progname = basename (argv[0]); // get program name + + if (argc > 1) { + print_help (); + exit (YAST_OK); + } + + signal_setup (); + + // set a defined umask + umask (0022); + + y2milestone ("Launched YaST2 %s", progname); + + Y2StdioComponent client (true,false); + Y2AgentComp <ScriptingAgent> server ("scr"); + + setenv ("YAST_IS_RUNNING", "yes", 1); + y2milestone ("YAST_IS_RUNNING is %s", getenv ("YAST_IS_RUNNING")); + + // Now start communication + YCPValue result = client.doActualWork(YCPList(), &server); + + // get result + server.result(result); + + // might be useful in tracking segmentation faults + y2milestone ("Finished YaST2 component '%s'", progname); + exit (YAST_OK); +} + diff --git a/core/base/src/signals.cc b/core/base/src/signals.cc new file mode 100644 index 0000000..8923638 --- /dev/null +++ b/core/base/src/signals.cc @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + + File: scr.cc, based on genericfrontend.cc + + Authors: Mathias Kettner <kettner@suse.de> + Arvin Schnell <arvin@suse.de> + Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Arvin Schnell <arvin@suse.de> + +/-*/ +#include <stdarg.h> +#include <unistd.h> +#include <signal.h> +#include <execinfo.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> + +#include <y2util/y2log.h> +#include <ycp/ExecutionEnvironment.h> + +extern ExecutionEnvironment ee; + +int signal_log_fd; // fd to use for logging in signal handler + +static +void +signal_log_to_fd (int fd, const char * cs) +{ + ssize_t n = strlen (cs); + while (true) { + ssize_t w = write(fd, cs, n); + if (w == n) + break; // success + else if (w == -1) { + if (errno == EINTR) { + // perror("gotcha"); // bnc#470645 + } + else { + perror("write"); // other cases + break; + } + } + else { + errno = 0; + cs += w; + n -= w; + } + } + +} + +static +void +signal_log (const char * cs) +{ + signal_log_to_fd (signal_log_fd, cs); +} + +static +bool +signal_log_ss (const string & s) +{ + signal_log (s.c_str ()); + return true; +} + + +static +void +signal_log_timestamp () +{ + char buffer[200]; + time_t time_time; + struct tm tm_time; + + time_time = time(NULL); + localtime_r (&time_time, &tm_time); + + if (strftime(buffer, sizeof(buffer), "=== %F %T %z ===\n", &tm_time) != 0) + { + signal_log (buffer); + } +} + +// fate#302166 "cache yast debugging logs in case of failure" +static +void signal_log_stored_debug () +{ + signal_log ("Liberating suppressed debugging messages:\n"); + blanik.for_each (signal_log_ss); + signal_log ("End of suppressed debugging messages\n"); +} + +// FATE 302167, info '(libc) Backtraces' +void +signal_log_backtrace () +{ + static const int N = 100; + void *frames[N]; + size_t size = backtrace (frames, N); + // demangling is not signal safe + signal_log ("Backtrace: (use c++filt to demangle)\n"); + backtrace_symbols_fd (frames, size, signal_log_fd); +} + +void +signal_log_open () +{ + signal_log_fd = -1; + + const char * logfns[] = { + "/var/log/YaST2/signal", + "y2signal.log", + NULL, // sentinel + }; + + for (const char ** logfn_p = &logfns[0]; *logfn_p != NULL; ++logfn_p) + { + signal_log_fd = open (*logfn_p, O_WRONLY | O_CREAT | O_APPEND, 0600); + if (signal_log_fd != -1) + break; + } +} + +void +signal_handler (int sig) +{ + signal (sig, SIG_IGN); + + // bnc#493152#c19 only signal-safe functions are allowed + char buffer[200]; + int n = snprintf (buffer, sizeof(buffer), + "YaST got signal %d at YCP file %s:%d\n", + sig, ee.filename ().c_str (), ee.linenumber ()); + if (n >= (int)sizeof(buffer) || n < 0) + strcpy (buffer, "YaST got a signal.\n"); + signal_log_to_fd (STDERR_FILENO, buffer); + + signal_log_open (); + if (signal_log_fd == -1) + { + signal_log_to_fd (STDERR_FILENO, "Could not open log file.\n"); + } + else + { + signal_log_timestamp (); + signal_log (buffer); + signal_log_stored_debug (); + signal_log_backtrace (); + + if (close (signal_log_fd) == -1) + perror ("log close"); + } + + // bye + signal (sig, SIG_DFL); + kill ( getpid (), sig); +} + +void +signal_setup () { + // Ignore SIGPIPE. No use in signals. Signals can't be assigned to + // components + signal(SIGPIPE, SIG_IGN); + + // Give some output for the SIGSEGV + // and other signals too, #238172 + // Note that USR1 and USR2 are handled by the logger. + signal (SIGHUP, signal_handler); + signal (SIGINT, signal_handler); + signal (SIGQUIT, signal_handler); + signal (SIGILL , signal_handler); + signal (SIGABRT, signal_handler); + signal (SIGFPE, signal_handler); + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); +} + diff --git a/core/base/src/signals.h b/core/base/src/signals.h new file mode 100644 index 0000000..9b457ce --- /dev/null +++ b/core/base/src/signals.h @@ -0,0 +1,22 @@ +/*---------------------------------------------------------------------\ +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + + File: scr.cc, based on genericfrontend.cc + + Authors: Mathias Kettner <kettner@suse.de> + Arvin Schnell <arvin@suse.de> + Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Arvin Schnell <arvin@suse.de> + +/-*/ +void signal_setup (); + diff --git a/core/base/src/y2base.cc b/core/base/src/y2base.cc index 444d02a..5e1fd3f 100644 --- a/core/base/src/y2base.cc +++ b/core/base/src/y2base.cc @@ -1,22 +1,930 @@ /*---------------------------------------------------------------------\ -| | -| __ __ ____ _____ ____ | -| \ \ / /_ _/ ___|_ _|___ \ | -| \ V / _` \___ \ | | __) | | -| | | (_| |___) || | / __/ | -| |_|\__,_|____/ |_| |_____| | -| | -| core system | -| (C) SuSE GmbH | -\----------------------------------------------------------------------/ - - File: y2base.cc - - Author: Mathias Kettner <kettner@suse.de> - Maintainer: Mathias Kettner <kettner@suse.de> +| | +| __ __ ____ _____ ____ | +| \ \ / /_ _/ ___|_ _|___ \ | +| \ V / _` \___ \ | | __) | | +| | | (_| |___) || | / __/ | +| |_|\__,_|____/ |_| |_____| | +| | +| core system | +| (C) SuSE GmbH | +\----------------------------------------------------------------------/ + + File: genericfrontend.cc + + Authors: Mathias Kettner <kettner@suse.de> + Arvin Schnell <arvin@suse.de> + Stanislav Visnovsky <visnov@suse.cz> + Maintainer: Arvin Schnell <arvin@suse.de> /-*/ -/* - * Hi. This file is empty on purpose :-) - * Nice, isn't it? +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // needed for vasprintf below +#endif + +/** + * \file + * Generic \ref main function handler for all YaST2 applications. + */ + +/** + * \mainpage Welcome to YaST2 Core System + * + * \section intro Introduction + * + * This is the main page of the YaST2 Core documentation. YaST Core is a generic component-based + * system to provide the infrastructure for implementing functionality of the YaST + * installation and configuration tool. + * + * \section whatis What is YaST2 Core? + * + * YaST Core is a collection of libraries to provide an infrastructure for rapid + * development of configuration tools. It is a component-based, cross-language + * system. + * + * Some of the general topics are covered by the following pages: + * + * - Component architecture + * - \ref components + * - \ref componentbroker + * - \ref componentsearch + * + * - Handling of error codes: \ref exitcodes + * + * - Libraries + * - \ref liby2 + * - \ref libycp + * - \ref libscr + * + * - Generic components + * - \ref SCR + * - \ref WFM + * + * \section community Join the community + * + * Visit our web site at : http://en.opensuse.org/YaST or #yast on irc.freenode.net + * + * \section License + * + * YaST is licensed under GPL v2. + * + */ + +/** + * \page exitcodes YaST2 Exit Codes + * + * All applications using liby2 library share a common \ref main function. The function handles the exit codes in the following way. + * + * The exit codes are described in \ref exitcodes.h header file. A special handling is applied to the value returned from the client. + * - If a value is \ref YCPNull or \ref YCPVoid, exitcode \ref YAST_OK will be used. + * - If the value is \ref YCPBoolean, \ref YAST_OK will be returned for true, \ref YAST_CLIENTRESULT for false. + * - If the value is \ref YCPInteger, the value will be added to \ref YAST_CLIENTRESULT and the resulting + * integer will be the process exitcode. + * - If the value is \ref YCPSymbol, for names defined by \ref ycp_error_exit_symbols \ref YAST_CLIENTRESULT + * will be returned, otherwise \ref YAST_OK. + */ +#include <stdarg.h> +#include <unistd.h> +#include <signal.h> +#include <execinfo.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sstream> +#include <iomanip> +#include <string> + +#include <ycp/y2log.h> +#include <ycp/ExecutionEnvironment.h> +#include "Y2Component.h" +#include "Y2ErrorComponent.h" +#include "Y2ComponentBroker.h" +#include <YCP.h> +#include <ycp/Parser.h> +#include <ycp/pathsearch.h> +#include "exitcodes.h" + +/// number of symbols that are handled as error codes +#define MAX_YCP_ERROR_EXIT_SYMBOLS 2 + +/// symbol names that are handled as error codes when returned by the client +const char* ycp_error_exit_symbols[MAX_YCP_ERROR_EXIT_SYMBOLS] = { + "abort", + "cancel" +}; + +using std::string; +ExecutionEnvironment ee; + +/// fallback name of the program +static const char *progname = "genericfrontend"; + +static void print_usage (); +static void print_help (); +static void print_error (const char*, ...) __attribute__ ((format (printf, 1, 2))); +static bool has_parens (const char* arg); + +int signal_log_fd; // fd to use for logging in signal handler + +static +void +signal_log_to_fd (int fd, const char * cs) +{ + ssize_t n = strlen (cs); + while (true) { + ssize_t w = write(fd, cs, n); + if (w == n) + break; // success + else if (w == -1) { + if (errno == EINTR) { + // perror("gotcha"); // bnc#470645 + } + else { + perror("write"); // other cases + break; + } + } + else { + errno = 0; + cs += w; + n -= w; + } + } + +} + +static +void +signal_log (const char * cs) +{ + signal_log_to_fd (signal_log_fd, cs); +} + +static +bool +signal_log_ss (const string & s) +{ + signal_log (s.c_str ()); + return true; +} + + +static +void +signal_log_timestamp () +{ + char buffer[200]; + time_t time_time; + struct tm tm_time; + + time_time = time(NULL); + localtime_r (&time_time, &tm_time); + + if (strftime(buffer, sizeof(buffer), "=== %F %T %z ===\n", &tm_time) != 0) + { + signal_log (buffer); + } +} + +// fate#302166 "cache yast debugging logs in case of failure" +static +void signal_log_stored_debug () +{ + signal_log ("Liberating suppressed debugging messages:\n"); + blanik.for_each (signal_log_ss); + signal_log ("End of suppressed debugging messages\n"); +} + +// FATE 302167, info '(libc) Backtraces' +void +signal_log_backtrace () +{ + static const int N = 100; + void *frames[N]; + size_t size = backtrace (frames, N); + // demangling is not signal safe + signal_log ("Backtrace: (use c++filt to demangle)\n"); + backtrace_symbols_fd (frames, size, signal_log_fd); +} + +void +signal_log_open () +{ + signal_log_fd = -1; + + const char * logfns[] = { + "/var/log/YaST2/signal", + "y2signal.log", + NULL, // sentinel + }; + + for (const char ** logfn_p = &logfns[0]; *logfn_p != NULL; ++logfn_p) + { + signal_log_fd = open (*logfn_p, O_WRONLY | O_CREAT | O_APPEND, 0600); + if (signal_log_fd != -1) + break; + } +} + +void +signal_handler (int sig) +{ + signal (sig, SIG_IGN); + + // bnc#493152#c19 only signal-safe functions are allowed + char buffer[200]; + int n = snprintf (buffer, sizeof(buffer), + "YaST got signal %d at YCP file %s:%d\n", + sig, ee.filename ().c_str (), ee.linenumber ()); + if (n >= (int)sizeof(buffer) || n < 0) + strcpy (buffer, "YaST got a signal.\n"); + signal_log_to_fd (STDERR_FILENO, buffer); + + signal_log_open (); + if (signal_log_fd == -1) + { + signal_log_to_fd (STDERR_FILENO, "Could not open log file.\n"); + } + else + { + signal_log_timestamp (); + signal_log (buffer); + signal_log_stored_debug (); + signal_log_backtrace (); + + if (close (signal_log_fd) == -1) + perror ("log close"); + } + + // bye + signal (sig, SIG_DFL); + kill ( getpid (), sig); +} + + +#include <blocxx/BLOCXX_config.h> +#include <blocxx/Logger.hpp> +#include <blocxx/LogMessage.hpp> +#if BLOCXX_LIBRARY_VERSION >= 5 +#include <blocxx/LogAppender.hpp> +#else +#include <blocxx/LogConfig.hpp> +#endif + +/** + * The YaST logger for LiMaL framework. It's just a wrapper around + * the standard YaST logging mechanism. */ +#if BLOCXX_LIBRARY_VERSION >= 5 +class YaSTLogger : public blocxx::LogAppender +#else +class YaSTLogger : public blocxx::Logger +#endif +{ +public: + virtual ~YaSTLogger() {}; + + /** + * Constructor. YaST will try to log every message level, + * because we filter on our own. + */ +#if BLOCXX_LIBRARY_VERSION >= 5 + YaSTLogger() : blocxx::LogAppender( + blocxx::LogAppender::ALL_COMPONENTS, + blocxx::LogAppender::ALL_CATEGORIES, + blocxx::LogAppender::STR_TTCC_MESSAGE_FORMAT + ) + {} +#else + YaSTLogger() : blocxx::Logger ("YaST",blocxx::E_ALL_LEVEL) {} +#endif + + /** + * The logging message processing. The method converts the + * Blocxx LogMessage into a YaST logger. Unfortunatelly, + * the log level can be received only as a string, so + * we have to do a conversion to loglevel_t used by YaST. + * + * @param m the message to be logged + */ +#if BLOCXX_LIBRARY_VERSION >= 5 + virtual void doProcessLogMessage(const blocxx::String & /*f*/, + const blocxx::LogMessage& m) const +#else + virtual void doProcessLogMessage(const blocxx::LogMessage& m) const +#endif + { + loglevel_t level = LOG_DEBUG; + if (m.category == blocxx::Logger::STR_FATAL_CATEGORY + || m.category == blocxx::Logger::STR_ERROR_CATEGORY) + { + level = LOG_ERROR; +#if BLOCXX_LIBRARY_VERSION >= 5 + } else if (m.category == blocxx::Logger::STR_WARNING_CATEGORY) + { + level = LOG_WARNING; +#endif + } else if (m.category == blocxx::Logger::STR_INFO_CATEGORY) + { + level = LOG_MILESTONE; + } + + y2_logger(level,m.component.c_str () + ,m.filename,m.fileline,m.methodname,"%s", m.message.c_str ()); + } +#if BLOCXX_LIBRARY_VERSION <= 4 + /** + * Clone this logger - create a new instance as a copy + * of this one and return a reference to the instance. + */ + virtual blocxx::LoggerRef doClone() const + { + return blocxx::LoggerRef(new YaSTLogger(*this)); + } +#endif +}; + +// YaSTLogger redirection factory for BloCxx/LiMaL +struct logger_initializer +{ + logger_initializer() + { +#if BLOCXX_LIBRARY_VERSION >= 5 + blocxx::LogAppender::setDefaultLogAppender( + blocxx::LogAppenderRef(new YaSTLogger()) + ); +#else + blocxx::Logger::setDefaultLogger( + blocxx::LoggerRef(new YaSTLogger()) + ); +#endif + } +}; +static logger_initializer initialize_logger; + +void +parse_client_and_options (int argc, char ** argv, int& arg, char *& client_name, YCPList& arglist) +{ + bool args_are_ycp = true; + + if (!argv[arg]) { + print_usage (); + exit (YAST_FEWARGUMENTS); + } + + client_name = argv[arg]; + arg++; // next argument (first client option) + + // Prepare client options + while (arg < argc) + { + if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) + { + // Logfile already done at program start --> ignore here + arg++; // skip filename + } + else if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) + { + // Logfile already done at program start --> ignore here + arg++; // skip filename + } + else if (!strcmp(argv[arg], "-S")) + { + args_are_ycp = false; + } + else if (!strcmp(argv[arg], "-s")) // Parse one value (YCPList of options) from stdin + { + Parser parser (0, "<stdin>"); // set parser to stdin + YCodePtr pc = parser.parse (); + + YCPValue option = YCPNull (); + if (pc) + { + option = pc->evaluate(true); // get one value (should be a YCPList) + } + + if (option.isNull()) + { + print_error ("Client option -s: Couldn't parse valid YCP value from stdin"); + exit (YAST_OPTIONERROR); + } + + if (!option->isList()) + { + print_error ("Client option -s: Parsed YCP value is NOT a YCPList"); + exit (YAST_OPTIONERROR); + } + + arglist = option->asList(); // the option read _IS_ arglist + } + else if (!strcmp(argv[arg], "-f")) // Parse values from file + { + arg++; // switch to filename + + if (arg >= argc) + { + print_error ("Client option -f is missing an argument"); + print_usage(); + exit(5); + } + + FILE *file = fopen (argv[arg], "r"); + if (!file) + { + print_error ("Client option -f: Couldn't open %s for reading", argv[arg]); + exit(5); + } + + bool one_value_parsed = false; + + while (!feof(file)) // Parse all values until EOF + { + Parser parser(file, argv[arg]); // set parser to file + + YCodePtr pc = parser.parse (); + + if ( pc ) + { + arglist->add( pc->evaluate(true) ); + one_value_parsed = true; + } + } + + fclose (file); + + if (!one_value_parsed) + { + print_error ("Client option -f: Couldn't parse valid YCP value from file %s", + argv[arg]); + exit(5); + } + } + else if (has_parens (argv[arg])) // client args + { + if (args_are_ycp) // bnc#382883 + { + Parser parser (argv[arg]); // set parser to option + + YCodePtr pc = parser.parse (); + + if (!pc ) + { + print_error ("Client option %s is not a valid YCP value", argv[arg]); + exit(5); + } + + arglist->add( pc->evaluate (true)); // add to arglist + } + else + { + string value(argv[arg] + 1, strlen (argv[arg]) - 2); + arglist->add (YCPString (value)); + } + } + else break; // must be server name + + arg++; // switch to next argument + } // Parsing client options +} + +void +parse_server_and_options (int argc, char ** argv, int& arg, char *& server_name, YCPList& preload) +{ + if (arg >= argc) + { + fprintf(stderr, "No server module given\n"); + print_usage (); + exit (YAST_OPTIONERROR); + } + + // now create server + if (!argv[arg]) { + print_usage (); + exit (YAST_FEWARGUMENTS); + } + + server_name = argv[arg]; + arg++; // next argument (first server option) + + // Prepare server and general options + + while (arg < argc) + { + if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) + { + // Logfile already done at program start --> ignore here + arg++; // skip filename + } + else if (!strcmp(argv[arg], "-p")) // preload + { + arg++; // switch to filename + + if (arg >= argc) + { + print_error ("Server option -p is missing an argument"); + print_usage(); + exit(5); + } + + FILE *file = fopen (argv[arg], "r"); + if (!file) + { + print_error ("Client option -p: Couldn't open %s for reading", argv[arg]); + exit(5); + } + + bool one_value_parsed = false; + + while (!feof(file)) // Parse all values until EOF + { + Parser parser(file, argv[arg]); // set parser to file + + YCodePtr pc = parser.parse (); + + if (pc) + { + preload->add(pc->evaluate (true)); // add to preload list + one_value_parsed = true; + } + } + + fclose (file); + + if (!one_value_parsed) + { + print_error ("Server option -p: Couldn't parse a valid YCP value from file %s", + argv[arg]); + exit(5); + } + } + else if (has_parens (argv[arg])) // option is a YCP value -> parse it directly + { + Parser parser (argv[arg]); // set parser to option + + YCodePtr pc = parser.parse (); + + if (!pc) + { + print_error ("Server option %s is not a valid YCP value", argv[arg]); + exit(5); + } + + preload->add (pc->evaluate (true)); // add to preload list + } + else break; // specific server options + + arg++; // switch to next argument + } // parsing server options + +} + +int +main (int argc, char **argv) +{ + if (!argv[0]) + { + fprintf (stderr, "Missing argv[0]. It is a NULL pointer."); + exit (YAST_OPTIONERROR); + } + + progname = basename (argv[0]); // get program name + + // Ignore SIGPIPE. No use in signals. Signals can't be assigned to + // components + signal(SIGPIPE, SIG_IGN); + + // Give some output for the SIGSEGV + // and other signals too, #238172 + // Note that USR1 and USR2 are handled by the logger. + signal (SIGHUP, signal_handler); + signal (SIGINT, signal_handler); + signal (SIGQUIT, signal_handler); + signal (SIGILL , signal_handler); + signal (SIGABRT, signal_handler); + signal (SIGFPE, signal_handler); + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); + + if (argc < 2) { + fprintf (stderr, "\nToo few arguments"); + print_usage(); + exit (YAST_FEWARGUMENTS); + } + + if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help")) { + print_help (); + exit (YAST_OK); + } + + // client _AND_ server must be given + if (argc < 3) + { + fprintf (stderr, "\nPlease give client and server as arguments"); + print_usage(); + exit(5); + } + + // Scan all options for -l/--logfile. They must be honored BEFORE + // the logger is used the first time. + for (int arg = 1; arg < argc; arg++) + { + if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) + { + arg++; // switch to filename + + if (arg >= argc) + { + print_error ("Option %s is missing an argument", argv[arg-1]); + exit(5); + } + + set_log_filename( argv[arg] ); // set logfile given in command line + } + if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) + { + arg++; // switch to filename + + if (arg >= argc) + { + print_error ("Option %s is missing an argument", argv[arg-1]); + exit(5); + } + + set_log_conf( argv[arg] ); + } + } + + // set a defined umask + umask (0022); + + YCPPathSearch::initialize(); + + ostringstream argdump; + for (int arg = 1; arg < argc; arg++) + { + argdump << " '" << argv[arg] << "'"; + } + + y2milestone ("Launched YaST2 component '%s'%s", progname, argdump.str().c_str()); + + // Now evaluate command line options in sequence + + int arg = 1; + + // The first argument might be the log option or MUST be the client name + if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) + { + // Logfile already done at program start --> ignore here + arg+=2; // skip over logfilename + } + if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) + { + // Logfile already done at program start --> ignore here + arg+=2; // skip over logfilename + } + // The first argument might be the log option or MUST be the client name + if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) + { + // Logfile already done at program start --> ignore here + arg+=2; // skip over logfilename + } + + + // Check for namespace exceptions registration + while (!strcmp(argv[arg], "-n")) + { + arg++; + char *pos = index (argv[arg], '='); + if (pos == NULL) + { + print_error ("Option %s argument must be in format namespace=component", argv[arg-1]); + exit (YAST_OPTIONERROR); + } + *pos = 0; + Y2ComponentBroker::registerNamespaceException (argv[arg], pos+1); + *pos = '='; + arg++; + } + +// FIXME the whole option parsing sucks **** ! + + // list of -I / -M pathes + // will be pushed to YCPPathSearch later to keep correct order + // (the last added path to YCPPathSearch will be searched first) + std::list<std::string> modpaths; + std::list<std::string> incpaths; + + // include paths + while (!strcmp(argv[arg], "-I")) + { + arg++; + incpaths.push_front (string (argv[arg])); // push to front so first one is last in list + arg++; + } + + while (!strcmp(argv[arg], "-M")) + { + arg++; + modpaths.push_front (string (argv[arg])); // push to front so first one is last in list + arg++; + } + + // add include and module pathes to YCPPathSearch so that the argument order is kept + + std::list<std::string>::iterator pathit; + for (pathit = incpaths.begin(); pathit != incpaths.end(); pathit++) + { + YCPPathSearch::addPath (YCPPathSearch::Include, pathit->c_str()); + } + for (pathit = modpaths.begin(); pathit != modpaths.end(); pathit++) + { + YCPPathSearch::addPath (YCPPathSearch::Module, pathit->c_str()); + } + + // "arg" and these two are output params + char * client_name; + YCPList arglist; + parse_client_and_options (argc, argv, arg, client_name, arglist); + + // "arg" and these two are output params + char * server_name; + YCPList preload; // prepare preload files from option -p + parse_server_and_options (argc, argv, arg, server_name, preload); + + // now create server + +#if 0 + Y2ComponentBroker::registerNamespaceException ("UI", server_name); +#endif + Y2ComponentBroker::getNamespaceComponent( "UI" ); + y2debug( "Creating server \"%s\"", server_name ); + Y2Component *server = Y2ComponentBroker::createServer( server_name ); + if (!server) { + print_error ("No such server module %s", server_name); + print_usage(); + exit(5); + } + + // Put argument into a nice new array and give them to the server + char **server_argv = new char *[argc-arg+2]; + server_argv[0] = strdup (server_name); + for (int i = arg; i < argc; i++) + server_argv[i-arg+1] = argv[i]; + argv[argc] = NULL; + + // set the server options directly + server->setServerOptions(argc-arg+1, server_argv); + + // Preload server with scripts from -p and directly given YCPValues + for (int i = 0; i < preload->size(); i++) + { + server->evaluate(preload->value(i)); + } + + // now create client + + Y2Component *client = Y2ComponentBroker::createClient (client_name); + if (!client) + { + print_error ("No such client module %s", client_name); + + std::list<string>::const_iterator + i = YCPPathSearch::searchListBegin(YCPPathSearch::Client), + e = YCPPathSearch::searchListEnd(YCPPathSearch::Client); + fprintf (stderr, "The search path follows. It does not include the current directory.\n"); + for (; i != e; ++i) + fprintf (stderr, " %s\n", i->c_str()); + + print_usage (); + exit (YAST_OPTIONERROR); + } + if (dynamic_cast<Y2ErrorComponent *>(client)) + { + print_error ("Error while creating client module %s", client_name); + exit (YAST_OPTIONERROR); + } + + + // The environment variable YAST_IS_RUNNING is checked in rpm + // post install scripts. Might be useful for other scripts as + // well. + if (strcmp (client_name, "live-installer") == 0 // bnc#389099 + || (strcmp (client_name, "installation") == 0 + && arglist->contains (YCPString ("initial")))) + { + setenv ("YAST_IS_RUNNING", "instsys", 1); + } + else + { + setenv ("YAST_IS_RUNNING", "yes", 1); + } + + y2milestone ("YAST_IS_RUNNING is %s", getenv ("YAST_IS_RUNNING")); + + + // Now start communication + YCPValue result = client->doActualWork(arglist, server); // give arglist collected above + + // get result + server->result(result); + + // Cleanup + delete server; + delete[] server_argv; + delete client; + + // might be useful in tracking segmentation faults + y2milestone ("Finished YaST2 component '%s'", progname); + + if( result.isNull () ) + exit (YAST_OK); + + y2milestone( "Exiting with client return value '%s'", result->toString ().c_str ()); + + if( result->isBoolean () ) + { + exit( result->asBoolean()->value() ? YAST_OK : YAST_CLIENTRESULT ); + } + + if( result->isInteger () ) + exit( YAST_CLIENTRESULT + result->asInteger ()->value () ); + + // if it is one of error symbols, return it as error + if( result->isSymbol () ) + { + string symbol = result->asSymbol()->symbol(); + for( int i = 0 ; i < MAX_YCP_ERROR_EXIT_SYMBOLS; i++ ) + if( symbol == ycp_error_exit_symbols[i] ) + exit( YAST_CLIENTRESULT ); + } + + // all other values + exit (YAST_OK); +} + + +static void +print_usage() +{ + fprintf (stderr, + "\nRun 'yast2 -h' for help on usage\n"); +} + + +static void +print_help() +{ + fprintf (stderr, "\n" + "Usage: %s [LogOpts] Client [ClientOpts] Server [Generic ServerOpts] " + "[Specific ServerOpts]\n", + progname); + + fprintf (stderr, + "LogOptions are:\n" + " -l | --logfile LogFile : Set logfile\n" + " -c | --logconf ConfFile : Configure logging\n" + " -n Namespace=Component : Override component for namespace\n" + " -I Path : Add include search path\n" + " -M Path : Add module search path\n" + "ClientOptions are:\n" + " -s : Get options as one YCPList from stdin\n" + " -f FileName : Get YCPValue(s) from file\n" + " -S : Parameters are strings, not YCP to be parsed\n" + " '(any YCPValue)...' : Parameter _IS_ a YCPValue\n" + " -S '(t1)' '(\\t2)' is equivalent to '(\"t1\")' '(\"\\\\t2\")'\n" + "Generic ServerOptions are:\n" + " -p FileName : Evaluate YCPValue(s) from file (preload)\n" + " '(any YCPValue)' : Parameter _IS_ a YCPValue to be evaluated\n" + "Specific ServerOptions are any options passed on unevaluated.\n\n" + "Examples:\n" + "y2base installation qt\n" + " Start binary y2base with intallation.ycp as client and qt as server\n" + "y2base installation '(\"test\")' qt\n" + " Provide YCPValue '\"test\"' as parameter for client installation\n" + "y2base installation qt -geometry 800x600\n" + " Provide geometry information as specific server options\n"); +} + + +static void +print_error (const char* format, ...) +{ + char* msg; + + va_list ap; + va_start (ap, format); + vasprintf (&msg, format, ap); + va_end (ap); + + fprintf (stderr, "%s\n", msg); + y2error ("%s", msg); + + free (msg); +} + + +static bool +has_parens (const char* arg) +{ + return arg[0] == '(' && arg[strlen (arg) - 1] == ')'; +} diff --git a/core/liby2/src/Makefile.am b/core/liby2/src/Makefile.am index 9644a09..5e388d8 100644 --- a/core/liby2/src/Makefile.am +++ b/core/liby2/src/Makefile.am @@ -15,7 +15,6 @@ liby2_la_SOURCES = \ Y2ComponentBroker.cc Y2ComponentCreator.cc \ Y2Namespace.cc \ Y2LanguageLoader.cc \ - genericfrontend.cc \ SymbolEntry.cc \ Y2ErrorComponent.cc \ Y2ProgramComponent.cc Y2CCProgram.cc \ diff --git a/core/liby2/src/genericfrontend.cc b/core/liby2/src/genericfrontend.cc deleted file mode 100644 index 5e1fd3f..0000000 --- a/core/liby2/src/genericfrontend.cc +++ /dev/null @@ -1,930 +0,0 @@ -/*---------------------------------------------------------------------\ -| | -| __ __ ____ _____ ____ | -| \ \ / /_ _/ ___|_ _|___ \ | -| \ V / _` \___ \ | | __) | | -| | | (_| |___) || | / __/ | -| |_|\__,_|____/ |_| |_____| | -| | -| core system | -| (C) SuSE GmbH | -\----------------------------------------------------------------------/ - - File: genericfrontend.cc - - Authors: Mathias Kettner <kettner@suse.de> - Arvin Schnell <arvin@suse.de> - Stanislav Visnovsky <visnov@suse.cz> - Maintainer: Arvin Schnell <arvin@suse.de> - -/-*/ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE // needed for vasprintf below -#endif - -/** - * \file - * Generic \ref main function handler for all YaST2 applications. - */ - -/** - * \mainpage Welcome to YaST2 Core System - * - * \section intro Introduction - * - * This is the main page of the YaST2 Core documentation. YaST Core is a generic component-based - * system to provide the infrastructure for implementing functionality of the YaST - * installation and configuration tool. - * - * \section whatis What is YaST2 Core? - * - * YaST Core is a collection of libraries to provide an infrastructure for rapid - * development of configuration tools. It is a component-based, cross-language - * system. - * - * Some of the general topics are covered by the following pages: - * - * - Component architecture - * - \ref components - * - \ref componentbroker - * - \ref componentsearch - * - * - Handling of error codes: \ref exitcodes - * - * - Libraries - * - \ref liby2 - * - \ref libycp - * - \ref libscr - * - * - Generic components - * - \ref SCR - * - \ref WFM - * - * \section community Join the community - * - * Visit our web site at : http://en.opensuse.org/YaST or #yast on irc.freenode.net - * - * \section License - * - * YaST is licensed under GPL v2. - * - */ - -/** - * \page exitcodes YaST2 Exit Codes - * - * All applications using liby2 library share a common \ref main function. The function handles the exit codes in the following way. - * - * The exit codes are described in \ref exitcodes.h header file. A special handling is applied to the value returned from the client. - * - If a value is \ref YCPNull or \ref YCPVoid, exitcode \ref YAST_OK will be used. - * - If the value is \ref YCPBoolean, \ref YAST_OK will be returned for true, \ref YAST_CLIENTRESULT for false. - * - If the value is \ref YCPInteger, the value will be added to \ref YAST_CLIENTRESULT and the resulting - * integer will be the process exitcode. - * - If the value is \ref YCPSymbol, for names defined by \ref ycp_error_exit_symbols \ref YAST_CLIENTRESULT - * will be returned, otherwise \ref YAST_OK. - */ -#include <stdarg.h> -#include <unistd.h> -#include <signal.h> -#include <execinfo.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sstream> -#include <iomanip> -#include <string> - -#include <ycp/y2log.h> -#include <ycp/ExecutionEnvironment.h> -#include "Y2Component.h" -#include "Y2ErrorComponent.h" -#include "Y2ComponentBroker.h" -#include <YCP.h> -#include <ycp/Parser.h> -#include <ycp/pathsearch.h> -#include "exitcodes.h" - -/// number of symbols that are handled as error codes -#define MAX_YCP_ERROR_EXIT_SYMBOLS 2 - -/// symbol names that are handled as error codes when returned by the client -const char* ycp_error_exit_symbols[MAX_YCP_ERROR_EXIT_SYMBOLS] = { - "abort", - "cancel" -}; - -using std::string; -ExecutionEnvironment ee; - -/// fallback name of the program -static const char *progname = "genericfrontend"; - -static void print_usage (); -static void print_help (); -static void print_error (const char*, ...) __attribute__ ((format (printf, 1, 2))); -static bool has_parens (const char* arg); - -int signal_log_fd; // fd to use for logging in signal handler - -static -void -signal_log_to_fd (int fd, const char * cs) -{ - ssize_t n = strlen (cs); - while (true) { - ssize_t w = write(fd, cs, n); - if (w == n) - break; // success - else if (w == -1) { - if (errno == EINTR) { - // perror("gotcha"); // bnc#470645 - } - else { - perror("write"); // other cases - break; - } - } - else { - errno = 0; - cs += w; - n -= w; - } - } - -} - -static -void -signal_log (const char * cs) -{ - signal_log_to_fd (signal_log_fd, cs); -} - -static -bool -signal_log_ss (const string & s) -{ - signal_log (s.c_str ()); - return true; -} - - -static -void -signal_log_timestamp () -{ - char buffer[200]; - time_t time_time; - struct tm tm_time; - - time_time = time(NULL); - localtime_r (&time_time, &tm_time); - - if (strftime(buffer, sizeof(buffer), "=== %F %T %z ===\n", &tm_time) != 0) - { - signal_log (buffer); - } -} - -// fate#302166 "cache yast debugging logs in case of failure" -static -void signal_log_stored_debug () -{ - signal_log ("Liberating suppressed debugging messages:\n"); - blanik.for_each (signal_log_ss); - signal_log ("End of suppressed debugging messages\n"); -} - -// FATE 302167, info '(libc) Backtraces' -void -signal_log_backtrace () -{ - static const int N = 100; - void *frames[N]; - size_t size = backtrace (frames, N); - // demangling is not signal safe - signal_log ("Backtrace: (use c++filt to demangle)\n"); - backtrace_symbols_fd (frames, size, signal_log_fd); -} - -void -signal_log_open () -{ - signal_log_fd = -1; - - const char * logfns[] = { - "/var/log/YaST2/signal", - "y2signal.log", - NULL, // sentinel - }; - - for (const char ** logfn_p = &logfns[0]; *logfn_p != NULL; ++logfn_p) - { - signal_log_fd = open (*logfn_p, O_WRONLY | O_CREAT | O_APPEND, 0600); - if (signal_log_fd != -1) - break; - } -} - -void -signal_handler (int sig) -{ - signal (sig, SIG_IGN); - - // bnc#493152#c19 only signal-safe functions are allowed - char buffer[200]; - int n = snprintf (buffer, sizeof(buffer), - "YaST got signal %d at YCP file %s:%d\n", - sig, ee.filename ().c_str (), ee.linenumber ()); - if (n >= (int)sizeof(buffer) || n < 0) - strcpy (buffer, "YaST got a signal.\n"); - signal_log_to_fd (STDERR_FILENO, buffer); - - signal_log_open (); - if (signal_log_fd == -1) - { - signal_log_to_fd (STDERR_FILENO, "Could not open log file.\n"); - } - else - { - signal_log_timestamp (); - signal_log (buffer); - signal_log_stored_debug (); - signal_log_backtrace (); - - if (close (signal_log_fd) == -1) - perror ("log close"); - } - - // bye - signal (sig, SIG_DFL); - kill ( getpid (), sig); -} - - -#include <blocxx/BLOCXX_config.h> -#include <blocxx/Logger.hpp> -#include <blocxx/LogMessage.hpp> -#if BLOCXX_LIBRARY_VERSION >= 5 -#include <blocxx/LogAppender.hpp> -#else -#include <blocxx/LogConfig.hpp> -#endif - -/** - * The YaST logger for LiMaL framework. It's just a wrapper around - * the standard YaST logging mechanism. - */ -#if BLOCXX_LIBRARY_VERSION >= 5 -class YaSTLogger : public blocxx::LogAppender -#else -class YaSTLogger : public blocxx::Logger -#endif -{ -public: - virtual ~YaSTLogger() {}; - - /** - * Constructor. YaST will try to log every message level, - * because we filter on our own. - */ -#if BLOCXX_LIBRARY_VERSION >= 5 - YaSTLogger() : blocxx::LogAppender( - blocxx::LogAppender::ALL_COMPONENTS, - blocxx::LogAppender::ALL_CATEGORIES, - blocxx::LogAppender::STR_TTCC_MESSAGE_FORMAT - ) - {} -#else - YaSTLogger() : blocxx::Logger ("YaST",blocxx::E_ALL_LEVEL) {} -#endif - - /** - * The logging message processing. The method converts the - * Blocxx LogMessage into a YaST logger. Unfortunatelly, - * the log level can be received only as a string, so - * we have to do a conversion to loglevel_t used by YaST. - * - * @param m the message to be logged - */ -#if BLOCXX_LIBRARY_VERSION >= 5 - virtual void doProcessLogMessage(const blocxx::String & /*f*/, - const blocxx::LogMessage& m) const -#else - virtual void doProcessLogMessage(const blocxx::LogMessage& m) const -#endif - { - loglevel_t level = LOG_DEBUG; - if (m.category == blocxx::Logger::STR_FATAL_CATEGORY - || m.category == blocxx::Logger::STR_ERROR_CATEGORY) - { - level = LOG_ERROR; -#if BLOCXX_LIBRARY_VERSION >= 5 - } else if (m.category == blocxx::Logger::STR_WARNING_CATEGORY) - { - level = LOG_WARNING; -#endif - } else if (m.category == blocxx::Logger::STR_INFO_CATEGORY) - { - level = LOG_MILESTONE; - } - - y2_logger(level,m.component.c_str () - ,m.filename,m.fileline,m.methodname,"%s", m.message.c_str ()); - } -#if BLOCXX_LIBRARY_VERSION <= 4 - /** - * Clone this logger - create a new instance as a copy - * of this one and return a reference to the instance. - */ - virtual blocxx::LoggerRef doClone() const - { - return blocxx::LoggerRef(new YaSTLogger(*this)); - } -#endif -}; - -// YaSTLogger redirection factory for BloCxx/LiMaL -struct logger_initializer -{ - logger_initializer() - { -#if BLOCXX_LIBRARY_VERSION >= 5 - blocxx::LogAppender::setDefaultLogAppender( - blocxx::LogAppenderRef(new YaSTLogger()) - ); -#else - blocxx::Logger::setDefaultLogger( - blocxx::LoggerRef(new YaSTLogger()) - ); -#endif - } -}; -static logger_initializer initialize_logger; - -void -parse_client_and_options (int argc, char ** argv, int& arg, char *& client_name, YCPList& arglist) -{ - bool args_are_ycp = true; - - if (!argv[arg]) { - print_usage (); - exit (YAST_FEWARGUMENTS); - } - - client_name = argv[arg]; - arg++; // next argument (first client option) - - // Prepare client options - while (arg < argc) - { - if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) - { - // Logfile already done at program start --> ignore here - arg++; // skip filename - } - else if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) - { - // Logfile already done at program start --> ignore here - arg++; // skip filename - } - else if (!strcmp(argv[arg], "-S")) - { - args_are_ycp = false; - } - else if (!strcmp(argv[arg], "-s")) // Parse one value (YCPList of options) from stdin - { - Parser parser (0, "<stdin>"); // set parser to stdin - YCodePtr pc = parser.parse (); - - YCPValue option = YCPNull (); - if (pc) - { - option = pc->evaluate(true); // get one value (should be a YCPList) - } - - if (option.isNull()) - { - print_error ("Client option -s: Couldn't parse valid YCP value from stdin"); - exit (YAST_OPTIONERROR); - } - - if (!option->isList()) - { - print_error ("Client option -s: Parsed YCP value is NOT a YCPList"); - exit (YAST_OPTIONERROR); - } - - arglist = option->asList(); // the option read _IS_ arglist - } - else if (!strcmp(argv[arg], "-f")) // Parse values from file - { - arg++; // switch to filename - - if (arg >= argc) - { - print_error ("Client option -f is missing an argument"); - print_usage(); - exit(5); - } - - FILE *file = fopen (argv[arg], "r"); - if (!file) - { - print_error ("Client option -f: Couldn't open %s for reading", argv[arg]); - exit(5); - } - - bool one_value_parsed = false; - - while (!feof(file)) // Parse all values until EOF - { - Parser parser(file, argv[arg]); // set parser to file - - YCodePtr pc = parser.parse (); - - if ( pc ) - { - arglist->add( pc->evaluate(true) ); - one_value_parsed = true; - } - } - - fclose (file); - - if (!one_value_parsed) - { - print_error ("Client option -f: Couldn't parse valid YCP value from file %s", - argv[arg]); - exit(5); - } - } - else if (has_parens (argv[arg])) // client args - { - if (args_are_ycp) // bnc#382883 - { - Parser parser (argv[arg]); // set parser to option - - YCodePtr pc = parser.parse (); - - if (!pc ) - { - print_error ("Client option %s is not a valid YCP value", argv[arg]); - exit(5); - } - - arglist->add( pc->evaluate (true)); // add to arglist - } - else - { - string value(argv[arg] + 1, strlen (argv[arg]) - 2); - arglist->add (YCPString (value)); - } - } - else break; // must be server name - - arg++; // switch to next argument - } // Parsing client options -} - -void -parse_server_and_options (int argc, char ** argv, int& arg, char *& server_name, YCPList& preload) -{ - if (arg >= argc) - { - fprintf(stderr, "No server module given\n"); - print_usage (); - exit (YAST_OPTIONERROR); - } - - // now create server - if (!argv[arg]) { - print_usage (); - exit (YAST_FEWARGUMENTS); - } - - server_name = argv[arg]; - arg++; // next argument (first server option) - - // Prepare server and general options - - while (arg < argc) - { - if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) - { - // Logfile already done at program start --> ignore here - arg++; // skip filename - } - else if (!strcmp(argv[arg], "-p")) // preload - { - arg++; // switch to filename - - if (arg >= argc) - { - print_error ("Server option -p is missing an argument"); - print_usage(); - exit(5); - } - - FILE *file = fopen (argv[arg], "r"); - if (!file) - { - print_error ("Client option -p: Couldn't open %s for reading", argv[arg]); - exit(5); - } - - bool one_value_parsed = false; - - while (!feof(file)) // Parse all values until EOF - { - Parser parser(file, argv[arg]); // set parser to file - - YCodePtr pc = parser.parse (); - - if (pc) - { - preload->add(pc->evaluate (true)); // add to preload list - one_value_parsed = true; - } - } - - fclose (file); - - if (!one_value_parsed) - { - print_error ("Server option -p: Couldn't parse a valid YCP value from file %s", - argv[arg]); - exit(5); - } - } - else if (has_parens (argv[arg])) // option is a YCP value -> parse it directly - { - Parser parser (argv[arg]); // set parser to option - - YCodePtr pc = parser.parse (); - - if (!pc) - { - print_error ("Server option %s is not a valid YCP value", argv[arg]); - exit(5); - } - - preload->add (pc->evaluate (true)); // add to preload list - } - else break; // specific server options - - arg++; // switch to next argument - } // parsing server options - -} - -int -main (int argc, char **argv) -{ - if (!argv[0]) - { - fprintf (stderr, "Missing argv[0]. It is a NULL pointer."); - exit (YAST_OPTIONERROR); - } - - progname = basename (argv[0]); // get program name - - // Ignore SIGPIPE. No use in signals. Signals can't be assigned to - // components - signal(SIGPIPE, SIG_IGN); - - // Give some output for the SIGSEGV - // and other signals too, #238172 - // Note that USR1 and USR2 are handled by the logger. - signal (SIGHUP, signal_handler); - signal (SIGINT, signal_handler); - signal (SIGQUIT, signal_handler); - signal (SIGILL , signal_handler); - signal (SIGABRT, signal_handler); - signal (SIGFPE, signal_handler); - signal (SIGSEGV, signal_handler); - signal (SIGTERM, signal_handler); - - if (argc < 2) { - fprintf (stderr, "\nToo few arguments"); - print_usage(); - exit (YAST_FEWARGUMENTS); - } - - if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help")) { - print_help (); - exit (YAST_OK); - } - - // client _AND_ server must be given - if (argc < 3) - { - fprintf (stderr, "\nPlease give client and server as arguments"); - print_usage(); - exit(5); - } - - // Scan all options for -l/--logfile. They must be honored BEFORE - // the logger is used the first time. - for (int arg = 1; arg < argc; arg++) - { - if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) - { - arg++; // switch to filename - - if (arg >= argc) - { - print_error ("Option %s is missing an argument", argv[arg-1]); - exit(5); - } - - set_log_filename( argv[arg] ); // set logfile given in command line - } - if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) - { - arg++; // switch to filename - - if (arg >= argc) - { - print_error ("Option %s is missing an argument", argv[arg-1]); - exit(5); - } - - set_log_conf( argv[arg] ); - } - } - - // set a defined umask - umask (0022); - - YCPPathSearch::initialize(); - - ostringstream argdump; - for (int arg = 1; arg < argc; arg++) - { - argdump << " '" << argv[arg] << "'"; - } - - y2milestone ("Launched YaST2 component '%s'%s", progname, argdump.str().c_str()); - - // Now evaluate command line options in sequence - - int arg = 1; - - // The first argument might be the log option or MUST be the client name - if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) - { - // Logfile already done at program start --> ignore here - arg+=2; // skip over logfilename - } - if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--logconf")) - { - // Logfile already done at program start --> ignore here - arg+=2; // skip over logfilename - } - // The first argument might be the log option or MUST be the client name - if (!strcmp(argv[arg], "-l") || !strcmp(argv[arg], "--logfile")) - { - // Logfile already done at program start --> ignore here - arg+=2; // skip over logfilename - } - - - // Check for namespace exceptions registration - while (!strcmp(argv[arg], "-n")) - { - arg++; - char *pos = index (argv[arg], '='); - if (pos == NULL) - { - print_error ("Option %s argument must be in format namespace=component", argv[arg-1]); - exit (YAST_OPTIONERROR); - } - *pos = 0; - Y2ComponentBroker::registerNamespaceException (argv[arg], pos+1); - *pos = '='; - arg++; - } - -// FIXME the whole option parsing sucks **** ! - - // list of -I / -M pathes - // will be pushed to YCPPathSearch later to keep correct order - // (the last added path to YCPPathSearch will be searched first) - std::list<std::string> modpaths; - std::list<std::string> incpaths; - - // include paths - while (!strcmp(argv[arg], "-I")) - { - arg++; - incpaths.push_front (string (argv[arg])); // push to front so first one is last in list - arg++; - } - - while (!strcmp(argv[arg], "-M")) - { - arg++; - modpaths.push_front (string (argv[arg])); // push to front so first one is last in list - arg++; - } - - // add include and module pathes to YCPPathSearch so that the argument order is kept - - std::list<std::string>::iterator pathit; - for (pathit = incpaths.begin(); pathit != incpaths.end(); pathit++) - { - YCPPathSearch::addPath (YCPPathSearch::Include, pathit->c_str()); - } - for (pathit = modpaths.begin(); pathit != modpaths.end(); pathit++) - { - YCPPathSearch::addPath (YCPPathSearch::Module, pathit->c_str()); - } - - // "arg" and these two are output params - char * client_name; - YCPList arglist; - parse_client_and_options (argc, argv, arg, client_name, arglist); - - // "arg" and these two are output params - char * server_name; - YCPList preload; // prepare preload files from option -p - parse_server_and_options (argc, argv, arg, server_name, preload); - - // now create server - -#if 0 - Y2ComponentBroker::registerNamespaceException ("UI", server_name); -#endif - Y2ComponentBroker::getNamespaceComponent( "UI" ); - y2debug( "Creating server \"%s\"", server_name ); - Y2Component *server = Y2ComponentBroker::createServer( server_name ); - if (!server) { - print_error ("No such server module %s", server_name); - print_usage(); - exit(5); - } - - // Put argument into a nice new array and give them to the server - char **server_argv = new char *[argc-arg+2]; - server_argv[0] = strdup (server_name); - for (int i = arg; i < argc; i++) - server_argv[i-arg+1] = argv[i]; - argv[argc] = NULL; - - // set the server options directly - server->setServerOptions(argc-arg+1, server_argv); - - // Preload server with scripts from -p and directly given YCPValues - for (int i = 0; i < preload->size(); i++) - { - server->evaluate(preload->value(i)); - } - - // now create client - - Y2Component *client = Y2ComponentBroker::createClient (client_name); - if (!client) - { - print_error ("No such client module %s", client_name); - - std::list<string>::const_iterator - i = YCPPathSearch::searchListBegin(YCPPathSearch::Client), - e = YCPPathSearch::searchListEnd(YCPPathSearch::Client); - fprintf (stderr, "The search path follows. It does not include the current directory.\n"); - for (; i != e; ++i) - fprintf (stderr, " %s\n", i->c_str()); - - print_usage (); - exit (YAST_OPTIONERROR); - } - if (dynamic_cast<Y2ErrorComponent *>(client)) - { - print_error ("Error while creating client module %s", client_name); - exit (YAST_OPTIONERROR); - } - - - // The environment variable YAST_IS_RUNNING is checked in rpm - // post install scripts. Might be useful for other scripts as - // well. - if (strcmp (client_name, "live-installer") == 0 // bnc#389099 - || (strcmp (client_name, "installation") == 0 - && arglist->contains (YCPString ("initial")))) - { - setenv ("YAST_IS_RUNNING", "instsys", 1); - } - else - { - setenv ("YAST_IS_RUNNING", "yes", 1); - } - - y2milestone ("YAST_IS_RUNNING is %s", getenv ("YAST_IS_RUNNING")); - - - // Now start communication - YCPValue result = client->doActualWork(arglist, server); // give arglist collected above - - // get result - server->result(result); - - // Cleanup - delete server; - delete[] server_argv; - delete client; - - // might be useful in tracking segmentation faults - y2milestone ("Finished YaST2 component '%s'", progname); - - if( result.isNull () ) - exit (YAST_OK); - - y2milestone( "Exiting with client return value '%s'", result->toString ().c_str ()); - - if( result->isBoolean () ) - { - exit( result->asBoolean()->value() ? YAST_OK : YAST_CLIENTRESULT ); - } - - if( result->isInteger () ) - exit( YAST_CLIENTRESULT + result->asInteger ()->value () ); - - // if it is one of error symbols, return it as error - if( result->isSymbol () ) - { - string symbol = result->asSymbol()->symbol(); - for( int i = 0 ; i < MAX_YCP_ERROR_EXIT_SYMBOLS; i++ ) - if( symbol == ycp_error_exit_symbols[i] ) - exit( YAST_CLIENTRESULT ); - } - - // all other values - exit (YAST_OK); -} - - -static void -print_usage() -{ - fprintf (stderr, - "\nRun 'yast2 -h' for help on usage\n"); -} - - -static void -print_help() -{ - fprintf (stderr, "\n" - "Usage: %s [LogOpts] Client [ClientOpts] Server [Generic ServerOpts] " - "[Specific ServerOpts]\n", - progname); - - fprintf (stderr, - "LogOptions are:\n" - " -l | --logfile LogFile : Set logfile\n" - " -c | --logconf ConfFile : Configure logging\n" - " -n Namespace=Component : Override component for namespace\n" - " -I Path : Add include search path\n" - " -M Path : Add module search path\n" - "ClientOptions are:\n" - " -s : Get options as one YCPList from stdin\n" - " -f FileName : Get YCPValue(s) from file\n" - " -S : Parameters are strings, not YCP to be parsed\n" - " '(any YCPValue)...' : Parameter _IS_ a YCPValue\n" - " -S '(t1)' '(\\t2)' is equivalent to '(\"t1\")' '(\"\\\\t2\")'\n" - "Generic ServerOptions are:\n" - " -p FileName : Evaluate YCPValue(s) from file (preload)\n" - " '(any YCPValue)' : Parameter _IS_ a YCPValue to be evaluated\n" - "Specific ServerOptions are any options passed on unevaluated.\n\n" - "Examples:\n" - "y2base installation qt\n" - " Start binary y2base with intallation.ycp as client and qt as server\n" - "y2base installation '(\"test\")' qt\n" - " Provide YCPValue '\"test\"' as parameter for client installation\n" - "y2base installation qt -geometry 800x600\n" - " Provide geometry information as specific server options\n"); -} - - -static void -print_error (const char* format, ...) -{ - char* msg; - - va_list ap; - va_start (ap, format); - vasprintf (&msg, format, ap); - va_end (ap); - - fprintf (stderr, "%s\n", msg); - y2error ("%s", msg); - - free (msg); -} - - -static bool -has_parens (const char* arg) -{ - return arg[0] == '(' && arg[strlen (arg) - 1] == ')'; -} diff --git a/core/liby2/src/include/y2/Makefile.am b/core/liby2/src/include/y2/Makefile.am index 3a1451e..9e6fe8b 100644 --- a/core/liby2/src/include/y2/Makefile.am +++ b/core/liby2/src/include/y2/Makefile.am @@ -14,8 +14,7 @@ pkginclude_HEADERS = \ Y2SerialComponent.h Y2StdioComponent.h \ Y2PluginComponent.h Y2CCPlugin.h \ Y2Namespace.h \ - Y2Function.h SymbolEntry.h \ - exitcodes.h + Y2Function.h SymbolEntry.h #<INSTALL-HEADER-TARGET> diff --git a/core/liby2/src/include/y2/exitcodes.h b/core/liby2/src/include/y2/exitcodes.h deleted file mode 100644 index a224093..0000000 --- a/core/liby2/src/include/y2/exitcodes.h +++ /dev/null @@ -1,31 +0,0 @@ -/*---------------------------------------------------------------------\ -| | -| __ __ ____ _____ ____ | -| \ \ / /_ _/ ___|_ _|___ \ | -| \ V / _` \___ \ | | __) | | -| | | (_| |___) || | / __/ | -| |_|\__,_|____/ |_| |_____| | -| | -| core system | -| (C) SuSE GmbH | -\----------------------------------------------------------------------/ - - File: exitcodes.h - - Author: Stanislav Visnovsky <visnov@suse.cz> - Maintainer: Stanislav Visnovsky <visnov@suse.cz> - -/-*/ -// -*- c++ -*- - -#ifndef exitcodes_h -#define exitcodes_h - -enum error_codes { - YAST_OK = 0, // process finished without errors - YAST_FEWARGUMENTS = 1, // too few arguments for the commandline - YAST_OPTIONERROR = 5, // error in provided arguments - YAST_CLIENTRESULT = 16 // client (YCP) returned special result, this is used as offset (or as generic error) -}; - -#endif // exitcodes_h -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
On Wed, Feb 23, 2011 at 10:36:47AM +0100, Stanislav Višňovský wrote:
From: Stanislav Visnovsky <visnov@novell.com>
This patch removes generic frontend from liby2 and moves it to /y2base where actual binaries are build. It also splits parts of the code to single files to improve readability and allow sharing with the 'scr' binary. scr becomes very specialized and does not provide any fancy options (which are not used anyway)
Here are combined patches 05 06 08 10 11, but I am not applying them yet because you have removed /usr/include/YaST2/y2/exitcodes.h and I don't have time to check before the weekend whether it actually breaks anything. Did I mention git would be so much easier? So this mail serves as a staging area. BTW I have fixed the wfm testsuite fragility, so go forth and make check. -- Martin Vidner, YaST developer http://en.opensuse.org/User:Mvidner Kuracke oddeleni v restauraci je jako fekalni oddeleni v bazenu
From: Stanislav Visnovsky <visnov@novell.com> --- core/base/tools/ycpc/ycpc.cc | 2 +- core/libscr/testsuite/runscr.cc | 2 ++ core/libycp/testsuite/runc.cc | 2 ++ core/libycp/testsuite/runycp.cc | 2 +- core/wfm/testsuite/runc.cc | 2 ++ core/wfm/testsuite/runwfm.cc | 1 + 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/core/base/tools/ycpc/ycpc.cc b/core/base/tools/ycpc/ycpc.cc index f2a33ea..d951eba 100644 --- a/core/base/tools/ycpc/ycpc.cc +++ b/core/base/tools/ycpc/ycpc.cc @@ -47,7 +47,7 @@ static Parser *parser = NULL; static char *outname = NULL; -extern ExecutionEnvironment ee; +ExecutionEnvironment ee; static int quiet = 0; // no output static int verbose = 0; // much output diff --git a/core/libscr/testsuite/runscr.cc b/core/libscr/testsuite/runscr.cc index 9385933..1245cd8 100644 --- a/core/libscr/testsuite/runscr.cc +++ b/core/libscr/testsuite/runscr.cc @@ -24,6 +24,8 @@ extern int yydebug; +ExecutionEnvironment ee; + int main (int argc, const char *argv[]) { diff --git a/core/libycp/testsuite/runc.cc b/core/libycp/testsuite/runc.cc index c54fcbe..94ae379 100644 --- a/core/libycp/testsuite/runc.cc +++ b/core/libycp/testsuite/runc.cc @@ -27,6 +27,8 @@ #include "config.h" +ExecutionEnvironment ee; + class TestY2Component : public Y2Component { virtual Y2Namespace *import (const char* name) { diff --git a/core/libycp/testsuite/runycp.cc b/core/libycp/testsuite/runycp.cc index b75b980..fee5a2e 100644 --- a/core/libycp/testsuite/runycp.cc +++ b/core/libycp/testsuite/runycp.cc @@ -29,7 +29,7 @@ #include <y2/Y2Component.h> #include <y2/Y2ComponentCreator.h> -extern ExecutionEnvironment ee; +ExecutionEnvironment ee; class TestY2Component : public Y2Component { virtual Y2Namespace *import (const char* name) diff --git a/core/wfm/testsuite/runc.cc b/core/wfm/testsuite/runc.cc index 8403adc..e226ee2 100644 --- a/core/wfm/testsuite/runc.cc +++ b/core/wfm/testsuite/runc.cc @@ -30,6 +30,8 @@ #include "config.h" +ExecutionEnvironment ee; + class TestY2Component : public Y2Component { virtual Y2Namespace *import (const char* name) { diff --git a/core/wfm/testsuite/runwfm.cc b/core/wfm/testsuite/runwfm.cc index a67b960..09a5e49 100644 --- a/core/wfm/testsuite/runwfm.cc +++ b/core/wfm/testsuite/runwfm.cc @@ -27,6 +27,7 @@ #include <ycp/y2log.h> #include <WFM.h> +ExecutionEnvironment ee; extern int yydebug; int -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> --- core/scr/testsuite/Makefile.am | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-) delete mode 100644 core/scr/testsuite/y2scr.cc diff --git a/core/scr/testsuite/Makefile.am b/core/scr/testsuite/Makefile.am index 9032ae6..81e7342 100644 --- a/core/scr/testsuite/Makefile.am +++ b/core/scr/testsuite/Makefile.am @@ -11,7 +11,7 @@ AUTOMAKE_OPTIONS = dejagnu INCLUDES = ${AGENT_INCLUDES} -noinst_PROGRAMS = runscr y2scr +noinst_PROGRAMS = runscr runscr_SOURCES = runscr.cc runscr_LDADD = ${AGENT_LIBADD} @@ -21,10 +21,3 @@ runscr_LDFLAGS = \ ../src/libpy2scr.la \ -Xlinker --no-whole-archive -y2scr_SOURCES = y2scr.cc -y2scr_LDADD = ${AGENT_LIBADD} -y2scr_LDFLAGS = \ - -Xlinker --whole-archive \ - $(top_builddir)/agent-dummy/src/libpy2ag_dummy.la \ - ../src/libpy2scr.la \ - -Xlinker --no-whole-archive diff --git a/core/scr/testsuite/y2scr.cc b/core/scr/testsuite/y2scr.cc deleted file mode 100644 index e69de29..0000000 -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> --- core/libscr/src/include/scr/run_agent.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/core/libscr/src/include/scr/run_agent.h b/core/libscr/src/include/scr/run_agent.h index ec14e85..1c40b37 100644 --- a/core/libscr/src/include/scr/run_agent.h +++ b/core/libscr/src/include/scr/run_agent.h @@ -14,6 +14,7 @@ #include <scr/SCRAgent.h> #include <scr/SCR.h> +ExecutionEnvironment ee; void run_agent_instance (int, char*[], bool, SCRAgent*); -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> This patch moves the agent to new test framework (like agent-resolver). It also does not log using ycpdebug bug proper y2debug. --- core/agent-dummy/src/DummyAgent.cc | 8 +- core/agent-dummy/testsuite/Makefile.am | 22 ++++--- .../testsuite/ag_dummy.test/Makefile.am | 3 + .../testsuite/ag_dummy.test/ag_dummy.exp | 12 +++ core/agent-dummy/testsuite/config/Makefile.am | 3 + core/agent-dummy/testsuite/config/default.exp | 2 + core/agent-dummy/testsuite/config/unix.exp | 5 ++ core/agent-dummy/testsuite/config/unknown.exp | 2 + core/agent-dummy/testsuite/lib/Makefile.am | 3 + core/agent-dummy/testsuite/lib/ag_dummy_init.exp | 76 ++++++++++++++++++++ core/agent-dummy/testsuite/rundummy.cc | 14 ++++ core/agent-dummy/testsuite/tests/Makefile.am | 3 + core/agent-dummy/testsuite/tests/runtest.sh | 18 +++++ 13 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 core/agent-dummy/testsuite/ag_dummy.test/Makefile.am create mode 100644 core/agent-dummy/testsuite/ag_dummy.test/ag_dummy.exp create mode 100644 core/agent-dummy/testsuite/config/Makefile.am create mode 100644 core/agent-dummy/testsuite/config/default.exp create mode 100644 core/agent-dummy/testsuite/config/unix.exp create mode 100644 core/agent-dummy/testsuite/config/unknown.exp create mode 100644 core/agent-dummy/testsuite/lib/Makefile.am create mode 100644 core/agent-dummy/testsuite/lib/ag_dummy_init.exp create mode 100644 core/agent-dummy/testsuite/rundummy.cc create mode 100644 core/agent-dummy/testsuite/tests/Makefile.am create mode 100755 core/agent-dummy/testsuite/tests/runtest.sh delete mode 100644 core/agent-dummy/testsuite/y2ag_dummy.cc diff --git a/core/agent-dummy/src/DummyAgent.cc b/core/agent-dummy/src/DummyAgent.cc index e778738..c59b0b2 100644 --- a/core/agent-dummy/src/DummyAgent.cc +++ b/core/agent-dummy/src/DummyAgent.cc @@ -50,7 +50,7 @@ DummyAgent::Read (const YCPPath& path, const YCPValue& arg , const YCPValue&) v = checkPath(path, defaultMap, deflt); } - ycpdebug("%sRead %s", DUMMY_LOG_STRING, + y2debug("%sRead %s", DUMMY_LOG_STRING, (path->toString() + (arg.isNull()?"":(" "+arg->toString())) + (v.isNull()?"":(" "+v->toString())) ).c_str()); @@ -78,7 +78,7 @@ DummyAgent::Write (const YCPPath& path, const YCPValue& value, v = checkPath(path, defaultMap, deflt); } - ycpdebug("%sWrite %s", DUMMY_LOG_STRING, + y2debug("%sWrite %s", DUMMY_LOG_STRING, (path->toString() + " " + value->toString() + (arg.isNull()?"":(" "+arg->toString())) + (v.isNull()?"":(" "+v->toString())) ).c_str()); @@ -107,7 +107,7 @@ DummyAgent::Execute (const YCPPath& path, const YCPValue& value, v = checkPath(path, defaultMap, deflt); } - ycpdebug("%sExecute %s", DUMMY_LOG_STRING, + y2debug("%sExecute %s", DUMMY_LOG_STRING, (path->toString() + " " + value->toString() + (arg.isNull()?"":(" "+arg->toString())) + (v.isNull()?"":(" "+v->toString())) ).c_str()); @@ -136,7 +136,7 @@ YCPList DummyAgent::Dir(const YCPPath& path) } } - ycpdebug("%sDir %s: %s", DUMMY_LOG_STRING, + y2debug("%sDir %s: %s", DUMMY_LOG_STRING, path->toString().c_str(), l->toString ().c_str ()); return l; diff --git a/core/agent-dummy/testsuite/Makefile.am b/core/agent-dummy/testsuite/Makefile.am index 9a4d0a4..6d6bb74 100644 --- a/core/agent-dummy/testsuite/Makefile.am +++ b/core/agent-dummy/testsuite/Makefile.am @@ -1,19 +1,23 @@ -# # Makefile.am for core/agent-dummy/testsuite -# + +SUBDIRS = config lib ag_dummy.test tests AM_CXXFLAGS = -DY2LOG=\"agent-dummy\" +PACKAGE = ag_dummy AUTOMAKE_OPTIONS = dejagnu -INCLUDES = \ - ${Y2UTIL_CFLAGS} +INCLUDES = ${AGENT_INCLUDES} -noinst_PROGRAMS = y2ag_dummy +noinst_PROGRAMS = rundummy -y2ag_dummy_SOURCES = y2ag_dummy.cc -y2ag_dummy_LDADD = ${AGENT_LIBADD} -y2ag_dummy_LDFLAGS = \ - -Xlinker --whole-archive \ +rundummy_SOURCES = rundummy.cc +rundummy_LDADD = ${AGENT_LIBADD} +rundummy_LDFLAGS = \ + -Xlinker --whole-archive \ ../src/libpy2ag_dummy.la \ -Xlinker --no-whole-archive + +clean-local: + rm -f tmp.err.* tmp.out.* site.exp *.log *.sum *.bak + diff --git a/core/agent-dummy/testsuite/ag_dummy.test/Makefile.am b/core/agent-dummy/testsuite/ag_dummy.test/Makefile.am new file mode 100644 index 0000000..be14737 --- /dev/null +++ b/core/agent-dummy/testsuite/ag_dummy.test/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for core/agent-resolver/testsuite/ag_dummy.test + +EXTRA_DIST = ag_dummy.exp diff --git a/core/agent-dummy/testsuite/ag_dummy.test/ag_dummy.exp b/core/agent-dummy/testsuite/ag_dummy.test/ag_dummy.exp new file mode 100644 index 0000000..af44db5 --- /dev/null +++ b/core/agent-dummy/testsuite/ag_dummy.test/ag_dummy.exp @@ -0,0 +1,12 @@ +# +# ag_rcconfig.exp +# 'main' file for all ag_rcconfig tests +# + +# get all files matching tests/*.ycp + +set filenames [lsort [glob $srcdir/tests/*.ycp]] + +# foreach file, call ycp-run (from testsuite/lib) + +foreach file $filenames { ycp-run $file } diff --git a/core/agent-dummy/testsuite/config/Makefile.am b/core/agent-dummy/testsuite/config/Makefile.am new file mode 100644 index 0000000..8a4c15c --- /dev/null +++ b/core/agent-dummy/testsuite/config/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for core/agent-resolver/testsuite/config + +EXTRA_DIST = default.exp unix.exp unknown.exp diff --git a/core/agent-dummy/testsuite/config/default.exp b/core/agent-dummy/testsuite/config/default.exp new file mode 100644 index 0000000..fe1e08a --- /dev/null +++ b/core/agent-dummy/testsuite/config/default.exp @@ -0,0 +1,2 @@ +# default.exp -- empty + diff --git a/core/agent-dummy/testsuite/config/unix.exp b/core/agent-dummy/testsuite/config/unix.exp new file mode 100644 index 0000000..956160e --- /dev/null +++ b/core/agent-dummy/testsuite/config/unix.exp @@ -0,0 +1,5 @@ +load_lib "ag_dummy_init.exp" + +proc ag_dummy_exit {} {} +proc ag_dummy_version {} {} + diff --git a/core/agent-dummy/testsuite/config/unknown.exp b/core/agent-dummy/testsuite/config/unknown.exp new file mode 100644 index 0000000..fe48c2f --- /dev/null +++ b/core/agent-dummy/testsuite/config/unknown.exp @@ -0,0 +1,2 @@ +perror "No setup for current configuration" +exit 1 diff --git a/core/agent-dummy/testsuite/lib/Makefile.am b/core/agent-dummy/testsuite/lib/Makefile.am new file mode 100644 index 0000000..da7c1ba --- /dev/null +++ b/core/agent-dummy/testsuite/lib/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for core/agent-dummy/testsuite/lib + +EXTRA_DIST = ag_dummy_init.exp diff --git a/core/agent-dummy/testsuite/lib/ag_dummy_init.exp b/core/agent-dummy/testsuite/lib/ag_dummy_init.exp new file mode 100644 index 0000000..5740bfe --- /dev/null +++ b/core/agent-dummy/testsuite/lib/ag_dummy_init.exp @@ -0,0 +1,76 @@ +# +# run a ycp file +# +proc ycp-run { src } { + + set path [split $src "/"] + set filename [lindex $path [expr [llength $path]-1]] + + # extract basename and check extension + + set fname [split $filename "."] + + if {[llength $fname] < 2} { + fail "Bad filename syntax '$src'" + return -1 + } + if {[lindex $fname [expr [llength $fname]-1]] != "ycp"} { + fail "Not .ycp extension '$src'" + return -1 + } + + # setup filenames + + # $src is the name of the original testfile with absolute path + # tests/$filename is the name of the original testfile with relative path, + # relative to the testsuite directory + set test_input "tests/$filename" + + set base_name [lindex $fname 0] + + set stdout_name "tests/$base_name.out" + set stderr_name "tests/$base_name.err" + set log_name "tests/$base_name.log" + set tmpout_name "tmp.out.$base_name" + set tmperr_name "tmp.err.$base_name" + set tmplog_name "tmp.log.$base_name" + + puts "Running $base_name..." + + # run the test + + set result "" + set oops [catch { set result [exec "tests/runtest.sh" "$test_input" "$tmpout_name" "$tmperr_name" ] } catched] + + if {$oops != 0} { + fail "test case failed for $base_name: $catched" + return -1 + } + + # check return code from runycp + + if {$result != ""} { + warning "Compilation of $base_name results in '$result'" + return -1 + } + + # check stderr + + if {[diff $stderr_name "tmp.err.$base_name"] != 1} { + fail "Wrong stderr for $base_name" + return -1 + } + + # check stdout + + if {[diff $stdout_name "tmp.out.$base_name"] != 1} { + fail "Wrong stdout for $base_name" + return -1 + } + + # ok, all is fine + + pass $base_name + + return 0 +} diff --git a/core/agent-dummy/testsuite/rundummy.cc b/core/agent-dummy/testsuite/rundummy.cc new file mode 100644 index 0000000..801b12e --- /dev/null +++ b/core/agent-dummy/testsuite/rundummy.cc @@ -0,0 +1,14 @@ +/* + * Author: Arvin Schnell <arvin@suse.de> + */ + +#include <scr/run_agent.h> + +#include "../src/DummyAgent.h" + + +int +main (int argc, char *argv[]) +{ + run_agent <DummyAgent> (argc, argv, true); +} diff --git a/core/agent-dummy/testsuite/tests/Makefile.am b/core/agent-dummy/testsuite/tests/Makefile.am new file mode 100644 index 0000000..fca63e0 --- /dev/null +++ b/core/agent-dummy/testsuite/tests/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for core/agent-dummy/testsuite/tests + +EXTRA_DIST = *.ycp *.in *.out *.err runtest.sh diff --git a/core/agent-dummy/testsuite/tests/runtest.sh b/core/agent-dummy/testsuite/tests/runtest.sh new file mode 100755 index 0000000..a4a5177 --- /dev/null +++ b/core/agent-dummy/testsuite/tests/runtest.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +unset Y2DEBUG +unset Y2DEBUGALL +unset Y2DEBUGGER + +IN_FILE=${1%.*}".in" +rm -f "$IN_FILE.test" 2>/dev/null +cp $IN_FILE "$IN_FILE.test" 2>/dev/null + +SCR_FILE=${1%.*}".scr" +rm -f "$SCR_FILE" 2>/dev/null +echo -e ".\n\n\`ag_resolver(\n \`ResolverAgent(\"$IN_FILE.test\")\n)\n" >"$SCR_FILE" + +(./runresolver -l - "$1" >"$2") 2>&1 | fgrep -v " <0> " | grep -v "^$" | sed 's/^....-..-.. ..:..:.. [^)]*) //g' >$3 + +cat "$IN_FILE.test" >>"$2" 2>/dev/null +exit 0 diff --git a/core/agent-dummy/testsuite/y2ag_dummy.cc b/core/agent-dummy/testsuite/y2ag_dummy.cc deleted file mode 100644 index e69de29..0000000 -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> --- core/base/src/y2base.cc | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/base/src/y2base.cc b/core/base/src/y2base.cc index 5e1fd3f..d69e119 100644 --- a/core/base/src/y2base.cc +++ b/core/base/src/y2base.cc @@ -96,9 +96,9 @@ #include <ycp/y2log.h> #include <ycp/ExecutionEnvironment.h> -#include "Y2Component.h" -#include "Y2ErrorComponent.h" -#include "Y2ComponentBroker.h" +#include <y2/Y2Component.h> +#include <y2/Y2ErrorComponent.h> +#include <y2/Y2ComponentBroker.h> #include <YCP.h> #include <ycp/Parser.h> #include <ycp/pathsearch.h> -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
From: Stanislav Visnovsky <visnov@novell.com> --- core/base/src/scr.cc | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/core/base/src/scr.cc b/core/base/src/scr.cc index e75f856..f5114f8 100644 --- a/core/base/src/scr.cc +++ b/core/base/src/scr.cc @@ -70,7 +70,7 @@ main (int argc, char **argv) progname = basename (argv[0]); // get program name - if (argc > 1) { + if (argc != 3) { print_help (); exit (YAST_OK); } -- 1.7.3.2 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
On Wednesday, February 23, 2011 10:36:42 am visnov@suse.cz wrote:
This is a bunch of patches for yast2-core. Some are pure clean up, but there is also a removal of genericfrontend.cc and replacing it with non-generic scr and y2base binaries.
Hi Stano, Thank you for your patches for yast2-core. Did you commit these patches to svn? Cheers Thomas -- Thomas Goettlicher SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nuernberg) -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
On streda 23 Február 2011 11:03:37 Thomas Goettlicher wrote:
On Wednesday, February 23, 2011 10:36:42 am visnov@suse.cz wrote:
This is a bunch of patches for yast2-core. Some are pure clean up, but there is also a removal of genericfrontend.cc and replacing it with non-generic scr and y2base binaries.
Hi Stano,
Thank you for your patches for yast2-core. Did you commit these patches to svn?
No, that's why they are sent to yast2-devel. First, they are not suitable for 11.4 and also removal of generic frontend might be considered up for discussion. Stano -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org For additional commands, e-mail: yast-devel+help@opensuse.org
participants (4)
-
Martin Vidner
-
Stanislav Visnovsky
-
Thomas Goettlicher
-
visnov@suse.cz