summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-05-21 15:12:18 +0200
committerLennart Poettering <lennart@poettering.net>2012-05-21 15:14:51 +0200
commit49dbfa7b2b0bf3906704dac1eaeb4eba91056a19 (patch)
treeb7bf6ad5bef741f68b45a431807f58a81a5c845a /src/core
parenta223b325b409b325f4c2c2e11268596edd842631 (diff)
units: introduce new Documentation= field and make use of it everywhere
This should help making the boot process a bit easier to explore and understand for the administrator. The simple idea is that "systemctl status" now shows a link to documentation alongside the other status and decriptionary information of a service. This patch adds the necessary fields to all our shipped units if we have proper documentation for them.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-unit.c1
-rw-r--r--src/core/dbus-unit.h1
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/load-fragment.c37
-rw-r--r--src/core/load-fragment.h1
-rw-r--r--src/core/unit.c8
-rw-r--r--src/core/unit.h1
7 files changed, 47 insertions, 3 deletions
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 834fbd7693..812f1b9f16 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -808,6 +808,7 @@ const BusProperty bus_unit_properties[] = {
{ "PropagateReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_TO]), true },
{ "PropagateReloadFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_FROM]), true },
{ "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
+ { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
{ "Description", bus_unit_append_description, "s", 0 },
{ "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
{ "ActiveState", bus_unit_append_active_state, "s", 0 },
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index d22802d274..9680b56f06 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -87,6 +87,7 @@
" <property name=\"PropagateReloadFrom\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SubState\" type=\"s\" access=\"read\"/>\n" \
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index d929273877..f0e25c0c5d 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -92,6 +92,7 @@ $1.ControlGroupPersistent, config_parse_tristate, 0,
)m4_dnl
Unit.Names, config_parse_unit_names, 0, 0
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
+Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
Unit.RequiresOverridable, config_parse_unit_deps, UNIT_REQUIRES_OVERRIDABLE, 0
Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index c2efec6657..3bc053341c 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2063,6 +2063,43 @@ int config_parse_unit_requires_mounts_for(
return r;
}
+int config_parse_documentation(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Unit *u = userdata;
+ int r;
+ char **a, **b;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(u);
+
+ r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
+ if (r < 0)
+ return r;
+
+ for (a = b = u->documentation; a && *a; a++) {
+
+ if (is_valid_documentation_url(*a))
+ *(b++) = *a;
+ else {
+ log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
+ free(*a);
+ }
+ }
+ *b = NULL;
+
+ return r;
+}
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index ccc436420e..3b2ed096b5 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -36,6 +36,7 @@ int config_parse_unit_names(const char *filename, unsigned line, const char *sec
int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/core/unit.c b/src/core/unit.c
index 200d196878..1f1a5314f7 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -397,6 +397,7 @@ void unit_free(Unit *u) {
cgroup_attribute_free_list(u->cgroup_attributes);
free(u->description);
+ strv_free(u->documentation);
free(u->fragment_path);
free(u->instance);
@@ -624,7 +625,7 @@ const char *unit_description(Unit *u) {
}
void unit_dump(Unit *u, FILE *f, const char *prefix) {
- char *t;
+ char *t, **j;
UnitDependency d;
Iterator i;
char *p2;
@@ -672,6 +673,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
SET_FOREACH(t, u->names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
+ STRV_FOREACH(j, u->documentation)
+ fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
+
if ((following = unit_following(u)))
fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
@@ -698,8 +702,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
}
if (!strv_isempty(u->requires_mounts_for)) {
- char **j;
-
fprintf(f,
"%s\tRequiresMountsFor:", prefix);
diff --git a/src/core/unit.h b/src/core/unit.h
index e8e6b09866..87dc88c961 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -157,6 +157,7 @@ struct Unit {
char **requires_mounts_for;
char *description;
+ char **documentation;
char *fragment_path; /* if loaded from a config file this is the primary path to it */
usec_t fragment_mtime;