home *** CD-ROM | disk | FTP | other *** search
Text File | 2006-11-29 | 49.6 KB | 1,774 lines |
- /**
- * File:
- * ui.ycp
- *
- * Module:
- * System Services (Runlevel) (formerly known as Runlevel Editor)
- *
- * Summary:
- * Runlevel Editor user interface.
- *
- * Authors:
- * Martin Vidner <mvidner@suse.cz>
- * Petr Blahos <pblahos@suse.cz>
- * Martin Lazar <mlazar@suse.cz>
- *
- * $Id: ui.ycp 33299 2006-10-10 09:39:23Z locilka $
- *
- * Runlevel editor user interface functions.
- */
-
- {
- textdomain "runlevel";
-
- import "Service";
- import "RunlevelEd";
- import "Wizard";
- import "Label";
- import "Popup";
- import "FileUtils";
-
- define string StartedText (integer started);
- define string BstatusText (boolean disabled, integer started);
- define list mapkeys (map m);
- define string formatLine (list<string> l, integer len);
- define list startStopService (string service_name, string command);
- define boolean LongContinueCancelHeadlinePopup (string headline, term richtext, integer hdim, integer vdim);
- define void setServiceToDefault (string service_name);
- define map<string, boolean> tomap_true (list<string> l);
- define void updateServiceStatus (boolean use_func, string service_name);
-
- string current_service = "";
- boolean do_abort_now = false;
-
- // We read service status when dialog with services is shown.
- // We read status for services taken from list of services (service_list)
- // and then update map services.
- integer fetching_service_index = 0;
- // when fetching_service_status becomes false, we stop fetching services
- boolean fetching_service_status = true;
-
- // columns in the table where these items are located
- // -1 means it is not there
- integer c_dirty = -1;
- integer c_bstatus = -1;
- integer c_rstatus = -1;
- integer c_runlevels = -1;
- integer c_descr = -1;
- // index into table column for each runlevel
- map runlevel2tableindex = $[];
-
- // map of services listed in table
- map <string, boolean> service_ids_listed_in_table = $[];
-
- /**
- * Create term of checkboxes for runlevel selection.
- * @return HBox full of checkboxes.
- */
- define term getRlCheckBoxes () ``{
- term rls = `HBox (`opt (`hstretch));
- foreach (string i, RunlevelEd::runlevels, ``{
- if (size (rls) > 1)
- rls = add (rls, `HStretch ());
- rls = add (rls, `CheckBox (`id (i), `opt (`notify), "&" + i));
- });
- return rls;
- }
- /**
- * Changes value of a runlevel checkbox.
- * Prevents triggering userinput by disabling notify.
- * @param service @ref service
- * @param rl which runlevel
- */
- define void updateRlCheckBox (map service, string rl) ``{
- list start = service["start"]:[];
- boolean old_notify = (boolean) UI::QueryWidget (`id (rl), `Notify);
- UI::ChangeWidget (`id (rl), `Notify, false);
- UI::ChangeWidget (`id (rl), `Value, contains (start, rl));
- UI::ChangeWidget (`id (rl), `Notify, old_notify);
- }
- /**
- * Changes values of runlevel checkboxes.
- * @param service @ref service
- */
- define void updateRlCheckBoxes (map service) ``{
- foreach (string i, RunlevelEd::runlevels, ``{
- updateRlCheckBox (service, i);
- });
- }
- /**
- * Update the long description text box
- * @param service @ref service
- */
- define void updateDescription (map service) ``{
- // For the box, use the long description.
- // The short one as a fallback. #20853
- string descr = service["description"]:"";
- if (descr == "")
- {
- descr = service["shortdescription"]:"";
- }
- UI::ChangeWidget (`id (`description), `Value, descr);
- }
- /**
- * Sets runlevel columns in the table.
- * @param service_name which line
- * @param service @ref service
- * @param rls which columns to update, nil == all
- */
- define void updateRlColumns (string service_name, map service,
- list<string> rls) ``{
- if (c_runlevels == -1)
- {
- return;
- }
-
- list start = service["start"]:[];
- if (rls == nil)
- {
- rls = RunlevelEd::runlevels;
- }
- foreach (string rl, rls, ``{
- UI::ChangeWidget (`id (`table),
- `Item (service_name, runlevel2tableindex[rl]:-1),
- contains (start, rl) ? rl : " ");
- });
- }
-
- /**
- * Returns whether the service is listed in the table of services
- *
- * @param string service_name
- */
- define boolean ServiceListedInTable (string service_name) {
- return service_ids_listed_in_table[service_name]:false;
- }
-
- /**
- * Update run-time status column.
- * @param service_name which line
- * @param started status or -1 (unknown yet)
- */
- define void updateStatusColumn (string service_name, integer started) ``{
- if (c_rstatus >= 0) {
- // cannot change item which is not listed in the table
- if (ServiceListedInTable(service_name))
- UI::ChangeWidget(`id(`table), `Item(service_name, c_rstatus), StartedText(started));
- }
- if (c_bstatus >= 0) {
-
- // cannot change item which is not listed in the table
- if (ServiceListedInTable(service_name)) {
- boolean disabled = RunlevelEd::isDisabled(RunlevelEd::services[service_name]:$[]);
- UI::ChangeWidget(`id(`table), `Item(service_name, c_bstatus), BstatusText(disabled, started));
- }
- }
- }
- /**
- * Helper function for fetching service status in run-time.
- * @param service_name which line
- * @param service @ref service
- * @param started status or -1 (unknown yet)
- */
- define void updateStatusInTable (string service_name, map service,
- integer started) ``{
- // just translate the arguments. the callback is generic
- // because of the future simple UI, bug #13789
- updateStatusColumn (service_name, started);
- }
-
- /**
- * Changes values of runlevel checkboxes.
- * Get the status if not known yet.
- */
- define void changeService1 (map service) ``{
- if (service["started"]:-1 < 0)
- {
- integer started = Service::RunInitScriptWithTimeOut (current_service,
- "status" + sformat(" 2>&1 1>%1/runlevel_out", SCR::Read(.target.tmpdir)));
- service["started"] = started;
- RunlevelEd::services[current_service] = service;
- updateStatusColumn (current_service, started);
- }
- updateRlCheckBoxes (service);
- updateDescription (service);
- }
-
- /**
- * Reads data from checkboxes and updates service
- * and RunlevelEd::services maps.
- * @param service_name which service
- * @param service @ref service
- * @return @ref service
- */
- define map queryRlCheckBoxes (string service_name, map service) ``{
- list start_in = [];
- foreach (string i, RunlevelEd::runlevels, ``{
- if ((boolean) UI::QueryWidget (`id (i), `Value))
- {
- start_in[size(start_in)] = i;
- }
- });
- if (service["start"]:[] != start_in)
- {
- service = union (service, $[
- "start": start_in,
- "dirty": true
- ]);
- RunlevelEd::services[service_name] = service;
- }
- return service;
- }
-
- // mapping numbers to descriptions
- /**
- * Get help text for rcscript start|stop command exit value.
- * @param exit exit value
- * @return string help text
- */
- define string getActionReturnHelp (integer exit) ``{
- map <integer, string> descr =
- $[
- // Init script non-status-command return codes
- // http://www.linuxbase.org/spec/gLSB/gLSB/iniscrptact.html
- // status code.
- // Changed "Foo bar." to "foo bar", #25082
- 0: _("success"),
- /* 1: handled as default below */
- // status code.
- 2: _("invalid or excess arguments"),
- // status code.
- 3: _("unimplemented feature"),
- // status code.
- 4: _("user had insufficient privileges"),
- // status code.
- 5: _("program is not installed"),
- // status code.
- 6: _("program is not configured"),
- // status code.
- 7: _("program is not running"),
- ];
- // status code.
- return descr[exit]:_("unspecified error");
- }
- /**
- * Get help text for rcscript status return value
- * according to LSB.
- * @param exit exit value
- * @return string help text
- */
- define string getStatusReturnHelp (integer exit) ``{
- map <integer, string> descr =
- $[
- // Init script "status" command return codes
- // http://www.linuxbase.org/spec/gLSB/gLSB/iniscrptact.html
- // status code.
- // Changed "Foo bar." to "foo bar", #25082
- 0: _("program is running"),
- // status code.
- 1: _("program is dead and /var/run pid file exists"),
- // status code.
- 2: _("program is dead and /var/lock lock file exists"),
- // status code.
- 3: _("program is stopped"),
- // status code.
- 4: _("program or service status is unknown"),
- ];
- // status code.
- return descr[exit]:_("unspecified error");
- }
-
- /**
- * @param rll a list of runlevels or nil, meaning "all"
- * @return "in [these] runlevels" (translated)
- */
- define string getInRunlevels (list<string> rll) ``{
- if (rll == nil)
- {
- // translators: substituted into a message like
- // "To enable/disable foo IN ALL RUNLEVELS, this must be done..."
- // (do not include the trailing comma here)
- return _("in all runlevels");
- }
- else
- {
- string s = mergestring (rll, ", ");
- // translators: substituted into a message like
- // "To enable/disable foo IN RUNLEVELS 3, 5, this must be done..."
- // (do not include the trailing comma here)
- return size(rll)>1 ? sformat(_("in runlevels %1"), s) : sformat(_("in runlevel %1"), s);
- }
- }
-
- /**
- * @param started status or -1 (unknown yet)
- * @return "Yes", "No" or "???"
- */
- define string StartedText (integer started) ``{
- return (0 == started ?
- // is the service started?
- _("Yes") :
- (started > 0 ?
- // is the service started?
- _("No") :
- // is the service started?
- // ???: we do not know yet what is the service state
- _("???")));
- }
-
- /**
- * @param disabled status
- * @param started status or -1 (unknown yet)
- * @return "Yes", "Yes*", "No", "No*" or "???"
- */
- define string BstatusText (boolean disabled, integer started) ``{
- // TRANSLATORS: Unknown service status, presented in table
- string state = _("???");
- if (disabled != nil) {
- // TRANSLATORS: Unknown service status presented in table
- state = (started<0) ? _("???") : (!disabled ?
- // TRANSLATORS: Service status presented in table, Enabled: Yes
- _("Yes")
- :
- // TRANSLATORS: Service status presented in table, Enabled: No
- _("No")
- );
- if (started>=0 && (started>0 != disabled)) {
- state = state + "*";
- }
- }
- return state;
- }
-
-
- //start unsorted
- /**
- * Ask if really abort. Uses boolean changed_settings. Sets boolean do_abort_now.
- * @return boolean true if user really wants to abort
- */
- define boolean reallyAbort ()``{
- if (do_abort_now || !RunlevelEd::isDirty ())
- {
- do_abort_now = true;
- return true;
- }
- do_abort_now = Popup::ReallyAbort (true);
- return do_abort_now;
- }
-
-
- /**
- * Create table items from services.
- * For simple mode, also filter out critical services: boot ones.
- * For Expert mode:
- * Mixin: started, start, (short)description.
- * @param mix which items to mix in:<pre>
- *`simple: id=name, name, bstatus, (short)description
- *`complex: id=name, name, rstatus, runlevels, (short)description
- *`auto: id=name, name, dirty, runlevels, ?(short)description
- *</pre>
- * @return list List of items for table.
- */
- define list servicesToTable (symbol mix) ``{
- boolean m_dirty = mix == `auto;
- boolean m_bstatus = mix == `simple;
- boolean m_rstatus = mix == `complex;
- boolean m_runlevels = mix != `simple;
- boolean m_descr = true;
-
- // assume it is not there until placed in
- c_dirty = -1;
- c_bstatus = -1;
- c_rstatus = -1;
- c_runlevels = -1;
- c_descr = -1;
- runlevel2tableindex = $[];
-
- // filter out services that are too important to be messed with
- // in the simple mode
- map<string,map> services = RunlevelEd::services;
- if (mix == `simple)
- {
- services = (map<string, map>)filter (string s_name, map s, services, ``(
- ! contains (s["defstart"]:[], "B")
- ));
- }
-
- list items = [];
- boolean first = true;
- foreach (string k, map v, services, ``{
- if (first)
- {
- first = false;
- // preserve current service when switching modes
- if (!haskey (services, current_service))
- {
- current_service = k;
- }
- }
- // id=name, name
- term item = `item (`id (k), k);
- // column where a item is added
- integer col = 1;
- if (m_dirty)
- {
- // dirty
- service_ids_listed_in_table[k] = true;
- c_dirty = col;
- item = add (item, v["dirty"]:false ? UI::Glyph(`CheckMark) : " ");
- col = col + 1;
- }
- if (m_bstatus)
- {
- // boot status
- service_ids_listed_in_table[k] = true;
- boolean disabled = RunlevelEd::isDisabled(v);
- integer started = v["started"]:-1;
- c_bstatus = col;
- item = add (item, BstatusText(disabled, started));
- col = col + 1;
- }
- if (m_rstatus)
- {
- // runtime status
- service_ids_listed_in_table[k] = true;
- integer started = v["started"]:-1;
- c_rstatus = col;
- item = add (item, StartedText (started));
- col = col + 1;
- }
- if (m_runlevels)
- {
- // runlevels
- service_ids_listed_in_table[k] = true;
- list rl = v["start"]:[];
- c_runlevels = col;
- foreach (string i, RunlevelEd::runlevels, ``{
- runlevel2tableindex[i] = col;
- item = add (item, (contains (rl, i)? i : " "));
- col = col + 1;
- });
- }
- if (m_descr)
- {
- // (short)description
- // For the table, use the short description.
- // The long one as a fallback. #20853
- service_ids_listed_in_table[k] = true;
- string descr = v["shortdescription"]:"";
- if (descr == "")
- {
- descr = v["description"]:"";
- }
- c_descr = col;
- item = add (item, descr);
- col = col + 1;
- }
- // next
- items[size(items)] = item;
- });
- return items;
- }
-
- map <string, boolean> fetched_service_status = $[];
-
- /**
- * For each service, determines its status and calls a supplied function.
- * @param func function to call
- * @see updateStatusInTable
- */
- define void serviceStatusIterator (boolean use_func) ``{
- if (!fetching_service_status)
- {
- return;
- }
- if (fetching_service_index >= size (RunlevelEd::service_list))
- {
- fetching_service_status = false;
- return;
- }
- string service_name = RunlevelEd::service_list[fetching_service_index]:"";
- fetching_service_index = fetching_service_index + 1;
-
- // every switch between `complex and `simple the fetching_service_index is changed to zero
- // but only services which were not checked before are checked now
- if (fetched_service_status[service_name]:false == false) {
- if (ServiceListedInTable(service_name)) {
- updateServiceStatus(use_func, service_name);
- fetched_service_status[service_name] = true;
- }
- }
- }
-
- /**
- * For specified service, determines its status and calls a supplied function.
- * @param func function to call
- * @see updateStatusInTable
- */
- define void updateServiceStatus (boolean use_func, string service_name) ``{
- if (RunlevelEd::services[service_name, "started"]:-1 < 0) {
- integer started = Service::RunInitScriptWithTimeOut (service_name,
- "status" + sformat(" 2>&1 1>%1/runlevel_out", SCR::Read(.target.tmpdir)));
-
- RunlevelEd::services[service_name, "started"] = started;
-
- if (use_func)
- updateStatusInTable(service_name, RunlevelEd::services[service_name]:$[], started);
- }
- }
-
- /**
- * help text for progress
- * @return help text
- */
- define string getHelpProgress () ``{
- return
- // help text
- _("<P><BIG><B>System Service (Runlevel) Initialization</B></BIG><BR>
- Please wait...</P>
- ")
- +
- // warning
- _("<p><b>Note:</b> The system services (runlevel editor) is an expert tool. Only change settings if
- you know what you are doing. Otherwise your system might not function properly afterwards.</p>
- ")
- ;
- }
-
- /**
- * Enable or disable a service in some runlevels.
- * Set the variables and update the ui (rl columns).
- * @param service_name a service
- * @param rls which runlevels, nil == disable in all
- * @param enable enabling or disabling?
- */
- define void SetService (string service_name,
- list<string> rls, boolean enable) ``{
- map service = RunlevelEd::services[service_name]:$[];
- list<string> start_in = nil;
- if (rls == nil)
- {
- start_in = [];
- }
- else
- {
- map<string, boolean> start = tomap_true (service["start"]:[]);
- foreach (string rl, rls, ``{
- start = (map<string, boolean>) add (start, rl, enable);
- });
- start = (map<string, boolean>) filter (string k, boolean v, start, ``( v == true));
- start_in = (list<string>) mapkeys (start);
- }
-
- if (service["start"]:[] != start_in)
- {
- service = union (service, $[
- "start": start_in,
- "dirty": true
- ]);
- RunlevelEd::services[service_name] = service;
-
- updateRlColumns (service_name, service, rls);
- updateStatusColumn (service_name, service["started"]:-1);
- }
- }
-
- /**
- * Check that all the services exist (in RunlevelEd::services).
- * If not, popup a list of the missing ones and ask whether
- * continue or not. Filter out the missing ones.
- * @param services a service list
- * @return [continue?, filtered list]
- */
- define list CheckMissingServices (list<string> services) ``{
- list<string> missing = [];
- boolean ok = true;
- services = filter (string s, services, ``{
- if (haskey (RunlevelEd::services, s))
- {
- return true;
- }
- else
- {
- missing[size(missing)] = s;
- return false;
- }
- });
- if (size (missing) > 0)
- {
- // missing services only occur when enabling
- ok = Popup::ContinueCancel (
- sformat (
- // continue-cancel popup when enabling a service
- // %1 is a list of unsatisfied dependencies
- _("These required services are missing:\n%1."),
- formatLine (missing, 40)));
- }
- return [ok, services];
- }
-
-
- /**
- * Generic function to handle enabling, disabling, starting and
- * stoping services and their dependencies, in various runlevels.
- * Piece of cake ;-) <br>
-
- * Either of init_time or run_time can be specified (for complex
- * mode) or both (for simple mode).
-
- * rls: ignored for -init +run
-
- * What it does: gets dependent services (in the correct order),
- * filters ones that are already in the desired state, if there
- * are dependencies left, pop up a confirmation dialog, check for
- * missing dependencies, perform the action (run-time, then init-time)
- * for the deps and the
- * service (in this order), displaying output after each error and
- * at the end.
- *
-
- * @param service_name name of service
- * @param rls in which run levels, nil == all
- * @param enable on/off
- * @param init_time do enable/disable
- * @param run_time do start/stop
- * @return success (may have been canceled because of dependencies)
- */
- define boolean ModifyServiceDep (string service_name,
- list<string> rls,
- boolean enable,
- boolean init_time,
- boolean run_time) ``{
- y2debug (1, "Modify: %1 %2 %3 %4 %5",
- service_name,
- rls,
- enable,
- init_time? "+init": "-init",
- run_time? "+run": "-run");
- boolean one = (rls != nil) ? (size (rls) == 1) : false;
- string command = enable? "start": "stop";
-
- // get dependent services
- list<string> dep_s = RunlevelEd::ServiceDependencies (service_name, enable);
- y2debug ("DEP: %1", dep_s);
-
- // ensure we have already determined the service status (#36171)
- foreach(string service_name, dep_s, {
- updateServiceStatus(false, service_name);
- });
-
- // filter ones that are ok already
- dep_s = RunlevelEd::FilterAlreadyDoneServices (dep_s, rls, enable,
- init_time, run_time);
- y2debug ("DEP filtered: %1", dep_s);
-
- boolean doit = size (dep_s) == 0;
- // if there are dependencies left, pop up a confirmation dialog
- if (!doit)
- {
- string key =
- (run_time? "+run": "-run") + "," +
- (init_time? "+init": "-init") + "," +
- (enable? "on": "off");
- map texts = $[
- //"-run,-init,..." does not make sense
-
- // *disable*
- // continue-cancel popup
- // translators: %2 is "in runlevel(s) 3, 5"
- // or "in all runlevels"
- "-run,+init,off" : _("To disable service %1 %2,
- these services must be additionally disabled,
- because they depend on it:
- %3."),
- // *enable*
- // continue-cancel popup
- // translators: %2 is "in runlevel(s) 3, 5"
- // or "in all runlevels"
- "-run,+init,on" : _("To enable service %1 %2,
- these services must be additionally enabled,
- because it depends on them:
- %3."),
- // *stop*
- // continue-cancel popup
- "+run,-init,off" : _("To stop service %1,
- these services must be additionally stopped,
- because they depend on it:
- %2."),
- // *start*
- // continue-cancel popup
- "+run,-init,on" : _("To start service %1,
- these services must be additionally started,
- because it depends on them:
- %2."),
- // *stop and disable*
- // continue-cancel popup
- // translators: %2 is "in runlevel(s) 3, 5"
- // or "in all runlevels"
- "+run,+init,off" :_("To stop service %1 and disable it %2,
- these services must be additionally stopped
- and disabled, because they depend on it:
- %3."),
- // *start and enable*
- // continue-cancel popup
- // translators: %2 is "in runlevel(s) 3, 5"
- // or "in all runlevels"
- "+run,+init,on" : _("To start service %1 and enable it %2,
- these services must be additionally started
- and enabled, because it depends on them:
- %3."),
- ];
- string dep_formatted = formatLine (dep_s, 40);
- doit = Popup::ContinueCancel (
- sformat (
- texts[key]:"?",
- service_name,
- // non-init-time does not need the runlevels
- // so we omit it not to confuser the translators
- init_time? getInRunlevels (rls): dep_formatted,
- dep_formatted
- )
- );
- }
-
- // check for missing services
- if (doit)
- {
- list r = CheckMissingServices (dep_s);
- doit = r[0]:false;
- dep_s = r[1]:[];
- }
-
-
- string rich_message = "";
- if (doit)
- {
- // iterate dep_s, not including service_name
- // because we will ask "continue?" on error
- // Foreach with a break: find the failing one
- find (string s, dep_s, ``{
- if (run_time)
- {
- list ret = startStopService (s, command);
-
- rich_message = rich_message + ret[1]:"";
- integer exit = ret[0]:-1;
- if (exit != 0)
- {
- doit = LongContinueCancelHeadlinePopup (
- // popup heading
- _("An error has occurred."), `RichText (rich_message),
- 70, 10);
- // don't show what we've already seen
- rich_message = "";
- if (!doit)
- {
- return true; // break(foreach)
- }
- }
- }
- if (init_time)
- {
- // set the variables and update the ui
- SetService (s, rls, enable);
- }
- return false;
- });
- }
- if (doit)
- {
- // only for service_name
- if (run_time)
- {
- list ret = startStopService (service_name, command);
-
- rich_message = rich_message + ret[1]:"";
- Popup::LongText ("", `RichText(rich_message), 70, 5);
-
- // don't enable the service if it can't be started, #36176
- if (ret[0]:-1 != 0) return false;
- }
-
- if (init_time)
- {
- // set the variables and update the ui
- SetService (service_name, rls, enable);
- }
- }
- return doit;
- }
-
-
- /**
- * Turns a service on or off in the simple mode, ie. resolving
- * dependencies and for each service doing start,enable or
- * stop,disable.
- * @param service_name name of service
- * @param rls in which run levels, nil == all
- * @return success (may have been canceled because of dependencies)
- */
- define boolean SimpleSetServiceDep (string service_name,
- boolean enable) ``{
- list<string> rls = enable?
- RunlevelEd::services[current_service, "defstart"]:[] :
- nil;
- return ModifyServiceDep (service_name, rls, enable, true, true);
- }
-
-
- /**
- * Used for enabling/disabling a service and services depending on
- * it in a runlevel or a set of runlevels.
- * @param service_name name of service
- * @param rls in which run levels, nil == all
- * @param enable enable/disable
- * @return success (may have been canceled because of dependencies)
- */
- define boolean EnableDisableServiceDep (string service_name,
- list<string> rls,
- boolean enable) ``{
- return ModifyServiceDep (service_name, rls, enable, true, false);
- }
-
- /**
- * Used for starting/stopping a service and services depending on it.
- * Displays result popups.
- * @param service_name name of service
- * @param enable start/stop
- * @return success (may have been canceled because of dependencies)
- */
- define boolean StartStopServiceDep (string service_name,
- boolean enable) ``{
- return ModifyServiceDep (service_name, [], enable, false, true);
- }
-
-
- /**
- * Starts/stops/checks status of a service
- * @param service_name service to start/stop
- * @param command "start" or "stop" or "status"
- * @return [integer exit_status, string rich_message]
- */
- define list startStopService (string service_name,
- string command) ``{
- UI::OpenDialog (`Label (service_name + " " + command));
- y2milestone("%1 -> %2", service_name, command);
- string log_filename = sformat("%1/runlevel_out", (string) SCR::Read(.target.tmpdir));
- integer cmd_run = Service::RunInitScriptWithTimeOut (
- service_name,
- command + sformat(" 2>&1 1>%1", log_filename)
- );
- map out = $[ "exit" : cmd_run ];
- if (FileUtils::Exists(log_filename)) {
- out["stdout"] = (string) SCR::Read(.target.string, log_filename);
- }
-
- UI::CloseDialog ();
-
- integer exit = out["exit"]:-1;
- string rich_message = sformat (
- // %1 service, %2 command,
- // %3 exit status, %4 status description, %5 stdout
- // added a colon
- _("<p><b>/etc/init.d/%1 %2</b> returned %3 (%4):<br>%5</p>"),
- service_name, command, exit,
- (command == "status" ?
- getStatusReturnHelp (exit) :
- getActionReturnHelp (exit)),
- sformat ("<pre>%1</pre>", out["stdout"]:"")
- );
- // succesful stop => status: program not running
- integer started = (exit == 0 && command == "stop")? 3: exit;
- // normally "started" has the exit code of "status",
- // and we may be adding output of a different command
- // but it is only tested against zero anyway
- map service = RunlevelEd::services[service_name]:$[];
- service["started"] = started;
- RunlevelEd::services[service_name] = service;
- // this won't work in simple mode
- // make a map "item"->column_number, depending on mode
- // then the functions can consult it and do nothing if not present
- updateStatusColumn (service_name, service["started"]:-1);
- return [exit, rich_message];
- }
-
- /**
- * Prints list items into a string, separating them by commas
- * and when line exceeds len characters, it does line break (\n).
- * It adds 5 spaces before each line.
- * Do not expect reasonable results if you set len < 0.
- * @param l list of strings
- * @param len minimal length of line
- * @return string formated string
- */
- define string formatLine (list<string> l, integer len) ``{
- string s = "";
- string line = " ";
- string add_sep = "";
- string line_sep = "";
- foreach (string i, l, ``{
- if (size (line) > len)
- {
- s = s + line_sep + line;
- line_sep = ",\n";
- line = " ";
- }
- else
- {
- line = line + add_sep;
- }
- line = line + i;
- add_sep = ", ";
- });
- if (size (line) > 0)
- {
- s = s + line_sep + line;
- }
- return s;
- }
-
- /**
- * Checks what services should run in this runlevel and do not run
- * or what services run but should not run.
- * @return string overview text
- */
- define string overviewText () ``{
- list<string> should_not_run = [];
- list<string> should_run = [];
- foreach (string k, map v, RunlevelEd::services, ``{
- if (RunlevelEd::StartContainsImplicitly (v["start"]:[],
- RunlevelEd::current))
- { // it should run
- if (0 != v["started"]:-1)
- {
- should_run[size(should_run)] = k;
- }
- }
- else
- {
- if (0 == v["started"]:-1)
- {
- should_not_run[size(should_not_run)] = k;
- }
- }
- });
- string s = "";
- if (size (should_run) + size (should_not_run) > 0)
- {
- // message label
- s = s + "\n\n"/* + _("Overview") + "\n\n"*/;
- if (size (should_not_run) > 0)
- {
- // list of services will follow
- s = s + _("Following services run in current\nrunlevel although they should not:");
- s = s + "\n" + formatLine (should_not_run, 35) + "\n\n";
- }
-
- if (size (should_run) > 0)
- {
- // list of services will follow
- s = s + _("Following services do not run in current\nrunlevel although they should:");
- s = s + "\n" + formatLine (should_run, 35) + "\n\n";
- }
- }
- return s;
- }
-
- /**
- * Radio buttons (faking tabs) for switching modes
- * @param mode `simple or `complex, which one are we in
- * @return RadioButtonGroup term
- */
- define term ModeTabs (symbol mode) ``{
- term rbg =
- // fake tabs using radio buttons
- `RadioButtonGroup (
- `id (`rbg),
- `HBox (
- `RadioButton (`id (`simple), `opt (`notify),
- // radio button label
- _("&Simple Mode"), mode == `simple),
- `HSpacing (3),
- `RadioButton (`id (`complex), `opt (`notify, `key_F7),
- // radio button label
- _("&Expert Mode"), mode == `complex)
- )
- );
- return `Left (rbg);
- }
-
-
- /**
- * help text services dialog
- * @return help text
- */
- define string getHelpComplex () ``{
- // help text
- return
- // help text
- _("<p>Assign system services to runlevels by selecting the list entry of the respective service then
- checking or unchecking the <b>check boxes B-S</b> for the runlevel.</p>
- ")
- +
- // help text
- _("<p><b>Start/Stop/Refresh:</b> Use this to start or stop services individually.</p>")
- +
- // help text
- _("<P><B>Set and Reset:</B>
- Select runlevels in which to run the currently selected service.<ul>
- <li><b>Enable the service:</b> Activates the service in the standard runlevels.</li>
- <li><b>Disable the service:</b> Deactivates service.</li>
- <li><b>Enable all services:</b> Activates all services in their standard runlevels.</li>
- </ul></p>
- ")
- +
- // The change does not occur immediately. After a reboot the system boots into the specified runlevel.
- _("<p>Changes to the <b>default runlevel</b> will take effect next time you boot your computer.</p>")
- ;
- }
-
- /**
- * Main dialog for changing services.
- * @return symbol for wizard sequencer
- */
- define symbol ComplexDialog () ``{
- Wizard::SetScreenShotName ("runlevel-2-services");
-
- // currently selected service we are working with
- map service = $[];
-
- term header = `header (
- // table header
- _("Service"),
- // table header. is a service running?
- _("Running"));
- foreach (string i, RunlevelEd::runlevels, ``{
- // header = add (header, `Center (" " + i + " "));
- header = add (header, `Center (i));
- });
- // headers in table
- header = add (header, _("Description"));
-
- list args = WFM::Args ();
- // should we show debugging buttons?
- boolean show_debug = args[0]:"" == "debug";
- // should we show the Restore to default button?
- boolean show_restore = true;
-
- term contents = `VBox (
- `VSpacing (0.4),
- ModeTabs (`complex),
- /*
- `HBox (
- // preserve 2 spaces at the end.
- `Label (_("Current runlevel: ")),
- `Label (`opt (`outputField, `hstretch), getRunlevelDescr (RunlevelEd::current))
- ),
- */
- // combo box label
- `ComboBox (`id (`default_rl), `opt (`hstretch), _("&Set default runlevel after booting to:"), RunlevelEd::getDefaultPicker (`complex)),
-
- `VSpacing (0.4),
- `Table (`id (`table), `opt (`notify, `immediate),
- header,
- servicesToTable (`complex)
- ),
- `VSquash (
- `HBox (
- `VSpacing (4.3), // 3+borders in qt, 3 in curses
- `RichText (`id (`description), `opt (`shrinkable, `vstretch), "")
- )
- ),
- `VBox (
- // label above checkboxes
- `Label (`id (`service_label), `opt (`hstretch), _("Service will be started in following runlevels:")),
- getRlCheckBoxes ()
- ),
- `HBox (
- // menubutton label
- `MenuButton (_("S&tart/Stop/Refresh"), [
- // menu item
- `item (`id (`start), _("&Start now ...")),
- // menu item
- `item (`id (`stop), _("S&top now ...")),
- // menu item
- `item (`id (`status), _("&Refresh status ...")),
- ]),
- `HStretch (),
- `ReplacePoint (
- `id (`menubutton),
- // menubutton label
- `MenuButton (_("Set/&Reset"), [
- // menu item
- `item (`id (`to_enable), /*`opt (`key_F3),*/ _("&Enable the service")),
- // menu item
- `item (`id (`to_disable), /*`opt (`key_F5),*/ _("&Disable the service")),
- ]
- + (!show_restore ? [] :
- [
- //TODO
- ])
- +
- [
- // menu item
- `item (`id (`to_all_enable), _("Enable &all services")),
- ]
- + (!show_debug ? [] :
- [
- // menu item
- `item (`id (`depviz), _("Save Dependency &Graph")),
- ])
- )
- )
- )
- );
- // dialog caption.
- Wizard::SetContents (_("System Services (Runlevel): Details"), contents, getHelpComplex (), true, true);
- Wizard::DisableBackButton ();
-
- UI::ChangeWidget (`id (`table), `CurrentItem, current_service);
- service = RunlevelEd::services[current_service]:$[];
- changeService1 (service);
-
- any ret = nil;
-
- // fetch service which were not checked before
- fetching_service_status = true;
- fetching_service_index = 0;
-
- while (`next != ret && `back != ret && `abort != ret && `simple != ret)
- {
- if (ret != nil) y2milestone("RET: %1", ret);
- // Kludge, because a `Table still does not have a shortcut.
- // #16116
- UI::SetFocus (`id (`table));
-
- if (fetching_service_status)
- {
- ret = UI::PollInput ();
- UI::NormalCursor ();
- if (nil == ret)
- {
- serviceStatusIterator (true);
- continue;
- }
- UI::BusyCursor ();
- }
- else
- {
- ret = UI::UserInput ();
- }
- if (ret == `cancel)
- {
- ret = `abort;
- }
-
- current_service = (string) UI::QueryWidget (`id (`table), `CurrentItem);
-
- if (`abort == ret)
- {
- if (!reallyAbort ())
- {
- ret = nil;
- continue;
- }
- }
- else if (`next == ret)
- {
- // TODO: check dependencies of all services? (on demand?)
- // string nfs_adj = RunlevelEd::CheckPortmap ();
- // ...
-
- if (RunlevelEd::isDirty ())
- {
- // yes-no popup
- if (!Popup::YesNo (_("Now the changes to runlevels \nwill be saved.")))
- {
- ret = nil;
- continue;
- }
- }
- RunlevelEd::default_runlevel = (string) UI::QueryWidget (`id (`default_rl), `Value);
- break;
- }
- else if (`table == ret)
- {
- service = RunlevelEd::services[current_service]:$[];
- changeService1 (service);
- }
- else if (nil != ret && is (ret, string))
- {
- // checkbox pressed
- // - enable/disable current_service in one runlevel
- boolean enable = (boolean) UI::QueryWidget (`id (ret), `Value);
- list<string> rls = (list<string>) [ret];
- if (!EnableDisableServiceDep (current_service, (list<string>) [ret], enable))
- {
- // restore the check box
- updateRlCheckBox (service, (string) ret);
- }
- }
- else if (`depviz == ret)
- {
- string filename = UI::AskForSaveFileName(".", "*", "");
- SCR::Write (.target.string, filename,
- RunlevelEd::DotRequires ());
- }
- else if (`to_enable == ret)
- {
- list<string> default_runlevel = RunlevelEd::services[current_service, "defstart"]:[];
- EnableDisableServiceDep (current_service, default_runlevel, true);
- service = RunlevelEd::services[current_service]:$[];
- changeService1 (service);
- }
- else if (`to_disable == ret)
- {
- EnableDisableServiceDep (current_service, nil, false);
- service = RunlevelEd::services[current_service]:$[];
- changeService1 (service);
- }
- else if (`to_all_enable == ret)
- {
- // yes-no popup
- if (Popup::YesNo (_("Really enable all services?")))
- {
- foreach (string k, map v, RunlevelEd::services, ``{
- setServiceToDefault (k);
- });
- UI::ChangeWidget (`id (`table), `Items, servicesToTable (`complex));
- // message popup
- Popup::Message (_("Each service was enabled\nin the appropriate runlevels."));
- }
- }
- else if (`start == ret || `stop == ret)
- {
- boolean really = true;
- if (`stop == ret && "xdm" == current_service)
- {
- // yes-no popup. the user wants to stop xdm
- if (!Popup::YesNo ( _("This may kill your X session.\n\nProceed?")))
- {
- really = false;
- }
- }
- if (really)
- {
- StartStopServiceDep (current_service, ret == `start);
- }
- }
- else if (`status == ret)
- {
- // similar to startStopService but there will be changes
- // when dependencies are checked
-
- //TODO: find a place for it
- //Popup::Message (overviewText ());
- list r = startStopService (current_service, "status");
- Popup::LongText ("", `RichText(r[1]:""), 70, 5);
- }
- }
-
- Wizard::RestoreScreenShotName ();
- return (symbol) ret;
- }
-
- // simple mode
- /**
- * Main dialog for changing services.
- * @return symbol for wizard sequencer
- */
- define symbol SimpleDialog () ``{
- Wizard::SetScreenShotName ("runlevel-2-simple");
- map service = $[];
-
- string help_text =
- // Simple mode dialog
- // help text
- _("<p>Here, specify which system services should be started.</p>")
- +
- // warning
- _("<p><b>Warning:</b> The system services (runlevel editor) is an expert tool. Only change settings if you know
- what you are doing. Otherwise your system might not function properly afterwards.</p>
- ")
- +
- // help text
- // Activate is a button
- _("<p><b>Activate</b> starts the selected service and services
- that it depends on and enables them to start at system boot time.
- Likewise, <b>Deactivate</b> stops services that depend on a given service
- and the service itself and disables their start at system boot time.</p>")
- +
- // help text
- _("<p>An asterisk (*) after a service status means that the service is enabled but not running or is disabled but running now.</p>")
- +
- // help text
- _("<p>To change the behavior of runlevels and system services in detail, click <b>Expert Mode</b>.</p>\n")
- ;
-
- term contents = `VBox (
- `VSpacing (0.4),
- ModeTabs (`simple),
- `VSpacing (0.4),
- `Table (`id (`table), `opt (`notify, `immediate),
- `header (_("Service"), _("Enabled"), _("Description")),
- servicesToTable (`simple)
- ),
- `VSquash (
- `HBox (
- `VSpacing (4.3), // 3+borders in qt, 3 in curses
- `RichText (`id (`description), `opt (`shrinkable, `vstretch), "")
- )
- ),
- `HBox (
- // Button label
- `PushButton (`id (`enable), `opt (`key_F3), _("Ena&ble")),
- // Button label
- `PushButton (`id (`disable), `opt (`key_F5), _("&Disable"))
- )
- );
- // dialog caption.
- Wizard::SetContentsButtons (_("System Services (Runlevel): Services"), contents, help_text, Label::BackButton(), Label::FinishButton());
- Wizard::DisableBackButton ();
-
- UI::ChangeWidget (`id (`table), `CurrentItem, current_service);
- service = RunlevelEd::services[current_service]:$[];
- updateDescription (service);
-
-
- UI::SetFocus (`id (`table));
- any ret = nil;
- boolean focustable = false;
-
- // fetch service which were not checked before
- fetching_service_status = true;
- fetching_service_index = 0;
-
- while (`next != ret && `back != ret && `abort != ret && `complex != ret)
- {
- if (ret != nil) y2milestone("RET: %1", ret);
- if (focustable) {
- // Kludge, because a `Table still does not have a shortcut.
- // #16116
- UI::SetFocus (`id (`table));
- }
-
- if (fetching_service_status)
- {
- ret = UI::PollInput ();
- UI::BusyCursor ();
- if (nil == ret)
- {
- serviceStatusIterator (true);
- continue ;
- }
- }
- else
- {
- ret = UI::UserInput ();
- focustable = true;
- }
- if (ret == `cancel)
- {
- ret = `abort;
- }
-
- current_service = (string) UI::QueryWidget (`id (`table), `CurrentItem);
-
- if (`abort == ret)
- {
- if (!reallyAbort ())
- {
- ret = nil;
- continue;
- }
- }
- else if (`next == ret)
- {
- // FIXME copied from ComplexDialog, make it a function
- // Misaligned for consistency with the original
-
- // TODO: check dependencies of all services? (on demand?)
- // string nfs_adj = RunlevelEd::CheckPortmap ();
- // ...
-
- if (RunlevelEd::isDirty ())
- {
- // yes-no popup
- if (!Popup::YesNo (_("Now the changes to runlevels \nwill be saved.")))
- {
- ret = nil;
- continue;
- }
- }
- break;
- }
- else if (`table == ret)
- {
- service = RunlevelEd::services[current_service]:$[];
- updateDescription (service);
- }
- else if (`disable == ret)
- { //FIXME...
- y2milestone ("%1", ret);
- SimpleSetServiceDep (current_service, false);
- }
- else if (`enable == ret)
- { //FIXME...
- y2milestone ("%1", ret);
- SimpleSetServiceDep (current_service, true);
- }
- }
- Wizard::RestoreScreenShotName ();
- return (symbol) ret;
- }
-
-
- // Autoyast UI
- /**
- * Help text for auto-complex-screen
- * @return help text
- */
- define string getHelpAuto () ``{
- return
- // help text
- _("<p><b>Prepare data for autoinstallation.</b></p>")
- +
- // help text
- _("<p>Change the services to requested state. Only services marked as changed will really be changed in the target system.</p>")
- +
- // help text
- _("<p>If you made a mistake and want to undo the change, press <b>Clear</b> or <b>Clear all</b>.</p>")
- ;
- }
- /**
- * Add service by hand.
- * @return new service name (already added to RunlevelEd::services) or ""
- */
- define string addService () ``{
- UI::OpenDialog (`VBox (
- // dialog heading
- `Heading (`opt (`hstretch), _("Add service")),
- `VSpacing (1),
- // text entry
- `TextEntry (`id (`name), _("Service &name")),
- // label
- `Label (`opt (`hstretch), _("Starts in these runlevels by default:")),
- getRlCheckBoxes (),
- `VSpacing (1),
- // text entry
- `TextEntry (`id (`des), _("&Description (optional)"), ""),
- `VSpacing (1),
- `HBox (`PushButton (`id (`ok), `opt (`default, `key_F10),
- Label::OKButton ()),
- `PushButton (`id (`cancel), `opt (`key_F9),
- Label::CancelButton ()))
- ));
- UI::SetFocus (`id (`name));
-
- any ret = nil; // (symbol|string)
- string name = "";
- while (true)
- {
- ret = UI::UserInput ();
- if (`ok == ret)
- {
- name = (string) UI::QueryWidget (`id (`name), `Value);
- if (nil == name || "" == name || haskey (RunlevelEd::services, name))
- {
- // message popup
- Popup::Message (_("Invalid service name. You did not specify service
- name or the name specified is already in use."));
- continue;
- }
- list def = [];
- foreach (string i, RunlevelEd::runlevels, ``{
- if ((boolean) UI::QueryWidget (`id (i), `Value))
- {
- def[size(def)] = i;
- }
- });
- map m = $[
- "dirty" : true,
- "defstart" : def,
- "start" : def,
- "description" : UI::QueryWidget (`id (`des), `Value)
- ];
- RunlevelEd::services[name] = m;
- break;
- }
- if (`cancel == ret)
- {
- name = "";
- break;
- }
- }
- UI::CloseDialog ();
- return name;
- }
-
- /**
- * Main dialog for changing services.
- * @return symbol for wizard sequencer
- */
- define symbol AutoDialog () ``{
- Wizard::SetScreenShotName ("runlevel-2-auto");
- // currently selected service we are working with
- map service = $[];
-
- /**
- * Sets columns 0-S (runlevels) in table so they are synchronized with checkboxes.
- */
- define void refreshTableLine2 () ``{
- updateRlColumns (current_service, service, nil);
- UI::ChangeWidget (`id (`table), `Item (current_service, c_dirty),
- service["dirty"]:false ? UI::Glyph(`CheckMark) : " ");
- }
-
- // headers in table
- term header = `header (
- // table header
- _("Service"),
- // table header. has the service state changed?
- _("Changed"));
- foreach (string i, RunlevelEd::runlevels, ``{
- // header = add (header, `Center (" " + i + " "));
- header = add (header, `Center (i));
- });
- // headers in table
- header = add (header, _("Description"));
- term contents = `VBox (
- `VSpacing (0.4),
- // combo box label
- `ComboBox (`id (`default_rl), `opt (`hstretch), _("&Set default runlevel after booting to:"), RunlevelEd::getDefaultPicker (`auto)),
-
- `VSpacing (0.4),
- `Table (`id (`table), `opt (`notify, `immediate),
- header,
- servicesToTable (`auto)
- ),
- `VBox (
- // label above checkboxed
- `Label (`id (`service_label), `opt (`hstretch), _("Service will be started in following runlevels:")),
- getRlCheckBoxes ()
- ),
- `HBox (
- // button label
- `PushButton (`id (`add), `opt (`key_F3), _("A&dd")),
- `HStretch (),
- // button label
- `PushButton (`id (`clear), _("&Clear")),
- // button label
- `PushButton (`id (`clear_all), _("Clea&r All")),
- // button label
- `PushButton (`id (`default), _("D&efault"))
- )
- );
- // dialog caption.
- Wizard::SetContentsButtons (_("System Services (Runlevel): Details"), contents, getHelpAuto (), Label::BackButton(), Label::FinishButton());
- Wizard::DisableBackButton ();
-
- UI::ChangeWidget (`id (`table), `CurrentItem, current_service);
- service = RunlevelEd::services[current_service]:$[];
- updateRlCheckBoxes (service);
- any ret = nil;
- while (nil != UI::PollInput ()) {sleep(50);}
- while (`next != ret && `back != ret && `abort != ret)
- {
- // Kludge, because a `Table still does not have a shortcut.
- // #16116
- UI::SetFocus (`id (`table));
-
- ret = UI::UserInput ();
- if (ret == `cancel)
- {
- ret = `abort;
- }
-
- if (`abort == ret)
- {
- if (!reallyAbort ())
- {
- ret = nil;
- continue;
- }
- }
- else if (`next == ret)
- {
- //FIXME dependencies none or proper
-
- string nfs_adj = RunlevelEd::CheckPortmap ();
- if (nil != nfs_adj)
- {
- UI::ChangeWidget (`id (`table), `CurrentItem, "portmap");
- current_service = "portmap";
- service = RunlevelEd::services["portmap"]:$[];
- updateRlCheckBoxes (service);
- while (nil != UI::PollInput ()) {sleep(50);}
- // yes-no popup
- if (!Popup::YesNo (sformat (_("Service portmap, which is required by
- %1, is disabled. Enable
- portmap if you want to run %1.
-
- Leave portmap
- disabled?\n"), nfs_adj)))
- {
- ret = nil;
- continue;
- }
- }
- RunlevelEd::default_runlevel = (string) UI::QueryWidget (`id (`default_rl), `Value);
- break;
- }
- else if (`add == ret)
- {
- string name = addService ();
- if ("" != name)
- {
- UI::ChangeWidget (`id (`table), `Items, servicesToTable (`auto));
- UI::ChangeWidget (`id (`table), `CurrentItem, name);
- // qt and curses behave differently:
- // one of them sends notification after changewidget
- // and the other does not.
- // So eat it.
- while (nil != UI::PollInput ()) {sleep(50);}
- ret = `table;
- }
- }
- else if (`default == ret)
- {
- setServiceToDefault (current_service);
- service = RunlevelEd::services[current_service]:$[];
- refreshTableLine2 ();
- ret = `table;
- }
- else if (`clear == ret)
- {
- // re-read from SCR
- service = Service::Info (current_service);
- RunlevelEd::services[current_service] = service;
- refreshTableLine2 ();
- ret = `table;
- }
- else if (`clear_all == ret)
- {
- RunlevelEd::ClearServices ();
- UI::ChangeWidget (`id (`table), `Items, servicesToTable (`auto));
- ret = `table;
- }
- else if (nil != ret && is (ret, string))
- {
- // checkbox pressed
- // checked or unchecked?
- string checked = (((boolean) UI::QueryWidget (`id (ret), `Value)) ? (string) ret : " ");
- service = queryRlCheckBoxes (current_service, service);
- UI::ChangeWidget (`id (`table), `Item (current_service, runlevel2tableindex[ret]:-1), checked);
- UI::ChangeWidget (`id (`table), `Item (current_service, c_dirty), UI::Glyph(`CheckMark));
- }
-
- // not a part of the else-if chain above!
- if (`table == ret)
- {
- current_service = (string) UI::QueryWidget (`id (`table), `CurrentItem);
- service = RunlevelEd::services[current_service]:$[];
- updateRlCheckBoxes (service);
- while (nil != UI::PollInput ()) {sleep(50);}
- }
- }
- Wizard::RestoreScreenShotName ();
- return (symbol) ret;
- }
-
- // generic ui helpers
- /**
- * Like Popup::LongText
- * @param headline a headline
- * @param richtext `RichText(_("<p>foo...</p>"))
- * @param hdim popup width
- * @param vdim popup height
- * @return continue?
- */
- define boolean LongContinueCancelHeadlinePopup (
- string headline, term richtext, integer hdim, integer vdim) ``{
-
- UI::OpenDialog (
- `opt (`decorated),
- `HBox (
- `VSpacing (vdim),
- `VBox (
- `HSpacing (hdim),
- `Left (`Heading (headline)),
- `VSpacing (0.2),
- richtext, // scrolled text
- `HBox (
- `PushButton (
- `id (`continue),
- `opt (`default, `key_F10),
- Label::ContinueButton ()),
- `PushButton (
- `id (`cancel),
- `opt (`key_F9),
- Label::CancelButton ())
- )
- )
- )
- );
-
- UI::SetFocus (`id (`continue));
-
- boolean ret = UI::UserInput() == `continue;
- UI::CloseDialog();
- return ret;
- }
-
- // move them to the module
- // (no ui interaction)
- /**
- * Disable the service. Changes global services.
- * @param service_name name of the service.
- */
- define void setServiceDisable (string service_name) ``{
- map service = RunlevelEd::services[service_name]:$[];
- RunlevelEd::services[service_name] = union (service,
- $[
- "start": [],
- "dirty": true,
- ]);
- }
- /**
- * DUH, in fact ENABLES the service.
- * but the described function will be there sometime
- *
- * Set service to its default state upon installation.
- * Changes global services.
- * @param service_name Name of service to process.
- */
- define void setServiceToDefault (string service_name) ``{
- map service = RunlevelEd::services[service_name]:$[];
- RunlevelEd::services[service_name] = union (service,
- $[
- "start": service["defstart"]:[],
- "dirty": true,
- ]);
- }
-
- // favorite missing builtins
- /**
- * Converts a list to a map with values of true
- * @param l a list
- * @return a map
- */
- define map<string, boolean> tomap_true (list<string> l) ``{
- return (map<string, boolean>) listmap (string i, l, ``( $[i: true] ));
- }
-
- /**
- * @param m a map
- * @return keys of the map
- */
- define list mapkeys (map m) ``{
- return maplist (any k, any v, m, ``( k ));
- }
-
-
- }
-