#include "socket-util.h"
#include "fileio.h"
-static const char *arg_type = NULL;
-static const char *arg_load_state = NULL;
-static char **arg_property = NULL;
+static char **arg_types = NULL;
+static char **arg_load_states = NULL;
+static char **arg_properties = NULL;
static bool arg_all = false;
static const char *arg_job_mode = "replace";
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
if (arg_failed)
return streq(u->active_state, "failed");
- return (!arg_type || ((dot = strrchr(u->id, '.')) &&
- streq(dot+1, arg_type))) &&
- (!arg_load_state || streq(u->load_state, arg_load_state)) &&
+ return (!arg_types || ((dot = strrchr(u->id, '.')) &&
+ strv_find(arg_types, dot+1))) &&
+ (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
(arg_all || !(streq(u->active_state, "inactive")
|| u->following[0]) || u->job_id > 0);
}
for (u = unit_infos; u < unit_infos + c; u++) {
char _cleanup_free_ *e = NULL;
- const char *on_loaded, *off_loaded;
- const char *on_active, *off_active;
+ const char *on_loaded, *off_loaded, *on = "";
+ const char *on_active, *off_active, *off = "";
if (!output_show_unit(u))
continue;
n_shown++;
if (streq(u->load_state, "error")) {
- on_loaded = ansi_highlight_red(true);
- off_loaded = ansi_highlight_red(false);
+ on_loaded = on = ansi_highlight_red(true);
+ off_loaded = off = ansi_highlight_red(false);
} else
on_loaded = off_loaded = "";
if (streq(u->active_state, "failed")) {
- on_active = ansi_highlight_red(true);
- off_active = ansi_highlight_red(false);
+ on_active = on = ansi_highlight_red(true);
+ off_active = off = ansi_highlight_red(false);
} else
on_active = off_active = "";
e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
- printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
- id_len, e ? e : u->id,
+ printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
+ on, id_len, e ? e : u->id, off,
on_loaded, u->load_state, off_loaded,
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
static bool output_show_unit_file(const UnitFileList *u) {
const char *dot;
- return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
+ return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
}
static void output_unit_file_list(const UnitFileList *units, unsigned c) {
return list_dependencies_one(bus, u, 0, NULL, 0);
}
+struct job_info {
+ uint32_t id;
+ char *name, *type, *state;
+};
+
+static void list_jobs_print(struct job_info* jobs, size_t n) {
+ size_t i;
+ struct job_info *j;
+ const char *on, *off;
+ bool shorten = false;
+
+ assert(n == 0 || jobs);
+
+ if (n == 0) {
+ on = ansi_highlight_green(true);
+ off = ansi_highlight_green(false);
+
+ printf("%sNo jobs running.%s\n", on, off);
+ return;
+ }
+
+ pager_open_if_enabled();
+
+ {
+ /* JOB UNIT TYPE STATE */
+ unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
+
+ for (i = 0, j = jobs; i < n; i++, j++) {
+ assert(j->name && j->type && j->state);
+ l0 = MAX(l0, decimal_str_max(j->id));
+ l1 = MAX(l1, strlen(j->name));
+ l2 = MAX(l2, strlen(j->type));
+ l3 = MAX(l3, strlen(j->state));
+ }
+
+ if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
+ l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
+ shorten = true;
+ }
+
+ if (on_tty())
+ printf("%*s %-*s %-*s %-*s\n",
+ l0, "JOB",
+ l1, "UNIT",
+ l2, "TYPE",
+ l3, "STATE");
+
+ for (i = 0, j = jobs; i < n; i++, j++) {
+ char _cleanup_free_ *e = NULL;
+
+ if (streq(j->state, "running")) {
+ on = ansi_highlight(true);
+ off = ansi_highlight(false);
+ } else
+ on = off = "";
+
+ e = shorten ? ellipsize(j->name, l1, 33) : NULL;
+ printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
+ l0, j->id,
+ on, l1, e ? e : j->name, off,
+ l2, j->type,
+ on, l3, j->state, off);
+ }
+ }
+
+ on = ansi_highlight(true);
+ off = ansi_highlight(false);
+
+ if (on_tty())
+ printf("\n%s%zu jobs listed%s.\n", on, n, off);
+}
+
static int list_jobs(DBusConnection *bus, char **args) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub, sub2;
- unsigned k = 0;
int r;
-
- pager_open_if_enabled();
+ struct job_info *jobs = NULL;
+ size_t size = 0, used = 0;
r = bus_method_call_with_reply(
bus,
dbus_message_iter_recurse(&iter, &sub);
- if (on_tty())
- printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
-
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
const char *name, *type, *state, *job_path, *unit_path;
uint32_t id;
- char _cleanup_free_ *e = NULL;
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
log_error("Failed to parse reply.");
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
log_error("Failed to parse reply.");
- return -EIO;
+ r = -EIO;
+ goto finish;
}
- e = arg_full ? NULL : ellipsize(name, 25, 33);
- printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
+ if (!greedy_realloc((void**) &jobs, &size,
+ sizeof(struct job_info) * (used + 1))) {
+ r = log_oom();
+ goto finish;
+ }
- k++;
+ jobs[used++] = (struct job_info) { id,
+ strdup(name),
+ strdup(type),
+ strdup(state) };
+ if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
+ r = log_oom();
+ goto finish;
+ }
dbus_message_iter_next(&sub);
}
- if (on_tty())
- printf("\n%u jobs listed.\n", k);
+ list_jobs_print(jobs, used);
+
+ finish:
+ while (used--) {
+ free(jobs[used].name);
+ free(jobs[used].type);
+ free(jobs[used].state);
+ }
+ free(jobs);
return 0;
}
static int wait_for_jobs(DBusConnection *bus, Set *s) {
int r = 0;
- WaitData d;
+ WaitData d = { .set = s };
assert(bus);
assert(s);
- zero(d);
- d.set = s;
-
if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
return log_oom();
const char *source_path;
const char *default_control_group;
+ char **dropin_paths;
+
const char *load_error;
const char *result;
unsigned n_connections;
bool accept;
+ /* Pairs of type, path */
char **listen;
/* Device */
on_tty() * OUTPUT_COLOR |
!arg_quiet * OUTPUT_WARN_CUTOFF |
arg_full * OUTPUT_FULL_WIDTH;
+ int maxlen = 8; /* a value that'll suffice most of the time */
+ char **t, **t2;
assert(i);
+ STRV_FOREACH_PAIR(t, t2, i->listen)
+ maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
+ if (i->accept)
+ maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
+ if (i->main_pid > 0)
+ maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
+ else if (i->control_pid > 0)
+ maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
+
/* This shows pretty information about a unit. See
* print_property() for a low-level property printer */
printf("\n");
if (i->following)
- printf("\t Follow: unit currently follows state of %s\n", i->following);
+ printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
if (streq_ptr(i->load_state, "error")) {
on = ansi_highlight_red(true);
path = i->source_path ? i->source_path : i->fragment_path;
if (i->load_error)
- printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
+ printf(" %*s: %s%s%s (Reason: %s)\n",
+ maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
else if (path && i->unit_file_state)
- printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
+ printf(" %*s: %s%s%s (%s; %s)\n",
+ maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
else if (path)
- printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
+ printf(" %*s: %s%s%s (%s)\n",
+ maxlen, "Loaded", on, strna(i->load_state), off, path);
else
- printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
+ printf(" %*s: %s%s%s\n",
+ maxlen, "Loaded", on, strna(i->load_state), off);
+
+ if (!strv_isempty(i->dropin_paths)) {
+ char ** dropin;
+ char * dir = NULL;
+ bool last = false;
+
+ STRV_FOREACH(dropin, i->dropin_paths) {
+ if (! dir || last) {
+ printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
+
+ free(dir);
+
+ if (path_get_parent(*dropin, &dir) < 0) {
+ log_oom();
+ return;
+ }
+
+ printf("%s\n %*s %s", dir, maxlen, "",
+ draw_special_char(DRAW_TREE_RIGHT));
+ }
+
+ last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
+
+ printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
+ }
+
+ free(dir);
+ }
ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
on = off = "";
if (ss)
- printf("\t Active: %s%s (%s)%s",
- on,
- strna(i->active_state),
- ss,
- off);
+ printf(" %*s: %s%s (%s)%s",
+ maxlen, "Active", on, strna(i->active_state), ss, off);
else
- printf("\t Active: %s%s%s",
- on,
- strna(i->active_state),
- off);
+ printf(" %*s: %s%s%s",
+ maxlen, "Active", on, strna(i->active_state), off);
if (!isempty(i->result) && !streq(i->result, "success"))
printf(" (Result: %s)", i->result);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
if (s1)
- printf("\t start condition failed at %s; %s\n", s2, s1);
+ printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
else if (s2)
- printf("\t start condition failed at %s\n", s2);
+ printf(" %*s start condition failed at %s\n", maxlen, "", s2);
}
if (i->sysfs_path)
- printf("\t Device: %s\n", i->sysfs_path);
+ printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
if (i->where)
- printf("\t Where: %s\n", i->where);
+ printf(" %*s: %s\n", maxlen, "Where", i->where);
if (i->what)
- printf("\t What: %s\n", i->what);
+ printf(" %*s: %s\n", maxlen, "What", i->what);
- if (!strv_isempty(i->documentation)) {
- char **t;
- bool first = true;
+ STRV_FOREACH(t, i->documentation)
+ printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
- STRV_FOREACH(t, i->documentation) {
- if (first) {
- printf("\t Docs: %s\n", *t);
- first = false;
- } else
- printf("\t %s\n", *t);
- }
- }
-
- if (!strv_isempty(i->listen)) {
- char **t;
- bool first = true;
-
- STRV_FOREACH(t, i->listen) {
- if (first) {
- printf("\t Listen: %s\n", *t);
- first = false;
- } else
- printf("\t %s\n", *t);
- }
- }
+ STRV_FOREACH_PAIR(t, t2, i->listen)
+ printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
if (i->accept)
- printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
+ printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
LIST_FOREACH(exec, p, i->exec) {
- _cleanup_free_ char *t = NULL;
+ _cleanup_free_ char *argv = NULL;
bool good;
/* Only show exited processes here */
if (p->code == 0)
continue;
- t = strv_join(p->argv, " ");
- printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
+ argv = strv_join(p->argv, " ");
+ printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
good = is_clean_exit_lsb(p->code, p->status, NULL);
if (!good) {
}
if (i->main_pid > 0 || i->control_pid > 0) {
- printf("\t");
-
if (i->main_pid > 0) {
- printf("Main PID: %u", (unsigned) i->main_pid);
+ printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
if (i->running) {
- _cleanup_free_ char *t = NULL;
- get_process_comm(i->main_pid, &t);
- if (t)
- printf(" (%s)", t);
+ _cleanup_free_ char *comm = NULL;
+ get_process_comm(i->main_pid, &comm);
+ if (comm)
+ printf(" (%s)", comm);
} else if (i->exit_code > 0) {
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
printf("signal=%s", signal_to_string(i->exit_status));
printf(")");
}
- }
- if (i->main_pid > 0 && i->control_pid > 0)
- printf(";");
+ if (i->control_pid > 0)
+ printf(";");
+ }
if (i->control_pid > 0) {
- _cleanup_free_ char *t = NULL;
+ _cleanup_free_ char *c = NULL;
- printf(" Control: %u", (unsigned) i->control_pid);
+ printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
- get_process_comm(i->control_pid, &t);
- if (t)
- printf(" (%s)", t);
+ get_process_comm(i->control_pid, &c);
+ if (c)
+ printf(" (%s)", c);
}
printf("\n");
}
if (i->status_text)
- printf("\t Status: \"%s\"\n", i->status_text);
+ printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
if (i->default_control_group &&
(i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
unsigned c;
- printf("\t CGroup: %s\n", i->default_control_group);
+ printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
if (arg_transport != TRANSPORT_SSH) {
unsigned k = 0;
pid_t extra[2];
+ char prefix[maxlen + 4];
+ memset(prefix, ' ', sizeof(prefix) - 1);
+ prefix[sizeof(prefix) - 1] = '\0';
c = columns();
- if (c > 18)
- c -= 18;
+ if (c > sizeof(prefix) - 1)
+ c -= sizeof(prefix) - 1;
else
c = 0;
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
+ show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
+ c, false, extra, k, flags);
}
}
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
- char * buf, **l;
- if (asprintf(&buf, "%s: %s", type, path) < 0)
- return -ENOMEM;
-
- l = strv_append(i->listen, buf);
- free(buf);
-
- if (!l)
- return -ENOMEM;
-
- strv_free(i->listen);
- i->listen = l;
+ int r;
+
+ r = strv_extend(&i->listen, type);
+ if (r < 0)
+ return r;
+ r = strv_extend(&i->listen, path);
+ if (r < 0)
+ return r;
}
dbus_message_iter_next(&sub);
return 0;
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
+ int r = bus_parse_strv_iter(iter, &i->dropin_paths);
+ if (r < 0)
+ return r;
+
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
streq(name, "Documentation")) {
dbus_message_iter_recurse(iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
const char *s;
- char **l;
+ int r;
dbus_message_iter_get_basic(&sub, &s);
- l = strv_append(i->documentation, s);
- if (!l)
- return -ENOMEM;
-
- strv_free(i->documentation);
- i->documentation = l;
+ r = strv_extend(&i->documentation, s);
+ if (r < 0)
+ return r;
dbus_message_iter_next(&sub);
}
/* This is a low-level property printer, see
* print_status_info() for the nicer output */
- if (arg_property && !strv_find(arg_property, name))
+ if (arg_properties && !strv_find(arg_properties, name))
return 0;
switch (dbus_message_iter_get_arg_type(iter)) {
printf("%s={ value=%s ; next_elapse=%s }\n",
base,
- format_timespan(timespan1, sizeof(timespan1), value),
- format_timespan(timespan2, sizeof(timespan2), next_elapse));
+ format_timespan(timespan1, sizeof(timespan1), value, 0),
+ format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
}
dbus_message_iter_next(&sub);
dbus_message_iter_recurse(iter, &sub);
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- ExecStatusInfo info;
+ ExecStatusInfo info = {};
- zero(info);
if (exec_status_info_deserialize(&sub, &info) >= 0) {
char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
char _cleanup_free_ *t;
const char *interface = "";
int r;
DBusMessageIter iter, sub, sub2, sub3;
- UnitStatusInfo info;
+ UnitStatusInfo info = {};
ExecStatusInfo *p;
assert(path);
assert(new_line);
- zero(info);
-
r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
}
strv_free(info.documentation);
+ strv_free(info.dropin_paths);
strv_free(info.listen);
if (!streq_ptr(info.active_state, "active") &&
#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
const char *verb = args[0];
unsigned f = 1, t = 1;
- LookupPaths paths;
+ LookupPaths paths = {};
if (arg_scope != UNIT_FILE_SYSTEM)
return 0;
/* Processes all SysV units, and reshuffles the array so that
* afterwards only the native units remain */
- zero(paths);
r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
if (r < 0)
return r;
puts(SYSTEMD_FEATURES);
return 0;
- case 't':
- if (streq(optarg, "help")) {
- help_types();
- return 0;
- }
+ case 't': {
+ char *word, *state;
+ size_t size;
- if (unit_type_from_string(optarg) >= 0) {
- arg_type = optarg;
- break;
- }
- if (unit_load_state_from_string(optarg) >= 0) {
- arg_load_state = optarg;
- break;
+ FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ char _cleanup_free_ *type;
+
+ type = strndup(word, size);
+ if (!type)
+ return -ENOMEM;
+
+ if (streq(type, "help")) {
+ help_types();
+ return 0;
+ }
+
+ if (unit_type_from_string(type) >= 0) {
+ if (strv_push(&arg_types, type))
+ return log_oom();
+ type = NULL;
+ continue;
+ }
+
+ if (unit_load_state_from_string(optarg) >= 0) {
+ if (strv_push(&arg_load_states, type))
+ return log_oom();
+ type = NULL;
+ continue;
+ }
+
+ log_error("Unkown unit type or load state '%s'.", type);
+ log_info("Use -t help to see a list of allowed values.");
+ return -EINVAL;
}
- log_error("Unkown unit type or load state '%s'.",
- optarg);
- log_info("Use -t help to see a list of allowed values.");
- return -EINVAL;
+
+ break;
+ }
+
case 'p': {
- char *word, *state;
- size_t size;
/* Make sure that if the empty property list
was specified, we won't show any properties. */
- const char *source = isempty(optarg) ? " " : optarg;
-
- FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
- char _cleanup_free_ *prop;
- char **tmp;
+ if (isempty(optarg) && !arg_properties) {
+ arg_properties = strv_new(NULL, NULL);
+ if (!arg_properties)
+ return log_oom();
+ } else {
+ char *word, *state;
+ size_t size;
- prop = strndup(word, size);
- if (!prop)
- return -ENOMEM;
+ FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ char *prop;
- tmp = strv_append(arg_property, prop);
- if (!tmp)
- return -ENOMEM;
+ prop = strndup(word, size);
+ if (!prop)
+ return log_oom();
- strv_free(arg_property);
- arg_property = tmp;
+ if (strv_push(&arg_properties, prop)) {
+ free(prop);
+ return log_oom();
+ }
+ }
}
/* If the user asked for a particular
} else {
char *e = NULL;
long hour, minute;
- struct tm tm;
+ struct tm tm = {};
time_t s;
usec_t n;
n = now(CLOCK_REALTIME);
s = (time_t) (n / USEC_PER_SEC);
- zero(tm);
assert_se(localtime_r(&s, &tm));
tm.tm_hour = (int) hour;
}
static int talk_initctl(void) {
- struct init_request request = {0};
+ struct init_request request = {};
int r;
int _cleanup_close_ fd = -1;
char rl;
static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
int _cleanup_close_ fd;
- struct msghdr msghdr;
- struct iovec iovec[2];
- union sockaddr_union sockaddr;
- struct sd_shutdown_command c;
+ struct sd_shutdown_command c = {
+ .usec = t,
+ .mode = mode,
+ .dry_run = dry_run,
+ .warn_wall = warn,
+ };
+ union sockaddr_union sockaddr = {
+ .un.sun_family = AF_UNIX,
+ .un.sun_path = "/run/systemd/shutdownd",
+ };
+ struct iovec iovec[2] = {
+ {.iov_base = (char*) &c,
+ .iov_len = offsetof(struct sd_shutdown_command, wall_message),
+ }
+ };
+ struct msghdr msghdr = {
+ .msg_name = &sockaddr,
+ .msg_namelen = offsetof(struct sockaddr_un, sun_path)
+ + sizeof("/run/systemd/shutdownd") - 1,
+ .msg_iov = iovec,
+ .msg_iovlen = 1,
+ };
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
- zero(c);
- c.usec = t;
- c.mode = mode;
- c.dry_run = dry_run;
- c.warn_wall = warn;
-
- zero(sockaddr);
- sockaddr.sa.sa_family = AF_UNIX;
- strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
-
- zero(msghdr);
- msghdr.msg_name = &sockaddr;
- msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
-
- zero(iovec);
- iovec[0].iov_base = (char*) &c;
- iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
-
- if (isempty(message))
- msghdr.msg_iovlen = 1;
- else {
+ if (!isempty(message)) {
iovec[1].iov_base = (char*) message;
iovec[1].iov_len = strlen(message);
- msghdr.msg_iovlen = 2;
+ msghdr.msg_iovlen++;
}
- msghdr.msg_iov = iovec;
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
return -errno;
dbus_shutdown();
- strv_free(arg_property);
+ strv_free(arg_types);
+ strv_free(arg_load_states);
+ strv_free(arg_properties);
pager_close();
ask_password_agent_close();