1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4
This file is part of systemd.
6
Copyright 2010 Lennart Poettering
8
systemd is free software; you can redistribute it and/or modify it
9
under the terms of the GNU Lesser General Public License as published by
10
the Free Software Foundation; either version 2.1 of the License, or
11
(at your option) any later version.
13
systemd is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
Lesser General Public License for more details.
18
You should have received a copy of the GNU Lesser General Public License
19
along with systemd; If not, see <http://www.gnu.org/licenses/>.
22
#include <sys/reboot.h>
29
#include <sys/ioctl.h>
33
#include <sys/socket.h>
36
#include <sys/prctl.h>
37
#include <dbus/dbus.h>
39
#include <systemd/sd-daemon.h>
40
#include <systemd/sd-shutdown.h>
41
#include <systemd/sd-login.h>
47
#include "utmp-wtmp.h"
50
#include "path-util.h"
52
#include "dbus-common.h"
53
#include "cgroup-show.h"
54
#include "cgroup-util.h"
56
#include "path-lookup.h"
57
#include "conf-parser.h"
58
#include "exit-status.h"
59
#include "bus-errors.h"
61
#include "unit-name.h"
63
#include "spawn-ask-password-agent.h"
64
#include "spawn-polkit-agent.h"
66
#include "logs-show.h"
67
#include "path-util.h"
68
#include "socket-util.h"
71
static char **arg_types = NULL;
72
static char **arg_load_states = NULL;
73
static char **arg_properties = NULL;
74
static bool arg_all = false;
75
static enum dependency {
80
} arg_dependency = DEPENDENCY_FORWARD;
81
static const char *arg_job_mode = "replace";
82
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83
static bool arg_no_block = false;
84
static bool arg_no_legend = false;
85
static bool arg_no_pager = false;
86
static bool arg_no_wtmp = false;
87
static bool arg_no_wall = false;
88
static bool arg_no_reload = false;
89
static bool arg_show_types = false;
90
static bool arg_ignore_inhibitors = false;
91
static bool arg_dry = false;
92
static bool arg_quiet = false;
93
static bool arg_full = false;
94
static int arg_force = 0;
95
static bool arg_ask_password = true;
96
static bool arg_failed = false;
97
static bool arg_runtime = false;
98
static char **arg_wall = NULL;
99
static const char *arg_kill_who = NULL;
100
static int arg_signal = SIGTERM;
101
static const char *arg_root = NULL;
102
static usec_t arg_when = 0;
124
ACTION_CANCEL_SHUTDOWN,
126
} arg_action = ACTION_SYSTEMCTL;
127
static enum transport {
131
} arg_transport = TRANSPORT_NORMAL;
132
static const char *arg_host = NULL;
133
static unsigned arg_lines = 10;
134
static OutputMode arg_output = OUTPUT_SHORT;
135
static bool arg_plain = false;
137
static bool private_bus = false;
139
static int daemon_reload(DBusConnection *bus, char **args);
140
static void halt_now(enum action a);
142
static void pager_open_if_enabled(void) {
150
static void ask_password_agent_open_if_enabled(void) {
152
/* Open the password agent as a child process if necessary */
154
if (!arg_ask_password)
157
if (arg_scope != UNIT_FILE_SYSTEM)
160
ask_password_agent_open();
164
static void polkit_agent_open_if_enabled(void) {
166
/* Open the polkit agent as a child process if necessary */
168
if (!arg_ask_password)
171
if (arg_scope != UNIT_FILE_SYSTEM)
178
static const char *ansi_highlight(bool b) {
183
return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
186
static const char *ansi_highlight_red(bool b) {
191
return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
194
static const char *ansi_highlight_green(bool b) {
199
return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
202
static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
205
if (!dbus_error_is_set(error))
208
if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
209
dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
210
dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
211
dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
212
return EXIT_NOPERMISSION;
214
if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
215
return EXIT_NOTINSTALLED;
217
if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
218
dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
219
return EXIT_NOTIMPLEMENTED;
221
if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
222
return EXIT_NOTCONFIGURED;
230
static void warn_wall(enum action a) {
231
static const char *table[_ACTION_MAX] = {
232
[ACTION_HALT] = "The system is going down for system halt NOW!",
233
[ACTION_REBOOT] = "The system is going down for reboot NOW!",
234
[ACTION_POWEROFF] = "The system is going down for power-off NOW!",
235
[ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
236
[ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
237
[ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
238
[ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
245
_cleanup_free_ char *p;
247
p = strv_join(arg_wall, " ");
262
utmp_wall(table[a], NULL);
265
static bool avoid_bus(void) {
267
if (running_in_chroot() > 0)
270
if (sd_booted() <= 0)
273
if (!isempty(arg_root))
276
if (arg_scope == UNIT_FILE_GLOBAL)
282
static int compare_unit_info(const void *a, const void *b) {
284
const struct unit_info *u = a, *v = b;
286
d1 = strrchr(u->id, '.');
287
d2 = strrchr(v->id, '.');
292
r = strcasecmp(d1, d2);
297
return strcasecmp(u->id, v->id);
300
static bool output_show_unit(const struct unit_info *u) {
304
return streq(u->active_state, "failed");
306
return (!arg_types || ((dot = strrchr(u->id, '.')) &&
307
strv_find(arg_types, dot+1))) &&
308
(!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
309
(arg_all || !(streq(u->active_state, "inactive")
310
|| u->following[0]) || u->job_id > 0);
313
static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
314
unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
315
const struct unit_info *u;
318
max_id_len = sizeof("UNIT")-1;
319
active_len = sizeof("ACTIVE")-1;
320
sub_len = sizeof("SUB")-1;
321
job_len = sizeof("JOB")-1;
324
for (u = unit_infos; u < unit_infos + c; u++) {
325
if (!output_show_unit(u))
328
max_id_len = MAX(max_id_len, strlen(u->id));
329
active_len = MAX(active_len, strlen(u->active_state));
330
sub_len = MAX(sub_len, strlen(u->sub_state));
331
if (u->job_id != 0) {
332
job_len = MAX(job_len, strlen(u->job_type));
339
id_len = MIN(max_id_len, 25u);
340
basic_len = 5 + id_len + 5 + active_len + sub_len;
342
basic_len += job_len + 1;
343
if (basic_len < (unsigned) columns()) {
344
unsigned extra_len, incr;
345
extra_len = columns() - basic_len;
346
/* Either UNIT already got 25, or is fully satisfied.
347
* Grant up to 25 to DESC now. */
348
incr = MIN(extra_len, 25u);
351
/* split the remaining space between UNIT and DESC,
352
* but do not give UNIT more than it needs. */
354
incr = MIN(extra_len / 2, max_id_len - id_len);
356
desc_len += extra_len - incr;
362
for (u = unit_infos; u < unit_infos + c; u++) {
363
_cleanup_free_ char *e = NULL;
364
const char *on_loaded, *off_loaded, *on = "";
365
const char *on_active, *off_active, *off = "";
367
if (!output_show_unit(u))
370
if (!n_shown && !arg_no_legend) {
371
printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
372
active_len, "ACTIVE", sub_len, "SUB");
374
printf("%-*s ", job_len, "JOB");
375
if (!arg_full && arg_no_pager)
376
printf("%.*s\n", desc_len, "DESCRIPTION");
378
printf("%s\n", "DESCRIPTION");
383
if (streq(u->load_state, "error")) {
384
on_loaded = on = ansi_highlight_red(true);
385
off_loaded = off = ansi_highlight_red(false);
387
on_loaded = off_loaded = "";
389
if (streq(u->active_state, "failed")) {
390
on_active = on = ansi_highlight_red(true);
391
off_active = off = ansi_highlight_red(false);
393
on_active = off_active = "";
395
e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
397
printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
398
on, id_len, e ? e : u->id, off,
399
on_loaded, u->load_state, off_loaded,
400
on_active, active_len, u->active_state,
401
sub_len, u->sub_state, off_active,
402
job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
403
if (!arg_full && arg_no_pager)
404
printf("%.*s\n", desc_len, u->description);
406
printf("%s\n", u->description);
409
if (!arg_no_legend) {
410
const char *on, *off;
413
printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
414
"ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
415
"SUB = The low-level unit activation state, values depend on unit type.\n");
417
printf("JOB = Pending job for the unit.\n");
419
on = ansi_highlight(true);
420
off = ansi_highlight(false);
422
on = ansi_highlight_red(true);
423
off = ansi_highlight_red(false);
427
printf("%s%u loaded units listed.%s\n"
428
"To show all installed unit files use 'systemctl list-unit-files'.\n",
431
printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
432
"To show all installed unit files use 'systemctl list-unit-files'.\n",
437
static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
438
struct unit_info **unit_infos, unsigned *c) {
439
DBusMessageIter iter, sub;
447
r = bus_method_call_with_reply(
449
"org.freedesktop.systemd1",
450
"/org/freedesktop/systemd1",
451
"org.freedesktop.systemd1.Manager",
459
if (!dbus_message_iter_init(*reply, &iter) ||
460
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
461
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
462
log_error("Failed to parse reply.");
466
dbus_message_iter_recurse(&iter, &sub);
468
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
469
if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
472
bus_parse_unit_info(&sub, *unit_infos + *c);
475
dbus_message_iter_next(&sub);
481
static int list_units(DBusConnection *bus, char **args) {
482
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
483
_cleanup_free_ struct unit_info *unit_infos = NULL;
487
pager_open_if_enabled();
489
r = get_unit_list(bus, &reply, &unit_infos, &c);
493
qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
495
output_units_list(unit_infos, c);
500
static int get_triggered_units(DBusConnection *bus, const char* unit_path,
503
const char *interface = "org.freedesktop.systemd1.Unit",
504
*triggers_property = "Triggers";
505
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
506
DBusMessageIter iter, sub;
509
r = bus_method_call_with_reply(bus,
510
"org.freedesktop.systemd1",
512
"org.freedesktop.DBus.Properties",
516
DBUS_TYPE_STRING, &interface,
517
DBUS_TYPE_STRING, &triggers_property,
522
if (!dbus_message_iter_init(reply, &iter) ||
523
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
524
log_error("Failed to parse reply.");
528
dbus_message_iter_recurse(&iter, &sub);
529
dbus_message_iter_recurse(&sub, &iter);
532
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
535
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
536
log_error("Failed to parse reply.");
540
dbus_message_iter_get_basic(&sub, &unit);
541
r = strv_extend(triggered, unit);
545
dbus_message_iter_next(&sub);
551
static int get_listening(DBusConnection *bus, const char* unit_path,
552
char*** listen, unsigned *c)
554
const char *interface = "org.freedesktop.systemd1.Socket",
555
*listen_property = "Listen";
556
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
557
DBusMessageIter iter, sub;
560
r = bus_method_call_with_reply(bus,
561
"org.freedesktop.systemd1",
563
"org.freedesktop.DBus.Properties",
567
DBUS_TYPE_STRING, &interface,
568
DBUS_TYPE_STRING, &listen_property,
573
if (!dbus_message_iter_init(reply, &iter) ||
574
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
575
log_error("Failed to parse reply.");
579
dbus_message_iter_recurse(&iter, &sub);
580
dbus_message_iter_recurse(&sub, &iter);
583
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
584
DBusMessageIter sub2;
585
const char *type, *path;
587
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
588
log_error("Failed to parse reply.");
592
dbus_message_iter_recurse(&sub, &sub2);
594
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
595
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
596
r = strv_extend(listen, type);
600
r = strv_extend(listen, path);
607
dbus_message_iter_next(&sub);
619
/* Note: triggered is a list here, although it almost certainly
620
* will always be one unit. Nevertheless, dbus API allows for multiple
621
* values, so let's follow that.*/
624
/* The strv above is shared. free is set only in the first one. */
628
static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
629
int o = strcmp(a->path, b->path);
631
o = strcmp(a->type, b->type);
635
static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
636
struct socket_info *s;
637
unsigned pathlen = sizeof("LISTEN") - 1,
638
typelen = (sizeof("TYPE") - 1) * arg_show_types,
639
socklen = sizeof("UNIT") - 1,
640
servlen = sizeof("ACTIVATES") - 1;
641
const char *on, *off;
643
for (s = socket_infos; s < socket_infos + cs; s++) {
647
socklen = MAX(socklen, strlen(s->id));
649
typelen = MAX(typelen, strlen(s->type));
650
pathlen = MAX(pathlen, strlen(s->path));
652
STRV_FOREACH(a, s->triggered)
653
tmp += strlen(*a) + 2*(a != s->triggered);
654
servlen = MAX(servlen, tmp);
658
printf("%-*s %-*.*s%-*s %s\n",
660
typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
664
for (s = socket_infos; s < socket_infos + cs; s++) {
668
printf("%-*s %-*s %-*s",
669
pathlen, s->path, typelen, s->type, socklen, s->id);
672
pathlen, s->path, socklen, s->id);
673
STRV_FOREACH(a, s->triggered)
675
a == s->triggered ? "" : ",", *a);
679
on = ansi_highlight(true);
680
off = ansi_highlight(false);
683
on = ansi_highlight_red(true);
684
off = ansi_highlight_red(false);
687
printf("%s%u sockets listed.%s\n", on, cs, off);
689
printf("Pass --all to see loaded but inactive sockets, too.\n");
694
static int list_sockets(DBusConnection *bus, char **args) {
695
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
696
_cleanup_free_ struct unit_info *unit_infos = NULL;
697
struct socket_info *socket_infos = NULL;
698
const struct unit_info *u;
699
struct socket_info *s;
700
unsigned cu = 0, cs = 0;
704
pager_open_if_enabled();
706
r = get_unit_list(bus, &reply, &unit_infos, &cu);
710
for (u = unit_infos; u < unit_infos + cu; u++) {
712
_cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
715
if (!output_show_unit(u))
718
if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
721
r = get_triggered_units(bus, u->unit_path, &triggered);
725
r = get_listening(bus, u->unit_path, &listen, &c);
729
if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
734
for (i = 0; i < c; i++)
735
socket_infos[cs + i] = (struct socket_info) {
738
.path = listen[i*2 + 1],
739
.triggered = triggered,
740
.own_triggered = i==0,
743
/* from this point on we will cleanup those socket_infos */
746
listen = triggered = NULL; /* avoid cleanup */
749
qsort(socket_infos, cs, sizeof(struct socket_info),
750
(__compar_fn_t) socket_info_compare);
752
output_sockets_list(socket_infos, cs);
755
assert(cs == 0 || socket_infos);
756
for (s = socket_infos; s < socket_infos + cs; s++) {
759
if (s->own_triggered)
760
strv_free(s->triggered);
767
static int compare_unit_file_list(const void *a, const void *b) {
769
const UnitFileList *u = a, *v = b;
771
d1 = strrchr(u->path, '.');
772
d2 = strrchr(v->path, '.');
777
r = strcasecmp(d1, d2);
782
return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
785
static bool output_show_unit_file(const UnitFileList *u) {
788
return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
791
static void output_unit_file_list(const UnitFileList *units, unsigned c) {
792
unsigned max_id_len, id_cols, state_cols, n_shown = 0;
793
const UnitFileList *u;
795
max_id_len = sizeof("UNIT FILE")-1;
796
state_cols = sizeof("STATE")-1;
797
for (u = units; u < units + c; u++) {
798
if (!output_show_unit_file(u))
801
max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
802
state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
807
id_cols = MIN(max_id_len, 25u);
808
basic_cols = 1 + id_cols + state_cols;
809
if (basic_cols < (unsigned) columns())
810
id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
812
id_cols = max_id_len;
815
printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
817
for (u = units; u < units + c; u++) {
818
_cleanup_free_ char *e = NULL;
819
const char *on, *off;
822
if (!output_show_unit_file(u))
827
if (u->state == UNIT_FILE_MASKED ||
828
u->state == UNIT_FILE_MASKED_RUNTIME ||
829
u->state == UNIT_FILE_DISABLED ||
830
u->state == UNIT_FILE_INVALID) {
831
on = ansi_highlight_red(true);
832
off = ansi_highlight_red(false);
833
} else if (u->state == UNIT_FILE_ENABLED) {
834
on = ansi_highlight_green(true);
835
off = ansi_highlight_green(false);
839
id = path_get_file_name(u->path);
841
e = arg_full ? NULL : ellipsize(id, id_cols, 33);
843
printf("%-*s %s%-*s%s\n",
845
on, state_cols, unit_file_state_to_string(u->state), off);
849
printf("\n%u unit files listed.\n", n_shown);
852
static int list_unit_files(DBusConnection *bus, char **args) {
853
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
854
_cleanup_free_ UnitFileList *units = NULL;
855
DBusMessageIter iter, sub, sub2;
856
unsigned c = 0, n_units = 0;
859
pager_open_if_enabled();
866
h = hashmap_new(string_hash_func, string_compare_func);
870
r = unit_file_get_list(arg_scope, arg_root, h);
872
unit_file_list_free(h);
873
log_error("Failed to get unit file list: %s", strerror(-r));
877
n_units = hashmap_size(h);
878
units = new(UnitFileList, n_units);
880
unit_file_list_free(h);
884
HASHMAP_FOREACH(u, h, i) {
885
memcpy(units + c++, u, sizeof(UnitFileList));
891
r = bus_method_call_with_reply(
893
"org.freedesktop.systemd1",
894
"/org/freedesktop/systemd1",
895
"org.freedesktop.systemd1.Manager",
903
if (!dbus_message_iter_init(reply, &iter) ||
904
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
905
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
906
log_error("Failed to parse reply.");
910
dbus_message_iter_recurse(&iter, &sub);
912
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
916
assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
921
n_units = MAX(2*c, 16u);
922
w = realloc(units, sizeof(struct UnitFileList) * n_units);
931
dbus_message_iter_recurse(&sub, &sub2);
933
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
934
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
935
log_error("Failed to parse reply.");
939
u->state = unit_file_state_from_string(state);
941
dbus_message_iter_next(&sub);
947
qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
948
output_unit_file_list(units, c);
954
static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
956
_cleanup_free_ char *n = NULL;
958
size_t max_len = MAX(columns(),20u);
961
for (i = level - 1; i >= 0; i--) {
963
if(len > max_len - 3 && !arg_full) {
964
printf("%s...\n",max_len % 2 ? "" : " ");
967
printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
970
if(len > max_len - 3 && !arg_full) {
971
printf("%s...\n",max_len % 2 ? "" : " ");
974
printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
978
printf("%s\n", name);
982
n = ellipsize(name, max_len-len, 100);
990
static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
991
static const char *dependencies[] = {
992
[DEPENDENCY_FORWARD] = "Requires\0"
993
"RequiresOverridable\0"
995
"RequisiteOverridable\0"
997
[DEPENDENCY_REVERSE] = "RequiredBy\0"
998
"RequiredByOverridable\0"
1001
[DEPENDENCY_AFTER] = "After\0",
1002
[DEPENDENCY_BEFORE] = "Before\0",
1005
_cleanup_free_ char *path;
1006
const char *interface = "org.freedesktop.systemd1.Unit";
1008
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1009
DBusMessageIter iter, sub, sub2, sub3;
1018
path = unit_dbus_path_from_name(name);
1024
r = bus_method_call_with_reply(
1026
"org.freedesktop.systemd1",
1028
"org.freedesktop.DBus.Properties",
1032
DBUS_TYPE_STRING, &interface,
1037
if (!dbus_message_iter_init(reply, &iter) ||
1038
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1039
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1040
log_error("Failed to parse reply.");
1045
dbus_message_iter_recurse(&iter, &sub);
1047
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1050
assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1051
dbus_message_iter_recurse(&sub, &sub2);
1053
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1054
log_error("Failed to parse reply.");
1059
if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1060
log_error("Failed to parse reply.");
1065
dbus_message_iter_recurse(&sub2, &sub3);
1066
dbus_message_iter_next(&sub);
1068
assert(arg_dependency < ELEMENTSOF(dependencies));
1069
if (!nulstr_contains(dependencies[arg_dependency], prop))
1072
if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1073
if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1074
DBusMessageIter sub4;
1075
dbus_message_iter_recurse(&sub3, &sub4);
1077
while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1080
assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1081
dbus_message_iter_get_basic(&sub4, &s);
1083
r = strv_extend(&ret, s);
1089
dbus_message_iter_next(&sub4);
1102
static int list_dependencies_compare(const void *_a, const void *_b) {
1103
const char **a = (const char**) _a, **b = (const char**) _b;
1104
if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1106
if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1108
return strcasecmp(*a, *b);
1111
static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1112
_cleanup_strv_free_ char **deps = NULL, **u;
1116
u = strv_append(*units, name);
1120
r = list_dependencies_get_dependencies(bus, name, &deps);
1124
qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1126
STRV_FOREACH(c, deps) {
1127
if (strv_contains(u, *c)) {
1129
r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1136
r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1140
if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1141
r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1154
static int list_dependencies(DBusConnection *bus, char **args) {
1155
_cleanup_free_ char *unit = NULL;
1156
_cleanup_strv_free_ char **units = NULL;
1162
unit = unit_name_mangle(args[1]);
1167
u = SPECIAL_DEFAULT_TARGET;
1169
pager_open_if_enabled();
1173
return list_dependencies_one(bus, u, 0, &units, 0);
1178
char *name, *type, *state;
1181
static void list_jobs_print(struct job_info* jobs, size_t n) {
1184
const char *on, *off;
1185
bool shorten = false;
1187
assert(n == 0 || jobs);
1190
on = ansi_highlight_green(true);
1191
off = ansi_highlight_green(false);
1193
printf("%sNo jobs running.%s\n", on, off);
1197
pager_open_if_enabled();
1200
/* JOB UNIT TYPE STATE */
1201
unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1203
for (i = 0, j = jobs; i < n; i++, j++) {
1204
assert(j->name && j->type && j->state);
1205
l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1206
l1 = MAX(l1, strlen(j->name));
1207
l2 = MAX(l2, strlen(j->type));
1208
l3 = MAX(l3, strlen(j->state));
1211
if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1212
l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1217
printf("%*s %-*s %-*s %-*s\n",
1223
for (i = 0, j = jobs; i < n; i++, j++) {
1224
_cleanup_free_ char *e = NULL;
1226
if (streq(j->state, "running")) {
1227
on = ansi_highlight(true);
1228
off = ansi_highlight(false);
1232
e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1233
printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1235
on, l1, e ? e : j->name, off,
1237
on, l3, j->state, off);
1241
on = ansi_highlight(true);
1242
off = ansi_highlight(false);
1245
printf("\n%s%zu jobs listed%s.\n", on, n, off);
1248
static int list_jobs(DBusConnection *bus, char **args) {
1249
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1250
DBusMessageIter iter, sub, sub2;
1252
struct job_info *jobs = NULL;
1253
size_t size = 0, used = 0;
1255
r = bus_method_call_with_reply(
1257
"org.freedesktop.systemd1",
1258
"/org/freedesktop/systemd1",
1259
"org.freedesktop.systemd1.Manager",
1267
if (!dbus_message_iter_init(reply, &iter) ||
1268
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1269
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1270
log_error("Failed to parse reply.");
1274
dbus_message_iter_recurse(&iter, &sub);
1276
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1277
const char *name, *type, *state, *job_path, *unit_path;
1280
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1281
log_error("Failed to parse reply.");
1285
dbus_message_iter_recurse(&sub, &sub2);
1287
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1288
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1289
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1290
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1291
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1292
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1293
log_error("Failed to parse reply.");
1298
if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1303
jobs[used++] = (struct job_info) { id,
1307
if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1312
dbus_message_iter_next(&sub);
1315
list_jobs_print(jobs, used);
1319
free(jobs[used].name);
1320
free(jobs[used].type);
1321
free(jobs[used].state);
1328
static int load_unit(DBusConnection *bus, char **args) {
1333
STRV_FOREACH(name, args+1) {
1334
_cleanup_free_ char *n = NULL;
1337
n = unit_name_mangle(*name);
1341
r = bus_method_call_with_reply(
1343
"org.freedesktop.systemd1",
1344
"/org/freedesktop/systemd1",
1345
"org.freedesktop.systemd1.Manager",
1349
DBUS_TYPE_STRING, &n,
1358
static int cancel_job(DBusConnection *bus, char **args) {
1363
if (strv_length(args) <= 1)
1364
return daemon_reload(bus, args);
1366
STRV_FOREACH(name, args+1) {
1370
r = safe_atou32(*name, &id);
1372
log_error("Failed to parse job id: %s", strerror(-r));
1376
r = bus_method_call_with_reply(
1378
"org.freedesktop.systemd1",
1379
"/org/freedesktop/systemd1",
1380
"org.freedesktop.systemd1.Manager",
1384
DBUS_TYPE_UINT32, &id,
1393
static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1394
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1395
dbus_bool_t b = FALSE;
1396
DBusMessageIter iter, sub;
1398
*interface = "org.freedesktop.systemd1.Unit",
1399
*property = "NeedDaemonReload",
1401
_cleanup_free_ char *n = NULL;
1404
/* We ignore all errors here, since this is used to show a warning only */
1406
n = unit_name_mangle(unit);
1410
r = bus_method_call_with_reply(
1412
"org.freedesktop.systemd1",
1413
"/org/freedesktop/systemd1",
1414
"org.freedesktop.systemd1.Manager",
1418
DBUS_TYPE_STRING, &n,
1423
if (!dbus_message_get_args(reply, NULL,
1424
DBUS_TYPE_OBJECT_PATH, &path,
1428
dbus_message_unref(reply);
1431
r = bus_method_call_with_reply(
1433
"org.freedesktop.systemd1",
1435
"org.freedesktop.DBus.Properties",
1439
DBUS_TYPE_STRING, &interface,
1440
DBUS_TYPE_STRING, &property,
1445
if (!dbus_message_iter_init(reply, &iter) ||
1446
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1449
dbus_message_iter_recurse(&iter, &sub);
1450
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1453
dbus_message_iter_get_basic(&sub, &b);
1457
typedef struct WaitData {
1464
static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1465
_cleanup_dbus_error_free_ DBusError error;
1468
dbus_error_init(&error);
1474
log_debug("Got D-Bus request: %s.%s() on %s",
1475
dbus_message_get_interface(message),
1476
dbus_message_get_member(message),
1477
dbus_message_get_path(message));
1479
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1480
log_error("Warning! D-Bus connection terminated.");
1481
dbus_connection_close(connection);
1483
} else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1485
const char *path, *result, *unit;
1487
if (dbus_message_get_args(message, &error,
1488
DBUS_TYPE_UINT32, &id,
1489
DBUS_TYPE_OBJECT_PATH, &path,
1490
DBUS_TYPE_STRING, &unit,
1491
DBUS_TYPE_STRING, &result,
1492
DBUS_TYPE_INVALID)) {
1494
free(set_remove(d->set, (char*) path));
1496
if (!isempty(result))
1497
d->result = strdup(result);
1500
d->name = strdup(unit);
1502
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1505
dbus_error_free(&error);
1506
if (dbus_message_get_args(message, &error,
1507
DBUS_TYPE_UINT32, &id,
1508
DBUS_TYPE_OBJECT_PATH, &path,
1509
DBUS_TYPE_STRING, &result,
1510
DBUS_TYPE_INVALID)) {
1511
/* Compatibility with older systemd versions <
1512
* 183 during upgrades. This should be dropped
1514
free(set_remove(d->set, (char*) path));
1517
d->result = strdup(result);
1519
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1523
log_error("Failed to parse message: %s", bus_error_message(&error));
1526
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1529
static int enable_wait_for_jobs(DBusConnection *bus) {
1537
dbus_error_init(&error);
1538
dbus_bus_add_match(bus,
1540
"sender='org.freedesktop.systemd1',"
1541
"interface='org.freedesktop.systemd1.Manager',"
1542
"member='JobRemoved',"
1543
"path='/org/freedesktop/systemd1'",
1546
if (dbus_error_is_set(&error)) {
1547
log_error("Failed to add match: %s", bus_error_message(&error));
1548
dbus_error_free(&error);
1552
/* This is slightly dirty, since we don't undo the match registrations. */
1556
static int wait_for_jobs(DBusConnection *bus, Set *s) {
1558
WaitData d = { .set = s };
1563
if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1566
while (!set_isempty(s)) {
1568
if (!dbus_connection_read_write_dispatch(bus, -1)) {
1569
log_error("Disconnected from bus.");
1570
return -ECONNREFUSED;
1577
if (streq(d.result, "timeout"))
1578
log_error("Job for %s timed out.", strna(d.name));
1579
else if (streq(d.result, "canceled"))
1580
log_error("Job for %s canceled.", strna(d.name));
1581
else if (streq(d.result, "dependency"))
1582
log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1583
else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1584
log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1587
if (streq_ptr(d.result, "timeout"))
1589
else if (streq_ptr(d.result, "canceled"))
1591
else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1602
dbus_connection_remove_filter(bus, wait_filter, &d);
1606
static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1607
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1608
_cleanup_free_ char *n = NULL;
1609
DBusMessageIter iter, sub;
1611
*interface = "org.freedesktop.systemd1.Unit",
1612
*property = "ActiveState";
1613
const char *state, *path;
1619
dbus_error_init(&error);
1621
n = unit_name_mangle(name);
1625
r = bus_method_call_with_reply (
1627
"org.freedesktop.systemd1",
1628
"/org/freedesktop/systemd1",
1629
"org.freedesktop.systemd1.Manager",
1633
DBUS_TYPE_STRING, &n,
1636
dbus_error_free(&error);
1643
if (!dbus_message_get_args(reply, NULL,
1644
DBUS_TYPE_OBJECT_PATH, &path,
1645
DBUS_TYPE_INVALID)) {
1646
log_error("Failed to parse reply.");
1650
dbus_message_unref(reply);
1653
r = bus_method_call_with_reply(
1655
"org.freedesktop.systemd1",
1657
"org.freedesktop.DBus.Properties",
1661
DBUS_TYPE_STRING, &interface,
1662
DBUS_TYPE_STRING, &property,
1670
if (!dbus_message_iter_init(reply, &iter) ||
1671
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1672
log_error("Failed to parse reply.");
1676
dbus_message_iter_recurse(&iter, &sub);
1678
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1679
log_error("Failed to parse reply.");
1683
dbus_message_iter_get_basic(&sub, &state);
1688
return strv_find(check_states, state) ? 1 : 0;
1691
static void check_triggering_units(
1692
DBusConnection *bus,
1693
const char *unit_name) {
1695
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1696
DBusMessageIter iter, sub;
1697
const char *interface = "org.freedesktop.systemd1.Unit",
1698
*load_state_property = "LoadState",
1699
*triggered_by_property = "TriggeredBy",
1701
_cleanup_free_ char *unit_path = NULL, *n = NULL;
1702
bool print_warning_label = true;
1705
n = unit_name_mangle(unit_name);
1711
unit_path = unit_dbus_path_from_name(n);
1717
r = bus_method_call_with_reply(
1719
"org.freedesktop.systemd1",
1721
"org.freedesktop.DBus.Properties",
1725
DBUS_TYPE_STRING, &interface,
1726
DBUS_TYPE_STRING, &load_state_property,
1731
if (!dbus_message_iter_init(reply, &iter) ||
1732
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1733
log_error("Failed to parse reply.");
1737
dbus_message_iter_recurse(&iter, &sub);
1739
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1740
log_error("Failed to parse reply.");
1744
dbus_message_iter_get_basic(&sub, &state);
1746
if (streq(state, "masked"))
1749
dbus_message_unref(reply);
1752
r = bus_method_call_with_reply(
1754
"org.freedesktop.systemd1",
1756
"org.freedesktop.DBus.Properties",
1760
DBUS_TYPE_STRING, &interface,
1761
DBUS_TYPE_STRING, &triggered_by_property,
1766
if (!dbus_message_iter_init(reply, &iter) ||
1767
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1768
log_error("Failed to parse reply.");
1772
dbus_message_iter_recurse(&iter, &sub);
1773
dbus_message_iter_recurse(&sub, &iter);
1776
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1777
const char * const check_states[] = {
1782
const char *service_trigger;
1784
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1785
log_error("Failed to parse reply.");
1789
dbus_message_iter_get_basic(&sub, &service_trigger);
1791
r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1795
if (print_warning_label) {
1796
log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1797
print_warning_label = false;
1800
log_warning(" %s", service_trigger);
1803
dbus_message_iter_next(&sub);
1807
static int start_unit_one(
1808
DBusConnection *bus,
1815
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1816
_cleanup_free_ char *n;
1825
n = unit_name_mangle(name);
1829
r = bus_method_call_with_reply(
1831
"org.freedesktop.systemd1",
1832
"/org/freedesktop/systemd1",
1833
"org.freedesktop.systemd1.Manager",
1837
DBUS_TYPE_STRING, &n,
1838
DBUS_TYPE_STRING, &mode,
1841
if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1842
/* There's always a fallback possible for
1843
* legacy actions. */
1846
log_error("Failed to issue method call: %s", bus_error_message(error));
1851
if (!dbus_message_get_args(reply, error,
1852
DBUS_TYPE_OBJECT_PATH, &path,
1853
DBUS_TYPE_INVALID)) {
1854
log_error("Failed to parse reply: %s", bus_error_message(error));
1858
if (need_daemon_reload(bus, n))
1859
log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1860
n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1869
r = set_consume(s, p);
1871
log_error("Failed to add path to set.");
1879
static const struct {
1883
} action_table[_ACTION_MAX] = {
1884
[ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1885
[ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1886
[ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1887
[ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1888
[ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1889
[ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1890
[ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1891
[ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1892
[ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1893
[ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1894
[ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1895
[ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1896
[ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1897
[ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1898
[ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1901
static enum action verb_to_action(const char *verb) {
1904
for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1905
if (action_table[i].verb && streq(verb, action_table[i].verb))
1907
return ACTION_INVALID;
1910
static int start_unit(DBusConnection *bus, char **args) {
1913
const char *method, *mode, *one_name;
1914
_cleanup_set_free_free_ Set *s = NULL;
1915
_cleanup_dbus_error_free_ DBusError error;
1918
dbus_error_init(&error);
1922
ask_password_agent_open_if_enabled();
1924
if (arg_action == ACTION_SYSTEMCTL) {
1927
streq(args[0], "stop") ||
1928
streq(args[0], "condstop") ? "StopUnit" :
1929
streq(args[0], "reload") ? "ReloadUnit" :
1930
streq(args[0], "restart") ? "RestartUnit" :
1932
streq(args[0], "try-restart") ||
1933
streq(args[0], "condrestart") ? "TryRestartUnit" :
1935
streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1937
streq(args[0], "reload-or-try-restart") ||
1938
streq(args[0], "condreload") ||
1940
streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1942
action = verb_to_action(args[0]);
1944
mode = streq(args[0], "isolate") ? "isolate" :
1945
action_table[action].mode ?: arg_job_mode;
1947
one_name = action_table[action].target;
1950
assert(arg_action < ELEMENTSOF(action_table));
1951
assert(action_table[arg_action].target);
1953
method = "StartUnit";
1955
mode = action_table[arg_action].mode;
1956
one_name = action_table[arg_action].target;
1959
if (!arg_no_block) {
1960
ret = enable_wait_for_jobs(bus);
1962
log_error("Could not watch jobs: %s", strerror(-ret));
1966
s = set_new(string_hash_func, string_compare_func);
1972
ret = start_unit_one(bus, method, one_name, mode, &error, s);
1974
ret = translate_bus_error_to_exit_status(ret, &error);
1976
STRV_FOREACH(name, args+1) {
1977
r = start_unit_one(bus, method, *name, mode, &error, s);
1979
ret = translate_bus_error_to_exit_status(r, &error);
1980
dbus_error_free(&error);
1985
if (!arg_no_block) {
1986
r = wait_for_jobs(bus, s);
1990
/* When stopping units, warn if they can still be triggered by
1991
* another active unit (socket, path, timer) */
1992
if (!arg_quiet && streq(method, "StopUnit")) {
1994
check_triggering_units(bus, one_name);
1996
STRV_FOREACH(name, args+1)
1997
check_triggering_units(bus, *name);
2004
/* Ask systemd-logind, which might grant access to unprivileged users
2005
* through PolicyKit */
2006
static int reboot_with_logind(DBusConnection *bus, enum action a) {
2009
dbus_bool_t interactive = true;
2014
polkit_agent_open_if_enabled();
2022
case ACTION_POWEROFF:
2023
method = "PowerOff";
2026
case ACTION_SUSPEND:
2030
case ACTION_HIBERNATE:
2031
method = "Hibernate";
2034
case ACTION_HYBRID_SLEEP:
2035
method = "HybridSleep";
2042
return bus_method_call_with_reply(
2044
"org.freedesktop.login1",
2045
"/org/freedesktop/login1",
2046
"org.freedesktop.login1.Manager",
2050
DBUS_TYPE_BOOLEAN, &interactive,
2057
static int check_inhibitors(DBusConnection *bus, enum action a) {
2059
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2060
DBusMessageIter iter, sub, sub2;
2063
_cleanup_strv_free_ char **sessions = NULL;
2069
if (arg_ignore_inhibitors || arg_force > 0)
2081
r = bus_method_call_with_reply(
2083
"org.freedesktop.login1",
2084
"/org/freedesktop/login1",
2085
"org.freedesktop.login1.Manager",
2091
/* If logind is not around, then there are no inhibitors... */
2094
if (!dbus_message_iter_init(reply, &iter) ||
2095
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2096
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2097
log_error("Failed to parse reply.");
2101
dbus_message_iter_recurse(&iter, &sub);
2102
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2103
const char *what, *who, *why, *mode;
2105
_cleanup_strv_free_ char **sv = NULL;
2106
_cleanup_free_ char *comm = NULL, *user = NULL;
2108
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2109
log_error("Failed to parse reply.");
2113
dbus_message_iter_recurse(&sub, &sub2);
2115
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2116
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2117
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2118
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2119
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2120
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2121
log_error("Failed to parse reply.");
2125
if (!streq(mode, "block"))
2128
sv = strv_split(what, ":");
2132
if (!strv_contains(sv,
2134
a == ACTION_POWEROFF ||
2135
a == ACTION_REBOOT ||
2136
a == ACTION_KEXEC ? "shutdown" : "sleep"))
2139
get_process_comm(pid, &comm);
2140
user = uid_to_name(uid);
2141
log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2142
who, (unsigned long) pid, strna(comm), strna(user), why);
2146
dbus_message_iter_next(&sub);
2149
dbus_message_iter_recurse(&iter, &sub);
2151
/* Check for current sessions */
2152
sd_get_sessions(&sessions);
2153
STRV_FOREACH(s, sessions) {
2155
_cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2157
if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2160
if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2163
if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2166
sd_session_get_tty(*s, &tty);
2167
sd_session_get_seat(*s, &seat);
2168
sd_session_get_service(*s, &service);
2169
user = uid_to_name(uid);
2171
log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2178
log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2179
action_table[a].verb);
2187
static int start_special(DBusConnection *bus, char **args) {
2193
a = verb_to_action(args[0]);
2195
r = check_inhibitors(bus, a);
2199
if (arg_force >= 2 && geteuid() != 0) {
2200
log_error("Must be root.");
2204
if (arg_force >= 2 &&
2205
(a == ACTION_HALT ||
2206
a == ACTION_POWEROFF ||
2207
a == ACTION_REBOOT))
2210
if (arg_force >= 1 &&
2211
(a == ACTION_HALT ||
2212
a == ACTION_POWEROFF ||
2213
a == ACTION_REBOOT ||
2214
a == ACTION_KEXEC ||
2216
return daemon_reload(bus, args);
2218
/* first try logind, to allow authentication with polkit */
2219
if (geteuid() != 0 &&
2220
(a == ACTION_POWEROFF ||
2221
a == ACTION_REBOOT ||
2222
a == ACTION_SUSPEND ||
2223
a == ACTION_HIBERNATE ||
2224
a == ACTION_HYBRID_SLEEP)) {
2225
r = reboot_with_logind(bus, a);
2230
r = start_unit(bus, args);
2231
if (r == EXIT_SUCCESS)
2237
static int check_unit_active(DBusConnection *bus, char **args) {
2238
const char * const check_states[] = {
2245
int r = 3; /* According to LSB: "program is not running" */
2250
STRV_FOREACH(name, args+1) {
2253
state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2263
static int check_unit_failed(DBusConnection *bus, char **args) {
2264
const char * const check_states[] = {
2275
STRV_FOREACH(name, args+1) {
2278
state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2288
static int kill_unit(DBusConnection *bus, char **args) {
2296
arg_kill_who = "all";
2298
STRV_FOREACH(name, args+1) {
2299
_cleanup_free_ char *n = NULL;
2301
n = unit_name_mangle(*name);
2305
r = bus_method_call_with_reply(
2307
"org.freedesktop.systemd1",
2308
"/org/freedesktop/systemd1",
2309
"org.freedesktop.systemd1.Manager",
2313
DBUS_TYPE_STRING, &n,
2314
DBUS_TYPE_STRING, &arg_kill_who,
2315
DBUS_TYPE_INT32, &arg_signal,
2323
static int set_cgroup(DBusConnection *bus, char **args) {
2324
_cleanup_free_ char *n = NULL;
2325
const char *method, *runtime;
2333
streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2334
streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2335
: "UnsetUnitControlGroupAttribute";
2337
runtime = arg_runtime ? "runtime" : "persistent";
2339
n = unit_name_mangle(args[1]);
2343
STRV_FOREACH(argument, args + 2) {
2345
r = bus_method_call_with_reply(
2347
"org.freedesktop.systemd1",
2348
"/org/freedesktop/systemd1",
2349
"org.freedesktop.systemd1.Manager",
2353
DBUS_TYPE_STRING, &n,
2354
DBUS_TYPE_STRING, argument,
2355
DBUS_TYPE_STRING, &runtime,
2364
static int set_cgroup_attr(DBusConnection *bus, char **args) {
2365
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2367
DBusMessageIter iter;
2368
_cleanup_free_ char *n = NULL;
2369
const char *runtime;
2375
dbus_error_init(&error);
2377
runtime = arg_runtime ? "runtime" : "persistent";
2379
n = unit_name_mangle(args[1]);
2383
m = dbus_message_new_method_call(
2384
"org.freedesktop.systemd1",
2385
"/org/freedesktop/systemd1",
2386
"org.freedesktop.systemd1.Manager",
2387
"SetUnitControlGroupAttribute");
2391
dbus_message_iter_init_append(m, &iter);
2392
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2393
!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2396
r = bus_append_strv_iter(&iter, args + 3);
2400
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2403
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2405
log_error("Failed to issue method call: %s", bus_error_message(&error));
2406
dbus_error_free(&error);
2413
static int get_cgroup_attr(DBusConnection *bus, char **args) {
2414
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2415
_cleanup_free_ char *n = NULL;
2422
n = unit_name_mangle(args[1]);
2426
STRV_FOREACH(argument, args + 2) {
2427
_cleanup_strv_free_ char **list = NULL;
2428
DBusMessageIter iter;
2431
r = bus_method_call_with_reply(
2433
"org.freedesktop.systemd1",
2434
"/org/freedesktop/systemd1",
2435
"org.freedesktop.systemd1.Manager",
2436
"GetUnitControlGroupAttribute",
2439
DBUS_TYPE_STRING, &n,
2440
DBUS_TYPE_STRING, argument,
2445
if (!dbus_message_iter_init(reply, &iter)) {
2446
log_error("Failed to initialize iterator.");
2450
r = bus_parse_strv_iter(&iter, &list);
2452
log_error("Failed to parse value list.");
2456
STRV_FOREACH(a, list) {
2457
if (endswith(*a, "\n"))
2467
typedef struct ExecStatusInfo {
2475
usec_t start_timestamp;
2476
usec_t exit_timestamp;
2481
LIST_FIELDS(struct ExecStatusInfo, exec);
2484
static void exec_status_info_free(ExecStatusInfo *i) {
2493
static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2494
uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2495
DBusMessageIter sub2, sub3;
2499
int32_t code, status;
2505
if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2508
dbus_message_iter_recurse(sub, &sub2);
2510
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2513
i->path = strdup(path);
2517
if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2518
dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2522
dbus_message_iter_recurse(&sub2, &sub3);
2523
while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2524
assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2525
dbus_message_iter_next(&sub3);
2529
i->argv = new0(char*, n+1);
2534
dbus_message_iter_recurse(&sub2, &sub3);
2535
while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2538
assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2539
dbus_message_iter_get_basic(&sub3, &s);
2540
dbus_message_iter_next(&sub3);
2542
i->argv[n] = strdup(s);
2549
if (!dbus_message_iter_next(&sub2) ||
2550
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2551
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2552
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2553
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2554
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2555
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2556
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2557
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2561
i->start_timestamp = (usec_t) start_timestamp;
2562
i->exit_timestamp = (usec_t) exit_timestamp;
2563
i->pid = (pid_t) pid;
2570
typedef struct UnitStatusInfo {
2572
const char *load_state;
2573
const char *active_state;
2574
const char *sub_state;
2575
const char *unit_file_state;
2577
const char *description;
2578
const char *following;
2580
char **documentation;
2582
const char *fragment_path;
2583
const char *source_path;
2584
const char *default_control_group;
2586
char **dropin_paths;
2588
const char *load_error;
2591
usec_t inactive_exit_timestamp;
2592
usec_t inactive_exit_timestamp_monotonic;
2593
usec_t active_enter_timestamp;
2594
usec_t active_exit_timestamp;
2595
usec_t inactive_enter_timestamp;
2597
bool need_daemon_reload;
2602
const char *status_text;
2605
usec_t start_timestamp;
2606
usec_t exit_timestamp;
2608
int exit_code, exit_status;
2610
usec_t condition_timestamp;
2611
bool condition_result;
2614
unsigned n_accepted;
2615
unsigned n_connections;
2618
/* Pairs of type, path */
2622
const char *sysfs_path;
2624
/* Mount, Automount */
2630
LIST_HEAD(ExecStatusInfo, exec);
2633
static void print_status_info(UnitStatusInfo *i) {
2635
const char *on, *off, *ss;
2637
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2638
char since2[FORMAT_TIMESTAMP_MAX], *s2;
2641
arg_all * OUTPUT_SHOW_ALL |
2642
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2643
on_tty() * OUTPUT_COLOR |
2644
!arg_quiet * OUTPUT_WARN_CUTOFF |
2645
arg_full * OUTPUT_FULL_WIDTH;
2646
int maxlen = 8; /* a value that'll suffice most of the time */
2651
STRV_FOREACH_PAIR(t, t2, i->listen)
2652
maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2654
maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2655
if (i->main_pid > 0)
2656
maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2657
else if (i->control_pid > 0)
2658
maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2660
/* This shows pretty information about a unit. See
2661
* print_property() for a low-level property printer */
2663
printf("%s", strna(i->id));
2665
if (i->description && !streq_ptr(i->id, i->description))
2666
printf(" - %s", i->description);
2671
printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2673
if (streq_ptr(i->load_state, "error")) {
2674
on = ansi_highlight_red(true);
2675
off = ansi_highlight_red(false);
2679
path = i->source_path ? i->source_path : i->fragment_path;
2682
printf(" %*s: %s%s%s (Reason: %s)\n",
2683
maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2684
else if (path && i->unit_file_state)
2685
printf(" %*s: %s%s%s (%s; %s)\n",
2686
maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2688
printf(" %*s: %s%s%s (%s)\n",
2689
maxlen, "Loaded", on, strna(i->load_state), off, path);
2691
printf(" %*s: %s%s%s\n",
2692
maxlen, "Loaded", on, strna(i->load_state), off);
2694
if (!strv_isempty(i->dropin_paths)) {
2699
STRV_FOREACH(dropin, i->dropin_paths) {
2700
if (! dir || last) {
2701
printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2705
if (path_get_parent(*dropin, &dir) < 0) {
2710
printf("%s\n %*s %s", dir, maxlen, "",
2711
draw_special_char(DRAW_TREE_RIGHT));
2714
last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2716
printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2722
ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2724
if (streq_ptr(i->active_state, "failed")) {
2725
on = ansi_highlight_red(true);
2726
off = ansi_highlight_red(false);
2727
} else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2728
on = ansi_highlight_green(true);
2729
off = ansi_highlight_green(false);
2734
printf(" %*s: %s%s (%s)%s",
2735
maxlen, "Active", on, strna(i->active_state), ss, off);
2737
printf(" %*s: %s%s%s",
2738
maxlen, "Active", on, strna(i->active_state), off);
2740
if (!isempty(i->result) && !streq(i->result, "success"))
2741
printf(" (Result: %s)", i->result);
2743
timestamp = (streq_ptr(i->active_state, "active") ||
2744
streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2745
(streq_ptr(i->active_state, "inactive") ||
2746
streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2747
streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2748
i->active_exit_timestamp;
2750
s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2751
s2 = format_timestamp(since2, sizeof(since2), timestamp);
2754
printf(" since %s; %s\n", s2, s1);
2756
printf(" since %s\n", s2);
2760
if (!i->condition_result && i->condition_timestamp > 0) {
2761
s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2762
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2765
printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2767
printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2771
printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2773
printf(" %*s: %s\n", maxlen, "Where", i->where);
2775
printf(" %*s: %s\n", maxlen, "What", i->what);
2777
STRV_FOREACH(t, i->documentation)
2778
printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2780
STRV_FOREACH_PAIR(t, t2, i->listen)
2781
printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2784
printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2786
LIST_FOREACH(exec, p, i->exec) {
2787
_cleanup_free_ char *argv = NULL;
2790
/* Only show exited processes here */
2794
argv = strv_join(p->argv, " ");
2795
printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2797
good = is_clean_exit_lsb(p->code, p->status, NULL);
2799
on = ansi_highlight_red(true);
2800
off = ansi_highlight_red(false);
2804
printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2806
if (p->code == CLD_EXITED) {
2809
printf("status=%i", p->status);
2811
c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2816
printf("signal=%s", signal_to_string(p->status));
2818
printf(")%s\n", off);
2820
if (i->main_pid == p->pid &&
2821
i->start_timestamp == p->start_timestamp &&
2822
i->exit_timestamp == p->start_timestamp)
2823
/* Let's not show this twice */
2826
if (p->pid == i->control_pid)
2830
if (i->main_pid > 0 || i->control_pid > 0) {
2831
if (i->main_pid > 0) {
2832
printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2835
_cleanup_free_ char *comm = NULL;
2836
get_process_comm(i->main_pid, &comm);
2838
printf(" (%s)", comm);
2839
} else if (i->exit_code > 0) {
2840
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2842
if (i->exit_code == CLD_EXITED) {
2845
printf("status=%i", i->exit_status);
2847
c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2852
printf("signal=%s", signal_to_string(i->exit_status));
2856
if (i->control_pid > 0)
2860
if (i->control_pid > 0) {
2861
_cleanup_free_ char *c = NULL;
2863
printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2865
get_process_comm(i->control_pid, &c);
2874
printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2876
if (i->default_control_group &&
2877
(i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2880
printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2882
if (arg_transport != TRANSPORT_SSH) {
2885
char prefix[maxlen + 4];
2886
memset(prefix, ' ', sizeof(prefix) - 1);
2887
prefix[sizeof(prefix) - 1] = '\0';
2890
if (c > sizeof(prefix) - 1)
2891
c -= sizeof(prefix) - 1;
2895
if (i->main_pid > 0)
2896
extra[k++] = i->main_pid;
2898
if (i->control_pid > 0)
2899
extra[k++] = i->control_pid;
2901
show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2902
c, false, extra, k, flags);
2906
if (i->id && arg_transport != TRANSPORT_SSH) {
2908
show_journal_by_unit(stdout,
2912
i->inactive_exit_timestamp_monotonic,
2916
arg_scope == UNIT_FILE_SYSTEM);
2919
if (i->need_daemon_reload)
2920
printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2921
ansi_highlight_red(true),
2922
ansi_highlight_red(false),
2923
arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2926
static void show_unit_help(UnitStatusInfo *i) {
2931
if (!i->documentation) {
2932
log_info("Documentation for %s not known.", i->id);
2936
STRV_FOREACH(p, i->documentation) {
2938
if (startswith(*p, "man:")) {
2941
_cleanup_free_ char *page = NULL, *section = NULL;
2942
const char *args[4] = { "man", NULL, NULL, NULL };
2947
if ((*p)[k-1] == ')')
2948
e = strrchr(*p, '(');
2951
page = strndup((*p) + 4, e - *p - 4);
2952
section = strndup(e + 1, *p + k - e - 2);
2953
if (!page || !section) {
2965
log_error("Failed to fork: %m");
2971
execvp(args[0], (char**) args);
2972
log_error("Failed to execute man: %m");
2973
_exit(EXIT_FAILURE);
2976
wait_for_terminate(pid, NULL);
2978
log_info("Can't show: %s", *p);
2982
static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2988
switch (dbus_message_iter_get_arg_type(iter)) {
2990
case DBUS_TYPE_STRING: {
2993
dbus_message_iter_get_basic(iter, &s);
2996
if (streq(name, "Id"))
2998
else if (streq(name, "LoadState"))
3000
else if (streq(name, "ActiveState"))
3001
i->active_state = s;
3002
else if (streq(name, "SubState"))
3004
else if (streq(name, "Description"))
3006
else if (streq(name, "FragmentPath"))
3007
i->fragment_path = s;
3008
else if (streq(name, "SourcePath"))
3010
else if (streq(name, "DefaultControlGroup"))
3011
i->default_control_group = s;
3012
else if (streq(name, "StatusText"))
3014
else if (streq(name, "SysFSPath"))
3016
else if (streq(name, "Where"))
3018
else if (streq(name, "What"))
3020
else if (streq(name, "Following"))
3022
else if (streq(name, "UnitFileState"))
3023
i->unit_file_state = s;
3024
else if (streq(name, "Result"))
3031
case DBUS_TYPE_BOOLEAN: {
3034
dbus_message_iter_get_basic(iter, &b);
3036
if (streq(name, "Accept"))
3038
else if (streq(name, "NeedDaemonReload"))
3039
i->need_daemon_reload = b;
3040
else if (streq(name, "ConditionResult"))
3041
i->condition_result = b;
3046
case DBUS_TYPE_UINT32: {
3049
dbus_message_iter_get_basic(iter, &u);
3051
if (streq(name, "MainPID")) {
3053
i->main_pid = (pid_t) u;
3056
} else if (streq(name, "ControlPID"))
3057
i->control_pid = (pid_t) u;
3058
else if (streq(name, "ExecMainPID")) {
3060
i->main_pid = (pid_t) u;
3061
} else if (streq(name, "NAccepted"))
3063
else if (streq(name, "NConnections"))
3064
i->n_connections = u;
3069
case DBUS_TYPE_INT32: {
3072
dbus_message_iter_get_basic(iter, &j);
3074
if (streq(name, "ExecMainCode"))
3075
i->exit_code = (int) j;
3076
else if (streq(name, "ExecMainStatus"))
3077
i->exit_status = (int) j;
3082
case DBUS_TYPE_UINT64: {
3085
dbus_message_iter_get_basic(iter, &u);
3087
if (streq(name, "ExecMainStartTimestamp"))
3088
i->start_timestamp = (usec_t) u;
3089
else if (streq(name, "ExecMainExitTimestamp"))
3090
i->exit_timestamp = (usec_t) u;
3091
else if (streq(name, "ActiveEnterTimestamp"))
3092
i->active_enter_timestamp = (usec_t) u;
3093
else if (streq(name, "InactiveEnterTimestamp"))
3094
i->inactive_enter_timestamp = (usec_t) u;
3095
else if (streq(name, "InactiveExitTimestamp"))
3096
i->inactive_exit_timestamp = (usec_t) u;
3097
else if (streq(name, "InactiveExitTimestampMonotonic"))
3098
i->inactive_exit_timestamp_monotonic = (usec_t) u;
3099
else if (streq(name, "ActiveExitTimestamp"))
3100
i->active_exit_timestamp = (usec_t) u;
3101
else if (streq(name, "ConditionTimestamp"))
3102
i->condition_timestamp = (usec_t) u;
3107
case DBUS_TYPE_ARRAY: {
3109
if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3110
startswith(name, "Exec")) {
3111
DBusMessageIter sub;
3113
dbus_message_iter_recurse(iter, &sub);
3114
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3115
ExecStatusInfo *info;
3118
if (!(info = new0(ExecStatusInfo, 1)))
3121
if (!(info->name = strdup(name))) {
3126
if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3131
LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3133
dbus_message_iter_next(&sub);
3136
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3137
DBusMessageIter sub, sub2;
3139
dbus_message_iter_recurse(iter, &sub);
3140
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3141
const char *type, *path;
3143
dbus_message_iter_recurse(&sub, &sub2);
3145
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3146
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3149
r = strv_extend(&i->listen, type);
3152
r = strv_extend(&i->listen, path);
3157
dbus_message_iter_next(&sub);
3162
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3163
int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3167
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3168
streq(name, "Documentation")) {
3170
DBusMessageIter sub;
3172
dbus_message_iter_recurse(iter, &sub);
3173
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3177
dbus_message_iter_get_basic(&sub, &s);
3179
r = strv_extend(&i->documentation, s);
3183
dbus_message_iter_next(&sub);
3190
case DBUS_TYPE_STRUCT: {
3192
if (streq(name, "LoadError")) {
3193
DBusMessageIter sub;
3194
const char *n, *message;
3197
dbus_message_iter_recurse(iter, &sub);
3199
r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3203
r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3207
if (!isempty(message))
3208
i->load_error = message;
3218
static int print_property(const char *name, DBusMessageIter *iter) {
3222
/* This is a low-level property printer, see
3223
* print_status_info() for the nicer output */
3225
if (arg_properties && !strv_find(arg_properties, name))
3228
switch (dbus_message_iter_get_arg_type(iter)) {
3230
case DBUS_TYPE_STRUCT: {
3231
DBusMessageIter sub;
3232
dbus_message_iter_recurse(iter, &sub);
3234
if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3237
dbus_message_iter_get_basic(&sub, &u);
3240
printf("%s=%u\n", name, (unsigned) u);
3242
printf("%s=\n", name);
3245
} else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3248
dbus_message_iter_get_basic(&sub, &s);
3250
if (arg_all || s[0])
3251
printf("%s=%s\n", name, s);
3254
} else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3255
const char *a = NULL, *b = NULL;
3257
if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3258
bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3260
if (arg_all || !isempty(a) || !isempty(b))
3261
printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3269
case DBUS_TYPE_ARRAY:
3271
if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3272
DBusMessageIter sub, sub2;
3274
dbus_message_iter_recurse(iter, &sub);
3275
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3279
dbus_message_iter_recurse(&sub, &sub2);
3281
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3282
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3283
printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3285
dbus_message_iter_next(&sub);
3290
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3291
DBusMessageIter sub, sub2;
3293
dbus_message_iter_recurse(iter, &sub);
3295
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3296
const char *type, *path;
3298
dbus_message_iter_recurse(&sub, &sub2);
3300
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3301
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3302
printf("%s=%s\n", type, path);
3304
dbus_message_iter_next(&sub);
3309
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3310
DBusMessageIter sub, sub2;
3312
dbus_message_iter_recurse(iter, &sub);
3313
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3314
const char *type, *path;
3316
dbus_message_iter_recurse(&sub, &sub2);
3318
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3319
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3320
printf("Listen%s=%s\n", type, path);
3322
dbus_message_iter_next(&sub);
3327
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3328
DBusMessageIter sub, sub2;
3330
dbus_message_iter_recurse(iter, &sub);
3331
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3333
uint64_t value, next_elapse;
3335
dbus_message_iter_recurse(&sub, &sub2);
3337
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3338
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3339
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3340
char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3342
printf("%s={ value=%s ; next_elapse=%s }\n",
3344
format_timespan(timespan1, sizeof(timespan1), value, 0),
3345
format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3348
dbus_message_iter_next(&sub);
3353
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3354
DBusMessageIter sub, sub2;
3356
dbus_message_iter_recurse(iter, &sub);
3357
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3358
const char *controller, *attr, *value;
3360
dbus_message_iter_recurse(&sub, &sub2);
3362
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3363
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3364
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3366
printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3372
dbus_message_iter_next(&sub);
3377
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3378
DBusMessageIter sub;
3380
dbus_message_iter_recurse(iter, &sub);
3381
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3382
ExecStatusInfo info = {};
3384
if (exec_status_info_deserialize(&sub, &info) >= 0) {
3385
char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3386
_cleanup_free_ char *t;
3388
t = strv_join(info.argv, " ");
3390
printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3394
yes_no(info.ignore),
3395
strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3396
strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3397
(unsigned) info. pid,
3398
sigchld_code_to_string(info.code),
3400
info.code == CLD_EXITED ? "" : "/",
3401
strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3405
strv_free(info.argv);
3407
dbus_message_iter_next(&sub);
3416
if (generic_print_property(name, iter, arg_all) > 0)
3420
printf("%s=[unprintable]\n", name);
3425
static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3426
_cleanup_free_ DBusMessage *reply = NULL;
3427
const char *interface = "";
3429
DBusMessageIter iter, sub, sub2, sub3;
3430
UnitStatusInfo info = {};
3436
r = bus_method_call_with_reply(
3438
"org.freedesktop.systemd1",
3440
"org.freedesktop.DBus.Properties",
3444
DBUS_TYPE_STRING, &interface,
3449
if (!dbus_message_iter_init(reply, &iter) ||
3450
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3451
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3452
log_error("Failed to parse reply.");
3456
dbus_message_iter_recurse(&iter, &sub);
3463
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3466
assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3467
dbus_message_iter_recurse(&sub, &sub2);
3469
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3470
dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3471
log_error("Failed to parse reply.");
3475
dbus_message_iter_recurse(&sub2, &sub3);
3477
if (show_properties)
3478
r = print_property(name, &sub3);
3480
r = status_property(name, &sub3, &info);
3482
log_error("Failed to parse reply.");
3486
dbus_message_iter_next(&sub);
3491
if (!show_properties) {
3492
if (streq(verb, "help"))
3493
show_unit_help(&info);
3495
print_status_info(&info);
3498
strv_free(info.documentation);
3499
strv_free(info.dropin_paths);
3500
strv_free(info.listen);
3502
if (!streq_ptr(info.active_state, "active") &&
3503
!streq_ptr(info.active_state, "reloading") &&
3504
streq(verb, "status"))
3505
/* According to LSB: "program not running" */
3508
while ((p = info.exec)) {
3509
LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3510
exec_status_info_free(p);
3516
static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3517
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3518
const char *path = NULL;
3519
_cleanup_dbus_error_free_ DBusError error;
3522
dbus_error_init(&error);
3524
r = bus_method_call_with_reply(
3526
"org.freedesktop.systemd1",
3527
"/org/freedesktop/systemd1",
3528
"org.freedesktop.systemd1.Manager",
3532
DBUS_TYPE_UINT32, &pid,
3537
if (!dbus_message_get_args(reply, &error,
3538
DBUS_TYPE_OBJECT_PATH, &path,
3539
DBUS_TYPE_INVALID)) {
3540
log_error("Failed to parse reply: %s", bus_error_message(&error));
3544
r = show_one(verb, bus, path, false, new_line);
3548
static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3549
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3550
_cleanup_free_ struct unit_info *unit_infos = NULL;
3552
const struct unit_info *u;
3555
r = get_unit_list(bus, &reply, &unit_infos, &c);
3559
qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3561
for (u = unit_infos; u < unit_infos + c; u++) {
3562
_cleanup_free_ char *p = NULL;
3564
if (!output_show_unit(u))
3567
p = unit_dbus_path_from_name(u->id);
3571
printf("%s -> '%s'\n", u->id, p);
3573
r = show_one(verb, bus, p, show_properties, new_line);
3581
static int show(DBusConnection *bus, char **args) {
3583
bool show_properties, show_status, new_line = false;
3589
show_properties = streq(args[0], "show");
3590
show_status = streq(args[0], "status");
3592
if (show_properties)
3593
pager_open_if_enabled();
3595
/* If no argument is specified inspect the manager itself */
3597
if (show_properties && strv_length(args) <= 1)
3598
return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3600
if (show_status && strv_length(args) <= 1)
3601
return show_all(args[0], bus, false, &new_line);
3603
STRV_FOREACH(name, args+1) {
3606
if (safe_atou32(*name, &id) < 0) {
3607
_cleanup_free_ char *p = NULL, *n = NULL;
3608
/* Interpret as unit name */
3610
n = unit_name_mangle(*name);
3614
p = unit_dbus_path_from_name(n);
3618
r = show_one(args[0], bus, p, show_properties, &new_line);
3622
} else if (show_properties) {
3623
_cleanup_free_ char *p = NULL;
3625
/* Interpret as job id */
3626
if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3629
r = show_one(args[0], bus, p, show_properties, &new_line);
3634
/* Interpret as PID */
3635
r = show_one_by_pid(args[0], bus, id, &new_line);
3644
static int dump(DBusConnection *bus, char **args) {
3645
_cleanup_free_ DBusMessage *reply = NULL;
3650
dbus_error_init(&error);
3652
pager_open_if_enabled();
3654
r = bus_method_call_with_reply(
3656
"org.freedesktop.systemd1",
3657
"/org/freedesktop/systemd1",
3658
"org.freedesktop.systemd1.Manager",
3666
if (!dbus_message_get_args(reply, &error,
3667
DBUS_TYPE_STRING, &text,
3668
DBUS_TYPE_INVALID)) {
3669
log_error("Failed to parse reply: %s", bus_error_message(&error));
3670
dbus_error_free(&error);
3674
fputs(text, stdout);
3678
static int snapshot(DBusConnection *bus, char **args) {
3679
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3682
dbus_bool_t cleanup = FALSE;
3683
DBusMessageIter iter, sub;
3686
*interface = "org.freedesktop.systemd1.Unit",
3688
_cleanup_free_ char *n = NULL;
3690
dbus_error_init(&error);
3692
if (strv_length(args) > 1)
3693
n = snapshot_name_mangle(args[1]);
3699
r = bus_method_call_with_reply (
3701
"org.freedesktop.systemd1",
3702
"/org/freedesktop/systemd1",
3703
"org.freedesktop.systemd1.Manager",
3707
DBUS_TYPE_STRING, &n,
3708
DBUS_TYPE_BOOLEAN, &cleanup,
3713
if (!dbus_message_get_args(reply, &error,
3714
DBUS_TYPE_OBJECT_PATH, &path,
3715
DBUS_TYPE_INVALID)) {
3716
log_error("Failed to parse reply: %s", bus_error_message(&error));
3717
dbus_error_free(&error);
3721
dbus_message_unref(reply);
3724
r = bus_method_call_with_reply (
3726
"org.freedesktop.systemd1",
3728
"org.freedesktop.DBus.Properties",
3732
DBUS_TYPE_STRING, &interface,
3733
DBUS_TYPE_STRING, &property,
3738
if (!dbus_message_iter_init(reply, &iter) ||
3739
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3740
log_error("Failed to parse reply.");
3744
dbus_message_iter_recurse(&iter, &sub);
3746
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3747
log_error("Failed to parse reply.");
3751
dbus_message_iter_get_basic(&sub, &id);
3759
static int delete_snapshot(DBusConnection *bus, char **args) {
3764
STRV_FOREACH(name, args+1) {
3765
_cleanup_free_ char *n = NULL;
3768
n = snapshot_name_mangle(*name);
3772
r = bus_method_call_with_reply(
3774
"org.freedesktop.systemd1",
3775
"/org/freedesktop/systemd1",
3776
"org.freedesktop.systemd1.Manager",
3780
DBUS_TYPE_STRING, &n,
3789
static int daemon_reload(DBusConnection *bus, char **args) {
3794
if (arg_action == ACTION_RELOAD)
3796
else if (arg_action == ACTION_REEXEC)
3797
method = "Reexecute";
3799
assert(arg_action == ACTION_SYSTEMCTL);
3802
streq(args[0], "clear-jobs") ||
3803
streq(args[0], "cancel") ? "ClearJobs" :
3804
streq(args[0], "daemon-reexec") ? "Reexecute" :
3805
streq(args[0], "reset-failed") ? "ResetFailed" :
3806
streq(args[0], "halt") ? "Halt" :
3807
streq(args[0], "poweroff") ? "PowerOff" :
3808
streq(args[0], "reboot") ? "Reboot" :
3809
streq(args[0], "kexec") ? "KExec" :
3810
streq(args[0], "exit") ? "Exit" :
3811
/* "daemon-reload" */ "Reload";
3814
r = bus_method_call_with_reply(
3816
"org.freedesktop.systemd1",
3817
"/org/freedesktop/systemd1",
3818
"org.freedesktop.systemd1.Manager",
3824
if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3825
/* There's always a fallback possible for
3826
* legacy actions. */
3828
else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3829
/* On reexecution, we expect a disconnect, not
3833
log_error("Failed to issue method call: %s", bus_error_message(&error));
3835
dbus_error_free(&error);
3839
static int reset_failed(DBusConnection *bus, char **args) {
3843
if (strv_length(args) <= 1)
3844
return daemon_reload(bus, args);
3846
STRV_FOREACH(name, args+1) {
3847
_cleanup_free_ char *n;
3849
n = unit_name_mangle(*name);
3853
r = bus_method_call_with_reply(
3855
"org.freedesktop.systemd1",
3856
"/org/freedesktop/systemd1",
3857
"org.freedesktop.systemd1.Manager",
3861
DBUS_TYPE_STRING, &n,
3870
static int show_enviroment(DBusConnection *bus, char **args) {
3871
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3872
DBusMessageIter iter, sub, sub2;
3875
*interface = "org.freedesktop.systemd1.Manager",
3876
*property = "Environment";
3878
pager_open_if_enabled();
3880
r = bus_method_call_with_reply(
3882
"org.freedesktop.systemd1",
3883
"/org/freedesktop/systemd1",
3884
"org.freedesktop.DBus.Properties",
3888
DBUS_TYPE_STRING, &interface,
3889
DBUS_TYPE_STRING, &property,
3894
if (!dbus_message_iter_init(reply, &iter) ||
3895
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3896
log_error("Failed to parse reply.");
3900
dbus_message_iter_recurse(&iter, &sub);
3902
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3903
dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3904
log_error("Failed to parse reply.");
3908
dbus_message_iter_recurse(&sub, &sub2);
3910
while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3913
if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3914
log_error("Failed to parse reply.");
3918
dbus_message_iter_get_basic(&sub2, &text);
3921
dbus_message_iter_next(&sub2);
3927
static int switch_root(DBusConnection *bus, char **args) {
3930
_cleanup_free_ char *init = NULL;
3932
l = strv_length(args);
3933
if (l < 2 || l > 3) {
3934
log_error("Wrong number of arguments.");
3941
init = strdup(args[2]);
3943
parse_env_file("/proc/cmdline", WHITESPACE,
3953
log_debug("switching root - root: %s; init: %s", root, init);
3955
return bus_method_call_with_reply(
3957
"org.freedesktop.systemd1",
3958
"/org/freedesktop/systemd1",
3959
"org.freedesktop.systemd1.Manager",
3963
DBUS_TYPE_STRING, &root,
3964
DBUS_TYPE_STRING, &init,
3968
static int set_environment(DBusConnection *bus, char **args) {
3969
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3972
DBusMessageIter iter;
3978
dbus_error_init(&error);
3980
method = streq(args[0], "set-environment")
3982
: "UnsetEnvironment";
3984
m = dbus_message_new_method_call(
3985
"org.freedesktop.systemd1",
3986
"/org/freedesktop/systemd1",
3987
"org.freedesktop.systemd1.Manager",
3992
dbus_message_iter_init_append(m, &iter);
3994
r = bus_append_strv_iter(&iter, args + 1);
3998
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4000
log_error("Failed to issue method call: %s", bus_error_message(&error));
4001
dbus_error_free(&error);
4008
static int enable_sysv_units(char **args) {
4011
#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4012
const char *verb = args[0];
4013
unsigned f = 1, t = 1;
4014
LookupPaths paths = {};
4016
if (arg_scope != UNIT_FILE_SYSTEM)
4019
if (!streq(verb, "enable") &&
4020
!streq(verb, "disable") &&
4021
!streq(verb, "is-enabled"))
4024
/* Processes all SysV units, and reshuffles the array so that
4025
* afterwards only the native units remain */
4027
r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4032
for (f = 1; args[f]; f++) {
4034
_cleanup_free_ char *p = NULL, *q = NULL;
4035
bool found_native = false, found_sysv;
4037
const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4045
if (!endswith(name, ".service"))
4048
if (path_is_absolute(name))
4051
STRV_FOREACH(k, paths.unit_path) {
4052
if (!isempty(arg_root))
4053
asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4055
asprintf(&p, "%s/%s", *k, name);
4062
found_native = access(p, F_OK) >= 0;
4073
if (!isempty(arg_root))
4074
asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4076
asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4082
p[strlen(p) - sizeof(".service") + 1] = 0;
4083
found_sysv = access(p, F_OK) >= 0;
4088
/* Mark this entry, so that we don't try enabling it as native unit */
4089
args[f] = (char*) "";
4091
log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4093
if (!isempty(arg_root))
4094
argv[c++] = q = strappend("--root=", arg_root);
4096
argv[c++] = path_get_file_name(p);
4098
streq(verb, "enable") ? "on" :
4099
streq(verb, "disable") ? "off" : "--level=5";
4102
l = strv_join((char**)argv, " ");
4108
log_info("Executing %s", l);
4113
log_error("Failed to fork: %m");
4116
} else if (pid == 0) {
4119
execv(argv[0], (char**) argv);
4120
_exit(EXIT_FAILURE);
4123
j = wait_for_terminate(pid, &status);
4125
log_error("Failed to wait for child: %s", strerror(-r));
4130
if (status.si_code == CLD_EXITED) {
4131
if (streq(verb, "is-enabled")) {
4132
if (status.si_status == 0) {
4141
} else if (status.si_status != 0) {
4152
lookup_paths_free(&paths);
4154
/* Drop all SysV units */
4155
for (f = 1, t = 1; args[f]; f++) {
4157
if (isempty(args[f]))
4160
args[t++] = args[f];
4169
static int mangle_names(char **original_names, char ***mangled_names) {
4170
char **i, **l, **name;
4172
l = new(char*, strv_length(original_names) + 1);
4177
STRV_FOREACH(name, original_names) {
4179
/* When enabling units qualified path names are OK,
4180
* too, hence allow them explicitly. */
4185
*i = unit_name_mangle(*name);
4201
static int enable_unit(DBusConnection *bus, char **args) {
4202
const char *verb = args[0];
4203
UnitFileChange *changes = NULL;
4204
unsigned n_changes = 0, i;
4205
int carries_install_info = -1;
4206
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4208
_cleanup_dbus_error_free_ DBusError error;
4209
_cleanup_strv_free_ char **mangled_names = NULL;
4211
dbus_error_init(&error);
4213
r = enable_sysv_units(args);
4220
if (!bus || avoid_bus()) {
4221
if (streq(verb, "enable")) {
4222
r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4223
carries_install_info = r;
4224
} else if (streq(verb, "disable"))
4225
r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4226
else if (streq(verb, "reenable")) {
4227
r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4228
carries_install_info = r;
4229
} else if (streq(verb, "link"))
4230
r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4231
else if (streq(verb, "preset")) {
4232
r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4233
carries_install_info = r;
4234
} else if (streq(verb, "mask"))
4235
r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4236
else if (streq(verb, "unmask"))
4237
r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4239
assert_not_reached("Unknown verb");
4242
log_error("Operation failed: %s", strerror(-r));
4247
for (i = 0; i < n_changes; i++) {
4248
if (changes[i].type == UNIT_FILE_SYMLINK)
4249
log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4251
log_info("rm '%s'", changes[i].path);
4258
bool send_force = true, expect_carries_install_info = false;
4260
DBusMessageIter iter, sub, sub2;
4262
if (streq(verb, "enable")) {
4263
method = "EnableUnitFiles";
4264
expect_carries_install_info = true;
4265
} else if (streq(verb, "disable")) {
4266
method = "DisableUnitFiles";
4268
} else if (streq(verb, "reenable")) {
4269
method = "ReenableUnitFiles";
4270
expect_carries_install_info = true;
4271
} else if (streq(verb, "link"))
4272
method = "LinkUnitFiles";
4273
else if (streq(verb, "preset")) {
4274
method = "PresetUnitFiles";
4275
expect_carries_install_info = true;
4276
} else if (streq(verb, "mask"))
4277
method = "MaskUnitFiles";
4278
else if (streq(verb, "unmask")) {
4279
method = "UnmaskUnitFiles";
4282
assert_not_reached("Unknown verb");
4284
m = dbus_message_new_method_call(
4285
"org.freedesktop.systemd1",
4286
"/org/freedesktop/systemd1",
4287
"org.freedesktop.systemd1.Manager",
4294
dbus_message_iter_init_append(m, &iter);
4296
r = mangle_names(args+1, &mangled_names);
4300
r = bus_append_strv_iter(&iter, mangled_names);
4302
log_error("Failed to append unit files.");
4307
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4308
log_error("Failed to append runtime boolean.");
4316
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4317
log_error("Failed to append force boolean.");
4323
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4325
log_error("Failed to issue method call: %s", bus_error_message(&error));
4330
if (!dbus_message_iter_init(reply, &iter)) {
4331
log_error("Failed to initialize iterator.");
4335
if (expect_carries_install_info) {
4336
r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4338
log_error("Failed to parse reply.");
4342
carries_install_info = b;
4345
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4346
dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4347
log_error("Failed to parse reply.");
4352
dbus_message_iter_recurse(&iter, &sub);
4353
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4354
const char *type, *path, *source;
4356
if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4357
log_error("Failed to parse reply.");
4362
dbus_message_iter_recurse(&sub, &sub2);
4364
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4365
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4366
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4367
log_error("Failed to parse reply.");
4373
if (streq(type, "symlink"))
4374
log_info("ln -s '%s' '%s'", source, path);
4376
log_info("rm '%s'", path);
4379
dbus_message_iter_next(&sub);
4382
/* Try to reload if enabeld */
4384
r = daemon_reload(bus, args);
4387
if (carries_install_info == 0)
4388
log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4389
"using systemctl.\n"
4390
"Possible reasons for having this kind of units are:\n"
4391
"1) A unit may be statically enabled by being symlinked from another unit's\n"
4392
" .wants/ or .requires/ directory.\n"
4393
"2) A unit's purpose may be to act as a helper for some other unit which has\n"
4394
" a requirement dependency on it.\n"
4395
"3) A unit may be started when needed via activation (socket, path, timer,\n"
4396
" D-Bus, udev, scripted systemctl call, ...).\n");
4399
unit_file_changes_free(changes, n_changes);
4404
static int unit_is_enabled(DBusConnection *bus, char **args) {
4405
_cleanup_dbus_error_free_ DBusError error;
4407
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4412
dbus_error_init(&error);
4414
r = enable_sysv_units(args);
4420
if (!bus || avoid_bus()) {
4422
STRV_FOREACH(name, args+1) {
4423
UnitFileState state;
4425
n = unit_name_mangle(*name);
4429
state = unit_file_get_state(arg_scope, arg_root, n);
4436
if (state == UNIT_FILE_ENABLED ||
4437
state == UNIT_FILE_ENABLED_RUNTIME ||
4438
state == UNIT_FILE_STATIC)
4442
puts(unit_file_state_to_string(state));
4446
STRV_FOREACH(name, args+1) {
4449
n = unit_name_mangle(*name);
4453
r = bus_method_call_with_reply (
4455
"org.freedesktop.systemd1",
4456
"/org/freedesktop/systemd1",
4457
"org.freedesktop.systemd1.Manager",
4461
DBUS_TYPE_STRING, &n,
4469
if (!dbus_message_get_args(reply, &error,
4470
DBUS_TYPE_STRING, &s,
4471
DBUS_TYPE_INVALID)) {
4472
log_error("Failed to parse reply: %s", bus_error_message(&error));
4476
dbus_message_unref(reply);
4479
if (streq(s, "enabled") ||
4480
streq(s, "enabled-runtime") ||
4489
return enabled ? 0 : 1;
4492
static int systemctl_help(void) {
4494
pager_open_if_enabled();
4496
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4497
"Query or send control commands to the systemd manager.\n\n"
4498
" -h --help Show this help\n"
4499
" --version Show package version\n"
4500
" -t --type=TYPE List only units of a particular type\n"
4501
" -p --property=NAME Show only properties by this name\n"
4502
" -a --all Show all loaded units/properties, including dead/empty\n"
4503
" ones. To list all units installed on the system, use\n"
4504
" the 'list-unit-files' command instead.\n"
4505
" --reverse Show reverse dependencies with 'list-dependencies'\n"
4506
" --failed Show only failed units\n"
4507
" --full Don't ellipsize unit names on output\n"
4508
" --fail When queueing a new job, fail if conflicting jobs are\n"
4510
" --irreversible Create jobs which cannot be implicitly cancelled\n"
4511
" --show-types When showing sockets, explicitly show their type\n"
4512
" --ignore-dependencies\n"
4513
" When queueing a new job, ignore all its dependencies\n"
4514
" -i --ignore-inhibitors\n"
4515
" When shutting down or sleeping, ignore inhibitors\n"
4516
" --kill-who=WHO Who to send signal to\n"
4517
" -s --signal=SIGNAL Which signal to send\n"
4518
" -H --host=[USER@]HOST\n"
4519
" Show information for remote host\n"
4520
" -P --privileged Acquire privileges before execution\n"
4521
" -q --quiet Suppress output\n"
4522
" --no-block Do not wait until operation finished\n"
4523
" --no-wall Don't send wall message before halt/power-off/reboot\n"
4524
" --no-reload When enabling/disabling unit files, don't reload daemon\n"
4526
" --no-legend Do not print a legend (column headers and hints)\n"
4527
" --no-pager Do not pipe output into a pager\n"
4528
" --no-ask-password\n"
4529
" Do not ask for system passwords\n"
4530
" --system Connect to system manager\n"
4531
" --user Connect to user service manager\n"
4532
" --global Enable/disable unit files globally\n"
4533
" -f --force When enabling unit files, override existing symlinks\n"
4534
" When shutting down, execute action immediately\n"
4535
" --root=PATH Enable unit files in the specified root directory\n"
4536
" --runtime Enable unit files only temporarily until next reboot\n"
4537
" -n --lines=INTEGER Journal entries to show\n"
4538
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4539
" verbose, export, json, json-pretty, json-sse, cat)\n\n"
4541
" list-units List loaded units\n"
4542
" start [NAME...] Start (activate) one or more units\n"
4543
" stop [NAME...] Stop (deactivate) one or more units\n"
4544
" reload [NAME...] Reload one or more units\n"
4545
" restart [NAME...] Start or restart one or more units\n"
4546
" try-restart [NAME...] Restart one or more units if active\n"
4547
" reload-or-restart [NAME...] Reload one or more units if possible,\n"
4548
" otherwise start or restart\n"
4549
" reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4550
" otherwise restart if active\n"
4551
" isolate [NAME] Start one unit and stop all others\n"
4552
" kill [NAME...] Send signal to processes of a unit\n"
4553
" is-active [NAME...] Check whether units are active\n"
4554
" is-failed [NAME...] Check whether units are failed\n"
4555
" status [NAME...|PID...] Show runtime status of one or more units\n"
4556
" show [NAME...|JOB...] Show properties of one or more\n"
4557
" units/jobs or the manager\n"
4558
" help [NAME...|PID...] Show manual for one or more units\n"
4559
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
4561
" get-cgroup-attr [NAME] [ATTR] ...\n"
4562
" Get control group attrubute\n"
4563
" set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4564
" Set control group attribute\n"
4565
" unset-cgroup-attr [NAME] [ATTR...]\n"
4566
" Unset control group attribute\n"
4567
" set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4568
" unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4569
" load [NAME...] Load one or more units\n"
4570
" list-dependencies [NAME] Recursively show units which are required\n"
4571
" or wanted by this unit or by which this\n"
4572
" unit is required or wanted\n\n"
4573
"Unit File Commands:\n"
4574
" list-unit-files List installed unit files\n"
4575
" enable [NAME...] Enable one or more unit files\n"
4576
" disable [NAME...] Disable one or more unit files\n"
4577
" reenable [NAME...] Reenable one or more unit files\n"
4578
" preset [NAME...] Enable/disable one or more unit files\n"
4579
" based on preset configuration\n"
4580
" mask [NAME...] Mask one or more units\n"
4581
" unmask [NAME...] Unmask one or more units\n"
4582
" link [PATH...] Link one or more units files into\n"
4583
" the search path\n"
4584
" is-enabled [NAME...] Check whether unit files are enabled\n\n"
4586
" list-jobs List jobs\n"
4587
" cancel [JOB...] Cancel all, one, or more jobs\n\n"
4588
"Status Commands:\n"
4589
" dump Dump server status\n"
4590
"Snapshot Commands:\n"
4591
" snapshot [NAME] Create a snapshot\n"
4592
" delete [NAME...] Remove one or more snapshots\n\n"
4593
"Environment Commands:\n"
4594
" show-environment Dump environment\n"
4595
" set-environment [NAME=VALUE...] Set one or more environment variables\n"
4596
" unset-environment [NAME...] Unset one or more environment variables\n\n"
4597
"Manager Lifecycle Commands:\n"
4598
" daemon-reload Reload systemd manager configuration\n"
4599
" daemon-reexec Reexecute systemd manager\n\n"
4600
"System Commands:\n"
4601
" default Enter system default mode\n"
4602
" rescue Enter system rescue mode\n"
4603
" emergency Enter system emergency mode\n"
4604
" halt Shut down and halt the system\n"
4605
" poweroff Shut down and power-off the system\n"
4606
" reboot Shut down and reboot the system\n"
4607
" kexec Shut down and reboot the system with kexec\n"
4608
" exit Request user instance exit\n"
4609
" switch-root [ROOT] [INIT] Change to a different root file system\n"
4610
" suspend Suspend the system\n"
4611
" hibernate Hibernate the system\n"
4612
" hybrid-sleep Hibernate and suspend the system\n",
4613
program_invocation_short_name);
4618
static int halt_help(void) {
4620
printf("%s [OPTIONS...]\n\n"
4621
"%s the system.\n\n"
4622
" --help Show this help\n"
4623
" --halt Halt the machine\n"
4624
" -p --poweroff Switch off the machine\n"
4625
" --reboot Reboot the machine\n"
4626
" -f --force Force immediate halt/power-off/reboot\n"
4627
" -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4628
" -d --no-wtmp Don't write wtmp record\n"
4629
" --no-wall Don't send wall message before halt/power-off/reboot\n",
4630
program_invocation_short_name,
4631
arg_action == ACTION_REBOOT ? "Reboot" :
4632
arg_action == ACTION_POWEROFF ? "Power off" :
4638
static int shutdown_help(void) {
4640
printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4641
"Shut down the system.\n\n"
4642
" --help Show this help\n"
4643
" -H --halt Halt the machine\n"
4644
" -P --poweroff Power-off the machine\n"
4645
" -r --reboot Reboot the machine\n"
4646
" -h Equivalent to --poweroff, overridden by --halt\n"
4647
" -k Don't halt/power-off/reboot, just send warnings\n"
4648
" --no-wall Don't send wall message before halt/power-off/reboot\n"
4649
" -c Cancel a pending shutdown\n",
4650
program_invocation_short_name);
4655
static int telinit_help(void) {
4657
printf("%s [OPTIONS...] {COMMAND}\n\n"
4658
"Send control commands to the init daemon.\n\n"
4659
" --help Show this help\n"
4660
" --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4662
" 0 Power-off the machine\n"
4663
" 6 Reboot the machine\n"
4664
" 2, 3, 4, 5 Start runlevelX.target unit\n"
4665
" 1, s, S Enter rescue mode\n"
4666
" q, Q Reload init daemon configuration\n"
4667
" u, U Reexecute init daemon\n",
4668
program_invocation_short_name);
4673
static int runlevel_help(void) {
4675
printf("%s [OPTIONS...]\n\n"
4676
"Prints the previous and current runlevel of the init system.\n\n"
4677
" --help Show this help\n",
4678
program_invocation_short_name);
4683
static int help_types(void) {
4687
puts("Available unit types:");
4688
for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4689
t = unit_type_to_string(i);
4694
puts("\nAvailable unit load states: ");
4695
for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4696
t = unit_load_state_to_string(i);
4704
static int systemctl_parse_argv(int argc, char *argv[]) {
4713
ARG_IGNORE_DEPENDENCIES,
4726
ARG_NO_ASK_PASSWORD,
4733
static const struct option options[] = {
4734
{ "help", no_argument, NULL, 'h' },
4735
{ "version", no_argument, NULL, ARG_VERSION },
4736
{ "type", required_argument, NULL, 't' },
4737
{ "property", required_argument, NULL, 'p' },
4738
{ "all", no_argument, NULL, 'a' },
4739
{ "reverse", no_argument, NULL, ARG_REVERSE },
4740
{ "after", no_argument, NULL, ARG_AFTER },
4741
{ "before", no_argument, NULL, ARG_BEFORE },
4742
{ "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4743
{ "failed", no_argument, NULL, ARG_FAILED },
4744
{ "full", no_argument, NULL, ARG_FULL },
4745
{ "fail", no_argument, NULL, ARG_FAIL },
4746
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4747
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4748
{ "ignore-inhibitors", no_argument, NULL, 'i' },
4749
{ "user", no_argument, NULL, ARG_USER },
4750
{ "system", no_argument, NULL, ARG_SYSTEM },
4751
{ "global", no_argument, NULL, ARG_GLOBAL },
4752
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
4753
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4754
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
4755
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
4756
{ "quiet", no_argument, NULL, 'q' },
4757
{ "root", required_argument, NULL, ARG_ROOT },
4758
{ "force", no_argument, NULL, ARG_FORCE },
4759
{ "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4760
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
4761
{ "signal", required_argument, NULL, 's' },
4762
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4763
{ "host", required_argument, NULL, 'H' },
4764
{ "privileged",no_argument, NULL, 'P' },
4765
{ "runtime", no_argument, NULL, ARG_RUNTIME },
4766
{ "lines", required_argument, NULL, 'n' },
4767
{ "output", required_argument, NULL, 'o' },
4768
{ "plain", no_argument, NULL, ARG_PLAIN },
4769
{ NULL, 0, NULL, 0 }
4777
while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4786
puts(PACKAGE_STRING);
4787
puts(SYSTEMD_FEATURES);
4794
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4795
_cleanup_free_ char *type;
4797
type = strndup(word, size);
4801
if (streq(type, "help")) {
4806
if (unit_type_from_string(type) >= 0) {
4807
if (strv_push(&arg_types, type))
4813
if (unit_load_state_from_string(optarg) >= 0) {
4814
if (strv_push(&arg_load_states, type))
4820
log_error("Unknown unit type or load state '%s'.", type);
4821
log_info("Use -t help to see a list of allowed values.");
4829
/* Make sure that if the empty property list
4830
was specified, we won't show any properties. */
4831
if (isempty(optarg) && !arg_properties) {
4832
arg_properties = strv_new(NULL, NULL);
4833
if (!arg_properties)
4839
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4842
prop = strndup(word, size);
4846
if (strv_push(&arg_properties, prop)) {
4853
/* If the user asked for a particular
4854
* property, show it to him, even if it is
4866
arg_dependency = DEPENDENCY_REVERSE;
4870
arg_dependency = DEPENDENCY_AFTER;
4874
arg_dependency = DEPENDENCY_BEFORE;
4877
case ARG_SHOW_TYPES:
4878
arg_show_types = true;
4882
arg_job_mode = "fail";
4885
case ARG_IRREVERSIBLE:
4886
arg_job_mode = "replace-irreversibly";
4889
case ARG_IGNORE_DEPENDENCIES:
4890
arg_job_mode = "ignore-dependencies";
4894
arg_scope = UNIT_FILE_USER;
4898
arg_scope = UNIT_FILE_SYSTEM;
4902
arg_scope = UNIT_FILE_GLOBAL;
4906
arg_no_block = true;
4910
arg_no_legend = true;
4914
arg_no_pager = true;
4946
arg_no_reload = true;
4950
arg_kill_who = optarg;
4954
if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4955
log_error("Failed to parse signal string %s.", optarg);
4960
case ARG_NO_ASK_PASSWORD:
4961
arg_ask_password = false;
4965
arg_transport = TRANSPORT_POLKIT;
4969
arg_transport = TRANSPORT_SSH;
4978
if (safe_atou(optarg, &arg_lines) < 0) {
4979
log_error("Failed to parse lines '%s'", optarg);
4985
arg_output = output_mode_from_string(optarg);
4986
if (arg_output < 0) {
4987
log_error("Unknown output '%s'.", optarg);
4993
arg_ignore_inhibitors = true;
5004
log_error("Unknown option code '%c'.", c);
5009
if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5010
log_error("Cannot access user instance remotely.");
5017
static int halt_parse_argv(int argc, char *argv[]) {
5026
static const struct option options[] = {
5027
{ "help", no_argument, NULL, ARG_HELP },
5028
{ "halt", no_argument, NULL, ARG_HALT },
5029
{ "poweroff", no_argument, NULL, 'p' },
5030
{ "reboot", no_argument, NULL, ARG_REBOOT },
5031
{ "force", no_argument, NULL, 'f' },
5032
{ "wtmp-only", no_argument, NULL, 'w' },
5033
{ "no-wtmp", no_argument, NULL, 'd' },
5034
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
5035
{ NULL, 0, NULL, 0 }
5043
if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5044
if (runlevel == '0' || runlevel == '6')
5047
while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5055
arg_action = ACTION_HALT;
5059
if (arg_action != ACTION_REBOOT)
5060
arg_action = ACTION_POWEROFF;
5064
arg_action = ACTION_REBOOT;
5086
/* Compatibility nops */
5093
log_error("Unknown option code '%c'.", c);
5098
if (optind < argc) {
5099
log_error("Too many arguments.");
5106
static int parse_time_spec(const char *t, usec_t *_u) {
5110
if (streq(t, "now"))
5112
else if (!strchr(t, ':')) {
5115
if (safe_atou64(t, &u) < 0)
5118
*_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5127
hour = strtol(t, &e, 10);
5128
if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5131
minute = strtol(e+1, &e, 10);
5132
if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5135
n = now(CLOCK_REALTIME);
5136
s = (time_t) (n / USEC_PER_SEC);
5138
assert_se(localtime_r(&s, &tm));
5140
tm.tm_hour = (int) hour;
5141
tm.tm_min = (int) minute;
5144
assert_se(s = mktime(&tm));
5146
*_u = (usec_t) s * USEC_PER_SEC;
5149
*_u += USEC_PER_DAY;
5155
static int shutdown_parse_argv(int argc, char *argv[]) {
5162
static const struct option options[] = {
5163
{ "help", no_argument, NULL, ARG_HELP },
5164
{ "halt", no_argument, NULL, 'H' },
5165
{ "poweroff", no_argument, NULL, 'P' },
5166
{ "reboot", no_argument, NULL, 'r' },
5167
{ "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5168
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
5169
{ NULL, 0, NULL, 0 }
5177
while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5185
arg_action = ACTION_HALT;
5189
arg_action = ACTION_POWEROFF;
5194
arg_action = ACTION_KEXEC;
5196
arg_action = ACTION_REBOOT;
5200
arg_action = ACTION_KEXEC;
5204
if (arg_action != ACTION_HALT)
5205
arg_action = ACTION_POWEROFF;
5218
/* Compatibility nops */
5222
arg_action = ACTION_CANCEL_SHUTDOWN;
5229
log_error("Unknown option code '%c'.", c);
5234
if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5235
r = parse_time_spec(argv[optind], &arg_when);
5237
log_error("Failed to parse time specification: %s", argv[optind]);
5241
arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5243
if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5244
/* No time argument for shutdown cancel */
5245
arg_wall = argv + optind;
5246
else if (argc > optind + 1)
5247
/* We skip the time argument */
5248
arg_wall = argv + optind + 1;
5255
static int telinit_parse_argv(int argc, char *argv[]) {
5262
static const struct option options[] = {
5263
{ "help", no_argument, NULL, ARG_HELP },
5264
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
5265
{ NULL, 0, NULL, 0 }
5268
static const struct {
5272
{ '0', ACTION_POWEROFF },
5273
{ '6', ACTION_REBOOT },
5274
{ '1', ACTION_RESCUE },
5275
{ '2', ACTION_RUNLEVEL2 },
5276
{ '3', ACTION_RUNLEVEL3 },
5277
{ '4', ACTION_RUNLEVEL4 },
5278
{ '5', ACTION_RUNLEVEL5 },
5279
{ 's', ACTION_RESCUE },
5280
{ 'S', ACTION_RESCUE },
5281
{ 'q', ACTION_RELOAD },
5282
{ 'Q', ACTION_RELOAD },
5283
{ 'u', ACTION_REEXEC },
5284
{ 'U', ACTION_REEXEC }
5293
while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5308
log_error("Unknown option code '%c'.", c);
5313
if (optind >= argc) {
5318
if (optind + 1 < argc) {
5319
log_error("Too many arguments.");
5323
if (strlen(argv[optind]) != 1) {
5324
log_error("Expected single character argument.");
5328
for (i = 0; i < ELEMENTSOF(table); i++)
5329
if (table[i].from == argv[optind][0])
5332
if (i >= ELEMENTSOF(table)) {
5333
log_error("Unknown command '%s'.", argv[optind]);
5337
arg_action = table[i].to;
5344
static int runlevel_parse_argv(int argc, char *argv[]) {
5350
static const struct option options[] = {
5351
{ "help", no_argument, NULL, ARG_HELP },
5352
{ NULL, 0, NULL, 0 }
5360
while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5371
log_error("Unknown option code '%c'.", c);
5376
if (optind < argc) {
5377
log_error("Too many arguments.");
5384
static int parse_argv(int argc, char *argv[]) {
5388
if (program_invocation_short_name) {
5390
if (strstr(program_invocation_short_name, "halt")) {
5391
arg_action = ACTION_HALT;
5392
return halt_parse_argv(argc, argv);
5393
} else if (strstr(program_invocation_short_name, "poweroff")) {
5394
arg_action = ACTION_POWEROFF;
5395
return halt_parse_argv(argc, argv);
5396
} else if (strstr(program_invocation_short_name, "reboot")) {
5398
arg_action = ACTION_KEXEC;
5400
arg_action = ACTION_REBOOT;
5401
return halt_parse_argv(argc, argv);
5402
} else if (strstr(program_invocation_short_name, "shutdown")) {
5403
arg_action = ACTION_POWEROFF;
5404
return shutdown_parse_argv(argc, argv);
5405
} else if (strstr(program_invocation_short_name, "init")) {
5407
if (sd_booted() > 0) {
5408
arg_action = ACTION_INVALID;
5409
return telinit_parse_argv(argc, argv);
5411
/* Hmm, so some other init system is
5412
* running, we need to forward this
5413
* request to it. For now we simply
5414
* guess that it is Upstart. */
5416
execv(TELINIT, argv);
5418
log_error("Couldn't find an alternative telinit implementation to spawn.");
5422
} else if (strstr(program_invocation_short_name, "runlevel")) {
5423
arg_action = ACTION_RUNLEVEL;
5424
return runlevel_parse_argv(argc, argv);
5428
arg_action = ACTION_SYSTEMCTL;
5429
return systemctl_parse_argv(argc, argv);
5432
_pure_ static int action_to_runlevel(void) {
5434
static const char table[_ACTION_MAX] = {
5435
[ACTION_HALT] = '0',
5436
[ACTION_POWEROFF] = '0',
5437
[ACTION_REBOOT] = '6',
5438
[ACTION_RUNLEVEL2] = '2',
5439
[ACTION_RUNLEVEL3] = '3',
5440
[ACTION_RUNLEVEL4] = '4',
5441
[ACTION_RUNLEVEL5] = '5',
5442
[ACTION_RESCUE] = '1'
5445
assert(arg_action < _ACTION_MAX);
5447
return table[arg_action];
5450
static int talk_upstart(void) {
5451
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5452
_cleanup_dbus_error_free_ DBusError error;
5453
int previous, rl, r;
5455
env1_buf[] = "RUNLEVEL=X",
5456
env2_buf[] = "PREVLEVEL=X";
5457
char *env1 = env1_buf, *env2 = env2_buf;
5458
const char *emit = "runlevel";
5459
dbus_bool_t b_false = FALSE;
5460
DBusMessageIter iter, sub;
5461
DBusConnection *bus;
5463
dbus_error_init(&error);
5465
if (!(rl = action_to_runlevel()))
5468
if (utmp_get_runlevel(&previous, NULL) < 0)
5471
if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5472
if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5477
log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5482
if ((r = bus_check_peercred(bus)) < 0) {
5483
log_error("Failed to verify owner of bus.");
5487
if (!(m = dbus_message_new_method_call(
5488
"com.ubuntu.Upstart",
5489
"/com/ubuntu/Upstart",
5490
"com.ubuntu.Upstart0_6",
5493
log_error("Could not allocate message.");
5498
dbus_message_iter_init_append(m, &iter);
5500
env1_buf[sizeof(env1_buf)-2] = rl;
5501
env2_buf[sizeof(env2_buf)-2] = previous;
5503
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5504
!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5505
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5506
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5507
!dbus_message_iter_close_container(&iter, &sub) ||
5508
!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5509
log_error("Could not append arguments to message.");
5514
if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5516
if (bus_error_is_no_service(&error)) {
5521
log_error("Failed to issue method call: %s", bus_error_message(&error));
5530
dbus_connection_flush(bus);
5531
dbus_connection_close(bus);
5532
dbus_connection_unref(bus);
5538
static int talk_initctl(void) {
5539
struct init_request request = {};
5541
_cleanup_close_ int fd = -1;
5544
rl = action_to_runlevel();
5548
request.magic = INIT_MAGIC;
5549
request.sleeptime = 0;
5550
request.cmd = INIT_CMD_RUNLVL;
5551
request.runlevel = rl;
5553
fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5555
if (errno == ENOENT)
5558
log_error("Failed to open "INIT_FIFO": %m");
5563
r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5565
log_error("Failed to write to "INIT_FIFO": %m");
5566
return errno > 0 ? -errno : -EIO;
5572
static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5574
static const struct {
5582
int (* const dispatch)(DBusConnection *bus, char **args);
5584
{ "list-units", LESS, 1, list_units },
5585
{ "list-unit-files", EQUAL, 1, list_unit_files },
5586
{ "list-sockets", LESS, 1, list_sockets },
5587
{ "list-jobs", EQUAL, 1, list_jobs },
5588
{ "clear-jobs", EQUAL, 1, daemon_reload },
5589
{ "load", MORE, 2, load_unit },
5590
{ "cancel", MORE, 2, cancel_job },
5591
{ "start", MORE, 2, start_unit },
5592
{ "stop", MORE, 2, start_unit },
5593
{ "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5594
{ "reload", MORE, 2, start_unit },
5595
{ "restart", MORE, 2, start_unit },
5596
{ "try-restart", MORE, 2, start_unit },
5597
{ "reload-or-restart", MORE, 2, start_unit },
5598
{ "reload-or-try-restart", MORE, 2, start_unit },
5599
{ "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5600
{ "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5601
{ "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5602
{ "isolate", EQUAL, 2, start_unit },
5603
{ "set-cgroup", MORE, 3, set_cgroup },
5604
{ "unset-cgroup", MORE, 3, set_cgroup },
5605
{ "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5606
{ "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5607
{ "unset-cgroup-attr", MORE, 3, set_cgroup },
5608
{ "kill", MORE, 2, kill_unit },
5609
{ "is-active", MORE, 2, check_unit_active },
5610
{ "check", MORE, 2, check_unit_active },
5611
{ "is-failed", MORE, 2, check_unit_failed },
5612
{ "show", MORE, 1, show },
5613
{ "status", MORE, 1, show },
5614
{ "help", MORE, 2, show },
5615
{ "dump", EQUAL, 1, dump },
5616
{ "snapshot", LESS, 2, snapshot },
5617
{ "delete", MORE, 2, delete_snapshot },
5618
{ "daemon-reload", EQUAL, 1, daemon_reload },
5619
{ "daemon-reexec", EQUAL, 1, daemon_reload },
5620
{ "show-environment", EQUAL, 1, show_enviroment },
5621
{ "set-environment", MORE, 2, set_environment },
5622
{ "unset-environment", MORE, 2, set_environment },
5623
{ "halt", EQUAL, 1, start_special },
5624
{ "poweroff", EQUAL, 1, start_special },
5625
{ "reboot", EQUAL, 1, start_special },
5626
{ "kexec", EQUAL, 1, start_special },
5627
{ "suspend", EQUAL, 1, start_special },
5628
{ "hibernate", EQUAL, 1, start_special },
5629
{ "hybrid-sleep", EQUAL, 1, start_special },
5630
{ "default", EQUAL, 1, start_special },
5631
{ "rescue", EQUAL, 1, start_special },
5632
{ "emergency", EQUAL, 1, start_special },
5633
{ "exit", EQUAL, 1, start_special },
5634
{ "reset-failed", MORE, 1, reset_failed },
5635
{ "enable", MORE, 2, enable_unit },
5636
{ "disable", MORE, 2, enable_unit },
5637
{ "is-enabled", MORE, 2, unit_is_enabled },
5638
{ "reenable", MORE, 2, enable_unit },
5639
{ "preset", MORE, 2, enable_unit },
5640
{ "mask", MORE, 2, enable_unit },
5641
{ "unmask", MORE, 2, enable_unit },
5642
{ "link", MORE, 2, enable_unit },
5643
{ "switch-root", MORE, 2, switch_root },
5644
{ "list-dependencies", LESS, 2, list_dependencies },
5654
left = argc - optind;
5657
/* Special rule: no arguments means "list-units" */
5660
if (streq(argv[optind], "help") && !argv[optind+1]) {
5661
log_error("This command expects one or more "
5662
"unit names. Did you mean --help?");
5666
for (i = 0; i < ELEMENTSOF(verbs); i++)
5667
if (streq(argv[optind], verbs[i].verb))
5670
if (i >= ELEMENTSOF(verbs)) {
5671
log_error("Unknown operation '%s'.", argv[optind]);
5676
switch (verbs[i].argc_cmp) {
5679
if (left != verbs[i].argc) {
5680
log_error("Invalid number of arguments.");
5687
if (left < verbs[i].argc) {
5688
log_error("Too few arguments.");
5695
if (left > verbs[i].argc) {
5696
log_error("Too many arguments.");
5703
assert_not_reached("Unknown comparison operator.");
5706
/* Require a bus connection for all operations but
5708
if (!streq(verbs[i].verb, "enable") &&
5709
!streq(verbs[i].verb, "disable") &&
5710
!streq(verbs[i].verb, "is-enabled") &&
5711
!streq(verbs[i].verb, "list-unit-files") &&
5712
!streq(verbs[i].verb, "reenable") &&
5713
!streq(verbs[i].verb, "preset") &&
5714
!streq(verbs[i].verb, "mask") &&
5715
!streq(verbs[i].verb, "unmask") &&
5716
!streq(verbs[i].verb, "link")) {
5718
if (running_in_chroot() > 0) {
5719
log_info("Running in chroot, ignoring request.");
5723
if (((!streq(verbs[i].verb, "reboot") &&
5724
!streq(verbs[i].verb, "halt") &&
5725
!streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5726
log_error("Failed to get D-Bus connection: %s",
5727
dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5733
if (!bus && !avoid_bus()) {
5734
log_error("Failed to get D-Bus connection: %s",
5735
dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5740
return verbs[i].dispatch(bus, argv + optind);
5743
static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5744
_cleanup_close_ int fd;
5745
struct sd_shutdown_command c = {
5751
union sockaddr_union sockaddr = {
5752
.un.sun_family = AF_UNIX,
5753
.un.sun_path = "/run/systemd/shutdownd",
5755
struct iovec iovec[2] = {
5756
{.iov_base = (char*) &c,
5757
.iov_len = offsetof(struct sd_shutdown_command, wall_message),
5760
struct msghdr msghdr = {
5761
.msg_name = &sockaddr,
5762
.msg_namelen = offsetof(struct sockaddr_un, sun_path)
5763
+ sizeof("/run/systemd/shutdownd") - 1,
5768
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5772
if (!isempty(message)) {
5773
iovec[1].iov_base = (char*) message;
5774
iovec[1].iov_len = strlen(message);
5775
msghdr.msg_iovlen++;
5778
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5784
static int reload_with_fallback(DBusConnection *bus) {
5787
/* First, try systemd via D-Bus. */
5788
if (daemon_reload(bus, NULL) >= 0)
5792
/* Nothing else worked, so let's try signals */
5793
assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5795
if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5796
log_error("kill() failed: %m");
5803
static int start_with_fallback(DBusConnection *bus) {
5806
/* First, try systemd via D-Bus. */
5807
if (start_unit(bus, NULL) >= 0)
5811
/* Hmm, talking to systemd via D-Bus didn't work. Then
5812
* let's try to talk to Upstart via D-Bus. */
5813
if (talk_upstart() > 0)
5816
/* Nothing else worked, so let's try
5818
if (talk_initctl() > 0)
5821
log_error("Failed to talk to init daemon.");
5825
warn_wall(arg_action);
5829
static _noreturn_ void halt_now(enum action a) {
5831
/* Make sure C-A-D is handled by the kernel from this
5833
reboot(RB_ENABLE_CAD);
5838
log_info("Halting.");
5839
reboot(RB_HALT_SYSTEM);
5842
case ACTION_POWEROFF:
5843
log_info("Powering off.");
5844
reboot(RB_POWER_OFF);
5848
log_info("Rebooting.");
5849
reboot(RB_AUTOBOOT);
5853
assert_not_reached("Unknown halt action.");
5856
assert_not_reached("Uh? This shouldn't happen.");
5859
static int halt_main(DBusConnection *bus) {
5862
r = check_inhibitors(bus, arg_action);
5866
if (geteuid() != 0) {
5867
/* Try logind if we are a normal user and no special
5868
* mode applies. Maybe PolicyKit allows us to shutdown
5871
if (arg_when <= 0 &&
5874
(arg_action == ACTION_POWEROFF ||
5875
arg_action == ACTION_REBOOT)) {
5876
r = reboot_with_logind(bus, arg_action);
5881
log_error("Must be root.");
5886
_cleanup_free_ char *m;
5888
m = strv_join(arg_wall, " ");
5889
r = send_shutdownd(arg_when,
5890
arg_action == ACTION_HALT ? 'H' :
5891
arg_action == ACTION_POWEROFF ? 'P' :
5892
arg_action == ACTION_KEXEC ? 'K' :
5899
log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5901
char date[FORMAT_TIMESTAMP_MAX];
5903
log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5904
format_timestamp(date, sizeof(date), arg_when));
5909
if (!arg_dry && !arg_force)
5910
return start_with_fallback(bus);
5913
if (sd_booted() > 0)
5914
log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5916
r = utmp_put_shutdown();
5918
log_warning("Failed to write utmp record: %s", strerror(-r));
5925
halt_now(arg_action);
5926
/* We should never reach this. */
5930
static int runlevel_main(void) {
5931
int r, runlevel, previous;
5933
r = utmp_get_runlevel(&runlevel, &previous);
5940
previous <= 0 ? 'N' : previous,
5941
runlevel <= 0 ? 'N' : runlevel);
5946
int main(int argc, char*argv[]) {
5947
int r, retval = EXIT_FAILURE;
5948
DBusConnection *bus = NULL;
5949
_cleanup_dbus_error_free_ DBusError error;
5951
dbus_error_init(&error);
5953
setlocale(LC_ALL, "");
5954
log_parse_environment();
5957
r = parse_argv(argc, argv);
5961
retval = EXIT_SUCCESS;
5965
/* /sbin/runlevel doesn't need to communicate via D-Bus, so
5966
* let's shortcut this */
5967
if (arg_action == ACTION_RUNLEVEL) {
5968
r = runlevel_main();
5969
retval = r < 0 ? EXIT_FAILURE : r;
5973
if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5974
log_info("Running in chroot, ignoring request.");
5980
if (arg_transport == TRANSPORT_NORMAL)
5981
bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5982
else if (arg_transport == TRANSPORT_POLKIT) {
5983
bus_connect_system_polkit(&bus, &error);
5984
private_bus = false;
5985
} else if (arg_transport == TRANSPORT_SSH) {
5986
bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5987
private_bus = false;
5989
assert_not_reached("Uh, invalid transport...");
5992
switch (arg_action) {
5994
case ACTION_SYSTEMCTL:
5995
r = systemctl_main(bus, argc, argv, &error);
5999
case ACTION_POWEROFF:
6005
case ACTION_RUNLEVEL2:
6006
case ACTION_RUNLEVEL3:
6007
case ACTION_RUNLEVEL4:
6008
case ACTION_RUNLEVEL5:
6010
case ACTION_EMERGENCY:
6011
case ACTION_DEFAULT:
6012
r = start_with_fallback(bus);
6017
r = reload_with_fallback(bus);
6020
case ACTION_CANCEL_SHUTDOWN: {
6024
m = strv_join(arg_wall, " ");
6026
retval = EXIT_FAILURE;
6030
r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6032
log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6037
case ACTION_INVALID:
6038
case ACTION_RUNLEVEL:
6040
assert_not_reached("Unknown action");
6043
retval = r < 0 ? EXIT_FAILURE : r;
6047
dbus_connection_flush(bus);
6048
dbus_connection_close(bus);
6049
dbus_connection_unref(bus);
6054
strv_free(arg_types);
6055
strv_free(arg_load_states);
6056
strv_free(arg_properties);
6059
ask_password_agent_close();
6060
polkit_agent_close();