ACC SHELL
/**
* Module:
* Misc
* File:
* Misc.ycp
* Purpose:
* miscellaneous definitions for installation
* Author: Klaus Kaempf <kkaempf@suse.de>
* $Id: Misc.ycp 56192 2009-03-17 19:32:08Z lslezak $
*/
{
module "Misc";
import "Mode";
/*
* Message after finishing installation and before the system
* boots for the first time.
*
*/
global string boot_msg = "";
/**
* @param first string name of first file to try
* @param second string name of second file to try
* @return any content of file
*
* try to read first file, if it doesn't exist, read second
* files must reside below /usr/lib/YaST2
* files must have ycp syntax
*/
global define any ReadAlternateFile ( string first, string second)
``{
any result = SCR::Read (.target.yast2, [first, nil]);
if (result == nil)
result = SCR::Read (.target.yast2, second);
return result;
}
/**
* @param hardware_entry map map of .probe entry
* @return string vendor and device name
*
* common function to extract 'name' of hardware
*/
global define string hardware_name (map hardware_entry)
``{
string sub_vendor = "";
string sub_device = "";
sub_vendor = hardware_entry["sub_vendor"]:"";
sub_device = hardware_entry["sub_device"]:"";
if ((sub_vendor != "") && (sub_device != ""))
{
return (sub_vendor + "\n" + sub_device);
}
else
{
string vendor = hardware_entry["vendor"]:"";
return (vendor
+ ((vendor != "") ? "\n" : "")
+ hardware_entry["device"]:"");
}
}
/**
* @param lmap map map of language codes and translations
* e.g. $[ "default" : "Defaultstring", "de" : "German....", ...]
* @param lang string language as ISO code, either 2 chars (de)
* or 5 chars (de_DE)
* @return string translation
*
* Define a macro that looks up a localized string in a language map
* of the form $[ "default" : "Defaultstring", "de" : "German....", ...]
*/
global define string translate(map lmap, string lang)
``{
string t = lmap[lang]:"";
if ((size (t) == 0)
&& size(lang) > 2)
{
t = lmap[substring(lang, 0, 2)]:"";
}
if (size (t) == 0)
{
t = lmap["default"]:"";
}
return t;
}
/**
* SysconfigWrite()
* @param path level path behind .sysconfig for all values
* @param list values list of [ .NAME, value] lists
*
* @returns boolean false if SCR::Write reported error
*
* write list of sysyconfig entries via rcconfig agent
*/
global define boolean SysconfigWrite (path level, list<list> values)
``{
boolean result = true;
if (level == .)
level = .sysconfig;
else
level = .sysconfig + level;
foreach (list entry, values,
``{
if (size (entry) != 2)
y2error ("bad entry in rc_write()");
else
{
if (!SCR::Write (level + entry[0]:., entry[1]:""))
result = false;
}
});
return result;
}
/**
* MergeOptions
* Merges "opt1=val1 opt2=val2 ..." and $["opta":"vala", ..."]
* to $["opt1":"val1", "opt2":"val2", "opta":"vala", ...]
* as needed by modules.conf agent
* @param options string module options, e.g. "opt1=val1 opt2=val2 ..."
* @param optmap map possible old options $["opta":"vala", ...]
* @returns map $["opt1":"val1", "opt2":"val2", ...]
*/
global define map SplitOptions (string options, map optmap)
``{
// step 1: split "opt1=val1 opt2=val2 ..."
// to ["opt1=val1", "opt2=val2", "..."]
list<string> options_split = splitstring (options, " ");
foreach (string options_element, options_split,
``{
list options_values = splitstring (options_element, "=");
if ((size (options_values) == 1)
&& (optmap[options_element]:"" == ""))
{
// single argument
optmap[options_element] = "";
}
else if (size (options_values) == 2)
{
// argument with value
optmap[options_values[0]:""] = options_values[1]:"";
}
});
return optmap;
}
/**
* SysconfigRead()
*
* Try an SCR::Read(...) and return the result if successful.
* On failure return the the second parameter (default value)
*
* @param sysconfig_path Sysconfig SCR path.
* @param defaultv Default value
*
* @return Success --> Result of SCR::Read<br>
* Failure --> Default value
*
*/
global define string SysconfigRead( path sysconfig_path, string defaultv )
``{
string local_ret = (string)SCR::Read( sysconfig_path );
if ( local_ret == nil )
{
y2warning("Failed reading '%1', using default value", sysconfig_path );
return( defaultv );
}
else
{
y2milestone("%1: '%2'", sysconfig_path, local_ret );
return( local_ret );
}
} // SysconfigRead()
/**
* Try to read value from sysconfig file and return the result if successful.
* Function reads from arbitrary sysconfig file, for which the agent
* doesn't exist: e.g. from different partition like /mnt/etc/sysconfig/file.
*
* @param key Key of the value we want to read from sysconfig file.
* @param defaultv Default value
* @param location Full path to target sysconfig file.
*
* @return Success --> Result of SCR::Read<br>
* Failure --> Default value
*
* @example Misc::CustomSysconfigRead ("INSTALLED_LANGUAGES", "", Installation::destdir + "/etc/sysconfig/language");
*
*/
global define string CustomSysconfigRead (string key, string defval,string location)
{
if (location == "")
return defval;
path custom_path = topath (location);
SCR::RegisterAgent (custom_path, `ag_ini(
`SysConfigFile (location)
));
string ret = SysconfigRead (add (custom_path, key), defval);
SCR::UnregisterAgent (custom_path);
return ret;
}
/**
* Runs a bash command with timeout.
* @struct Returns map $[
* "exit" : int_return_code,
* "stdout" : [ "script", "stdout", "lines" ],
* "stderr" : [ "script", "stderr", "lines" ],
* ]
*
* @param run_command what to run
* @param log_command what to log (passwords masked)
* @param script_time_out in sec.
* @return map with out, err and ret_code
*/
global map RunCommandWithTimeout (string run_command, string log_command, integer script_time_out) {
y2milestone("Running command \"%1\" in background...", log_command);
integer processID = (integer)SCR::Execute(.process.start_shell, run_command);
if (processID == 0) {
y2error("Cannot run '%1'", run_command);
return nil;
}
list<string> script_out = [];
list<string> script_err = [];
integer time_spent = 0;
integer return_code = nil;
boolean timed_out = false;
integer sleep_step = 200; // ms
script_time_out = script_time_out * 1000;
// while continuing is needed and while it is possible
while (! timed_out) {
boolean running = (boolean) SCR::Read(.process.running, processID);
// debugging #165821
if (time_spent % 100000 == 0) {
y2milestone ("running: %1", running);
string flag = "/tmp/SourceManagerTimeout";
if (SCR::Read (.target.size, flag) != -1) {
y2milestone ("Emergency exit");
SCR::Execute (.target.remove, flag);
break;
}
}
if (! running) {
break;
}
// at last, enable aborting the sync
if (Mode::commandline ()) {
sleep (sleep_step);
}
else {
any ui = UI::TimeoutUserInput (sleep_step);
if (ui == `abort) {
y2milestone ("aborted");
timed_out = true;
break;
}
}
// time-out
if (time_spent >= script_time_out) {
y2error("Command timed out after %1 msec", time_spent);
timed_out = true;
}
time_spent = time_spent + sleep_step;
}
y2milestone("Time spent: %1 msec", time_spent);
// fetching the return code if not timed-out
if (! timed_out) {
y2milestone ("getting output");
script_out = splitstring((string)SCR::Read(.process.read, processID), "\n");
y2milestone ("getting errors");
script_err = splitstring((string)SCR::Read(.process.read_stderr, processID), "\n");
y2milestone ("getting status");
return_code = (integer) SCR::Read(.process.status, processID);
}
y2milestone ("killing");
SCR::Execute(.process.kill, processID);
// release the process from the agent
SCR::Execute(.process.release, processID);
map command_ret = $[
"exit" : return_code,
"stdout" : script_out,
"stderr" : script_err,
];
if (timed_out)
command_ret["timed_out"] = time_spent;
return command_ret;
}
/**
* Run
* - with a timeout
* - on dumb terminal to disable colors etc
* - using 'exit $?' because of buggy behavior '.background vs. ZMD' (FIXME still needed???)
* @param command a command
* @param log_command a command to log
* @param seconds timeout
* @return map with out, err and ret_code
*/
global map RunDumbTimeout (string command, string log_command, integer seconds) {
string dumb_format = "export TERM=dumb; %1; exit $?";
string dumb_command = sformat (dumb_format, command);
string dumb_log_command = sformat (dumb_format, log_command);
// explicit export in case TERM was not in the environment
map ret = RunCommandWithTimeout (dumb_command, dumb_log_command, seconds);
if (ret == nil) ret = $[];
return ret;
}
}
ACC SHELL 2018