summaryrefslogtreecommitdiff
path: root/src/systemctl/systemctl.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-05-31 04:11:57 +0200
committerLennart Poettering <lennart@poettering.net>2012-05-31 04:11:57 +0200
commit256425cc10d74c13602527eb86b4ba0938964565 (patch)
tree821d99b76251c40b60c1272e40607192051bed0a /src/systemctl/systemctl.c
parent4c8cd173305697f59adcebf980ad7babe751d38c (diff)
systemctl: introduce "systemctl man" to show man page for unit
For now this only reads man: URLs, but later on we might want to support info: too. http/https is probably out of focus.
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r--src/systemctl/systemctl.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 58b6035c69..f65bd2faa0 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2458,6 +2458,73 @@ static void print_status_info(UnitStatusInfo *i) {
arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
}
+static void man_status_info(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);
@@ -2952,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, "man"))
+ man_status_info(&info);
+ else
+ print_status_info(&info);
+ }
strv_free(info.documentation);
@@ -3044,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();
@@ -4213,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"
+ " man [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"
@@ -5176,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 },
+ { "man", MORE, 2, show },
{ "dump", EQUAL, 1, dump },
{ "dot", EQUAL, 1, dot },
{ "snapshot", LESS, 2, snapshot },