ACC SHELL

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

/**
 * File:	modules/LogViewCore.ycp
 * Package:	YaST2
 * Summary:	Displaying a log
 * Authors:	Jiri Srain <jsrain@suse.cz>
 *		Arvin Schnell <aschnell@suse.de>
 *
 * $Id: LogViewCore.ycp 45503 2008-03-17 09:46:23Z aschnell $
 */
{
    module "LogViewCore.ycp";

    textdomain "base";

    import "Report";


    /**
     * default value of maximum displayed lines
     */
    integer max_lines_default = 100;


    /**
     * lines of the log
     */
    list<string> lines = [];


    /**
     * data describing log:
     *   file:       filename to read from
     *   grep:       grep file with expression
     *   command:    command to run (use instead of file and grep)
     *   max_lines:  max lines to keep (0 -> infinite)
     */
    map<string, any> data = $[];


    /**
     * id of background process
     */
    integer id = nil;


    /**
     * flag indicating if background process is (or should be) running
     */
    boolean is_running = false;


    list<string> GetNewLines()
    {
	if (!is_running)
	{
	    return [];
	}

	if (!(boolean) SCR::Read(.process.running, id))
	{
	    is_running = false;
	    Report::Error(_("Error occurred while reading the log."));
	    return [];
	}

	list<string> new_lines = [];

	while(true)
	{
	    string line = (string) SCR::Read(.process.read_line, id);
	    if (line == nil)
		break;

	    new_lines = add(new_lines, line);
	}

	return new_lines;
    }


    /**
     * Remove unneeded items from a list of lines
     * If max_lines is 0, then don't remove anything
     */
    void DeleteOldLines()
    {
	integer max_lines = data["max_lines"]:max_lines_default;
	if (max_lines == 0)
	    return;

	if (size(lines) - max_lines - 1 > 0)
	    lines = sublist(lines, size(lines) - max_lines - 1);
    }


    /**
     * Starts the log reading command via process agent.
     *
     * The LogView widget must exist when calling this function. The `MaxLines
     * parameter of the widget will be set.
     */
    global void Start(term widget, map<string, any> d)
    {
	if (id != nil)
	{
	    SCR::Execute(.process.release, id);
	    id = nil;
	}

	data = d;

	string file = data["file"]:"";
	string grep = data["grep"]:"";
	string command = data["command"]:"";
	integer max_lines = data["max_lines"]:max_lines_default;

	if (command == "")
	{
	    if (grep == "")
	    {
		command = sformat("tail -n %1 -f '%2'", max_lines, file);
	    }
	    else
	    {
		command = sformat("tail -n +0 -f '%1' | grep --line-buffered '%2'", file, grep);

		if (max_lines != 0)
		{
		    string lc_command = sformat ("cat '%1' | grep '%2' | wc -l", file, grep);
		    map bash_output = (map) SCR::Execute (.target.bash_output, lc_command);
		    if (bash_output["exit"]:1 == 0)
		    {
			string lc = filterchars (bash_output["stdout"]:"", "1234567890");
			integer lines_count = tointeger (lc);

			// don't know why without doubling it discards more lines,
			// out of YaST2 it works
			lines_count = lines_count - 2 * max_lines;
			if (lines_count < 0)
			    lines_count = 0;

			if (lines_count > 0)
			    command = command + sformat(" | tail -n +%1", lines_count);
		    }
		}
	    }
	}

	y2milestone ("Calling process agent with command %1", command);

	id = (integer) SCR::Execute (.process.start_shell, command, $[ "tty" : true ]);
	is_running = true;

	sleep(100);

	lines = GetNewLines();
	DeleteOldLines();

	UI::ChangeWidget(widget, `MaxLines, max_lines);
	UI::ChangeWidget(widget, `Value, mergestring(
			     maplist(string line, lines, { return line + "\n"; } ), ""));
    }


    global void Update(term widget)
    {
	if (id != nil)
	{
	    list<string> new_lines = GetNewLines();
	    if (size(new_lines) > 0)
	    {
		lines = (list<string>) merge(lines, new_lines);
		DeleteOldLines();

		UI::ChangeWidget(widget, `LastLine, mergestring(
				     maplist(string line, new_lines, { return line + "\n"; } ), ""));
	    }
	}
    }


    global void Stop()
    {
	if (id != nil)
	{
	    SCR::Execute(.process.release, id);
	    id = nil;
	}
    }


    global list<string> GetLines()
    {
	return lines;
    }
}

ACC SHELL 2018