[systemd-commits] 3 commits - man/systemctl.xml src/core src/libsystemd src/login src/systemctl src/systemd
Lennart Poettering
lennart at kemper.freedesktop.org
Wed Mar 12 13:17:16 PDT 2014
man/systemctl.xml | 18 ++
src/core/dbus-manager.c | 38 ++++++
src/core/manager.c | 61 +++++++++
src/core/manager.h | 20 +++
src/core/unit.c | 10 +
src/libsystemd/libsystemd.sym.m4 | 11 +
src/login/sd-login.c | 47 ++++---
src/systemctl/systemctl.c | 243 +++++++++++++++++++++++++++++++++++++--
src/systemd/sd-login.h | 3
9 files changed, 415 insertions(+), 36 deletions(-)
New commits:
commit 0d292f5e7597a729365644edfbcdf2e5fac8beb4
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 12 21:13:58 2014 +0100
systemctl: add new "list-machines" command
"systemctl list-machines" shows one line per local container which
includes the current system state of the container, the number of failed
units as well as the number of currently queued jobs.
diff --git a/man/systemctl.xml b/man/systemctl.xml
index fef9578..174988c 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1042,6 +1042,24 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</refsect2>
<refsect2>
+ <title>Machine Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>list-machines <optional><replaceable>PATTERN</replaceable>...</optional></command></term>
+
+ <listitem>
+ <para>List the host and all running local containers with
+ their state. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only
+ containers matching one of them are shown.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
<title>Job Commands</title>
<variablelist>
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 17ad7f0..d4c71f5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1031,7 +1031,7 @@ static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
}
static void output_unit_file_list(const UnitFileList *units, unsigned c) {
- unsigned max_id_len, id_cols, state_cols, n_shown = 0;
+ unsigned max_id_len, id_cols, state_cols;
const UnitFileList *u;
max_id_len = sizeof("UNIT FILE")-1;
@@ -1062,8 +1062,6 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
const char *on, *off;
const char *id;
- n_shown++;
-
if (u->state == UNIT_FILE_MASKED ||
u->state == UNIT_FILE_MASKED_RUNTIME ||
u->state == UNIT_FILE_DISABLED ||
@@ -1086,7 +1084,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
}
if (!arg_no_legend)
- printf("\n%u unit files listed.\n", n_shown);
+ printf("\n%u unit files listed.\n", c);
}
static int list_unit_files(sd_bus *bus, char **args) {
@@ -1414,6 +1412,223 @@ static int list_dependencies(sd_bus *bus, char **args) {
return list_dependencies_one(bus, u, 0, &units, 0);
}
+struct machine_info {
+ bool is_host;
+ char *name;
+ unsigned n_failed_units;
+ unsigned n_jobs;
+ char *state;
+};
+
+static void free_machines_list(struct machine_info *machine_infos, int n) {
+ int i;
+
+ if (!machine_infos)
+ return;
+
+ for (i = 0; i < n; i++) {
+ free(machine_infos[i].name);
+ free(machine_infos[i].state);
+ }
+
+ free(machine_infos);
+}
+
+static int compare_machine_info(const void *a, const void *b) {
+ const struct machine_info *u = a, *v = b;
+
+ if (u->is_host != v->is_host)
+ return u->is_host > v->is_host ? 1 : -1;
+
+ return strcasecmp(u->name, v->name);
+}
+
+static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
+ static const struct bus_properties_map map[] = {
+ { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
+ { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
+ { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
+ {}
+ };
+
+ _cleanup_bus_unref_ sd_bus *container = NULL;
+ int r;
+
+ assert(mi);
+
+ if (!bus) {
+ r = sd_bus_open_system_container(&container, mi->name);
+ if (r < 0)
+ return r;
+
+ bus = container;
+ }
+
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", map, mi);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static bool output_show_machine(const char *name, char **patterns) {
+ char **i;
+
+ assert(name);
+
+ if (strv_isempty(patterns))
+ return true;
+
+ STRV_FOREACH(i, patterns)
+ if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
+ return true;
+
+ return false;
+}
+
+static int get_machine_list(
+ sd_bus *bus,
+ struct machine_info **_machine_infos,
+ char **patterns) {
+
+ struct machine_info *machine_infos = NULL;
+ _cleanup_strv_free_ char **m = NULL;
+ _cleanup_free_ char *hn = NULL;
+ size_t sz = 0;
+ char **i;
+ int c = 0;
+
+ hn = gethostname_malloc();
+ if (!hn)
+ return log_oom();
+
+ if (output_show_machine(hn, patterns)) {
+ if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
+ return log_oom();
+
+ machine_infos[c].is_host = true;
+ machine_infos[c].name = hn;
+ hn = NULL;
+
+ get_machine_properties(bus, &machine_infos[c]);
+ c++;
+ }
+
+ sd_get_machine_names(&m);
+ STRV_FOREACH(i, m) {
+ _cleanup_free_ char *class = NULL;
+
+ if (!output_show_machine(*i, patterns))
+ continue;
+
+ sd_machine_get_class(*i, &class);
+ if (!streq_ptr(class, "container"))
+ continue;
+
+ if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
+ free_machines_list(machine_infos, c);
+ return log_oom();
+ }
+
+ machine_infos[c].is_host = false;
+ machine_infos[c].name = strdup(*i);
+ if (!machine_infos[c].name) {
+ free_machines_list(machine_infos, c);
+ return log_oom();
+ }
+
+ get_machine_properties(NULL, &machine_infos[c]);
+ c++;
+ }
+
+ *_machine_infos = machine_infos;
+ return c;
+}
+
+static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
+ struct machine_info *m;
+ unsigned
+ namelen = sizeof("NAME") - 1,
+ statelen = sizeof("STATE") - 1,
+ failedlen = sizeof("FAILED") - 1,
+ jobslen = sizeof("JOBS") - 1;
+
+ assert(machine_infos || n == 0);
+
+ for (m = machine_infos; m < machine_infos + n; m++) {
+ namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
+ statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
+ failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
+ jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
+ }
+
+ if (!arg_no_legend)
+ printf("%-*s %-*s %-*s %-*s\n",
+ namelen, "NAME",
+ statelen, "STATE",
+ failedlen, "FAILED",
+ jobslen, "JOBS");
+
+ for (m = machine_infos; m < machine_infos + n; m++) {
+ const char *on_state, *off_state, *on_failed, *off_failed;
+
+ if (streq_ptr(m->state, "degraded")) {
+ on_state = ansi_highlight_red();
+ off_state = ansi_highlight_off();
+ } else if (!streq_ptr(m->state, "running")) {
+ on_state = ansi_highlight_yellow();
+ off_state = ansi_highlight_off();
+ } else
+ on_state = off_state = "";
+
+ if (m->n_failed_units > 0) {
+ on_failed = ansi_highlight_red();
+ off_failed = ansi_highlight_off();
+ } else
+ on_failed = off_failed = "";
+
+ if (m->is_host)
+ printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
+ (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
+ on_state, statelen, strna(m->state), off_state,
+ on_failed, failedlen, m->n_failed_units, off_failed,
+ jobslen, m->n_jobs);
+ else
+ printf("%-*s %s%-*s%s %s%*u%s %*u\n",
+ namelen, strna(m->name),
+ on_state, statelen, strna(m->state), off_state,
+ on_failed, failedlen, m->n_failed_units, off_failed,
+ jobslen, m->n_jobs);
+ }
+
+ if (!arg_no_legend)
+ printf("\n%u machines listed.\n", n);
+}
+
+static int list_machines(sd_bus *bus, char **args) {
+ struct machine_info *machine_infos = NULL;
+ int r;
+
+ assert(bus);
+
+ if (geteuid() != 0) {
+ log_error("Must be root.");
+ return -EPERM;
+ }
+
+ pager_open_if_enabled();
+
+ r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
+ if (r < 0)
+ return r;
+
+ qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
+ output_machines_list(machine_infos, r);
+ free_machines_list(machine_infos, r);
+
+ return 0;
+}
+
static int get_default(sd_bus *bus, char **args) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -1625,16 +1840,17 @@ static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipp
}
static bool output_show_job(struct job_info *job, char **patterns) {
- if (!strv_isempty(patterns)) {
- char **pattern;
+ char **pattern;
- STRV_FOREACH(pattern, patterns)
- if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
- return true;
- return false;
- }
+ assert(job);
- return true;
+ if (strv_isempty(patterns))
+ return true;
+
+ STRV_FOREACH(pattern, patterns)
+ if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
+ return true;
+ return false;
}
static int list_jobs(sd_bus *bus, char **args) {
@@ -4940,6 +5156,8 @@ static int systemctl_help(void) {
" the search path\n"
" get-default Get the name of the default target\n"
" set-default NAME Set the default target\n\n"
+ "Machine Commands:\n"
+ " list-machines [PATTERN...] List local containers and host\n\n"
"Job Commands:\n"
" list-jobs [PATTERN...] List jobs\n"
" cancel [JOB...] Cancel all, one, or more jobs\n\n"
@@ -5882,6 +6100,7 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
{ "list-sockets", MORE, 1, list_sockets },
{ "list-timers", MORE, 1, list_timers },
{ "list-jobs", MORE, 1, list_jobs },
+ { "list-machines", MORE, 1, list_machines },
{ "clear-jobs", EQUAL, 1, daemon_reload },
{ "cancel", MORE, 2, cancel_job },
{ "start", MORE, 2, start_unit },
commit f755e3b74b94296a534033dd6ae04d9506434210
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 12 20:55:13 2014 +0100
core: introduce system state enum
The system state knows the states starting â
running/degraded/maintenance â stopping, where:
starting = system startup
running = normal operation
degraded = at least one unit is currently in failed state
maintenance = rescue/emergency mode is active or queued
stopping = system shutdown
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 30f28b6..135d314 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -239,6 +239,24 @@ static int property_get_n_names(
return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
}
+static int property_get_n_failed_units(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+
+ assert(bus);
+ assert(reply);
+ assert(m);
+
+ return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units));
+}
+
static int property_get_n_jobs(
sd_bus *bus,
const char *path,
@@ -281,6 +299,24 @@ static int property_get_progress(
return sd_bus_message_append(reply, "d", d);
}
+static int property_get_system_state(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+
+ assert(bus);
+ assert(reply);
+ assert(m);
+
+ return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m)));
+}
+
static int property_set_runtime_watchdog(
sd_bus *bus,
const char *path,
@@ -1598,6 +1634,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
+ SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, 0),
SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
@@ -1611,6 +1648,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
+ SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/core/manager.c b/src/core/manager.c
index 78f4f3d..f618bed 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -140,6 +140,8 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
}
void manager_flip_auto_status(Manager *m, bool enable) {
+ assert(m);
+
if (enable) {
if (m->show_status == SHOW_STATUS_AUTO)
manager_set_show_status(m, SHOW_STATUS_TEMPORARY);
@@ -451,6 +453,10 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
if (r < 0)
goto fail;
+ r = set_ensure_allocated(&m->failed_units, trivial_hash_func, trivial_compare_func);
+ if (r < 0)
+ goto fail;
+
r = sd_event_default(&m->event);
if (r < 0)
goto fail;
@@ -778,6 +784,8 @@ void manager_free(Manager *m) {
hashmap_free(m->watch_pids2);
hashmap_free(m->watch_bus);
+ set_free(m->failed_units);
+
sd_event_source_unref(m->signal_event_source);
sd_event_source_unref(m->notify_event_source);
sd_event_source_unref(m->time_change_event_source);
@@ -1799,7 +1807,7 @@ int manager_loop(Manager *m) {
RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
assert(m);
- m->exit_code = MANAGER_RUNNING;
+ m->exit_code = MANAGER_OK;
/* Release the path cache */
set_free_free(m->unit_path_cache);
@@ -1813,7 +1821,7 @@ int manager_loop(Manager *m) {
if (r < 0)
return r;
- while (m->exit_code == MANAGER_RUNNING) {
+ while (m->exit_code == MANAGER_OK) {
usec_t wait_usec;
if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
@@ -2463,10 +2471,12 @@ void manager_check_finished(Manager *m) {
m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
if (hashmap_size(m->jobs) > 0) {
+
if (m->jobs_in_progress_event_source) {
- uint64_t next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC;
- sd_event_source_set_time(m->jobs_in_progress_event_source, next);
+ sd_event_source_set_time(m->jobs_in_progress_event_source,
+ now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
}
+
return;
}
@@ -2858,8 +2868,51 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
}
const char *manager_get_runtime_prefix(Manager *m) {
+ assert(m);
return m->running_as == SYSTEMD_SYSTEM ?
"/run" :
getenv("XDG_RUNTIME_DIR");
}
+
+ManagerState manager_state(Manager *m) {
+ Unit *u;
+
+ assert(m);
+
+ /* Did we ever finish booting? If not then we are still starting up */
+ if (!dual_timestamp_is_set(&m->finish_timestamp))
+ return MANAGER_STARTING;
+
+ /* Is the special shutdown target queued? If so, we are in shutdown state */
+ u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
+ if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))
+ return MANAGER_STOPPING;
+
+ /* Are the rescue or emergency targets active or queued? If so we are in maintenance state */
+ u = manager_get_unit(m, SPECIAL_RESCUE_TARGET);
+ if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
+ (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
+ return MANAGER_MAINTENANCE;
+
+ u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET);
+ if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
+ (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
+ return MANAGER_MAINTENANCE;
+
+ /* Are there any failed units? If so, we are in degraded mode */
+ if (set_size(m->failed_units) > 0)
+ return MANAGER_DEGRADED;
+
+ return MANAGER_RUNNING;
+}
+
+static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
+ [MANAGER_STARTING] = "starting",
+ [MANAGER_RUNNING] = "running",
+ [MANAGER_DEGRADED] = "degraded",
+ [MANAGER_MAINTENANCE] = "maintenance",
+ [MANAGER_STOPPING] = "stopping",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);
diff --git a/src/core/manager.h b/src/core/manager.h
index e014abd..38f1c89 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -35,8 +35,18 @@
typedef struct Manager Manager;
-typedef enum ManagerExitCode {
+typedef enum ManagerState {
+ MANAGER_STARTING,
MANAGER_RUNNING,
+ MANAGER_DEGRADED,
+ MANAGER_MAINTENANCE,
+ MANAGER_STOPPING,
+ _MANAGER_STATE_MAX,
+ _MANAGER_STATE_INVALID = -1
+} ManagerState;
+
+typedef enum ManagerExitCode {
+ MANAGER_OK,
MANAGER_EXIT,
MANAGER_RELOAD,
MANAGER_REEXECUTE,
@@ -106,6 +116,9 @@ struct Manager {
Hashmap *watch_pids1; /* pid => Unit object n:1 */
Hashmap *watch_pids2; /* pid => Unit object n:1 */
+ /* A set which contains all currently failed units */
+ Set *failed_units;
+
sd_event_source *run_queue_event_source;
char *notify_socket;
@@ -321,3 +334,8 @@ void manager_flip_auto_status(Manager *m, bool enable);
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
const char *manager_get_runtime_prefix(Manager *m);
+
+ManagerState manager_state(Manager *m);
+
+const char *manager_state_to_string(ManagerState m) _const_;
+ManagerState manager_state_from_string(const char *s) _pure_;
diff --git a/src/core/unit.c b/src/core/unit.c
index aa723cb..5c98843 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -471,6 +471,8 @@ void unit_free(Unit *u) {
free(u->cgroup_path);
}
+ set_remove(u->manager->failed_units, u);
+
free(u->description);
strv_free(u->documentation);
free(u->fragment_path);
@@ -1507,6 +1509,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
m = u->manager;
+ /* Update timestamps for state changes */
if (m->n_reloading <= 0) {
dual_timestamp ts;
@@ -1523,6 +1526,13 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
u->active_exit_timestamp = ts;
}
+ /* Keep track of failed of units */
+ if (ns == UNIT_FAILED && os != UNIT_FAILED)
+ set_put(u->manager->failed_units, u);
+ else if (os == UNIT_FAILED && ns != UNIT_FAILED)
+ set_remove(u->manager->failed_units, u);
+
+ /* Make sure the cgroup is always removed when we become inactive */
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
unit_destroy_cgroup(u);
commit 0325941fff60888ff3486f271b0d513a75f9a324
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 12 20:54:29 2014 +0100
sd-login: add sd_machine_get_class() call
diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4
index 9c29169..290eabe 100644
--- a/src/libsystemd/libsystemd.sym.m4
+++ b/src/libsystemd/libsystemd.sym.m4
@@ -122,6 +122,13 @@ global:
sd_session_is_remote;
sd_session_get_remote_user;
sd_session_get_remote_host;
+local:
+ *;
+};
+
+LIBSYSTEMD_211 {
+global:
+ sd_machine_get_class;
m4_ifdef(`ENABLE_KDBUS',
/* sd-bus */
@@ -389,6 +396,4 @@ m4_ifdef(`ENABLE_KDBUS',
sd_utf8_is_valid;
sd_ascii_is_valid;
)
-local:
- *;
-};
+} LIBSYSTEMD_209;
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
index ef67040..4ad250e 100644
--- a/src/login/sd-login.c
+++ b/src/login/sd-login.c
@@ -249,9 +249,7 @@ _public_ int sd_session_is_active(const char *session) {
if (!s)
return -EIO;
- r = parse_boolean(s);
-
- return r;
+ return parse_boolean(s);
}
_public_ int sd_session_is_remote(const char *session) {
@@ -269,9 +267,7 @@ _public_ int sd_session_is_remote(const char *session) {
if (!s)
return -EIO;
- r = parse_boolean(s);
-
- return r;
+ return parse_boolean(s);
}
_public_ int sd_session_get_state(const char *session, char **state) {
@@ -308,16 +304,13 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
return r;
r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
-
if (r < 0)
return r;
if (!s)
return -EIO;
- r = parse_uid(s, uid);
-
- return r;
+ return parse_uid(s, uid);
}
static int session_get_string(const char *session, const char *field, char **value) {
@@ -533,6 +526,8 @@ static int seat_get_can(const char *seat, const char *variable) {
_cleanup_free_ char *p = NULL, *s = NULL;
int r;
+ assert_return(variable, -EINVAL);
+
r = file_of_seat(seat, &p);
if (r < 0)
return r;
@@ -542,13 +537,10 @@ static int seat_get_can(const char *seat, const char *variable) {
NULL);
if (r < 0)
return r;
+ if (!s)
+ return 0;
- if (s)
- r = parse_boolean(s);
- else
- r = 0;
-
- return r;
+ return parse_boolean(s);
}
_public_ int sd_seat_can_multi_session(const char *seat) {
@@ -633,6 +625,8 @@ _public_ int sd_get_machine_names(char ***machines) {
char **l = NULL, **a, **b;
int r;
+ assert_return(machines, -EINVAL);
+
r = get_files_in_directory("/run/systemd/machines/", &l);
if (r < 0)
return r;
@@ -658,6 +652,27 @@ _public_ int sd_get_machine_names(char ***machines) {
return r;
}
+_public_ int sd_machine_get_class(const char *machine, char **class) {
+ _cleanup_free_ char *c = NULL;
+ const char *p;
+ int r;
+
+ assert_return(filename_is_safe(machine), -EINVAL);
+ assert_return(class, -EINVAL);
+
+ p = strappenda("/run/systemd/machines/", machine);
+ r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
+ if (r < 0)
+ return r;
+ if (!c)
+ return -EIO;
+
+ *class = c;
+ c = NULL;
+
+ return 0;
+}
+
static inline int MONITOR_TO_FD(sd_login_monitor *m) {
return (int) (unsigned long) m - 1;
}
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index 6de6932..d6cfbc3 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -153,6 +153,9 @@ int sd_seat_can_tty(const char *seat);
/* Return whether the seat is graphics capable, i.e. suitable for showing graphical UIs */
int sd_seat_can_graphical(const char *seat);
+/* Return the class of machine */
+int sd_machine_get_class(const char *machine, char **class);
+
/* Get all seats, store in *seats. Returns the number of seats. If
* seats is NULL only returns number of seats. */
int sd_get_seats(char ***seats);
More information about the systemd-commits
mailing list