![](https://seccdn.libravatar.org/avatar/c3c40c0a8c67869856fd7e06cbcb4099.jpg?s=120&d=mm&r=g)
Author: lslezak Date: Fri Feb 15 10:27:40 2008 New Revision: 44482 URL: http://svn.opensuse.org/viewcvs/yast?rev=44482&view=rev Log: - added new .process (agent-process) agent (obsoletes old .background agent) - handles multiple subprocess, complete I/O communication, tty support Added: trunk/core/agent-process/ (with props) trunk/core/agent-process/MAINTAINER trunk/core/agent-process/Makefile.am trunk/core/agent-process/conf/ (with props) trunk/core/agent-process/conf/Makefile.am trunk/core/agent-process/conf/process.scr trunk/core/agent-process/doc/ (with props) trunk/core/agent-process/doc/Makefile.am trunk/core/agent-process/doc/ag_process_example.ycp trunk/core/agent-process/doc/autodocs/ (with props) trunk/core/agent-process/doc/autodocs/Makefile.am trunk/core/agent-process/doc/process.html trunk/core/agent-process/src/ (with props) trunk/core/agent-process/src/Makefile.am trunk/core/agent-process/src/Process.cc trunk/core/agent-process/src/Process.h trunk/core/agent-process/src/ProcessAgent.cc trunk/core/agent-process/src/ProcessAgent.h trunk/core/agent-process/src/Y2CCProcessAgent.cc trunk/core/agent-process/testsuite/ (with props) trunk/core/agent-process/testsuite/Makefile.am trunk/core/agent-process/testsuite/ag_process.test/ (with props) trunk/core/agent-process/testsuite/ag_process.test/Makefile.am trunk/core/agent-process/testsuite/ag_process.test/ag_process.exp trunk/core/agent-process/testsuite/config/ (with props) trunk/core/agent-process/testsuite/config/Makefile.am trunk/core/agent-process/testsuite/config/default.exp trunk/core/agent-process/testsuite/config/unix.exp trunk/core/agent-process/testsuite/config/unknown.exp trunk/core/agent-process/testsuite/lib/ (with props) trunk/core/agent-process/testsuite/lib/Makefile.am trunk/core/agent-process/testsuite/lib/ag_process_init.exp trunk/core/agent-process/testsuite/run_ag_process.cc trunk/core/agent-process/testsuite/tests/ (with props) trunk/core/agent-process/testsuite/tests/C_locale.err trunk/core/agent-process/testsuite/tests/C_locale.out trunk/core/agent-process/testsuite/tests/C_locale.ycp trunk/core/agent-process/testsuite/tests/Dir.err trunk/core/agent-process/testsuite/tests/Dir.out trunk/core/agent-process/testsuite/tests/Dir.ycp trunk/core/agent-process/testsuite/tests/Makefile.am trunk/core/agent-process/testsuite/tests/env.err trunk/core/agent-process/testsuite/tests/env.out trunk/core/agent-process/testsuite/tests/env.ycp trunk/core/agent-process/testsuite/tests/invalid_paths.err trunk/core/agent-process/testsuite/tests/invalid_paths.out trunk/core/agent-process/testsuite/tests/invalid_paths.ycp trunk/core/agent-process/testsuite/tests/invalid_values.err trunk/core/agent-process/testsuite/tests/invalid_values.out trunk/core/agent-process/testsuite/tests/invalid_values.ycp trunk/core/agent-process/testsuite/tests/kill.ycp.disabled trunk/core/agent-process/testsuite/tests/runtest.sh (with props) trunk/core/agent-process/testsuite/tests/status.err trunk/core/agent-process/testsuite/tests/status.out trunk/core/agent-process/testsuite/tests/status.ycp trunk/core/agent-process/testsuite/tests/stderr.err trunk/core/agent-process/testsuite/tests/stderr.out trunk/core/agent-process/testsuite/tests/stderr.ycp trunk/core/agent-process/testsuite/tests/stdout.err trunk/core/agent-process/testsuite/tests/stdout.out trunk/core/agent-process/testsuite/tests/stdout.ycp trunk/core/agent-process/testsuite/tests/tty.err trunk/core/agent-process/testsuite/tests/tty.out trunk/core/agent-process/testsuite/tests/tty.ycp Modified: trunk/core/SUBDIRS trunk/core/agents-perl/ag_background trunk/core/package/yast2-core.changes Modified: trunk/core/SUBDIRS URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/SUBDIRS?rev=44482&r1=44481&r2=44482&view=diff ============================================================================== --- trunk/core/SUBDIRS (original) +++ trunk/core/SUBDIRS Fri Feb 15 10:27:40 2008 @@ -1 +1 @@ -liby2util-r liby2 libycp libyui libscr agent-dummy scr agent-system agent-any agent-ini agent-modules agent-resolver agents-non-y2 agents-perl wfm base autodocs +liby2util-r liby2 libycp libyui libscr agent-dummy scr agent-system agent-any agent-ini agent-modules agent-resolver agents-non-y2 agents-perl wfm base autodocs agent-process Added: trunk/core/agent-process/MAINTAINER URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/MAINTAINER?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/MAINTAINER (added) +++ trunk/core/agent-process/MAINTAINER Fri Feb 15 10:27:40 2008 @@ -0,0 +1 @@ +Ladislav Slezák <lslezak@novell.com> Added: trunk/core/agent-process/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/Makefile.am (added) +++ trunk/core/agent-process/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,5 @@ +# +# Makefile.am for core/agent-process +# + +SUBDIRS = conf doc src testsuite Added: trunk/core/agent-process/conf/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/conf/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/conf/Makefile.am (added) +++ trunk/core/agent-process/conf/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,7 @@ +# +# Makefile.am for .../agent-process/conf +# + +scrconf_DATA = process.scr + +EXTRA_DIST = $(scrconf_DATA) Added: trunk/core/agent-process/conf/process.scr URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/conf/process.scr?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/conf/process.scr (added) +++ trunk/core/agent-process/conf/process.scr Fri Feb 15 10:27:40 2008 @@ -0,0 +1,75 @@ +/** + * File: process.scr + * Summary: Process agent - run multiple processes in background + * Author: Ladislav Slezák <lslezak@novell.com> + * Access: read / write / execute + * See: anyagent libscr MANPAGE(1) file/relative/to/doc_home/file.html + * + * $Id$ + * + * Examples: + * + * // start a process using default locale + * `Execute(.process.start_shell, "/bin/date") + * (14896) + * `Read(.process.read, 14896) + * ("Pá úno 15 07:15:24 CET 2008\n") + * `Read(.process.running, 14896) + * (false) + * `Read(.process.status, 14896) + * (0) + * + * // start a process in C locale, in a terminal, set the environment + * `Execute(.process.start_shell, "/bin/date", $["C_locale":true, "tty":true, "env":$["FOOVAR":"FOO"]]) + * (14899) + * `Read(.process.read, 14899) + * ("Fri Feb 15 07:18:02 CET 2008\r\n") + * + * // list processes + * `Dir(.process) + * ([14896, 14899]) + * + * // release process (free allocated buffers...) + * `Execute(.process.release, 14896) + * (true) + * `Dir(.process) + * ([14858, 14899]) + * + * // read/write lines example + * `Execute(.process.start_shell, "cat") + * (14900) + * `Write(.process, 14900,"the first line\nthe second line\n") + * (true) + * `Read(.process.read_line, 14900) + * ("the first line") + * `Read(.process.read_line, 14900) + * ("the second line") + * `Read(.process.read_line, 14900) + * (nil) + * + * // read complete output + * `Write(.process, 14900,"the first line\nthe second line\n") + * (true) + * `Read(.process.read, 14900) + * ("the first line\nthe second line\n") + * + * // close input/output + * `Read(.process.running, 14900) + * (true) + * `Execute(.process.close, 14900) + * (0) + * `Read(.process.running, 14900) + * (false) + * + * + * The process agent can run multiple subprocesses in backgroung with full interaction + * (reading stdout/stderr, writing to stdin). + * It is possible to run a subprocess in terminal (instead of piped output/input). + * + * This agent obsoletes the background agent (ag_background). + */ +.process + +`ag_process( + `ProcessAgent() +) Added: trunk/core/agent-process/doc/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/doc/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/doc/Makefile.am (added) +++ trunk/core/agent-process/doc/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,10 @@ +# +# Makefile.am for .../agent-process/doc +# + +SUBDIRS = autodocs + +htmldir = $(docdir) + +html_DATA = process.html +EXTRA_DIST = $(html_DATA) Added: trunk/core/agent-process/doc/ag_process_example.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/doc/ag_process_example.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/doc/ag_process_example.ycp (added) +++ trunk/core/agent-process/doc/ag_process_example.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,76 @@ +/** + * File: + * ag_process_example.ycp + * + * Authors: + * Ladislav Slezák <lslezak@novell.com> + * + * Description: + * An example for the process agent + * + * $Id$ + * + * This is example program for the process agent. Find is used + * as the background script producing some output. + * + */ + +{ + +UI::OpenDialog( + `VBox( + `VSpacing(0.5), + `HSpacing( `opt(`hstretch), 80), + `HBox( + `Label("Searching in directory: "), + `Label(`id(`dir), `opt(`hstretch), "") + ), + `VSpacing(0.5), + `PushButton(`id(`abort), "Abort"), + `VSpacing(0.5) + ) +); + +// start subprocess, remember the id +integer id = (integer)(SCR::Execute(.process.start_shell, "/usr/bin/find /usr -type d")); + +symbol ret = nil; + +string line = ""; + +while(SCR::Read(.process.running, id) == true) +{ + line = (string)SCR::Read(.process.read_line_stderr, id); + if (line != nil) + { + y2warning("Error: %1", line); + } + + line = (string)SCR::Read(.process.read_line, id); + + if (line != nil) + { + UI::ChangeWidget(`id(`dir), `Value, line); + } + else + { + // there was no input, wait for a while + // give the subprocess time to print something + sleep(20); + } + + ret = (symbol) UI::PollInput(); + + // check if the abort button was pressed + if (ret == `abort) + { + SCR::Execute(.process.kill, id); // kill the subprocess + break; + } + +} + +UI::CloseDialog(); + +} + Added: trunk/core/agent-process/doc/autodocs/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/doc/autodocs/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/doc/autodocs/Makefile.am (added) +++ trunk/core/agent-process/doc/autodocs/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,18 @@ +# +# Makefile.am for core/agent-process/doc +# + +SUBDIRS = + +htmldir = $(docdir)/agent-process + +html_DATA = ag_process-builtins.html +EXTRA_DIST = $(html_DATA) + +builtin = $(srcdir)/../../src/ProcessAgent.cc + +ag_process-builtins.html: $(builtin) + `pkg-config --variable=ybindir yast2-devtools`/makebuiltindocs -t "SCR Process agent functions" -a $(builtin) > $@.new + mv $@.new $@ + +CLEANFILES = ag_process-builtins.html Added: trunk/core/agent-process/doc/process.html URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/doc/process.html?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/doc/process.html (added) +++ trunk/core/agent-process/doc/process.html Fri Feb 15 10:27:40 2008 @@ -0,0 +1,73 @@ +<HTML> +<HEAD> +<TITLE>Process agent description</TITLE> +<META http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<!-- $Id$ --> +</HEAD> +<BODY> +<H1>Process agent description</H1> +<HR> + +<H2>Purpose</H2> +The Process agent (<TT>ag_process</TT>) is used to manage multiple subprocesses running in background. +It is part of YaST2 SCR, the system configuration repository, +used to access configuration data on the target system. The general +SCR API allows <TT>Read()</TT> and <TT>Write()</TT> access to get and +change data. + +<P> +<H2>Implementation</H2> + +<P>The agent reuses ExternalProgram class from liby2util, class Process is derived from ExternalProgram and adds +stderr reading/writing, output buffering and a posibility to send a specified signal.</P> + + +<P> +<H2>Interface of the Process agent</H2> +The interface is implemented as a SCR agent with the usual <TT>Read()</TT>, +<TT>Write()</TT> and <TT>Dir()</TT> interface. The path prefix used is + +<UL><TT>.process</TT></UL> + +<P> +<I>The complete path description is available in the +<A HREF="autodocs/ag_process-builtins.html"><TT>autodocs/</TT></A> directory.</I> + +<P> +<H2>Details of API</H2> + +<H3>Start in shell vs. direct start</H3> + +<P>The agent can start a subprocess in two ways</P> + +<UL> + <LI>Using shell (/bin/sh) - the command is passed -c argument of shell executable. The advantage is that shell expanstion, IO redirection works as expected. The drawback is that there is an extra process started.</LI> + <LI>Direct execution - the command is executed directly, less possibilities but consumes less resources (no shell is started).</LI> +</UL> + +<P>Note that the arguments are passed differently in each case. Shell execution requires the argument in the command, the arguments must be escaped to be processes correctly. The direct execution uses an optional map, the arguments are passed as a list of strings at key "args". In this case the armunets need not to be escpaed.</P> + +<P><B>Example:</B><BR> +Start <TT>echo "\"foo bar\""</TT> command: +<UL> +<LI>Start in a shell: <TT>SCR::Execute(.process.start_shell, "/bin/echo \"\\\"foo bar\\\"\"");</TT></LI> +<LI>Direct start: <TT>SCR::Execute(.process.start, "/bin/echo", $["args" : "\"foo bar\"");</TT></LI> +</UL> +</P> + +<H3>Reading stdout/stderr to unblock a process</H3> + +<P> +When a subprocess produces too much output which is not read it is stopped when the buffers are full. (In my test it was about after 64kB, but this is system dependent.)</P> + +<P>So it is a good idea to read the output regularly. It is possible to read the output (using .process.read(_line) and .process.read_stderr(_line) paths) when the process is running or just read the output to the internal buffers in the agent (using Execute(.process.buffer)) and read them later at once when the process is finished. +</P> + +<P> +<ADDRESS> +Ladislav Slezák <lslezak@novell.com><BR> +</ADDRESS> + + +</BODY> +</HTML> Added: trunk/core/agent-process/src/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/Makefile.am (added) +++ trunk/core/agent-process/src/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,25 @@ +# +# Makefile.am for .../agent-process/src +# + +AM_CXXFLAGS = -DY2LOG=\"agent-process\" -Wall + +plugin_LTLIBRARIES = libpy2ag_process.la +noinst_LTLIBRARIES = liby2ag_process.la + +liby2ag_process_la_SOURCES = \ + ProcessAgent.cc \ + ProcessAgent.h \ + Process.cc \ + Process.h + +liby2ag_process_la_LDFLAGS = -version-info 2:0 +liby2ag_process_la_LIBADD = @AGENT_LIBADD@ + +libpy2ag_process_la_SOURCES = \ + $(liby2ag_process_la_SOURCES) \ + Y2CCProcessAgent.cc +libpy2ag_process_la_LDFLAGS = -version-info 2:0 +libpy2ag_process_la_LIBADD = @AGENT_LIBADD@ + +INCLUDES = -I$(includedir) Added: trunk/core/agent-process/src/Process.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/Process.cc?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/Process.cc (added) +++ trunk/core/agent-process/src/Process.cc Fri Feb 15 10:27:40 2008 @@ -0,0 +1,212 @@ +/* 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 <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(); +} + +// read a line from stdout +std::string Process::readLine() +{ + const std::string new_output = receiveUpto('\n'); + stdout_buffer += new_output; + + return GetLineFromBuffer(stdout_buffer); +} + +void Process::readStdoutToBuffer() +{ + const size_t b_size = 4096; + char buffer[b_size]; + + const size_t read = receive(buffer, b_size); + stdout_buffer += std::string(buffer, read); +} + +// 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::readToBuffer(int fd, std::string &buffer_str) +{ + const size_t b_size = 4096; + char buffer[b_size]; + + ssize_t len = ::read(fd, buffer, b_size); + + // no input so far + if (len == -1) + { + len = 0; + } + + const std::string new_output(buffer, len); + buffer_str += new_output; +} + +// 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(); +} + +// read a line from stderr +std::string Process::readErrLine() +{ + readToBuffer(stderr_pipes[0], stderr_buffer); + + return GetLineFromBuffer(stderr_buffer); +} + +void Process::readToBuffers() +{ + // read from stderr to the buffer + readToBuffer(stderr_pipes[0], stderr_buffer); + + readStdoutToBuffer(); +} + +// read data from stderr +std::string Process::readErr() +{ + // read from stderr to the buffer + readToBuffer(stderr_pipes[0], stderr_buffer); + + // 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() +{ + // 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]); + UnblockFD(stderr_pipes[1]); + + // return fd for writing + return stderr_pipes[1]; +} + +int Process::closeAll() +{ + // close stderr pipe + ::close(stderr_pipes[0]); + + return ExternalProgram::close(); +} + Added: trunk/core/agent-process/src/Process.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/Process.h?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/Process.h (added) +++ trunk/core/agent-process/src/Process.h Fri Feb 15 10:27:40 2008 @@ -0,0 +1,134 @@ +/* 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:$ + */ + +#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 + int stderr_pipes[2]; // a pipe for 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 + void readToBuffer(int fd, std::string &buffer_str); + + void readStdoutToBuffer(); + +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) + : ExternalProgram(commandline, Stderr_To_FileDesc, + use_pty, create_stderr_pipes(), default_locale) + {} + + /** + * 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) + : ExternalProgram(argv, environment, Stderr_To_FileDesc, + use_pty, create_stderr_pipes(), default_locale) + {} + + + ~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(); + + /** + * Read stdout and stderr of the process to buffers to unblock it + */ + void readToBuffers(); + + int closeAll(); +}; + +#endif // Process_h Added: trunk/core/agent-process/src/ProcessAgent.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/ProcessAgent.cc?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/ProcessAgent.cc (added) +++ trunk/core/agent-process/src/ProcessAgent.cc Fri Feb 15 10:27:40 2008 @@ -0,0 +1,559 @@ +/* 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 the Process agent + * + * Authors: Ladislav Slezák <lslezak@novell.com> + * + * $Id: ProcessAgent.cc 27914 2006-02-13 14:32:08Z locilka $ + */ + +#include "ProcessAgent.h" +#include "Process.h" + +#include <y2util/ExternalProgram.h> + +/** + * Constructor + */ +ProcessAgent::ProcessAgent() : SCRAgent() +{ +} + +/** + * Destructor - release all processes + */ +ProcessAgent::~ProcessAgent() +{ + // release created objects + for (ProcessContainer::iterator it = _processes.begin(); it != _processes.end(); it++) + { + delete it->second; + } + + // remove invalid pointers + _processes.clear(); +} + +/** + * Dir - return list of managed processes + */ +YCPList ProcessAgent::Dir(const YCPPath& path) +{ + /** + * @builtin Dir(.process) -> list<integer> + * Return list od processes (IDs) managed by the process agent. + * + * @example Dir(.process) -> [ 23568, 28896 ] + */ + // return all processes + if (path->isRoot()) + { + YCPList ret; + + for(ProcessContainer::const_iterator it = _processes.begin(); it != _processes.end(); it++) + { + ret->add(YCPInteger(it->first)); + } + + return ret; + } + + y2error("Wrong path '%s' in Dir().", path->toString().c_str()); + return YCPNull(); +} + +YCPValue ProcessAgent::ProcessOutput(std::string &output) +{ + // no output, return nil + if (output.empty()) + { + return YCPVoid(); + } + + // remove the trailing new line character, "" means empty line + output.erase(output.end() - 1); + + return YCPString(output); +} + +/** + * Read + */ +YCPValue ProcessAgent::Read(const YCPPath &path, const YCPValue& arg, const YCPValue& opt) +{ + std::string cmd(path->component_str(0)); + + if (arg.isNull() || !arg->isInteger()) + { + y2error("ID of the process is missing"); + return YCPNull(); + } + + pid_t id = arg->asInteger()->value(); + + y2debug("Requested path: %s, id: %d", cmd.c_str(), id); + + ProcessContainer::iterator proc(_processes.find(id)); + + if (proc == _processes.end()) + { + y2error("Process '%d' not found", id); + return YCPNull(); + } + + // handler for "running" path + if (cmd == "running") + { + /** + * @builtin Read (.process.running, integer id) -> boolean + * Returns true if the process is running + * + * @example Read (.process.running, 12345) -> true + */ + return YCPBoolean(proc->second->running()); + } + // handler for "pid" path + else if (cmd == "pid") + { + /** + * @builtin Read (.process.pid, integer id) -> integer + * Returns the PID of a process + * + * @example Read (.process.pid, 12345) -> 6789 + */ + return YCPInteger(id); + } + else if (cmd == "read_line") + { + /** + * @builtin Read (.process.read_line, integer id) -> string + * Returns one line from stdout of the process, nil if there is no output + * + * @example Read (.process.read_line, 12345) -> nil + */ + std::string out = proc->second->readLine(); + return ProcessOutput(out); + } + else if (cmd == "read") + { + /** + * @builtin Read (.process.read, integer id) -> string + * Returns read stdout of the process, nil if there is no output. + * This read function is not line-oriented, the output can contain multiple lines or just part of a line. + * + * @example Read (.process.read, 12345) -> nil + */ + std::string out(proc->second->read()); + + if (out.empty()) + { + return YCPVoid(); + } + else + { + return YCPString(out); + } + } + else if (cmd == "read_line_stderr") + { + /** + * @builtin Read (.process.read_line_stderr, integer id) -> string + * Returns one line from stderr of the process, nil if there is no output + * + * @example Read (.process.read_line_stderr, 12345) -> nil + */ + std::string err = proc->second->readErrLine(); + return ProcessOutput(err); + } + else if (cmd == "read_stderr") + { + /** + * @builtin Read (.process.read_stderr, integer id) -> string + * Returns read stderr of the process, nil if there is no output. + * This read function is not line-oriented, the output can contain multiple lines or just part of a line. + * + * @example Read (.process.read_stderr, 12345) -> nil + */ + std::string out(proc->second->readErr()); + + if (out.empty()) + { + return YCPVoid(); + } + else + { + return YCPString(out); + } + } + else if (cmd == "status") + { + /** + * @builtin Read (.process.status, integer id) -> integer + * Returns exit status of the process, if the process is still running nil is returned. + * + * @example Read (.process.status, 12345) -> 0 + */ + if (proc->second->running()) + { + // the process is still running + return YCPVoid(); + } + else + { + return YCPInteger(proc->second->close()); + } + } + + y2error("Wrong path '%s' in Read().", path->toString().c_str()); + return YCPNull(); +} + +/** + * Write + */ +YCPBoolean ProcessAgent::Write(const YCPPath &path, const YCPValue& value, + const YCPValue& arg) +{ + if (!path->isRoot()) + { + y2error("Unsupported path in Write(): %s", path->toString().c_str()); + return YCPNull(); + } + + if (value.isNull() || !value->isInteger()) + { + y2error("ID of the process is missing"); + return YCPNull(); + } + + pid_t id = value->asInteger()->value(); + + y2debug("Writing to %d", id); + + ProcessContainer::iterator proc(_processes.find(id)); + + if (proc == _processes.end()) + { + y2error("Process '%d' not found", id); + return YCPNull(); + } + + if (!arg.isNull() && arg->isString()) + { + if (!proc->second->running()) + { + y2warning("Process '%d' is not running, cannot write to stdin!", id); + return YCPBoolean(false); + } + /** + * @builtin Write(.process, integer id, input_string) -> boolean + * Wrtites the input string to stdin of the process. Returns true on success. + * + * @example Write(.process, 12345, "foo") -> true + */ + + return YCPBoolean(proc->second->send(arg->asString()->value())); + } + else + { + // wrong type of the arg + y2error("Value '%s' is not a string", arg->toString().c_str()); + return YCPBoolean(false); + } +} + +/** + * Execute + */ +YCPValue ProcessAgent::Execute(const YCPPath &path, + const YCPValue& value , const YCPValue& arg) +{ + std::string pth(path->component_str(0)); + + y2debug("Executing path: %s", pth.c_str()); + + // handler for ".start_shell" path + if (pth == "start_shell" || pth == "start") + { + /** + * @builtin Execute(.process.start_shell, string command, map options) -> integer + * Execute the command in a shell (/bin/sh). The command can contain all shell features like + * argument expansion, stdout/stderr redirection... + * + * The optional map can contain additional configuration: "tty" : boolean - run the command in terminal (instead of piped stdout/stderr), the default is false, + * "C_locale" : boolean - use C locale (default false), "env" : map<string variable, string value> - set additional environment variables. + * + * Returns ID of the started process + * + * @example Execute(.process.start_shell, "/bin/true") -> 12345 + */ + /** + * @builtin Execute(.process.start, string command, map options) -> integer + * Execute the command. The string command is a path to the program, arguments are passed in the map - value of key "args" must be list<string> with the required arguments. For other options see .start_shell info. + * + * Returns ID of the started process + * + * @example Execute(.process.start, "/bin/echo", $[ "args" : [ "arg1", "arg2" ] ]) -> 12345 + */ + + // check type of the argument + if (!value.isNull() && value->isString()) + { + std::string commandline = value->asString()->value(); + + bool use_pty = false; + bool default_locale = false; + + ExternalProgram::Environment env; + YCPList args; + + // set optional parameters + if (!arg.isNull() && arg->isMap()) + { + YCPMap opt_map = arg->asMap(); + + // start in a terminal? + if( ! opt_map->value( YCPString("tty")).isNull()) + { + if (opt_map->value(YCPString("tty"))->isBoolean()) + { + use_pty = opt_map->value(YCPString("tty"))->asBoolean()->value(); + } + else + { + y2warning("tty option '%s' is not a boolean value", opt_map->value(YCPString("tty"))->toString().c_str()); + } + } + + // use default locale? + if( ! opt_map->value( YCPString("C_locale")).isNull() && opt_map->value(YCPString("C_locale"))->isBoolean()) + { + default_locale = opt_map->value(YCPString("C_locale"))->asBoolean()->value(); + } + + // add environment variables + if( ! opt_map->value( YCPString("env")).isNull() && opt_map->value(YCPString("env"))->isMap()) + { + YCPMap envmt = opt_map->value(YCPString("env"))->asMap(); + + for(YCPMapIterator it = envmt.begin(); it != envmt.end(); it++) + { + YCPValue key = it.key(); + YCPValue val = it.value(); + + if (!key.isNull() && key->isString() && !val.isNull() && val->isString()) + { + env.insert(ExternalProgram::Environment::value_type( + key->asString()->value(), val->asString()->value()) + ); + } + else + { + y2error("Invalid pair in env map: $[ %s : %s ], map<string,string> is required", + key->toString().c_str(), val->toString().c_str()); + } + } + } + + if( ! opt_map->value( YCPString("args")).isNull() && opt_map->value(YCPString("args"))->isList()) + { + args = opt_map->value(YCPString("args"))->asList(); + } + } + else + { + if (!arg.isNull()) + { + y2error("Argument '%s' is not a map", arg->toString().c_str()); + return YCPNull(); + } + } + + Process *p; + + if (pth == "start_shell") + { + // start using shell + const char *argv[4]; + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = commandline.c_str(); + argv[3] = 0; + + p = new Process(argv, env, use_pty, default_locale); + } + else + { + int array_size = 1 + args->size(); + const char *argv[array_size + 1]; + + // store the path + argv[0] = commandline.c_str(); + + // store arguments + int index = 0; + for (; index < args->size(); index++) + { + if (args->value(index)->isString()) + { + argv[index + 1] = args->value(index)->asString()->value().c_str(); + } + } + + // terminate the array + argv[index + 1] = NULL; + + p = new Process(argv, env, use_pty, default_locale); + } + + // do not block reading + p->setBlocking(false); + + pid_t pid = p->getpid(); + + if (pid > 0) + { + // store the mapping PID->Process* + _processes.insert(ProcessContainer::value_type(pid, p)); + return YCPInteger(pid); + } + else + { + y2error("Program NOT started!"); + return YCPNull(); + } + } + else + { + y2error("Argument '%s' is not a string", value->toString().c_str()); + return YCPNull(); + } + } + else + { + if (value.isNull() || !value->isInteger()) + { + y2error("ID of the process is missing"); + return YCPNull(); + } + + pid_t id = value->asInteger()->value(); + + y2debug("Requested path: %s, id: %d", pth.c_str(), id); + + ProcessContainer::iterator proc(_processes.find(id)); + + if (proc == _processes.end()) + { + y2error("Process '%d' not found", id); + return YCPNull(); + } + + if (pth == "buffer") + { + /** + * @builtin Execute(.process.buffer, integer id) -> boolean + * Read stdout and stderr of the process to unblock it when there is full buffer and the process is stopped. + * This function (or .read and .read_stderr) should be called regularly to ensure that the process + * is not blocked and can run. + * + * @example Execute(.process.buffer, 12345) -> true + */ + y2milestone("Reading %d output to buffers...", id); + proc->second->readToBuffers(); + return YCPBoolean(true); + } + else if (pth == "kill") + { + /** + * @builtin Execute(.process.kill, integer id, integer signal) -> boolean + * Send a signal to the process, if signal is missing then SIGKILL is sent. + * + * @example Execute(.process.kill, 12345, 15) -> true // send SIGTERM + * @example Execute(.process.kill, 12345) -> true // send SIGKILL + */ + // check the value + if (!arg.isNull() && arg->isInteger()) + { + // send the requested signal + int sig = arg->asInteger()->value(); + + y2milestone("Sending signal %d to process %d...", sig, id); + return YCPBoolean(proc->second->kill(sig)); + } + else + { + // send SIGKILL + y2milestone("Sending SIGKILL to process %d...", id); + return YCPBoolean(proc->second->kill()); + } + } + else if (pth == "release") + { + /** + * @builtin Execute(.process.release, integer id) -> boolean + * Removes the process from the internal structure and releases all alocated resources (buffers). + * If the process is running then it is killed by SIGKILL at first. + * + * @example Execute(.process.release, 12345) -> true + */ + y2milestone("Releasing Process object %d...", id); + // relese the Process object + delete proc->second; + + // remove the entry + _processes.erase(proc); + return YCPBoolean(true); + } + else if (pth == "close") + { + /** + * @builtin Execute(.process.close, integer id) -> integer + * Close input/output of the process and wait until the process ends + * + * Returns Exit value of the process + * + * @example Execute(.process.close, 12345) -> 0 + */ + y2milestone("Closing output of %d...", id); + return YCPInteger(proc->second->closeAll()); + } + } + + y2error("Wrong path '%s' in Execute()", path->toString().c_str()); + return YCPNull(); +} + +/** + * otherCommand + */ +YCPValue ProcessAgent::otherCommand(const YCPTerm& term) +{ + std::string sym = term->name(); + + if (sym == "ProcessAgent") { + /* Your initialization */ + return YCPVoid(); + } + + return YCPVoid(); +} Added: trunk/core/agent-process/src/ProcessAgent.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/ProcessAgent.h?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/ProcessAgent.h (added) +++ trunk/core/agent-process/src/ProcessAgent.h Fri Feb 15 10:27:40 2008 @@ -0,0 +1,103 @@ +/* ProcessAgent.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. + * ------------------------------------------------------------------------------ + * + * An agent for managing multiple processes. + * + * Authors: Ladislav Slezák <lslezak@novell.com> + * + * $Id: ProcessAgent.h 27914 2006-02-13 14:32:08Z locilka $ + */ + +#ifndef _ProcessAgent_h +#define _ProcessAgent_h + +#include <Y2.h> +#include <scr/SCRAgent.h> + +#include <map> + +class Process; + +/** + * @short An interface class between YaST2 and Process Agent + */ +class ProcessAgent : public SCRAgent +{ +private: + /** + * Agent private variables + */ + + // typedef of internal data representation + typedef map<pid_t, Process*> ProcessContainer; + + ProcessContainer _processes; + +private: + + YCPValue ProcessOutput(std::string &output); + +public: + /** + * Default constructor. + */ + ProcessAgent(); + + /** + * Destructor. + */ + virtual ~ProcessAgent(); + + /** + * Provides SCR Read (). + * @param path Path that should be read. + * @param arg Additional parameter. + */ + virtual YCPValue Read(const YCPPath &path, + const YCPValue& arg = YCPNull(), + const YCPValue& opt = YCPNull()); + + /** + * Provides SCR Write (). + */ + virtual YCPBoolean Write(const YCPPath &path, + const YCPValue& value, + const YCPValue& arg = YCPNull()); + + /** + * Provides SCR Execute (). + */ + virtual YCPValue Execute(const YCPPath &path, + const YCPValue& value = YCPNull(), + const YCPValue& arg = YCPNull()); + + /** + * Provides SCR Dir (). + */ + virtual YCPList Dir(const YCPPath& path); + + /** + * Used for mounting the agent. + */ + virtual YCPValue otherCommand(const YCPTerm& term); +}; + +#endif /* _ProcessAgent_h */ Added: trunk/core/agent-process/src/Y2CCProcessAgent.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/src/Y2CCProcessAgent.cc?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/src/Y2CCProcessAgent.cc (added) +++ trunk/core/agent-process/src/Y2CCProcessAgent.cc Fri Feb 15 10:27:40 2008 @@ -0,0 +1,36 @@ +/* Y2CCProcessAgent.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. + * ------------------------------------------------------------------------------ + * + * Process agent implementation + * + * Authors: Ladislav Slezák <lslezak@novell.com> + * + * $Id: Y2CCProcessAgent.cc 27914 2006-02-13 14:32:08Z locilka $ + */ + +#include <scr/Y2AgentComponent.h> +#include <scr/Y2CCAgentComponent.h> + +#include "ProcessAgent.h" + +typedef Y2AgentComp <ProcessAgent> Y2ProcessAgentComp; + +Y2CCAgentComp <Y2ProcessAgentComp> g_y2ccag_process ("ag_process"); Added: trunk/core/agent-process/testsuite/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/Makefile.am (added) +++ trunk/core/agent-process/testsuite/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,23 @@ +# +# Makefile.am for core/agent-process/testsuite +# + +SUBDIRS = config lib ag_process.test tests + +CLEANFILES = $(wildcard tmp.out.* tmp.err.* tmp.write.* *.sum *.log) + +AM_CXXFLAGS = -DY2LOG=\"agent-process\" + +PACKAGE = ag_process +AUTOMAKE_OPTIONS = dejagnu + +INCLUDES = ${AGENT_INCLUDES} + +noinst_PROGRAMS = run_ag_process + +run_ag_process_SOURCES = run_ag_process.cc +run_ag_process_LDADD = ${AGENT_LIBADD} +run_ag_process_LDFLAGS = \ + -Xlinker --whole-archive \ + ../src/libpy2ag_process.la \ + -Xlinker --no-whole-archive Added: trunk/core/agent-process/testsuite/ag_process.test/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/ag_process.test/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/ag_process.test/Makefile.am (added) +++ trunk/core/agent-process/testsuite/ag_process.test/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,5 @@ +# +# Makefile.am for core/agent-system/testsuite/ag_system.test +# + +EXTRA_DIST = ag_process.exp Added: trunk/core/agent-process/testsuite/ag_process.test/ag_process.exp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/ag_process.test/ag_process.exp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/ag_process.test/ag_process.exp (added) +++ trunk/core/agent-process/testsuite/ag_process.test/ag_process.exp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,11 @@ +# +# ag_process.exp +# 'main' file for all ag_process tests +# + +# get all files matching tests/*.ycp +set filenames [glob $srcdir/tests/*.ycp] + +# foreach file, call ycp-run (from testsuite/lib) +foreach file $filenames { ycp-run $file } + Added: trunk/core/agent-process/testsuite/config/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/config/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/config/Makefile.am (added) +++ trunk/core/agent-process/testsuite/config/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,5 @@ +# +# Makefile.am for core/agent-system/testsuite/config +# + +EXTRA_DIST = default.exp unix.exp unknown.exp Added: trunk/core/agent-process/testsuite/config/default.exp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/config/default.exp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/config/default.exp (added) +++ trunk/core/agent-process/testsuite/config/default.exp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +# default.exp -- empty + Added: trunk/core/agent-process/testsuite/config/unix.exp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/config/unix.exp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/config/unix.exp (added) +++ trunk/core/agent-process/testsuite/config/unix.exp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,5 @@ +load_lib "ag_process_init.exp" + +proc ag_system_exit {} {} +proc ag_system_version {} {} + Added: trunk/core/agent-process/testsuite/config/unknown.exp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/config/unknown.exp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/config/unknown.exp (added) +++ trunk/core/agent-process/testsuite/config/unknown.exp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +perror "No setup for current configuration" +exit 1 Added: trunk/core/agent-process/testsuite/lib/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/lib/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/lib/Makefile.am (added) +++ trunk/core/agent-process/testsuite/lib/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,5 @@ +# +# Makefile.am for core/agent-system/testsuite/lib +# + +EXTRA_DIST = ag_system_init.exp Added: trunk/core/agent-process/testsuite/lib/ag_process_init.exp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/lib/ag_process_init.exp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/lib/ag_process_init.exp (added) +++ trunk/core/agent-process/testsuite/lib/ag_process_init.exp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,83 @@ +# +# 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 tmpout_name "tmp.out.$base_name" + set tmperr_name "tmp.err.$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 + } + + # check write + + if {[find . "tests/$base_name.write"] == "./tests/$base_name.write"} { + if {[diff "tests/$base_name.write" "tmp.write.$base_name"] != 1} { + fail "Wrong write for $base_name" + return -1 + } + } + + # ok, all is fine + + pass $base_name + + return 0 +} Added: trunk/core/agent-process/testsuite/run_ag_process.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/run_ag_process.cc?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/run_ag_process.cc (added) +++ trunk/core/agent-process/testsuite/run_ag_process.cc Fri Feb 15 10:27:40 2008 @@ -0,0 +1,17 @@ + + +/* + * Author: Ladislav Slezák <lslezak@novell.com> + */ + + +#include <scr/run_agent.h> + +#include "../src/ProcessAgent.h" + + +int +main (int argc, char *argv[]) +{ + run_agent <ProcessAgent> (argc, argv, true); +} Added: trunk/core/agent-process/testsuite/tests/C_locale.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/C_locale.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/C_locale.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/C_locale.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/C_locale.out (added) +++ trunk/core/agent-process/testsuite/tests/C_locale.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,4 @@ +(true) +(true) +(false) +(false) Added: trunk/core/agent-process/testsuite/tests/C_locale.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/C_locale.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/C_locale.ycp (added) +++ trunk/core/agent-process/testsuite/tests/C_locale.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,47 @@ + +// check setting an environment variable in both execution possibilities (direct and via shell) + +// set C locale +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/locale", $[ "C_locale" : true ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "LC_ALL=C"); +} + +// C locale option overrides the LC_ALL env variable +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/locale", $[ "C_locale" : true, "env" : $[ "LC_ALL" : "en_US" ] ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "LC_ALL=C"); +} + +// do not set C locale +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/locale", $[ "C_locale" : false ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "LC_ALL=C"); +} + +// do not set C locale +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/locale")); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "LC_ALL=C"); +} + Added: trunk/core/agent-process/testsuite/tests/Dir.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/Dir.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/Dir.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/Dir.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/Dir.out (added) +++ trunk/core/agent-process/testsuite/tests/Dir.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,3 @@ +([]) +(1) +([2, 1]) Added: trunk/core/agent-process/testsuite/tests/Dir.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/Dir.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/Dir.ycp (added) +++ trunk/core/agent-process/testsuite/tests/Dir.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,24 @@ +{ + return SCR::Dir(.); +} + +{ + // return only size of the result because the content is every time different + SCR::Execute(.start_shell, "exit 1"); + return size(SCR::Dir(.)); +} + +{ + integer i = (integer)(SCR::Execute(.start_shell, "exit 1")); + + // avoid killing the process in .release, wait until it is running + while(SCR::Read(.running, i) == true) sleep(20); + + integer size1 = size(SCR::Dir(.)); + SCR::Execute(.release, i); + integer size2 = size(SCR::Dir(.)); + + // return only sizes of the result because the content is every time different + return [ size1, size2 ]; +} + Added: trunk/core/agent-process/testsuite/tests/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/Makefile.am?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/Makefile.am (added) +++ trunk/core/agent-process/testsuite/tests/Makefile.am Fri Feb 15 10:27:40 2008 @@ -0,0 +1,6 @@ +# +# Makefile.am for core/agent-system/testsuite/tests +# + +EXTRA_DIST = *.ycp *.out *.err *.read *.write runtest.sh + Added: trunk/core/agent-process/testsuite/tests/env.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/env.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/env.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/env.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/env.out (added) +++ trunk/core/agent-process/testsuite/tests/env.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +(true) +(true) Added: trunk/core/agent-process/testsuite/tests/env.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/env.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/env.ycp (added) +++ trunk/core/agent-process/testsuite/tests/env.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,23 @@ + +// check setting an environment variable in both execution possibilities (direct and via shell) + +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/env", $[ "env" : $[ "FOOVAR" : "_FOO_"] ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "FOOVAR=_FOO_"); +} + +{ + integer id = (integer)(SCR::Execute(.start_shell, "/usr/bin/env", $[ "env" : $[ "FOOVAR" : "_FOO_"] ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return contains(splitstring(out, "\n"), "FOOVAR=_FOO_"); +} + Added: trunk/core/agent-process/testsuite/tests/invalid_paths.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_paths.err?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_paths.err (added) +++ trunk/core/agent-process/testsuite/tests/invalid_paths.err Fri Feb 15 10:27:40 2008 @@ -0,0 +1,6 @@ +[agent-process] ProcessAgent.cc(Dir):80 Wrong path '.non_existing_path' in Dir(). +[agent-process] ProcessAgent.cc(Read):107 ID of the process is missing +[agent-process] ProcessAgent.cc(Write):238 Unsupported path in Write(): .non_existing_path +[agent-process] ProcessAgent.cc(Execute):455 ID of the process is missing +[agent-process] ProcessAgent.cc(Read):119 Process '123' not found +[agent-process] ProcessAgent.cc(Write):256 Process '123' not found Added: trunk/core/agent-process/testsuite/tests/invalid_paths.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_paths.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_paths.out (added) +++ trunk/core/agent-process/testsuite/tests/invalid_paths.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,6 @@ +(nil) +(nil) +(nil) +(nil) +(nil) +(nil) Added: trunk/core/agent-process/testsuite/tests/invalid_paths.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_paths.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_paths.ycp (added) +++ trunk/core/agent-process/testsuite/tests/invalid_paths.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,30 @@ + +{ + // check a subpath - not supported, must log an error + return SCR::Dir(.non_existing_path); +} + +{ + // check a subpath - not supported, must log an error + return SCR::Read(.non_existing_path); +} + +{ + // check a subpath - not supported, must log an error + return SCR::Write(.non_existing_path, nil); +} + +{ + // check a subpath - not supported, must log an error + return SCR::Execute(.non_existing_path); +} + +{ + // not existing process + return SCR::Read(.read, 123); +} + +{ + // not existing process + return SCR::Write(., 123, ""); +} Added: trunk/core/agent-process/testsuite/tests/invalid_values.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_values.err?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_values.err (added) +++ trunk/core/agent-process/testsuite/tests/invalid_values.err Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +[agent-process] ProcessAgent.cc(Execute):343 tty option '"invalid"' is not a boolean value +[agent-process] ProcessAgent.cc(Execute):343 tty option '"invalid"' is not a boolean value Added: trunk/core/agent-process/testsuite/tests/invalid_values.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_values.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_values.out (added) +++ trunk/core/agent-process/testsuite/tests/invalid_values.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +(false) +(false) Added: trunk/core/agent-process/testsuite/tests/invalid_values.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/invalid_values.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/invalid_values.ycp (added) +++ trunk/core/agent-process/testsuite/tests/invalid_values.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,23 @@ + + +// "tty" is invalid - direct start +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/tty", $[ "tty" : "invalid" ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is invalid - start in a shell +{ + integer id = (integer)(SCR::Execute(.start_shell, "/usr/bin/tty", $[ "tty" : "invalid" ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} Added: trunk/core/agent-process/testsuite/tests/kill.ycp.disabled URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/kill.ycp.disabled?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/kill.ycp.disabled (added) +++ trunk/core/agent-process/testsuite/tests/kill.ycp.disabled Fri Feb 15 10:27:40 2008 @@ -0,0 +1,16 @@ + +// NOTE: the test is disabled because the output is different in each run +// so we cannot have any expected value for checking + +// check killing a process + +{ + string id = tostring(SCR::Execute(.start_shell, "cat")); + + // kill the process + SCR::Execute(.kill + id, 15); + while(SCR::Read(.running + id) == true) sleep(20); + + return true; +} + Added: trunk/core/agent-process/testsuite/tests/runtest.sh URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/runtest.sh?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/runtest.sh (added) +++ trunk/core/agent-process/testsuite/tests/runtest.sh Fri Feb 15 10:27:40 2008 @@ -0,0 +1,10 @@ +#!/bin/bash + +unset LANG +unset LC_ALL +unset Y2DEBUG +unset Y2DEBUGGER +export Y2DEBUGSHELL=1 + +# ignore also milestones (they are not constant and logged by liby2util - cannot be simply turned off) +(./run_ag_process -l - $1 >$2) 2>&1 | fgrep -v -e " <0> " -e " <1> " | grep -v "^$" | sed 's/^....-..-.. ..:..:.. [^)]*) //g' > $3 Added: trunk/core/agent-process/testsuite/tests/status.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/status.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/status.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/status.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/status.out (added) +++ trunk/core/agent-process/testsuite/tests/status.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,4 @@ +(0) +(1) +(255) +(nil) Added: trunk/core/agent-process/testsuite/tests/status.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/status.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/status.ycp (added) +++ trunk/core/agent-process/testsuite/tests/status.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,40 @@ +// check an exit value + +// exit 0 +{ + integer id = (integer)(SCR::Execute(.start_shell, "exit 0")); + + while(SCR::Read(.running, id) == true) sleep(20); + + return SCR::Read(.status, id); +} + +// exit 1 +{ + integer id = (integer)(SCR::Execute(.start_shell, "exit 1")); + + while(SCR::Read(.running, id) == true) sleep(20); + + return SCR::Read(.status, id); +} + +// exit -1 +{ + integer id = (integer)(SCR::Execute(.start_shell, "exit -1")); + + while(SCR::Read(.running, id) == true) sleep(20); + + return SCR::Read(.status, id); +} + +// no exit value +{ + integer id = (integer)(SCR::Execute(.start_shell, "cat")); + integer status = (integer)SCR::Read(.status, id); + + // close the communication channel + SCR::Execute(.close, id); + while(SCR::Read(.running, id) == true) sleep(20); + + return status; +} Added: trunk/core/agent-process/testsuite/tests/stderr.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stderr.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/stderr.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stderr.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/stderr.out (added) +++ trunk/core/agent-process/testsuite/tests/stderr.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +([nil, "foo\n", "foo2\nfoo2\n", nil]) +([nil, "foo", "foo2", "foo2", nil]) Added: trunk/core/agent-process/testsuite/tests/stderr.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stderr.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/stderr.ycp (added) +++ trunk/core/agent-process/testsuite/tests/stderr.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,59 @@ + +// check reading from stderr +{ + // redirect stdout to stderr + integer id = (integer)(SCR::Execute(.start_shell, "cat 1>&2")); + + // no output + string out1 = (string)SCR::Read(.read_stderr, id); + + SCR::Write(., id, "foo\n"); + sleep(50); + // read "foo\n" + string out2 = (string)SCR::Read(.read_stderr, id); + + SCR::Write(., id, "foo2\nfoo2\n"); + sleep(50); + // read "foo2\nfoo2\n" + string out3 = (string)SCR::Read(.read_stderr, id); + + // no output + string out4 = (string)SCR::Read(.read_stderr, id); + + // close the communication channel + SCR::Execute(.close, id); + while(SCR::Read(.running, id) == true) sleep(20); + + return [ out1, out2, out3, out4 ]; +} + +{ + // redirect stdout to stderr + integer id = (integer)(SCR::Execute(.start_shell, "cat 1>&2")); + + // no output + string out1 = (string)SCR::Read(.read_line_stderr, id); + + SCR::Write(., id, "foo\n"); + sleep(50); + // read "foo\n" + string out2 = (string)SCR::Read(.read_line_stderr, id); + + SCR::Write(., id, "foo2\nfoo2\n"); + sleep(50); + // read "foo2\n" + string out3 = (string)SCR::Read(.read_line_stderr, id); + + // read "foo2\n" + string out4 = (string)SCR::Read(.read_line_stderr, id); + + // no output + string out5 = (string)SCR::Read(.read_line_stderr, id); + + + // close the communication channel + SCR::Execute(.close, id); + while(SCR::Read(.running, id) == true) sleep(20); + + return [ out1, out2, out3, out4, out5 ]; +} Added: trunk/core/agent-process/testsuite/tests/stdout.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stdout.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/stdout.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stdout.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/stdout.out (added) +++ trunk/core/agent-process/testsuite/tests/stdout.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,2 @@ +([nil, "foo\n", "foo2\nfoo2\n", nil]) +([nil, "foo", "foo2", "foo2", nil]) Added: trunk/core/agent-process/testsuite/tests/stdout.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/stdout.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/stdout.ycp (added) +++ trunk/core/agent-process/testsuite/tests/stdout.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,58 @@ + +// check setting an environment variable in both execution possibilities (direct and via shell) + +{ + integer id = (integer)(SCR::Execute(.start_shell, "cat")); + + // no output + string out1 = (string)SCR::Read(.read, id); + + SCR::Write(., id, "foo\n"); + sleep(50); + // read "foo\n" + string out2 = (string)SCR::Read(.read, id); + + SCR::Write(., id, "foo2\nfoo2\n"); + sleep(50); + // read "foo2\nfoo2\n" + string out3 = (string)SCR::Read(.read, id); + + // no output + string out4 = (string)SCR::Read(.read, id); + + // close the communication channel + SCR::Execute(.close, id); + while(SCR::Read(.running, id) == true) sleep(20); + + return [ out1, out2, out3, out4 ]; +} + +{ + integer id = (integer)(SCR::Execute(.start_shell, "cat")); + + // no output + string out1 = (string)SCR::Read(.read_line, id); + + SCR::Write(., id, "foo\n"); + sleep(50); + // read "foo\n" + string out2 = (string)SCR::Read(.read_line, id); + + SCR::Write(., id, "foo2\nfoo2\n"); + sleep(50); + // read "foo2\n" + string out3 = (string)SCR::Read(.read_line, id); + + // read "foo2\n" + string out4 = (string)SCR::Read(.read_line, id); + + // no output + string out5 = (string)SCR::Read(.read_line, id); + + + // close the communication channel + SCR::Execute(.close, id); + while(SCR::Read(.running, id) == true) sleep(20); + + return [ out1, out2, out3, out4, out5 ]; +} Added: trunk/core/agent-process/testsuite/tests/tty.err URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/tty.err?rev=44482&view=auto ============================================================================== (empty) Added: trunk/core/agent-process/testsuite/tests/tty.out URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/tty.out?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/tty.out (added) +++ trunk/core/agent-process/testsuite/tests/tty.out Fri Feb 15 10:27:40 2008 @@ -0,0 +1,6 @@ +(true) +(true) +(false) +(false) +(false) +(false) Added: trunk/core/agent-process/testsuite/tests/tty.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agent-process/testsuite/tests/tty.ycp?rev=44482&view=auto ============================================================================== --- trunk/core/agent-process/testsuite/tests/tty.ycp (added) +++ trunk/core/agent-process/testsuite/tests/tty.ycp Fri Feb 15 10:27:40 2008 @@ -0,0 +1,67 @@ +// check running in a teminal both execution possibilities (direct and via shell) + +// "tty" is true - direct start +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/tty", $[ "tty" : true ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is true - start in a shell +{ + integer id = (integer)(SCR::Execute(.start_shell, "/usr/bin/tty", $[ "tty" : true ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is false - direct start +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/tty", $[ "tty" : false ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is false - start in a shell +{ + integer id = (integer)(SCR::Execute(.start_shell, "/usr/bin/tty", $[ "tty" : false ])); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is missing - direct start +{ + integer id = (integer)(SCR::Execute(.start, "/usr/bin/tty")); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} + +// "tty" is missing - start in a shell +{ + integer id = (integer)(SCR::Execute(.start_shell, "/usr/bin/tty")); + + while(SCR::Read(.running, id) == true) sleep(20); + + string out = (string)SCR::Read(.read, id); + + return regexpmatch(out, "^/dev/pts/[0-9]*\r\n$"); +} Modified: trunk/core/agents-perl/ag_background URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/agents-perl/ag_background?rev=44482&r1=44481&r2=44482&view=diff ============================================================================== --- trunk/core/agents-perl/ag_background (original) +++ trunk/core/agents-perl/ag_background Fri Feb 15 10:27:40 2008 @@ -164,6 +164,8 @@ my ($command, $path, $arg) = ycp::ParseCommand($line); + y2warning('WARNING: .background agent is obsoleted, use .process agent instead!'); + if ($command eq 'Execute') { if ($path eq '.run' || $path eq '.run_output' || $path eq '.run_output_err') Modified: trunk/core/package/yast2-core.changes URL: http://svn.opensuse.org/viewcvs/yast/trunk/core/package/yast2-core.changes?rev=44482&r1=44481&r2=44482&view=diff ============================================================================== --- trunk/core/package/yast2-core.changes (original) +++ trunk/core/package/yast2-core.changes Fri Feb 15 10:27:40 2008 @@ -1,4 +1,11 @@ ------------------------------------------------------------------- +Fri Feb 15 10:01:29 CET 2008 - lslezak@suse.cz + +- added new .process (agent-process) agent (obsoletes old + .background agent) - handles multiple subprocess, complete I/O + communication, tty support + +------------------------------------------------------------------- Wed Feb 13 19:24:07 CET 2008 - sh@suse.de - Made new UI logging thread-safe -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org