Hello community, here is the log from the commit of package yast2 for openSUSE:Factory checked in at Tue Sep 13 12:39:46 CEST 2011.
-------- --- yast2/yast2.changes 2011-09-08 11:37:35.000000000 +0200 +++ /mounts/work_src_done/STABLE/yast2/yast2.changes 2011-09-13 11:14:26.000000000 +0200 @@ -1,0 +2,19 @@ +Tue Sep 13 10:39:42 CEST 2011 - [email protected] + +- Fixed SuSEfirewall2 SCR agent to understand single-quoted and + double-quoted, single and multi-line variables and also + single-line variables without any quotes (bnc#716013). +- 2.21.19 + +------------------------------------------------------------------- +Fri Sep 9 15:56:48 CEST 2011 - [email protected] + +- Using ButtonBox in Wizard where possible (bnc#571939) + +------------------------------------------------------------------- +Thu Sep 8 16:13:26 UTC 2011 - [email protected] + +- adapted to systemd (bnc#664548) +- 2.21.18 + +------------------------------------------------------------------- calling whatdependson for head-i586 Old: ---- yast2-2.21.17.tar.bz2 New: ---- yast2-2.21.19.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2.spec ++++++ --- /var/tmp/diff_new_pack.wFe6Am/_old 2011-09-13 12:39:41.000000000 +0200 +++ /var/tmp/diff_new_pack.wFe6Am/_new 2011-09-13 12:39:41.000000000 +0200 @@ -19,11 +19,11 @@ Name: yast2 -Version: 2.21.17 +Version: 2.21.19 Release: 1 BuildRoot: %{_tmppath}/%{name}-%{version}-build -Source0: yast2-2.21.17.tar.bz2 +Source0: yast2-2.21.19.tar.bz2 Prefix: /usr @@ -130,7 +130,7 @@ installation with YaST2. %prep -%setup -n yast2-2.21.17 +%setup -n yast2-2.21.19 %build %{prefix}/bin/y2tool y2autoconf @@ -252,5 +252,4 @@ %doc %{prefix}/share/doc/packages/yast2/types %doc %{prefix}/share/doc/packages/yast2/wizard %doc %{prefix}/share/doc/packages/yast2/xml - %changelog ++++++ yast2-2.21.17.tar.bz2 -> yast2-2.21.19.tar.bz2 ++++++ ++++ 6586 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/VERSION new/yast2-2.21.19/VERSION --- old/yast2-2.21.17/VERSION 2011-09-08 11:23:53.000000000 +0200 +++ new/yast2-2.21.19/VERSION 2011-09-13 10:44:56.000000000 +0200 @@ -1 +1 @@ -2.21.17 +2.21.19 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/configure.in new/yast2-2.21.19/configure.in --- old/yast2-2.21.17/configure.in 2011-06-23 15:49:18.000000000 +0200 +++ new/yast2-2.21.19/configure.in 2011-09-13 11:04:20.000000000 +0200 @@ -3,7 +3,7 @@ dnl -- This file is generated by y2autoconf 2.18.11 - DO NOT EDIT! -- dnl (edit configure.in.in instead) -AC_INIT(yast2, 2.21.2, http://bugs.opensuse.org/, yast2) +AC_INIT(yast2, 2.21.19, http://bugs.opensuse.org/, yast2) dnl Check for presence of file 'RPMNAME' AC_CONFIG_SRCDIR([RPMNAME]) @@ -18,7 +18,7 @@ AM_INIT_AUTOMAKE(tar-ustar -Wno-portability) dnl Important YaST2 variables -VERSION="2.21.2" +VERSION="2.21.19" RPMNAME="yast2" MAINTAINER="Jiri Srain <[email protected]>" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/modules/Version.ycp new/yast2-2.21.19/library/modules/Version.ycp --- old/yast2-2.21.17/library/modules/Version.ycp 2011-09-08 11:34:32.000000000 +0200 +++ new/yast2-2.21.19/library/modules/Version.ycp 2011-09-13 11:04:28.000000000 +0200 @@ -20,7 +20,7 @@ /** * Version of the yast2 package */ -global string yast2 = "2.21.17"; +global string yast2 = "2.21.19"; /* EOF */ } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/network/agents/sysconfig_SuSEfirewall2.scr new/yast2-2.21.19/library/network/agents/sysconfig_SuSEfirewall2.scr --- old/yast2-2.21.17/library/network/agents/sysconfig_SuSEfirewall2.scr 2011-08-29 15:33:00.000000000 +0200 +++ new/yast2-2.21.19/library/network/agents/sysconfig_SuSEfirewall2.scr 2011-09-13 10:45:13.000000000 +0200 @@ -17,7 +17,7 @@ * // Don't forget to write nil to sync the settings! * Write(.sysconfig.SuSEfirewall2, nil) * - * $Id: sysconfig_SuSEfirewall2.scr 65400 2011-08-26 11:31:11Z locilka $ + * $Id: sysconfig_SuSEfirewall2.scr 65672 2011-09-13 08:45:12Z locilka $ * * Read/Sets the values defined in /etc/sysconfig/SuSEfirewall2 * in an easy manner. @@ -32,20 +32,19 @@ "options" : [ "line_can_continue", "global_values", "comments_last", "flat", ], "comments": [ "^[ \t]*#.*$", "#.*", "^[ \t]*$", ], "params" : [ + // single quotes $[ - // with quotes - "match" : [ "^[ \t]*([_a-zA-Z0-9]+)[ \t]*=[ \t]*\"(.*)\"[ \t]*$", "%s=\"%s\"" ], - // without quotes - "match" : [ "^[ \t]*([_a-zA-Z0-9]+)[ \t]*=[ \t]*([^\"]*)[ \t]*$", "%s=\"%s\"" ], + "match" : [ "^[ \t]*([a-zA-Z0-9_]+)=\"([^\"]*)\"", "%s=\"%s\"" ], + "multiline" : [ "^[ \t]*([^=]+)[ \t]*=[ \t]*\"([^\"]*)", "([^\"]*)\"" ], ], + // double (common) quotes $[ - "match" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*\"([^\"]*)\"", "%s=\"%s\"" ], - "multiline" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*\"([^\"]*)", "([^\"]*)\"", ], + "match" : [ "^[ \t]*([a-zA-Z0-9_]+)='([^']*)'", "%s='%s'" ], + "multiline" : [ "^[ \t]*([^=]+)[ \t]*=[ \t]*'([^']*)", "([^']*)'" ], ], - // also single quotes, bnc#327565 + // without any quotes $[ - "match" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*'([^']*)'", "%s=\"%s\"" ], - "multiline" : [ "([a-zA-Z0-9_]+)[ \t]*=[ \t]*'([^']*)", "([^\']*)'", ], + "match" : [ "^[ \t]*([a-zA-Z0-9_]+)=([^ \t\"']*)[ \t]*$", "%s=\"%s\"" ], ], ], ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/network/testsuite/tests/SuSEFirewall.ycp new/yast2-2.21.19/library/network/testsuite/tests/SuSEFirewall.ycp --- old/yast2-2.21.17/library/network/testsuite/tests/SuSEFirewall.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/network/testsuite/tests/SuSEFirewall.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -103,11 +103,15 @@ "tmpdir" : "/tmp", ], ]; - + map WRITE = $[ ]; - + map EXECUTE = $[ + "target" : $[ + "bash_output" : $[ "exit" : 0 ], + "bash" : 0 + ] ]; TESTSUITE_INIT([READ, WRITE, EXECUTE], nil); @@ -115,6 +119,9 @@ // Configuration must be read! SuSEFirewall::Read(); + // initialize to disabled, not running + SuSEFirewall::SetEnableService(false); + SuSEFirewall::SetStartService(false); DUMP("== SuSEfirewall2 service =="); TEST(``(SuSEFirewall::GetEnableService()), [READ, WRITE, EXECUTE], nil); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/src/Makefile.am new/yast2-2.21.19/library/runlevel/src/Makefile.am --- old/yast2-2.21.17/library/runlevel/src/Makefile.am 2011-09-08 11:00:16.000000000 +0200 +++ new/yast2-2.21.19/library/runlevel/src/Makefile.am 2011-09-09 14:30:46.000000000 +0200 @@ -9,4 +9,5 @@ EXTRA_DIST = $(agent_SCRIPTS) \ $(scrconf_DATA) $(module_DATA) +YCPCFLAGS = -M ../../types/src -M ../../modules include $(top_srcdir)/Makefile.am.common diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/src/Service.ycp new/yast2-2.21.19/library/runlevel/src/Service.ycp --- old/yast2-2.21.17/library/runlevel/src/Service.ycp 2010-02-25 09:03:43.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/src/Service.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -8,7 +8,7 @@ * Lukas Ocilka <[email protected]> * Flags: Stable * - * $Id: Service.ycp 58399 2009-08-20 13:39:06Z jsuchome $ + * $Id: Service.ycp 65637 2011-09-09 12:30:02Z lslezak $ * * Functions for service (init script) handling used by other modules. */ @@ -18,6 +18,8 @@ module "Service"; textdomain "base"; +import "FileUtils"; + /*** * Services Manipulation */ @@ -44,9 +46,17 @@ */ /** + * Program to invoke the service init scripts, or the systemd actions + */ +string invoker = "/sbin/service"; +/** * Script location */ string init_d = "/etc/init.d"; +/** + * Unit location for systemd + */ +string systemd_d = "/lib/systemd/system"; /** * After a function returns an error, this holds an error message, @@ -74,7 +84,13 @@ y2error(1, error_msg); return false; } - if(! (boolean) SCR::Read(.init.scripts.exists, name)) { + if (FileUtils::Exists(sformat("%1/%2", init_d,name))) { + return true; + } + else if (FileUtils::Exists(sformat("%1/%2.service", systemd_d,name))) { + return true; + } + else { // Error message. // %1 is a name of an init script in /etc/init.d, // eg. nfsserver @@ -82,7 +98,6 @@ y2milestone (1, error_msg); return false; } - return true; } /** @@ -111,7 +126,7 @@ */ global define integer Status (string name) { if(!checkExists (name)) return -1; - return (integer) SCR::Execute (.target.bash, sformat ("%2/%1 status", name, init_d), $["TERM":"raw"]); + return (integer) SCR::Execute (.target.bash, sformat ("%1 %2 status", invoker, name), $["TERM":"raw"]); } /** @@ -133,8 +148,8 @@ */ define boolean serviceDisable (string name, boolean force) { map ret = (map)SCR::Execute (.target.bash_output, - sformat ("/sbin/insserv -r%3 %2/%1", - name, init_d, force? "f": "")); + sformat ("/sbin/chkconfig -d%2 %1", + name, force? " -f": "")); if (0 != ret["exit"]:-1) { // Error message. @@ -166,9 +181,10 @@ return false; } map service = Info (name); + boolean is_enabled = size (service["start"]:[]) != 0; if ("disable" == action) { - if (size (service["start"]:[]) != 0) + if (is_enabled) { return serviceDisable (name, false); } @@ -176,7 +192,7 @@ } if (("default" == action) || ("enable" == action)) { - if ("enable" == action && size (service["start"]:[]) != 0) + if ("enable" == action && is_enabled) { // nothing to do return true; @@ -184,8 +200,8 @@ else { map ret = (map)SCR::Execute (.target.bash_output, - sformat ("/sbin/insserv -d %2/%1", - name, init_d)); + sformat ("/sbin/chkconfig -a %1", + name)); if (0 != ret["exit"]:-1) { // Error message. @@ -225,9 +241,8 @@ // and calls us only once for each modified service. // In general we cannot do it with dependencies in a single pass. - string rls = mergestring ((list<string>)rl, ","); - // we must remove it first because insserv start=... adds - // runlevels, not replace runlevels!! + string rls = mergestring ((list<string>)rl, ""); + // we must remove all runlevels and then add the selected if (! serviceDisable (name, true)) { y2error ("Cannot disable %1", name); @@ -237,7 +252,7 @@ // script has already been completely disabled // enable in required runlevels if needed if (rls != "") { - string command = sformat ("/sbin/insserv -f %2/%1,start=%3", name, init_d, rls); + string command = sformat ("/sbin/chkconfig -s -f %1 %2", name, rls); y2milestone ("Calling %1", command); map ret = (map)SCR::Execute (.target.bash_output, command); @@ -250,7 +265,7 @@ // %2 is the stderr output of insserv(8) // %3 is a comma separated list of runlevels error_msg = sformat(_("Unable to enable service %1 in runlevels %2:\n%3"), - name, rls, ret["stderr"]:""); + name, rl, ret["stderr"]:""); y2error (1, error_msg); return false; } @@ -262,19 +277,16 @@ } /** - * Check if service is enabled + * Check if service is enabled (in any runlevel) * - * Returns true if any link in /etc/init.d/rc?.d/ exists for this - * script. If service does not exist, logs an error. + * Forwards to chkconfig -l which decides between init and systemd * * @param name service name * @return true if service is set to run in any runlevel */ global define boolean Enabled (string name) { if(!checkExists (name)) return false; - map<string, any> details = (map<string, any>) SCR::Read (.init.scripts.runlevel, name); - map<string, any> detail = (map<string, any>) details[name]:$[]; - return size(detail["start"]:[]) != 0; + return 0 == SCR::Execute (.target.bash, sformat ("/sbin/chkconfig -l %1 | /usr/bin/grep -q '[0-6]:on'", name)); } /** @@ -285,7 +297,7 @@ */ global define integer RunInitScript (string name, string param) { y2milestone("Running service initscript %1 %2", name, param); - string command = sformat ("%2/%1 %3", name, init_d, param); + string command = sformat ("%1 %2 %3", invoker, name, param); map<string, any> output=(map<string, any>)SCR::Execute (.target.bash_output, command, $[ "TERM" : "raw"]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/src/Systemd.ycp new/yast2-2.21.19/library/runlevel/src/Systemd.ycp --- old/yast2-2.21.17/library/runlevel/src/Systemd.ycp 2011-09-08 11:00:16.000000000 +0200 +++ new/yast2-2.21.19/library/runlevel/src/Systemd.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -14,6 +14,7 @@ module "Systemd"; const string systemd_path = "/bin/systemd"; +const string default_symlink = "/etc/systemd/system/default.target"; textdomain "base"; @@ -40,6 +41,12 @@ string init_cmdline = (string)SCR::Read(.target.string, cmdline_path); y2milestone("Current init program: %1", init_cmdline); + if (init_cmdline == nil) + { + y2error("Cannot check systemd status"); + return nil; + } + boolean ret = substring(init_cmdline, 0, size(systemd_path)) == systemd_path; y2milestone("Systemd detected: %1", ret); @@ -53,8 +60,6 @@ */ global boolean SetDefaultRunlevel(integer runlevel) { - const string default_symlink = "/etc/systemd/system/default.target"; - if (runlevel == nil || runlevel < 0 || runlevel > 6) { y2error("Invalid default runlevel (must be in range 0..6): %1", runlevel); @@ -76,6 +81,57 @@ return ret; } +/** + * Get the default runlevel for systemd + * @return integer the default runlevel (or nil on error or unknown runlevel) + */ +global integer DefaultRunlevel() +{ + string target = (string)SCR::Read(.target.symlink, default_symlink); + y2milestone("Default symlink points to: %1", target); + + if (target == nil) + { + y2error("Cannot read symlink target of %1", default_symlink); + return nil; + } + + // check runlevel<number>.target + string runlevel = regexpsub(target, "/runlevel([0-6]).target$", "\\1"); + if (runlevel != nil) + { + integer ret = tointeger(runlevel); + y2milestone("Default runlevel: %1", ret); + + return ret; + } + + // check runlevel specified by a symbolic name + // (this is written in systemd documentation how to change the default, + // YaST should also support this style in case users do a manual change) + string runlevel_name = regexpsub(target, "/([^/]*).target$", "\\1"); + if (runlevel_name != nil) + { + y2milestone("Detected default runlevel name: %1", runlevel_name); + map<string, integer> mapping = $[ + "poweroff" : 0, + "rescue" : 1, + // this is ambiguous, runlevels 2 and 4 also point to multi-user + // assume runlevel 3 in this case (the most probable) + "multi-user": 3, + "graphical" : 5, + "reboot" : 6 + ]; + + integer ret = mapping[runlevel_name]:nil; + y2milestone("Default runlevel: %1", ret); + + return ret; + } + + y2error("Cannot determine the default runlevel"); + return nil; +} } /* EOF */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/RunInitScript.out new/yast2-2.21.19/library/runlevel/testsuite/tests/RunInitScript.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/RunInitScript.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/RunInitScript.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,2 +1,3 @@ -Execute .target.bash_output "/etc/init.d/aaa start" $["TERM":"raw"] $["exit":0] +Read .target.tmpdir "/tmp" +Execute .target.bash_output "/sbin/service aaa start" $["TERM":"raw"] $["exit":0] Return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/RunInitScript.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/RunInitScript.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/RunInitScript.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/RunInitScript.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,5 +1,8 @@ { include "testsuite.ycp"; + + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + import "Service"; TEST (``(Service::RunInitScript ("aaa", "start")), [$[], $[], $[ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceAdjust.out new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceAdjust.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceAdjust.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceAdjust.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,37 +1,39 @@ -Read .init.scripts.exists "aaa" false +Read .target.tmpdir "/tmp" +Read .target.stat "/etc/init.d/aaa" $[] +Read .target.stat "/lib/systemd/system/aaa.service" $[] Log Service aaa does not exist. Return false -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["0", "1", "3"], "stop":["4", "5", "6"]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] -Execute .target.bash_output "/sbin/insserv -r /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] +Execute .target.bash_output "/sbin/chkconfig -d aaa" $["exit":0, "stderr":"", "stdout":""] Return true -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":[], "stop":[]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] Return true -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":[], "stop":[]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] -Execute .target.bash_output "/sbin/insserv -d /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] +Execute .target.bash_output "/sbin/chkconfig -a aaa" $["exit":0, "stderr":"", "stdout":""] Return true -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["1"], "stop":[]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] Return true -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["1"], "stop":[]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] -Execute .target.bash_output "/sbin/insserv -d /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] +Execute .target.bash_output "/sbin/chkconfig -a aaa" $["exit":0, "stderr":"", "stdout":""] Return true -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["0", "1", "3"], "stop":[]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] -Execute .target.bash_output "/sbin/insserv -d /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] +Execute .target.bash_output "/sbin/chkconfig -a aaa" $["exit":0, "stderr":"", "stdout":""] Return true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceAdjust.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceAdjust.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceAdjust.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceAdjust.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,5 +1,8 @@ { include "testsuite.ycp"; + + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + import "Service"; map READ = $[]; @@ -25,7 +28,11 @@ ] ], "exists" : false, - ] ] ]; + ] ], + "target" : $[ + "stat" : $[] + ] + ]; TEST (``(Service::Adjust ("aaa", "disable")), [ READ, $[], EXEC ], nil); // service exists and may run @@ -43,7 +50,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "disable")), [ READ, $[], EXEC ], nil); // service exists and does not run @@ -61,7 +72,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "disable")), [ READ, $[], EXEC ], nil); // service exists and does not run @@ -79,7 +94,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "enable")), [ READ, $[], EXEC ], nil); READ = $[ "init" : $[ "scripts" : $[ @@ -96,7 +115,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "enable")), [ READ, $[], EXEC ], nil); READ = $[ "init" : $[ "scripts" : $[ @@ -113,7 +136,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "default")), [ READ, $[], EXEC ], nil); READ = $[ "init" : $[ "scripts" : $[ @@ -130,7 +157,11 @@ ] ], "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Adjust ("aaa", "default")), [ READ, $[], EXEC ], nil); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFinetune.out new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFinetune.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFinetune.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFinetune.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,7 +1,8 @@ -Read .init.scripts.exists "aaa" true -Execute .target.bash_output "/sbin/insserv -rf /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] -Execute .target.bash_output "/sbin/insserv -f /etc/init.d/aaa,start=A,B,C" $["exit":0, "stderr":"", "stdout":""] +Read .target.tmpdir "/tmp" +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Execute .target.bash_output "/sbin/chkconfig -d -f aaa" $["exit":0, "stderr":"", "stdout":""] +Execute .target.bash_output "/sbin/chkconfig -s -f aaa 135" $["exit":0, "stderr":"", "stdout":""] Return true -Read .init.scripts.exists "aaa" true -Execute .target.bash_output "/sbin/insserv -rf /etc/init.d/aaa" $["exit":0, "stderr":"", "stdout":""] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Execute .target.bash_output "/sbin/chkconfig -d -f aaa" $["exit":0, "stderr":"", "stdout":""] Return true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFinetune.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFinetune.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFinetune.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFinetune.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,5 +1,8 @@ { include "testsuite.ycp"; + + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + import "Service"; map READ = $[]; @@ -11,12 +14,20 @@ ]; READ = $[ "init" : $[ "scripts" : $[ - "exists" : true, - ] ] ]; - TEST (``(Service::Finetune ("aaa", ["A", "B", "C"])), [ READ, $[], EXEC ], nil); + "exists" : true + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; + TEST (``(Service::Finetune ("aaa", ["1", "3", "5"])), [ READ, $[], EXEC ], nil); READ = $[ "init" : $[ "scripts" : $[ "exists" : true, - ] ] ]; + ] ], + "target" : $[ + "stat" : $["isreg": true] + ] + ]; TEST (``(Service::Finetune ("aaa", [])), [ READ, $[], EXEC ], nil); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFullInfo.out new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFullInfo.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFullInfo.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFullInfo.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,7 +1,8 @@ -Read .init.scripts.exists "aaa" true -Read .init.scripts.exists "aaa" true +Read .target.tmpdir "/tmp" +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["0", "1", "3"], "stop":["4", "5", "6"]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] -Read .init.scripts.exists "aaa" true -Execute .target.bash "/etc/init.d/aaa status" $["TERM":"raw"] 3 +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Execute .target.bash "/sbin/service aaa status" $["TERM":"raw"] 3 Return $["defstart":["0", "1", "3"], "defstop":["4", "5", "6"], "start":["0", "1", "3"], "started":3, "stop":["4", "5", "6"]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFullInfo.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFullInfo.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceFullInfo.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceFullInfo.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,6 +1,9 @@ { include "testsuite.ycp"; + + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + import "Service"; map READ = $[]; @@ -24,7 +27,10 @@ ], "exists" : true, ] - ] + ], + "target" : $[ + "stat" : $["isreg": true] + ] ]; TEST (``(Service::FullInfo ("aaa")), [ READ, $[], EXEC ], nil); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceInfo.out new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceInfo.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceInfo.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceInfo.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,4 +1,5 @@ -Read .init.scripts.exists "aaa" true +Read .target.tmpdir "/tmp" +Read .target.stat "/etc/init.d/aaa" $["isreg":true] Read .init.scripts.runlevel "aaa" $["aaa":$["start":["0", "1", "3"], "stop":["4", "5", "6"]]] Read .init.scripts.comment "aaa" $["aaa":$["defstart":["0", "1", "3"], "defstop":["4", "5", "6"]]] Return $["defstart":["0", "1", "3"], "defstop":["4", "5", "6"], "start":["0", "1", "3"], "stop":["4", "5", "6"]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceInfo.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceInfo.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceInfo.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceInfo.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,6 +1,9 @@ { include "testsuite.ycp"; + + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + import "Service"; map READ = $[]; @@ -22,7 +25,10 @@ ], "exists" : true, ] - ] + ], + "target" : $[ + "stat" : $["isreg": true] + ] ]; TEST (``(Service::Info ("aaa")), [ READ, $[], $[] ], nil); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceStatus.out new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceStatus.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceStatus.out 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceStatus.out 2011-09-09 14:30:46.000000000 +0200 @@ -1,3 +1,4 @@ -Read .init.scripts.exists "aaa" true -Execute .target.bash "/etc/init.d/aaa status" $["TERM":"raw"] 3 +Read .target.tmpdir "/tmp" +Read .target.stat "/etc/init.d/aaa" $["isreg":true] +Execute .target.bash "/sbin/service aaa status" $["TERM":"raw"] 3 Return 3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceStatus.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceStatus.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/ServiceStatus.ycp 2008-12-18 14:46:52.000000000 +0100 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/ServiceStatus.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -1,13 +1,13 @@ { include "testsuite.ycp"; - import "Service"; - map READ = $[]; - map EXEC = $[]; + TESTSUITE_INIT ([$[ "target" : $[ "tmpdir": "/tmp" ] ], $[], $[]], nil); + + import "Service"; - READ = $[ "init" : $[ "scripts" : $[ "exists" : true, ] ] ]; - EXEC = $[ "target" : $[ "bash" : 3 ] ]; + map READ = $[ "target" : $[ "stat" : $["isreg": true] ] ]; + map EXEC = $[ "target" : $[ "bash" : 3 ] ]; TEST (``(Service::Status ("aaa")), [ READ, $[], EXEC ], nil); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/Systemd.out new/yast2-2.21.19/library/runlevel/testsuite/tests/Systemd.out --- old/yast2-2.21.17/library/runlevel/testsuite/tests/Systemd.out 2011-09-08 11:00:16.000000000 +0200 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/Systemd.out 2011-09-09 14:30:46.000000000 +0200 @@ -16,3 +16,13 @@ Return true Execute .target.bash "/bin/ln -s -f /lib/systemd/system/runlevel5.target /etc/systemd/system/default.target" 1 Return false +Dump Systemd::DefaultRunlevel() tests +Read .target.symlink "/etc/systemd/system/default.target" nil +Log Cannot read symlink target of /etc/systemd/system/default.target +Return nil +Read .target.symlink "/etc/systemd/system/default.target" "/lib/systemd/system/runlevel3.target" +Return 3 +Read .target.symlink "/etc/systemd/system/default.target" "/lib/systemd/system/graphical.target" +Return 5 +Read .target.symlink "/etc/systemd/system/default.target" "/lib/systemd/system/unknown_default.target" +Return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/runlevel/testsuite/tests/Systemd.ycp new/yast2-2.21.19/library/runlevel/testsuite/tests/Systemd.ycp --- old/yast2-2.21.17/library/runlevel/testsuite/tests/Systemd.ycp 2011-09-08 11:00:16.000000000 +0200 +++ new/yast2-2.21.19/library/runlevel/testsuite/tests/Systemd.ycp 2011-09-09 14:30:46.000000000 +0200 @@ -45,4 +45,19 @@ TEST (``(Systemd::SetDefaultRunlevel(5)), [$[], $[], $[ "target" : $[ "bash" : 1 ] ]], nil); + + + DUMP("Systemd::DefaultRunlevel() tests"); + + // test missing / invalid (not a symlink) default + TEST (``(Systemd::DefaultRunlevel()), [$[ "target" : $[ "symlink" : nil]], $[], $[]], nil); + + // test numeric runlevel + TEST (``(Systemd::DefaultRunlevel()), [$[ "target" : $[ "symlink" : "/lib/systemd/system/runlevel3.target"]], $[], $[]], nil); + + // test symbolic runlevel + TEST (``(Systemd::DefaultRunlevel()), [$[ "target" : $[ "symlink" : "/lib/systemd/system/graphical.target"]], $[], $[]], nil); + + // test unknown symbolic runlevel + TEST (``(Systemd::DefaultRunlevel()), [$[ "target" : $[ "symlink" : "/lib/systemd/system/unknown_default.target"]], $[], $[]], nil); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/yast2-2.21.17/library/wizard/src/Wizard.ycp new/yast2-2.21.19/library/wizard/src/Wizard.ycp --- old/yast2-2.21.17/library/wizard/src/Wizard.ycp 2010-01-07 15:30:29.000000000 +0100 +++ new/yast2-2.21.19/library/wizard/src/Wizard.ycp 2011-09-09 15:46:11.000000000 +0200 @@ -106,14 +106,10 @@ **/ global term CancelAcceptButtonBox() { - return `HBox( - `HWeight(1, `Empty() ), // Layout trick to make sure the center button is centered - `HStretch(), - `HWeight(1, `ReplacePoint(`id(`rep_abort), // Make sure HideAbortButton() works (bnc #444176) - `PushButton(`id(`cancel ), `opt (`key_F9), Label::CancelButton() ) ) ), - `HStretch(), - `HWeight(1, `PushButton(`id(`accept ), `opt (`key_F10, `default), Label::AcceptButton() ) ) - ); + return `ButtonBox ( + `PushButton(`id(`cancel), `opt (`key_F9, `cancelButton), Label::CancelButton()), + `PushButton(`id(`accept), `opt (`key_F10, `default, `okButton), Label::AcceptButton()) + ); } @@ -123,14 +119,10 @@ **/ global term CancelOKButtonBox() { - return `HBox( - `HWeight(1, `Empty() ), // Layout trick to make sure the center button is centered - `HStretch(), - `HWeight(1, `ReplacePoint(`id(`rep_abort), // Make sure HideAbortButton() works (bnc #444176) - `PushButton(`id(`cancel ), `opt (`key_F9), Label::CancelButton() ) ) ), - `HStretch(), - `HWeight(1, `PushButton(`id(`ok ), `opt (`key_F10, `default), Label::OKButton() ) ) - ); + return `ButtonBox ( + `PushButton(`id(`cancel), `opt(`key_F9, `cancelButton), Label::CancelButton()), + `PushButton(`id(`ok), `opt(`key_F10, `default, `okButton), Label::OKButton()) + ); } @@ -157,13 +149,10 @@ **/ global term AbortInstallationAcceptButtonBox() { - return `HBox( - `HWeight(1, `Empty() ), // Layout trick to make sure the center button is centered - `HStretch(), - `PushButton(`id(`abort ), `opt (`key_F9), Label::AbortInstallationButton() ), - `HStretch(), - `HWeight(1, `PushButton(`id(`accept ), `opt (`key_F10, `default), Label::AcceptButton() ) ) - ); + return `ButtonBox ( + `PushButton(`id(`abort), `opt (`key_F9, `cancelButton), Label::AbortInstallationButton()), + `PushButton(`id(`accept), `opt (`key_F10, `okButton, `default), Label::AcceptButton()) + ); } @@ -951,6 +940,8 @@ { if ( UI::WidgetExists(`id(`rep_abort ) ) ) UI::ReplaceWidget(`id(`rep_abort ), `Empty() ); + else if ( UI::WidgetExists(`id(`cancel ) ) ) + UI::ReplaceWidget(`id(`cancel ), `Empty() ); } } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
