X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=2fbfd7eb9bb3d0eb28d5415ad1af4bcd8f49f17a;hb=b43f208f78666fd27e274daa946ae57becd59dd6;hp=66f4113eb223c91c7e05848778f56245f3e92ba7;hpb=07719a21b6425d378b36bb8d7f47ad5ec5296d28;p=elogind.git diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 66f4113eb..2fbfd7eb9 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -171,6 +171,7 @@ static void ask_password_agent_open_if_enabled(void) { ask_password_agent_open(); } +#ifdef HAVE_LOGIND static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ @@ -183,6 +184,7 @@ static void polkit_agent_open_if_enabled(void) { polkit_agent_open(); } +#endif static const char *ansi_highlight_red(bool b) { @@ -2456,6 +2458,73 @@ static void print_status_info(UnitStatusInfo *i) { arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user"); } +static void show_unit_help(UnitStatusInfo *i) { + char **p; + + assert(i); + + if (!i->documentation) { + log_info("Documentation for %s not known.", i->id); + return; + } + + STRV_FOREACH(p, i->documentation) { + + if (startswith(*p, "man:")) { + size_t k; + char *e = NULL; + char *page = NULL, *section = NULL; + const char *args[4] = { "man", NULL, NULL, NULL }; + pid_t pid; + + k = strlen(*p); + + if ((*p)[k-1] == ')') + e = strrchr(*p, '('); + + if (e) { + page = strndup((*p) + 4, e - *p - 4); + if (!page) { + log_error("Out of memory."); + return; + } + + section = strndup(e + 1, *p + k - e - 2); + if (!section) { + free(page); + log_error("Out of memory"); + return; + } + + args[1] = section; + args[2] = page; + } else + args[1] = *p + 4; + + pid = fork(); + if (pid < 0) { + log_error("Failed to fork: %m"); + free(page); + free(section); + continue; + } + + if (pid == 0) { + /* Child */ + execvp(args[0], (char**) args); + log_error("Failed to execute man: %m"); + _exit(EXIT_FAILURE); + } + + free(page); + free(section); + + wait_for_terminate(pid, NULL); + } else + log_info("Can't show %s.", *p); + } +} + static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) { assert(name); @@ -2950,8 +3019,12 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo r = 0; - if (!show_properties) - print_status_info(&info); + if (!show_properties) { + if (streq(verb, "help")) + show_unit_help(&info); + else + print_status_info(&info); + } strv_free(info.documentation); @@ -3042,7 +3115,7 @@ static int show(DBusConnection *bus, char **args) { assert(bus); assert(args); - show_properties = !streq(args[0], "status"); + show_properties = streq(args[0], "show"); if (show_properties) pager_open_if_enabled(); @@ -4211,6 +4284,7 @@ static int systemctl_help(void) { " status [NAME...|PID...] Show runtime status of one or more units\n" " show [NAME...|JOB...] Show properties of one or more\n" " units/jobs or the manager\n" + " help [NAME...|PID...] Show manual for one or more units\n" " reset-failed [NAME...] Reset failed state for all, one, or more\n" " units\n" " load [NAME...] Load one or more units\n\n" @@ -5174,6 +5248,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "check", MORE, 2, check_unit }, { "show", MORE, 1, show }, { "status", MORE, 2, show }, + { "help", MORE, 2, show }, { "dump", EQUAL, 1, dump }, { "dot", EQUAL, 1, dot }, { "snapshot", LESS, 2, snapshot }, @@ -5218,9 +5293,10 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError /* Special rule: no arguments means "list-units" */ i = 0; else { - if (streq(argv[optind], "help")) { - systemctl_help(); - return 0; + if (streq(argv[optind], "help") && !argv[optind+1]) { + log_error("This command expects one or more " + "unit names. Did you mean --help?"); + return -EINVAL; } for (i = 0; i < ELEMENTSOF(verbs); i++)