ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/AutoinstScripts.ycp

/**
 * File:	modules/AutoinstScripts.ycp
 * Module:	Auto-Installation
 * Summary:	Custom scripts
 * Authors:	Anas Nashif <nashif@suse.de>
 *
 * $Id: AutoinstScripts.ycp 61507 2010-03-26 09:44:13Z ug $
 */

{
    module "AutoinstScripts";
    textdomain "autoinst";

    import "Mode";
    import "AutoinstConfig";
    import "Summary";
    import "URL";
    import "Service";
    import "Popup";
    import "Label";
    import "Report";

    include "autoinstall/io.ycp";

    /* Pre scripts */
    global list<map> pre = [];

    /* Post scripts */
    global list<map> post = [];

    /* Chroot scripts */
    global list<map> chroot = [];

    /* Init scripts */
    global list<map> init = [];

    /* postpart scripts */
    global list<map> postpart = [];


    /* Merged scripts */
    global list<map> merged = [];

    /* default value of settings modified */
    global boolean modified = false;

    /**
     * Function sets internal variable, which indicates, that any
     * settings were modified, to "true"
     */
    global define void SetModified ()
    {
        modified = true;
    }

    /**
     * Functions which returns if the settings were modified
     * @return boolean  settings were modified
     */
    global define boolean GetModified ()
    {
        return modified;
    }


    /**
     * merge all types of scripts into one single list
     * @param -
     * @return merged list
     */
    list<map> mergeScripts ()
    {

        list<map> result = maplist (map p, pre,
                                 ``{
                                     p = add(p,"type","pre-scripts");
                                     return p;
                                 });
        result = (list<map>)union(result,	maplist (map p, post,
                                         ``{
                                             p = add(p,"type","post-scripts");
                                             return p;
                                         })
                       );
        result = (list<map>)union(result,	maplist (map p, chroot,
                                         ``{
                                             p = add(p,"type","chroot-scripts");
                                             return p;
                                         })
                       );
        result = (list<map>)union(result,	maplist (map p, init,
                                         ``{
                                             p = add(p,"type","init-scripts");
                                             return p;
                                         })
                       );
        result = (list<map>)union(result,	maplist (map p, postpart,
                                         ``{
                                             p = add(p,"type","postpartitioning-scripts");
                                             return p;
                                         })
                       );
        return result;
    }


    /**
     * Constructor
     */
    define void AutoinstScripts()
    {
        if ( !Mode::autoinst () )
        {
            merged = mergeScripts();
        }
    }


    /**
     * Dump the settings to a map, for autoinstallation use.
     * @return map
     */
    global define map<string, list> Export()
    {
        pre = [];
        post = [];
        chroot = [];
        init = [];
        postpart = [];
        y2milestone("Merged %1", merged);

        // split
        foreach(map s, merged, ``{
            if (s["type"]:"" == "pre-scripts")
                pre = add(pre,s);
            else if (s["type"]:"" == "post-scripts")
                post = add(post,s);
            else if (s["type"]:"" == "init-scripts")
                init = add(init,s);
            else if (s["type"]:"" == "chroot-scripts")
                chroot = add(chroot,s);
            else if (s["type"]:"" == "postpartitioning-scripts")
                postpart = add(postpart,s);
        });
        
        // clean
        list<map> expre =  maplist (map p, pre,  ``{
            return ($["filename":p["filename"]:"",
                      "interpreter": p["interpreter"]:"",
                      "source":p["source"]:"",
                      "notification":p["notification"]:"",
                      "location":p["location"]:"",
                      "feedback":p["feedback"]:false,
                      "feedback_type":p["feedback_type"]:"",
                      "debug":p["debug"]:true
                    ]);
        });
        list<map> expost =  maplist (map p, post, ``{
            return ($["filename":p["filename"]:"",
                      "interpreter": p["interpreter"]:"",
                      "source":p["source"]:"",
                      "location":p["location"]:"",
                      "notification":p["notification"]:"",
                      "feedback":p["feedback"]:false,
                      "feedback_type":p["feedback_type"]:"",
                      "debug":p["debug"]:true,
                      "network_needed":p["network_needed"]:false
                      ]
                    );
        });
        list<map> exchroot =  maplist (map p, chroot, ``{
            return ($["filename":p["filename"]:"",
                      "interpreter": p["interpreter"]:"",
                      "source":p["source"]:"",
                      "chrooted":p["chrooted"]:false,
                      "notification":p["notification"]:"",
                      "location":p["location"]:"",
                      "feedback":p["feedback"]:false,
                      "feedback_type":p["feedback_type"]:"",
                      "debug":p["debug"]:true
                    ]);
        });
        list<map> exinit =  maplist (map p, init, ``{
            return ($["filename":p["filename"]:"",
                      "source":p["source"]:"",
                      "location":p["location"]:"",
                      "debug":p["debug"]:true
                    ]);
        });
        list<map> expostpart =  maplist (map p, postpart, ``{
            return ($["filename":p["filename"]:"",
                      "interpreter": p["interpreter"]:"",
                      "source":p["source"]:"",
                      "location":p["location"]:"",
                      "notification":p["notification"]:"",
                      "feedback":p["feedback"]:false,
                      "feedback_type":p["feedback_type"]:"",
                      "debug":p["debug"]:true
                    ]);
        });

        map<string, list> result = $[];
        if (size(expre) > 0 )
            result["pre-scripts"] = expre;
        if (size(expost) > 0 )
            result["post-scripts"] = expost;
        if (size(exchroot) > 0 )
            result["chroot-scripts"] = exchroot;
        if (size(exinit) > 0 )
            result["init-scripts"] = exinit;
        if (size(expostpart) > 0 )
            result["postpartitioning-scripts"] = expostpart;

        return result;

    }

    global define list<map> Resolve_relurl( list<map> d ) {
        d = maplist (map script , d, ``{
            if( issubstring( script["location"]:"", "relurl://" ) ) {
                string l = script["location"]:"";
                l = substring ( l, 9 );
                string newloc = "";
                if( AutoinstConfig::scheme == "relurl" ) {
                    y2milestone("autoyast profile was relurl too");
                    newloc = (string)SCR::Read(.etc.install_inf.ayrelurl);
                    map tok = URL::Parse(newloc);
                    y2milestone("tok = %1", tok);
                    newloc = tok["scheme"]:"" + "://" + tok["host"]:"" + "/" + dirname(tok["path"]:"") + l;
                } else {
                    newloc = AutoinstConfig::scheme + "://" + AutoinstConfig::host + "/" + AutoinstConfig::directory + l;
                }
                script["location"] = newloc;
                y2milestone("changed relurl to %1 for script", newloc);
            }
            return script;
        });

        return d;
    }

    /**
     * Get all the configuration from a map.
     * When called by autoinst_<module name> (preparing autoinstallation data)
     * the map may be empty.
     * @param settings	$[...]
     * @return	success
     */
    global define boolean Import(map s)
    {
        y2debug("Calling AutoinstScripts::Import()");
        pre = s["pre-scripts"]:[];
        init = s["init-scripts"]:[];
        post = s["post-scripts"]:[];
        chroot = s["chroot-scripts"]:[];
        postpart = s["postpartitioning-scripts"]:[];

        pre = Resolve_relurl(pre);
        init = Resolve_relurl(init);
        post = Resolve_relurl(post);
        chroot = Resolve_relurl(chroot);
        postpart = Resolve_relurl(postpart);

        merged = mergeScripts();
        y2debug("merged: %1", merged);
        return true;
    }

    /**
     * Return Summary
     * @return string summary
     */
    global define string Summary()
    {
        string summary = "";
        summary = Summary::AddHeader(summary, _("Preinstallation Scripts"));
        if (size( pre) > 0 )
        {
            summary = Summary::OpenList(summary);
            foreach(map script, pre, ``{
                summary = Summary::AddListItem(summary, script["filename"]:"" );
            });
            summary = Summary::CloseList(summary);
        }
        else
        {
            summary = Summary::AddLine(summary, Summary::NotConfigured());
        }
        summary = Summary::AddHeader(summary, _("Postinstallation Scripts"));
        if (size( post) > 0)
        {
            summary = Summary::OpenList(summary);
            foreach(map script, post, ``{
                summary = Summary::AddListItem(summary, script["filename"]:"" );
            });
            summary = Summary::CloseList(summary);
        }
        else
        {
            summary = Summary::AddLine(summary, Summary::NotConfigured());
        }
        summary = Summary::AddHeader(summary, _("Chroot Scripts"));
        if (size( chroot) > 0 )
        {
            summary = Summary::OpenList(summary);
            foreach(map script, chroot, ``{
                summary = Summary::AddListItem(summary, script["filename"]:"" );
            });
            summary = Summary::CloseList(summary);
        }
        else
        {
            summary = Summary::AddLine(summary, Summary::NotConfigured());
        }
        summary = Summary::AddHeader(summary, _("Init Scripts"));
        if (size( init) > 0 )
        {
            summary = Summary::OpenList(summary);
            foreach(map script, init, ``{
                summary = Summary::AddListItem(summary, script["filename"]:"" );
            });
            summary = Summary::CloseList(summary);
        }
        else
        {
            summary = Summary::AddLine(summary, Summary::NotConfigured());
        }
        summary = Summary::AddHeader(summary, _("Postpartitioning Scripts"));
        if (size( postpart ) > 0 )
        {
            summary = Summary::OpenList(summary);
            foreach(map script, postpart, ``{
                summary = Summary::AddListItem(summary, script["filename"]:"" );
            });
            summary = Summary::CloseList(summary);
        }
        else
        {
            summary = Summary::AddLine(summary, Summary::NotConfigured());
        }
        return summary;
    }

    /**
     * delete a script from a list
     * @param script name
     * @return void
     */
    global define void  deleteScript(string scriptName)
    {
        list<map> clean = filter(map s, merged, ``(s["filename"]:"" != scriptName));
        merged = clean;
        return;
    }

    /**
     * Add or edit a script
     * @param scriptName script name
     * @param source source of script
     * @param interpreter interpreter to be used with script
     * @param type type of script
     * @return void
     */
    global define void AddEditScript(string scriptName,
            string source,
            string interpreter,
            string type,
            boolean chrooted,
            boolean debug,
            boolean feedback,
            boolean network,
            string feedback_type,
            string location,
            string notification
            )
    {
        boolean mod = false;
        merged = maplist (map script , merged, ``{
            // Edit
            if (script["filename"]:"" == scriptName)
            {
                map oldScript = $[];
                oldScript=add(oldScript,"filename", scriptName);
                oldScript=add(oldScript,"source", source);
                oldScript=add(oldScript,"interpreter", interpreter);
                oldScript=add(oldScript,"type", type);
                oldScript=add(oldScript,"chrooted", chrooted);
                oldScript=add(oldScript,"debug",debug);
                oldScript=add(oldScript,"feedback",feedback);
                oldScript=add(oldScript,"network_needed",network);
                oldScript=add(oldScript,"feedback_type", feedback_type);
                oldScript=add(oldScript,"location", location);
                oldScript=add(oldScript,"notification", notification);

                mod = true;
                return oldScript;
            }
            else {
                return script;
            }
        });

        if (!mod)
        {
            map script = $[];
            script=add(script,"filename", scriptName);
            script=add(script,"source", source);
            script=add(script,"interpreter", interpreter);
            script=add(script,"type", type);
            script=add(script,"chrooted", chrooted);
            script=add(script,"debug",debug);
            script=add(script,"feedback",feedback);
            script=add(script,"network_needed",network);
            script=add(script,"feedback_type", feedback_type);
            script=add(script,"location", location);
            script=add(script,"notification", notification);

            merged=add(merged,script);
        }
        y2debug("Merged scripts: %1", merged);
        return;
    }


    /**
     * return type of script as formatted string
     * @param script type
     * @return string type as translated string
     */
    global define string typeString(string type)
    {
        if (type == "pre-scripts")
        {
            return _("Pre");
        }
        else if (type == "post-scripts")
        {
            return _("Post");
        }
        else if (type == "init-scripts")
        {
            return _("Init");
        }
        else if (type == "chroot-scripts")
        {
            return _("Chroot");
        }
        else if (type == "postpartitioning-scripts")
        {
            return _("Postpartitioning");
        }
        return _("Unknown");
    }


/*
bidirectional feedback during script execution
Experimental
*/

    define map<string,string> splitParams( string s ) ``{
        list<string> l = splitstring( s, "|" );
        map<string,string> ret = $[];
        l = remove( l, 0 );
        foreach( string element, l, ``{
            list<string> p = splitstring( element, "=" );
            ret[ p[0]:"" ] = p[1]:"";
        });
        return ret;
    }

    define void interactiveScript( string shell, string debug, string scriptPath, string current_logdir, string scriptName ) ``{
        map data = $[];
        string widget = "";
        SCR::Execute(.target.remove, "/tmp/ay_opipe");
        SCR::Execute(.target.remove, "/tmp/ay_ipipe");
        SCR::Execute(.target.bash, "mkfifo -m 660 /tmp/ay_opipe", $[]);
        SCR::Execute(.target.bash, "mkfifo -m 660 /tmp/ay_ipipe", $[]);
        string execute = sformat("%1 %2 %3 2&> %4/%5.log ", shell, debug, scriptPath, current_logdir, scriptName);
        SCR::Execute(.target.bash_background, "OPIPE=/tmp/ay_opipe IPIPE=/tmp/ay_ipipe "+execute, $[]);
        boolean run = true;
        boolean ok_button = false;
        term vbox = `VBox();

        list<string> buffer = [];
        while( SCR::Read(.target.lstat, "/tmp/ay_opipe") != $[] && run ) {
            data = (map)SCR::Execute (.target.bash_output, "cat /tmp/ay_opipe", $[]);
            buffer = splitstring( data["stdout"]:"", "\n" );
            while( buffer != [] ) {
                string line = buffer[0]:"";
                buffer = remove( buffer, 0 );
                if( size(line) == 0 )
                    continue;
                data["stdout"] = line;
                y2milestone("working on line %1", line);
                if( substring( data["stdout"]:"", 0, 8 ) == "__EXIT__" ) {
                    if ( widget == "radiobutton" ) {
                        vbox = add( vbox, `PushButton(`id(`ok),  Label::OKButton() ) );
                        UI::OpenDialog( `RadioButtonGroup(`id(`rb), vbox) );
                    }
                    if( ok_button == true ) {
                        UI::ChangeWidget(`id(`ok) , `Enabled, true);
                        any ret = UI::UserInput();
                        if( widget == "radiobutton" ) {
                            any val = UI::QueryWidget(`id(`rb), `CurrentButton);
                            SCR::Execute (.target.bash, sformat("echo \"%1\" > /tmp/ay_ipipe", AutoinstConfig::ShellEscape((string)val) ), $[]);
                        } else if( widget == "entry" ) {
                            any val = UI::QueryWidget(`id(`ay_entry),  `Value);
                            SCR::Execute (.target.bash, sformat("echo \"%1\" > /tmp/ay_ipipe", AutoinstConfig::ShellEscape((string)(val)) ), $[]);
                        }
                        ok_button = false;
                    }
                    vbox = `VBox();
                    if( widget == "" )
                        run = false;
                    else
                        UI::CloseDialog();
                    widget = "";
                } else if( substring( data["stdout"]:"", 0, 12 ) == "__PROGRESS__" ) {
                    map<string,string> params = splitParams( data["stdout"]:"" );
                    UI::OpenDialog(
                        `VBox( `ProgressBar(`id(`pr), params["label"]:"", tointeger(params["max"]:"100"), 0 ) )
                    );
                    widget = "progressbar";
                } else if( substring( data["stdout"]:"", 0, 8 ) == "__TEXT__" ) {
                    map<string,string> params = splitParams( data["stdout"]:"" );
                    integer hspace = tointeger(params["width"]:"10");
                    integer vspace = tointeger(params["height"]:"20");
                    ok_button = haskey(params, "okbutton")?true:false;
                    vbox = `VBox( `HSpacing(hspace), `HBox( `VSpacing(vspace), `RichText( `id( `mle ), "" ) ) );
                    if( ok_button == true )
                        vbox = add( vbox, `PushButton(`id(`ok),  Label::OKButton() ) );
                    UI::OpenDialog( vbox );
                    if( ok_button == true )
                        UI::ChangeWidget(`id(`ok) , `Enabled, false);
                    widget = "text";
                } else if( substring( data["stdout"]:"", 0, 9 ) == "__ENTRY__" ) {
                    map<string,string> params = splitParams( data["stdout"]:"" );
                    if( haskey( params, "description" ) ) {
                        vbox = add( vbox, `HSpacing(40) );
                        vbox = add( vbox, `RichText( params["description"]:"" ) );
                    }
                    vbox = add( vbox, `TextEntry( `id(`ay_entry), params["label"]:"", params["default"]:"" ) );
                    vbox = add( vbox, `PushButton(`id(`ok),  Label::OKButton() ) );
                    UI::OpenDialog( vbox );
                    widget = "entry";
                    ok_button = true;
                } else if( substring( data["stdout"]:"", 0, 15 ) == "__RADIOBUTTON__" ) {
                    map<string,string> params = splitParams( data["stdout"]:"" );
                    if( haskey( params, "description" ) ) {
                        vbox = add( vbox, `HSpacing(60) );
                        vbox = add( vbox, `RichText( params["description"]:"" ) );
                    }
                    widget = "radiobutton";
                    ok_button = true;
                } else {
                    if( widget == "progressbar" ) {
                        UI::ChangeWidget(`id(`pr), `Value, tointeger(data["stdout"]:"0") );
                    } else if( widget == "text" ) {
                        UI::ChangeWidget(`id(`mle), `Value, (string)UI::QueryWidget(`id(`mle), `Value)+data["stdout"]:"" );
                    } else if( widget == "radiobutton" ) {
                        if( substring( data["stdout"]:"", 0, 10 ) == "__BUTTON__" ) {
                            map<string,string> params = splitParams( data["stdout"]:"" );
                            vbox = add( vbox, `Left(`RadioButton(`id(params["val"]:""), params["label"]:"")) );
                        } else {
                            y2milestone("*urgs* received '%1' instead of '__BUTTON__' during RADIOBUTTON creation",data["stdout"]:"");
                        }
                    }
                }
            };
        };
        SCR::Execute (.target.remove, "/tmp/ay_opipe");
        SCR::Execute (.target.remove, "/tmp/ay_ipipe");
    }


    /**
     * Execute pre scripts
     * @param string type of script
     * @param boolean if script should be executed in chroot env.
     * @return boolean true on success
     */
    global define boolean Write( string type , boolean special)
    {
        if (!Mode::autoinst ())
            return true;

        list<map> scripts = [];
        if (type == "pre-scripts")
        {
            scripts = pre;
        }
        else if (type == "init-scripts")
        {
            scripts = init;
        }
        else if ( type == "chroot-scripts" && !special)
        {
            scripts = filter(map s, chroot, ``(!s["chrooted"]:false));
        }
        else if ( type == "chroot-scripts" && special)
        {
            scripts = filter(map s, chroot, ``(s["chrooted"]:false));
        }
        else if (type == "post-scripts" && !special)
        {
            scripts = filter(map s, post, ``(!s["network_needed"]:false));
        }
        else if (type == "post-scripts" && special)
        {
            scripts = filter(map s, post, ``(s["network_needed"]:false));
        }
        else if (type == "postpartitioning-scripts" )
        {
            scripts = postpart;
        }
        else
        {
            y2error("Unsupported script type");
            return false;
        }


        string tmpdirString = "";
        string current_logdir = "";

        if (type == "pre-scripts" || type == "postpartitioning-scripts")
        {
            tmpdirString = sformat("%1/%2", AutoinstConfig::tmpDir, type);
            SCR::Execute (.target.mkdir, tmpdirString);

            current_logdir = sformat("%1/logs", tmpdirString);
            SCR::Execute (.target.mkdir,  current_logdir);
        }
        else if (type == "chroot-scripts")
        {
            if( !special ) {
                tmpdirString = sformat("%1%2", AutoinstConfig::destdir,  AutoinstConfig::scripts_dir);
                SCR::Execute (.target.mkdir, tmpdirString);

                current_logdir = sformat("%1%2", AutoinstConfig::destdir, AutoinstConfig::logs_dir);
                SCR::Execute (.target.mkdir, current_logdir);
            } else {
                tmpdirString = sformat("%1",  AutoinstConfig::scripts_dir);
                SCR::Execute (.target.mkdir, tmpdirString);

                current_logdir = sformat("%1", AutoinstConfig::logs_dir);
                SCR::Execute (.target.mkdir, current_logdir);
            }
        }
        else
        {
            current_logdir = AutoinstConfig::logs_dir;
        }


        foreach( map s, scripts,
                 ``{
            string scriptInterpreter	= s["interpreter"]:"shell";
            string scriptName = s["filename"]:"";
            if (scriptName=="")
            {
                map t = URL::Parse(s["location"]:"");
                scriptName=basename(t["path"]:"");
                if( scriptName == "" )
                    scriptName = type;
            }
            string scriptPath = "";

            if ( type == "pre-scripts" || type == "postpartitioning-scripts" )
            {
//        y2milestone("doing /sbin/udevcontrol stop_exec_queue now to prevent trouble if one is doing partitioning in a pre-script");
//        SCR::Execute( .target.bash, "/sbin/udevcontrol stop_exec_queue" );
                scriptPath = sformat("%1/%2/%3", AutoinstConfig::tmpDir, type, scriptName);
                y2milestone("Writing %1 script into %2", type, scriptPath);
                if (s["location"]:"" != "")
                {
                    y2debug("getting script: %1", s["location"]:"" );
                    if (!GetURL(s["location"]:"", scriptPath ) )
                    {
                       y2error("script %1 could not be retrieved", s["location"]:"");
                    }
                } else {
                    SCR::Write(.target.string,  scriptPath, s["source"]:"echo Empty script!");
                }
            }
            else if (type == "init-scripts")
            {
                scriptPath = sformat("%1/%2",  AutoinstConfig::initscripts_dir,  scriptName);
                y2milestone("Writing init script into %1", scriptPath);
                if (s["location"]:""!="")
                {
                    y2debug("getting script: %1", s["location"]:"" );
                    if (!GetURL(s["location"]:"", scriptPath ) )
                    {
                       y2error("script %1 could not be retrieved", s["location"]:"");
                    }
                } else {
                    SCR::Write(.target.string,  scriptPath, s["source"]:"echo Empty script!");
                }
                Service::Enable("autoyast");
            }
            else if (type == "chroot-scripts")
            {
                //scriptPath = sformat("%1%2/%3", (special) ? "" : AutoinstConfig::destdir,  AutoinstConfig::scripts_dir,  scriptName);

                map toks = URL::Parse(s["location"]:"");
                if( toks["scheme"]:"" == "nfs" || !special ) {
                    scriptPath = sformat("%1%2/%3",AutoinstConfig::destdir,  AutoinstConfig::scripts_dir,  scriptName);
                } else {
                    scriptPath = sformat("%1/%2",AutoinstConfig::scripts_dir,  scriptName);
                }


                y2milestone("Writing chroot script into %1", scriptPath);
                if (s["location"]:""!="")
                {
                    if (!GetURL(s["location"]:"", scriptPath ) )
                    {
                       y2error("script %1 could not be retrieved", s["location"]:"");
                    }
                } else {
                    SCR::Write(.target.string,  scriptPath, s["source"]:"echo Empty script!");
                }
                if( special && toks["scheme"]:"" == "nfs" ) {
                    scriptPath = substring (scriptPath, 4); // cut off the /mnt for later execution
                }
            }
            else
            {
                // disable all sources and finish target - no clue what this is good for.
                // triggers an error with post-script network_needed=true
//                Pkg::SourceFinishAll();
//                Pkg::TargetFinish();

                scriptPath = sformat("%1/%2", AutoinstConfig::scripts_dir, scriptName);
                y2milestone("Writing  script into %1", scriptPath);
                if (s["location"]:""!="")
                {
                    if (!GetURL(s["location"]:"", scriptPath ) )
                    {
                       y2error("script %1 could not be retrieved", s["location"]:"");
                    }
                } else {
                    SCR::Write(.target.string,  scriptPath, s["source"]:"echo Empty script!");
                }
            }

            if (type != "init-scripts")
            {
                // string message =  sformat(_("Executing user supplied script: %1"), scriptName);
                string executionString = "";
                boolean showFeedback = s["feedback"]:false;

                if( s["notification"]:"" != "" )
                    Popup::ShowFeedback( "", s["notification"]:"" );

                if (scriptInterpreter == "shell")
                {
                    string debug = ( s["debug"]:true ? "-x" : "" );
                    if( SCR::Read (.target.size, scriptPath+"-run" ) == -1 || s["rerun"]:false == true ) {
                        if( s["interactive"]:false == true ) {
                            interactiveScript( "/bin/sh", debug, scriptPath, current_logdir, scriptName );
                        } else {
                            executionString = sformat("/bin/sh %1 %2 2&> %3/%4.log ", debug, scriptPath, current_logdir, scriptName);
                            y2milestone("Script Execution command: %1", executionString );
                            SCR::Execute (.target.bash, executionString);
                            SCR::Execute (.target.bash, "/bin/touch $FILE", $["FILE":scriptPath+"-run"]);
                        }
                    }
                }
                else if (scriptInterpreter == "perl")
                {
                    string debug = ( s["debug"]:true ? "-w" : "" );
                    if( SCR::Read (.target.size, scriptPath+"-run" ) == -1 || s["rerun"]:false == true ) {
                        if( s["interactive"]:false == true ) {
                            interactiveScript( "/usr/bin/perl", debug, scriptPath, current_logdir, scriptName );
                        } else {
                            executionString = sformat("/usr/bin/perl %1 %2 2&> %3/%4.log ", debug, scriptPath, current_logdir, scriptName);
                            y2milestone("Script Execution command: %1", executionString );
                            SCR::Execute (.target.bash, executionString);
                            SCR::Execute (.target.bash, "/bin/touch $FILE", $["FILE":scriptPath+"-run"]);
                        }
                    }
                }
                else if (scriptInterpreter == "python")
                {
                    if( SCR::Read (.target.size, scriptPath+"-run" ) == -1 || s["rerun"]:false == true ) {
                        if( s["interactive"]:false == true ) {
                            interactiveScript( "/usr/bin/python", "", scriptPath, current_logdir, scriptName );
                        } else {
                            executionString = sformat("/usr/bin/python %1 2&> %2/%3.log ", scriptPath, current_logdir, scriptName );
                            y2milestone("Script Execution command: %1", executionString );
                            SCR::Execute (.target.bash, executionString);
                            SCR::Execute (.target.bash, "/bin/touch $FILE", $["FILE":scriptPath+"-run"]);
                        }
                    }
                }
                else
                {
                    y2error("Unknown interpreter: %1", scriptInterpreter);
                }
                string feedback = "";

                if( s["notification"]:"" != "" )
                    Popup::ClearFeedback();

                if( executionString != "" ) {
                    if( showFeedback ) {
                        feedback = (string)SCR::Read(.target.string, current_logdir+"/"+scriptName+".log" );
                    }
                    if( size(feedback) > 0 ) {
                        if( s["feedback_type"]:"" == "" ) {
                            Popup::LongText("", `RichText(`opt(`plainText), feedback), 50, 20 );
                        } else if( s["feedback_type"]:"" == "message" ) {
                            Report::Message( feedback );
                        } else if( s["feedback_type"]:"" == "warning" ) {
                            Report::Warning( feedback );
                        } else if( s["feedback_type"]:"" == "error" ) {
                            Report::Error( feedback );
                        }
                    }
                }
            }
        });

        return true;
    }
}



ACC SHELL 2018