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>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_dry = false;
82 static bool arg_quiet = false;
83 static bool arg_full = false;
84 static int arg_force = 0;
85 static bool arg_ask_password = true;
86 static bool arg_failed = false;
87 static bool arg_runtime = false;
88 static char **arg_wall = NULL;
89 static const char *arg_kill_who = NULL;
90 static int arg_signal = SIGTERM;
91 static const char *arg_root = NULL;
92 static usec_t arg_when = 0;
114 ACTION_CANCEL_SHUTDOWN,
116 } arg_action = ACTION_SYSTEMCTL;
122 static enum transport {
126 } arg_transport = TRANSPORT_NORMAL;
127 static const char *arg_host = NULL;
128 static unsigned arg_lines = 10;
129 static OutputMode arg_output = OUTPUT_SHORT;
131 static bool private_bus = false;
133 static int daemon_reload(DBusConnection *bus, char **args);
134 static void halt_now(enum action a);
136 static void pager_open_if_enabled(void) {
144 static void ask_password_agent_open_if_enabled(void) {
146 /* Open the password agent as a child process if necessary */
148 if (!arg_ask_password)
151 if (arg_scope != UNIT_FILE_SYSTEM)
154 ask_password_agent_open();
158 static void polkit_agent_open_if_enabled(void) {
160 /* Open the polkit agent as a child process if necessary */
162 if (!arg_ask_password)
165 if (arg_scope != UNIT_FILE_SYSTEM)
172 static const char *ansi_highlight(bool b) {
177 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
180 static const char *ansi_highlight_red(bool b) {
185 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
188 static const char *ansi_highlight_green(bool b) {
193 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
196 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
199 if (!dbus_error_is_set(error))
202 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
203 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
204 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
205 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
206 return EXIT_NOPERMISSION;
208 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
209 return EXIT_NOTINSTALLED;
211 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
212 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
213 return EXIT_NOTIMPLEMENTED;
215 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
216 return EXIT_NOTCONFIGURED;
224 static void warn_wall(enum action a) {
225 static const char *table[_ACTION_MAX] = {
226 [ACTION_HALT] = "The system is going down for system halt NOW!",
227 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
228 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
229 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
230 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
231 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
232 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
241 p = strv_join(arg_wall, " ");
243 log_error("Failed to join strings.");
259 utmp_wall(table[a], NULL);
262 static bool avoid_bus(void) {
264 if (running_in_chroot() > 0)
267 if (sd_booted() <= 0)
270 if (!isempty(arg_root))
273 if (arg_scope == UNIT_FILE_GLOBAL)
281 const char *description;
282 const char *load_state;
283 const char *active_state;
284 const char *sub_state;
285 const char *following;
286 const char *unit_path;
288 const char *job_type;
289 const char *job_path;
292 static int compare_unit_info(const void *a, const void *b) {
294 const struct unit_info *u = a, *v = b;
296 d1 = strrchr(u->id, '.');
297 d2 = strrchr(v->id, '.');
302 if ((r = strcasecmp(d1, d2)) != 0)
306 return strcasecmp(u->id, v->id);
309 static bool output_show_unit(const struct unit_info *u) {
313 return streq(u->active_state, "failed");
315 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
316 streq(dot+1, arg_type))) &&
317 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
318 (arg_all || !(streq(u->active_state, "inactive")
319 || u->following[0]) || u->job_id > 0);
322 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
323 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
324 const struct unit_info *u;
327 max_id_len = sizeof("UNIT")-1;
328 active_len = sizeof("ACTIVE")-1;
329 sub_len = sizeof("SUB")-1;
330 job_len = sizeof("JOB")-1;
333 for (u = unit_infos; u < unit_infos + c; u++) {
334 if (!output_show_unit(u))
337 max_id_len = MAX(max_id_len, strlen(u->id));
338 active_len = MAX(active_len, strlen(u->active_state));
339 sub_len = MAX(sub_len, strlen(u->sub_state));
340 if (u->job_id != 0) {
341 job_len = MAX(job_len, strlen(u->job_type));
348 id_len = MIN(max_id_len, 25);
349 basic_len = 5 + id_len + 5 + active_len + sub_len;
351 basic_len += job_len + 1;
352 if (basic_len < (unsigned) columns()) {
353 unsigned extra_len, incr;
354 extra_len = columns() - basic_len;
355 /* Either UNIT already got 25, or is fully satisfied.
356 * Grant up to 25 to DESC now. */
357 incr = MIN(extra_len, 25);
360 /* split the remaining space between UNIT and DESC,
361 * but do not give UNIT more than it needs. */
363 incr = MIN(extra_len / 2, max_id_len - id_len);
365 desc_len += extra_len - incr;
371 for (u = unit_infos; u < unit_infos + c; u++) {
373 const char *on_loaded, *off_loaded;
374 const char *on_active, *off_active;
376 if (!output_show_unit(u))
379 if (!n_shown && !arg_no_legend) {
380 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
381 active_len, "ACTIVE", sub_len, "SUB");
383 printf("%-*s ", job_len, "JOB");
384 if (!arg_full && arg_no_pager)
385 printf("%.*s\n", desc_len, "DESCRIPTION");
387 printf("%s\n", "DESCRIPTION");
392 if (streq(u->load_state, "error")) {
393 on_loaded = ansi_highlight_red(true);
394 off_loaded = ansi_highlight_red(false);
396 on_loaded = off_loaded = "";
398 if (streq(u->active_state, "failed")) {
399 on_active = ansi_highlight_red(true);
400 off_active = ansi_highlight_red(false);
402 on_active = off_active = "";
404 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
406 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
407 id_len, e ? e : u->id,
408 on_loaded, u->load_state, off_loaded,
409 on_active, active_len, u->active_state,
410 sub_len, u->sub_state, off_active,
411 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
412 if (!arg_full && arg_no_pager)
413 printf("%.*s\n", desc_len, u->description);
415 printf("%s\n", u->description);
420 if (!arg_no_legend) {
421 const char *on, *off;
424 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
425 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
426 "SUB = The low-level unit activation state, values depend on unit type.\n");
428 printf("JOB = Pending job for the unit.\n");
430 on = ansi_highlight(true);
431 off = ansi_highlight(false);
433 on = ansi_highlight_red(true);
434 off = ansi_highlight_red(false);
438 printf("%s%u loaded units listed.%s\n"
439 "To show all installed unit files use 'systemctl list-unit-files'.\n",
442 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
443 "To show all installed unit files use 'systemctl list-unit-files'.\n",
448 static int list_units(DBusConnection *bus, char **args) {
449 DBusMessage *reply = NULL;
451 DBusMessageIter iter, sub, sub2;
452 unsigned c = 0, n_units = 0;
453 struct unit_info *unit_infos = NULL;
455 pager_open_if_enabled();
457 r = bus_method_call_with_reply (
459 "org.freedesktop.systemd1",
460 "/org/freedesktop/systemd1",
461 "org.freedesktop.systemd1.Manager",
469 if (!dbus_message_iter_init(reply, &iter) ||
470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
471 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
472 log_error("Failed to parse reply.");
477 dbus_message_iter_recurse(&iter, &sub);
479 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
482 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
483 log_error("Failed to parse reply.");
491 n_units = MAX(2*c, 16);
492 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
495 log_error("Failed to allocate unit array.");
505 dbus_message_iter_recurse(&sub, &sub2);
507 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
508 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
517 log_error("Failed to parse reply.");
522 dbus_message_iter_next(&sub);
527 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
528 output_units_list(unit_infos, c);
533 dbus_message_unref(reply);
540 static int compare_unit_file_list(const void *a, const void *b) {
542 const UnitFileList *u = a, *v = b;
544 d1 = strrchr(u->path, '.');
545 d2 = strrchr(v->path, '.');
550 r = strcasecmp(d1, d2);
555 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
558 static bool output_show_unit_file(const UnitFileList *u) {
561 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
564 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
565 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
566 const UnitFileList *u;
568 max_id_len = sizeof("UNIT FILE")-1;
569 state_cols = sizeof("STATE")-1;
570 for (u = units; u < units + c; u++) {
571 if (!output_show_unit_file(u))
574 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
575 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
580 id_cols = MIN(max_id_len, 25);
581 basic_cols = 1 + id_cols + state_cols;
582 if (basic_cols < (unsigned) columns())
583 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
585 id_cols = max_id_len;
588 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
590 for (u = units; u < units + c; u++) {
592 const char *on, *off;
595 if (!output_show_unit_file(u))
600 if (u->state == UNIT_FILE_MASKED ||
601 u->state == UNIT_FILE_MASKED_RUNTIME ||
602 u->state == UNIT_FILE_DISABLED ||
603 u->state == UNIT_FILE_INVALID) {
604 on = ansi_highlight_red(true);
605 off = ansi_highlight_red(false);
606 } else if (u->state == UNIT_FILE_ENABLED) {
607 on = ansi_highlight_green(true);
608 off = ansi_highlight_green(false);
612 id = path_get_file_name(u->path);
614 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
616 printf("%-*s %s%-*s%s\n",
618 on, state_cols, unit_file_state_to_string(u->state), off);
624 printf("\n%u unit files listed.\n", n_shown);
627 static int list_unit_files(DBusConnection *bus, char **args) {
628 DBusMessage *reply = NULL;
630 DBusMessageIter iter, sub, sub2;
631 unsigned c = 0, n_units = 0;
632 UnitFileList *units = NULL;
634 pager_open_if_enabled();
641 h = hashmap_new(string_hash_func, string_compare_func);
645 r = unit_file_get_list(arg_scope, arg_root, h);
647 unit_file_list_free(h);
648 log_error("Failed to get unit file list: %s", strerror(-r));
652 n_units = hashmap_size(h);
653 units = new(UnitFileList, n_units);
655 unit_file_list_free(h);
659 HASHMAP_FOREACH(u, h, i) {
660 memcpy(units + c++, u, sizeof(UnitFileList));
666 r = bus_method_call_with_reply (
668 "org.freedesktop.systemd1",
669 "/org/freedesktop/systemd1",
670 "org.freedesktop.systemd1.Manager",
678 if (!dbus_message_iter_init(reply, &iter) ||
679 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
680 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
681 log_error("Failed to parse reply.");
686 dbus_message_iter_recurse(&iter, &sub);
688 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
692 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
693 log_error("Failed to parse reply.");
701 n_units = MAX(2*c, 16);
702 w = realloc(units, sizeof(struct UnitFileList) * n_units);
705 log_error("Failed to allocate unit array.");
715 dbus_message_iter_recurse(&sub, &sub2);
717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
719 log_error("Failed to parse reply.");
724 u->state = unit_file_state_from_string(state);
726 dbus_message_iter_next(&sub);
732 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
733 output_unit_file_list(units, c);
740 dbus_message_unref(reply);
747 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
748 static const char * const colors[] = {
749 "Requires", "[color=\"black\"]",
750 "RequiresOverridable", "[color=\"black\"]",
751 "Requisite", "[color=\"darkblue\"]",
752 "RequisiteOverridable", "[color=\"darkblue\"]",
753 "Wants", "[color=\"grey66\"]",
754 "Conflicts", "[color=\"red\"]",
755 "ConflictedBy", "[color=\"red\"]",
756 "After", "[color=\"green\"]"
759 const char *c = NULL;
766 for (i = 0; i < ELEMENTSOF(colors); i += 2)
767 if (streq(colors[i], prop)) {
775 if (arg_dot != DOT_ALL)
776 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
779 switch (dbus_message_iter_get_arg_type(iter)) {
781 case DBUS_TYPE_ARRAY:
783 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
786 dbus_message_iter_recurse(iter, &sub);
788 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
791 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
792 dbus_message_iter_get_basic(&sub, &s);
793 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
795 dbus_message_iter_next(&sub);
805 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
806 DBusMessage *reply = NULL;
807 const char *interface = "org.freedesktop.systemd1.Unit";
809 DBusMessageIter iter, sub, sub2, sub3;
813 r = bus_method_call_with_reply (
815 "org.freedesktop.systemd1",
817 "org.freedesktop.DBus.Properties",
821 DBUS_TYPE_STRING, &interface,
826 if (!dbus_message_iter_init(reply, &iter) ||
827 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
828 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
829 log_error("Failed to parse reply.");
834 dbus_message_iter_recurse(&iter, &sub);
836 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
839 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
840 log_error("Failed to parse reply.");
845 dbus_message_iter_recurse(&sub, &sub2);
847 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
848 log_error("Failed to parse reply.");
853 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
854 log_error("Failed to parse reply.");
859 dbus_message_iter_recurse(&sub2, &sub3);
861 if (dot_one_property(name, prop, &sub3)) {
862 log_error("Failed to parse reply.");
867 dbus_message_iter_next(&sub);
872 dbus_message_unref(reply);
877 static int dot(DBusConnection *bus, char **args) {
878 DBusMessage *reply = NULL;
880 DBusMessageIter iter, sub, sub2;
882 r = bus_method_call_with_reply (
884 "org.freedesktop.systemd1",
885 "/org/freedesktop/systemd1",
886 "org.freedesktop.systemd1.Manager",
894 if (!dbus_message_iter_init(reply, &iter) ||
895 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
896 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
897 log_error("Failed to parse reply.");
902 printf("digraph systemd {\n");
904 dbus_message_iter_recurse(&iter, &sub);
905 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
906 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
908 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
909 log_error("Failed to parse reply.");
914 dbus_message_iter_recurse(&sub, &sub2);
916 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
917 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
923 log_error("Failed to parse reply.");
928 if ((r = dot_one(bus, id, unit_path)) < 0)
931 /* printf("\t\"%s\";\n", id); */
932 dbus_message_iter_next(&sub);
937 log_info(" Color legend: black = Requires\n"
938 " dark blue = Requisite\n"
939 " dark grey = Wants\n"
944 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
945 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
951 dbus_message_unref(reply);
956 static int list_jobs(DBusConnection *bus, char **args) {
957 DBusMessage *reply = NULL;
959 DBusMessageIter iter, sub, sub2;
962 pager_open_if_enabled();
964 r = bus_method_call_with_reply (
966 "org.freedesktop.systemd1",
967 "/org/freedesktop/systemd1",
968 "org.freedesktop.systemd1.Manager",
976 if (!dbus_message_iter_init(reply, &iter) ||
977 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
978 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
979 log_error("Failed to parse reply.");
984 dbus_message_iter_recurse(&iter, &sub);
987 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
989 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
990 const char *name, *type, *state, *job_path, *unit_path;
994 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
995 log_error("Failed to parse reply.");
1000 dbus_message_iter_recurse(&sub, &sub2);
1002 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1008 log_error("Failed to parse reply.");
1013 e = arg_full ? NULL : ellipsize(name, 25, 33);
1014 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1019 dbus_message_iter_next(&sub);
1023 printf("\n%u jobs listed.\n", k);
1029 dbus_message_unref(reply);
1034 static int load_unit(DBusConnection *bus, char **args) {
1040 STRV_FOREACH(name, args+1) {
1041 n = unit_name_mangle(*name);
1042 r = bus_method_call_with_reply (
1044 "org.freedesktop.systemd1",
1045 "/org/freedesktop/systemd1",
1046 "org.freedesktop.systemd1.Manager",
1050 DBUS_TYPE_STRING, n ? &n : name,
1061 static int cancel_job(DBusConnection *bus, char **args) {
1062 DBusMessage *reply = NULL;
1068 if (strv_length(args) <= 1)
1069 return daemon_reload(bus, args);
1071 STRV_FOREACH(name, args+1) {
1075 r = safe_atou(*name, &id);
1077 log_error("Failed to parse job id: %s", strerror(-r));
1080 assert_cc(sizeof(uint32_t) == sizeof(id));
1082 r = bus_method_call_with_reply (
1084 "org.freedesktop.systemd1",
1085 "/org/freedesktop/systemd1",
1086 "org.freedesktop.systemd1.Manager",
1090 DBUS_TYPE_UINT32, &id,
1095 if (!dbus_message_get_args(reply, NULL,
1096 DBUS_TYPE_OBJECT_PATH, &path,
1097 DBUS_TYPE_INVALID)) {
1098 log_error("Failed to parse reply");
1099 dbus_message_unref(reply);
1103 dbus_message_unref(reply);
1105 r = bus_method_call_with_reply (
1107 "org.freedesktop.systemd1",
1109 "org.freedesktop.systemd1.Job",
1122 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1123 DBusMessage *reply = NULL;
1124 dbus_bool_t b = FALSE;
1125 DBusMessageIter iter, sub;
1127 *interface = "org.freedesktop.systemd1.Unit",
1128 *property = "NeedDaemonReload",
1133 /* We ignore all errors here, since this is used to show a warning only */
1135 n = unit_name_mangle(unit);
1136 r = bus_method_call_with_reply (
1138 "org.freedesktop.systemd1",
1139 "/org/freedesktop/systemd1",
1140 "org.freedesktop.systemd1.Manager",
1144 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1150 if (!dbus_message_get_args(reply, NULL,
1151 DBUS_TYPE_OBJECT_PATH, &path,
1155 dbus_message_unref(reply);
1156 r = bus_method_call_with_reply (
1158 "org.freedesktop.systemd1",
1160 "org.freedesktop.DBus.Properties",
1164 DBUS_TYPE_STRING, &interface,
1165 DBUS_TYPE_STRING, &property,
1170 if (!dbus_message_iter_init(reply, &iter) ||
1171 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1174 dbus_message_iter_recurse(&iter, &sub);
1176 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1179 dbus_message_iter_get_basic(&sub, &b);
1183 dbus_message_unref(reply);
1188 typedef struct WaitData {
1195 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1203 dbus_error_init(&error);
1205 log_debug("Got D-Bus request: %s.%s() on %s",
1206 dbus_message_get_interface(message),
1207 dbus_message_get_member(message),
1208 dbus_message_get_path(message));
1210 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1211 log_error("Warning! D-Bus connection terminated.");
1212 dbus_connection_close(connection);
1214 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1216 const char *path, *result, *unit;
1217 dbus_bool_t success = true;
1219 if (dbus_message_get_args(message, &error,
1220 DBUS_TYPE_UINT32, &id,
1221 DBUS_TYPE_OBJECT_PATH, &path,
1222 DBUS_TYPE_STRING, &unit,
1223 DBUS_TYPE_STRING, &result,
1224 DBUS_TYPE_INVALID)) {
1227 p = set_remove(d->set, (char*) path);
1230 if (!isempty(result))
1231 d->result = strdup(result);
1234 d->name = strdup(unit);
1239 dbus_error_free(&error);
1240 if (dbus_message_get_args(message, &error,
1241 DBUS_TYPE_UINT32, &id,
1242 DBUS_TYPE_OBJECT_PATH, &path,
1243 DBUS_TYPE_STRING, &result,
1244 DBUS_TYPE_INVALID)) {
1247 /* Compatibility with older systemd versions <
1248 * 183 during upgrades. This should be dropped
1250 p = set_remove(d->set, (char*) path);
1254 d->result = strdup(result);
1259 dbus_error_free(&error);
1260 if (dbus_message_get_args(message, &error,
1261 DBUS_TYPE_UINT32, &id,
1262 DBUS_TYPE_OBJECT_PATH, &path,
1263 DBUS_TYPE_BOOLEAN, &success,
1264 DBUS_TYPE_INVALID)) {
1267 /* Compatibility with older systemd versions <
1268 * 19 during upgrades. This should be dropped
1271 p = set_remove(d->set, (char*) path);
1275 d->result = strdup("failed");
1281 log_error("Failed to parse message: %s", bus_error_message(&error));
1285 dbus_error_free(&error);
1286 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1289 static int enable_wait_for_jobs(DBusConnection *bus) {
1297 dbus_error_init(&error);
1298 dbus_bus_add_match(bus,
1300 "sender='org.freedesktop.systemd1',"
1301 "interface='org.freedesktop.systemd1.Manager',"
1302 "member='JobRemoved',"
1303 "path='/org/freedesktop/systemd1'",
1306 if (dbus_error_is_set(&error)) {
1307 log_error("Failed to add match: %s", bus_error_message(&error));
1308 dbus_error_free(&error);
1312 /* This is slightly dirty, since we don't undo the match registrations. */
1316 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1326 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1329 while (!set_isempty(s)) {
1331 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1332 log_error("Disconnected from bus.");
1333 return -ECONNREFUSED;
1340 if (streq(d.result, "timeout"))
1341 log_error("Job for %s timed out.", strna(d.name));
1342 else if (streq(d.result, "canceled"))
1343 log_error("Job for %s canceled.", strna(d.name));
1344 else if (streq(d.result, "dependency"))
1345 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1346 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1347 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1350 if (streq_ptr(d.result, "timeout"))
1352 else if (streq_ptr(d.result, "canceled"))
1354 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1365 dbus_connection_remove_filter(bus, wait_filter, &d);
1369 static int check_one_unit(DBusConnection *bus, char *name, char **check_states, bool quiet) {
1370 DBusMessage *reply = NULL;
1371 DBusMessageIter iter, sub;
1373 *interface = "org.freedesktop.systemd1.Unit",
1374 *property = "ActiveState";
1375 const char *path = NULL;
1382 n = unit_name_mangle(name);
1383 r = bus_method_call_with_reply (
1385 "org.freedesktop.systemd1",
1386 "/org/freedesktop/systemd1",
1387 "org.freedesktop.systemd1.Manager",
1391 DBUS_TYPE_STRING, n ? &n : &name,
1395 if ((r != -ENOMEM) && (!quiet))
1400 if (!dbus_message_get_args(reply, NULL,
1401 DBUS_TYPE_OBJECT_PATH, &path,
1402 DBUS_TYPE_INVALID)) {
1403 log_error("Failed to parse reply.");
1408 dbus_message_unref(reply);
1409 r = bus_method_call_with_reply (
1411 "org.freedesktop.systemd1",
1413 "org.freedesktop.DBus.Properties",
1417 DBUS_TYPE_STRING, &interface,
1418 DBUS_TYPE_STRING, &property,
1423 if (!dbus_message_iter_init(reply, &iter) ||
1424 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1425 log_error("Failed to parse reply.");
1430 dbus_message_iter_recurse(&iter, &sub);
1432 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1433 log_error("Failed to parse reply.");
1438 dbus_message_iter_get_basic(&sub, &state);
1443 if (strv_find(check_states, state))
1446 r = 3; /* According to LSB: "program is not running" */
1450 dbus_message_unref(reply);
1455 static void check_triggering_units(
1456 DBusConnection *bus,
1457 const char *unit_name) {
1459 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1460 DBusMessageIter iter, sub;
1461 char *service_trigger = NULL;
1462 const char *interface = "org.freedesktop.systemd1.Unit",
1463 *triggered_by_property = "TriggeredBy";
1465 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1466 bool print_warning_label = true;
1469 n = unit_name_mangle(unit_name);
1475 unit_path = unit_dbus_path_from_name(n);
1481 r = bus_method_call_with_reply (
1483 "org.freedesktop.systemd1",
1485 "org.freedesktop.DBus.Properties",
1489 DBUS_TYPE_STRING, &interface,
1490 DBUS_TYPE_STRING, &triggered_by_property,
1495 if (!dbus_message_iter_init(reply, &iter) ||
1496 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1497 log_error("Failed to parse reply.");
1501 dbus_message_iter_recurse(&iter, &sub);
1502 dbus_message_iter_recurse(&sub, &iter);
1505 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1506 char **check_states = NULL;
1508 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1509 log_error("Failed to parse reply.");
1513 dbus_message_iter_get_basic(&sub, &service_trigger);
1515 check_states = strv_new("active", "reloading", NULL);
1516 r = check_one_unit(bus, service_trigger, check_states, true);
1517 strv_free(check_states);
1521 if (print_warning_label) {
1522 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1523 print_warning_label = false;
1525 log_warning(" %s", service_trigger);
1528 dbus_message_iter_next(&sub);
1532 static int start_unit_one(
1533 DBusConnection *bus,
1540 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1543 _cleanup_free_ char *n, *p = NULL;
1550 n = unit_name_mangle(name);
1554 r = bus_method_call_with_reply(
1556 "org.freedesktop.systemd1",
1557 "/org/freedesktop/systemd1",
1558 "org.freedesktop.systemd1.Manager",
1562 DBUS_TYPE_STRING, &n,
1563 DBUS_TYPE_STRING, &mode,
1566 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1567 /* There's always a fallback possible for
1568 * legacy actions. */
1571 log_error("Failed to issue method call: %s", bus_error_message(error));
1576 if (!dbus_message_get_args(reply, error,
1577 DBUS_TYPE_OBJECT_PATH, &path,
1578 DBUS_TYPE_INVALID)) {
1579 log_error("Failed to parse reply: %s", bus_error_message(error));
1583 if (need_daemon_reload(bus, n))
1584 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1585 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1594 log_error("Failed to add path to set.");
1604 static enum action verb_to_action(const char *verb) {
1605 if (streq(verb, "halt"))
1607 else if (streq(verb, "poweroff"))
1608 return ACTION_POWEROFF;
1609 else if (streq(verb, "reboot"))
1610 return ACTION_REBOOT;
1611 else if (streq(verb, "kexec"))
1612 return ACTION_KEXEC;
1613 else if (streq(verb, "rescue"))
1614 return ACTION_RESCUE;
1615 else if (streq(verb, "emergency"))
1616 return ACTION_EMERGENCY;
1617 else if (streq(verb, "default"))
1618 return ACTION_DEFAULT;
1619 else if (streq(verb, "exit"))
1621 else if (streq(verb, "suspend"))
1622 return ACTION_SUSPEND;
1623 else if (streq(verb, "hibernate"))
1624 return ACTION_HIBERNATE;
1625 else if (streq(verb, "hybrid-sleep"))
1626 return ACTION_HYBRID_SLEEP;
1628 return ACTION_INVALID;
1631 static int start_unit(DBusConnection *bus, char **args) {
1633 static const char * const table[_ACTION_MAX] = {
1634 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1635 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1636 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1637 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1638 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1639 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1640 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1641 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1642 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1643 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1644 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1645 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1646 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1647 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1648 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1652 const char *method, *mode, *one_name;
1657 dbus_error_init(&error);
1661 ask_password_agent_open_if_enabled();
1663 if (arg_action == ACTION_SYSTEMCTL) {
1665 streq(args[0], "stop") ||
1666 streq(args[0], "condstop") ? "StopUnit" :
1667 streq(args[0], "reload") ? "ReloadUnit" :
1668 streq(args[0], "restart") ? "RestartUnit" :
1670 streq(args[0], "try-restart") ||
1671 streq(args[0], "condrestart") ? "TryRestartUnit" :
1673 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1675 streq(args[0], "reload-or-try-restart") ||
1676 streq(args[0], "condreload") ||
1678 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1682 (streq(args[0], "isolate") ||
1683 streq(args[0], "rescue") ||
1684 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1686 one_name = table[verb_to_action(args[0])];
1689 assert(arg_action < ELEMENTSOF(table));
1690 assert(table[arg_action]);
1692 method = "StartUnit";
1694 mode = (arg_action == ACTION_EMERGENCY ||
1695 arg_action == ACTION_RESCUE ||
1696 arg_action == ACTION_RUNLEVEL2 ||
1697 arg_action == ACTION_RUNLEVEL3 ||
1698 arg_action == ACTION_RUNLEVEL4 ||
1699 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1701 one_name = table[arg_action];
1704 if (!arg_no_block) {
1705 ret = enable_wait_for_jobs(bus);
1707 log_error("Could not watch jobs: %s", strerror(-ret));
1711 s = set_new(string_hash_func, string_compare_func);
1719 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1721 ret = translate_bus_error_to_exit_status(ret, &error);
1723 STRV_FOREACH(name, args+1) {
1724 r = start_unit_one(bus, method, *name, mode, &error, s);
1726 ret = translate_bus_error_to_exit_status(r, &error);
1727 dbus_error_free(&error);
1732 if (!arg_no_block) {
1733 r = wait_for_jobs(bus, s);
1739 /* When stopping units, warn if they can still be triggered by
1740 * another active unit (socket, path, timer) */
1741 if (!arg_quiet && streq(method, "StopUnit")) {
1743 check_triggering_units(bus, one_name);
1745 STRV_FOREACH(name, args+1)
1746 check_triggering_units(bus, *name);
1752 dbus_error_free(&error);
1757 /* Ask systemd-logind, which might grant access to unprivileged users
1758 * through PolicyKit */
1759 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1762 dbus_bool_t interactive = true;
1764 polkit_agent_open_if_enabled();
1772 case ACTION_POWEROFF:
1773 method = "PowerOff";
1776 case ACTION_SUSPEND:
1780 case ACTION_HIBERNATE:
1781 method = "Hibernate";
1784 case ACTION_HYBRID_SLEEP:
1785 method = "HybridSleep";
1792 return bus_method_call_with_reply (
1794 "org.freedesktop.login1",
1795 "/org/freedesktop/login1",
1796 "org.freedesktop.login1.Manager",
1800 DBUS_TYPE_BOOLEAN, &interactive,
1807 static int start_special(DBusConnection *bus, char **args) {
1813 a = verb_to_action(args[0]);
1815 if (arg_force >= 2 && geteuid() != 0) {
1816 log_error("Must be root.");
1820 if (arg_force >= 2 &&
1821 (a == ACTION_HALT ||
1822 a == ACTION_POWEROFF ||
1823 a == ACTION_REBOOT))
1826 if (arg_force >= 1 &&
1827 (a == ACTION_HALT ||
1828 a == ACTION_POWEROFF ||
1829 a == ACTION_REBOOT ||
1830 a == ACTION_KEXEC ||
1832 return daemon_reload(bus, args);
1834 /* first try logind, to allow authentication with polkit */
1835 if (geteuid() != 0 &&
1836 (a == ACTION_POWEROFF ||
1837 a == ACTION_REBOOT ||
1838 a == ACTION_SUSPEND ||
1839 a == ACTION_HIBERNATE ||
1840 a == ACTION_HYBRID_SLEEP)) {
1841 r = reboot_with_logind(bus, a);
1846 r = start_unit(bus, args);
1853 static int check_unit_active(DBusConnection *bus, char **args) {
1855 int r = 3; /* According to LSB: "program is not running" */
1860 STRV_FOREACH(name, args+1) {
1861 char **check_states = strv_new("active", "reloading", NULL);
1862 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1863 strv_free(check_states);
1873 static int check_unit_failed(DBusConnection *bus, char **args) {
1880 STRV_FOREACH(name, args+1) {
1881 char **check_states = strv_new("failed", NULL);
1882 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1883 strv_free(check_states);
1893 static int kill_unit(DBusConnection *bus, char **args) {
1900 arg_kill_who = "all";
1902 STRV_FOREACH(name, args+1) {
1903 n = unit_name_mangle(*name);
1904 r = bus_method_call_with_reply (
1906 "org.freedesktop.systemd1",
1907 "/org/freedesktop/systemd1",
1908 "org.freedesktop.systemd1.Manager",
1912 DBUS_TYPE_STRING, n ? &n : name,
1913 DBUS_TYPE_STRING, &arg_kill_who,
1914 DBUS_TYPE_INT32, &arg_signal,
1923 typedef struct ExecStatusInfo {
1931 usec_t start_timestamp;
1932 usec_t exit_timestamp;
1937 LIST_FIELDS(struct ExecStatusInfo, exec);
1940 static void exec_status_info_free(ExecStatusInfo *i) {
1949 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1950 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1951 DBusMessageIter sub2, sub3;
1955 int32_t code, status;
1961 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1964 dbus_message_iter_recurse(sub, &sub2);
1966 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1969 if (!(i->path = strdup(path)))
1972 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1973 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1977 dbus_message_iter_recurse(&sub2, &sub3);
1978 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1979 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1980 dbus_message_iter_next(&sub3);
1985 if (!(i->argv = new0(char*, n+1)))
1989 dbus_message_iter_recurse(&sub2, &sub3);
1990 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1993 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1994 dbus_message_iter_get_basic(&sub3, &s);
1995 dbus_message_iter_next(&sub3);
1997 if (!(i->argv[n++] = strdup(s)))
2001 if (!dbus_message_iter_next(&sub2) ||
2002 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2008 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2009 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2013 i->start_timestamp = (usec_t) start_timestamp;
2014 i->exit_timestamp = (usec_t) exit_timestamp;
2015 i->pid = (pid_t) pid;
2022 typedef struct UnitStatusInfo {
2024 const char *load_state;
2025 const char *active_state;
2026 const char *sub_state;
2027 const char *unit_file_state;
2029 const char *description;
2030 const char *following;
2032 char **documentation;
2034 const char *fragment_path;
2035 const char *source_path;
2036 const char *default_control_group;
2038 const char *load_error;
2041 usec_t inactive_exit_timestamp;
2042 usec_t inactive_exit_timestamp_monotonic;
2043 usec_t active_enter_timestamp;
2044 usec_t active_exit_timestamp;
2045 usec_t inactive_enter_timestamp;
2047 bool need_daemon_reload;
2052 const char *status_text;
2055 usec_t start_timestamp;
2056 usec_t exit_timestamp;
2058 int exit_code, exit_status;
2060 usec_t condition_timestamp;
2061 bool condition_result;
2064 unsigned n_accepted;
2065 unsigned n_connections;
2069 const char *sysfs_path;
2071 /* Mount, Automount */
2077 LIST_HEAD(ExecStatusInfo, exec);
2080 static void print_status_info(UnitStatusInfo *i) {
2082 const char *on, *off, *ss;
2084 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2085 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2090 /* This shows pretty information about a unit. See
2091 * print_property() for a low-level property printer */
2093 printf("%s", strna(i->id));
2095 if (i->description && !streq_ptr(i->id, i->description))
2096 printf(" - %s", i->description);
2101 printf("\t Follow: unit currently follows state of %s\n", i->following);
2103 if (streq_ptr(i->load_state, "error")) {
2104 on = ansi_highlight_red(true);
2105 off = ansi_highlight_red(false);
2109 path = i->source_path ? i->source_path : i->fragment_path;
2112 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2113 else if (path && i->unit_file_state)
2114 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2116 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2118 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2120 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2122 if (streq_ptr(i->active_state, "failed")) {
2123 on = ansi_highlight_red(true);
2124 off = ansi_highlight_red(false);
2125 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2126 on = ansi_highlight_green(true);
2127 off = ansi_highlight_green(false);
2132 printf("\t Active: %s%s (%s)%s",
2134 strna(i->active_state),
2138 printf("\t Active: %s%s%s",
2140 strna(i->active_state),
2143 if (!isempty(i->result) && !streq(i->result, "success"))
2144 printf(" (Result: %s)", i->result);
2146 timestamp = (streq_ptr(i->active_state, "active") ||
2147 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2148 (streq_ptr(i->active_state, "inactive") ||
2149 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2150 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2151 i->active_exit_timestamp;
2153 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2154 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2157 printf(" since %s; %s\n", s2, s1);
2159 printf(" since %s\n", s2);
2163 if (!i->condition_result && i->condition_timestamp > 0) {
2164 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2165 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2168 printf("\t start condition failed at %s; %s\n", s2, s1);
2170 printf("\t start condition failed at %s\n", s2);
2174 printf("\t Device: %s\n", i->sysfs_path);
2176 printf("\t Where: %s\n", i->where);
2178 printf("\t What: %s\n", i->what);
2180 if (!strv_isempty(i->documentation)) {
2184 STRV_FOREACH(t, i->documentation) {
2186 printf("\t Docs: %s\n", *t);
2189 printf("\t %s\n", *t);
2194 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2196 LIST_FOREACH(exec, p, i->exec) {
2200 /* Only show exited processes here */
2204 t = strv_join(p->argv, " ");
2205 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2208 good = is_clean_exit_lsb(p->code, p->status, NULL);
2210 on = ansi_highlight_red(true);
2211 off = ansi_highlight_red(false);
2215 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2217 if (p->code == CLD_EXITED) {
2220 printf("status=%i", p->status);
2222 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2227 printf("signal=%s", signal_to_string(p->status));
2229 printf(")%s\n", off);
2231 if (i->main_pid == p->pid &&
2232 i->start_timestamp == p->start_timestamp &&
2233 i->exit_timestamp == p->start_timestamp)
2234 /* Let's not show this twice */
2237 if (p->pid == i->control_pid)
2241 if (i->main_pid > 0 || i->control_pid > 0) {
2244 if (i->main_pid > 0) {
2245 printf("Main PID: %u", (unsigned) i->main_pid);
2249 get_process_comm(i->main_pid, &t);
2254 } else if (i->exit_code > 0) {
2255 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2257 if (i->exit_code == CLD_EXITED) {
2260 printf("status=%i", i->exit_status);
2262 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2267 printf("signal=%s", signal_to_string(i->exit_status));
2272 if (i->main_pid > 0 && i->control_pid > 0)
2275 if (i->control_pid > 0) {
2278 printf(" Control: %u", (unsigned) i->control_pid);
2280 get_process_comm(i->control_pid, &t);
2291 printf("\t Status: \"%s\"\n", i->status_text);
2293 if (i->default_control_group &&
2294 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2297 printf("\t CGroup: %s\n", i->default_control_group);
2299 if (arg_transport != TRANSPORT_SSH) {
2309 if (i->main_pid > 0)
2310 extra[k++] = i->main_pid;
2312 if (i->control_pid > 0)
2313 extra[k++] = i->control_pid;
2315 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2319 if (i->id && arg_transport != TRANSPORT_SSH) {
2321 arg_all * OUTPUT_SHOW_ALL |
2322 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2323 on_tty() * OUTPUT_COLOR |
2324 !arg_quiet * OUTPUT_WARN_CUTOFF;
2327 show_journal_by_unit(stdout,
2331 i->inactive_exit_timestamp_monotonic,
2336 if (i->need_daemon_reload)
2337 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2338 ansi_highlight_red(true),
2339 ansi_highlight_red(false),
2340 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2343 static void show_unit_help(UnitStatusInfo *i) {
2348 if (!i->documentation) {
2349 log_info("Documentation for %s not known.", i->id);
2353 STRV_FOREACH(p, i->documentation) {
2355 if (startswith(*p, "man:")) {
2358 char *page = NULL, *section = NULL;
2359 const char *args[4] = { "man", NULL, NULL, NULL };
2364 if ((*p)[k-1] == ')')
2365 e = strrchr(*p, '(');
2368 page = strndup((*p) + 4, e - *p - 4);
2374 section = strndup(e + 1, *p + k - e - 2);
2388 log_error("Failed to fork: %m");
2396 execvp(args[0], (char**) args);
2397 log_error("Failed to execute man: %m");
2398 _exit(EXIT_FAILURE);
2404 wait_for_terminate(pid, NULL);
2406 log_info("Can't show: %s", *p);
2410 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2416 switch (dbus_message_iter_get_arg_type(iter)) {
2418 case DBUS_TYPE_STRING: {
2421 dbus_message_iter_get_basic(iter, &s);
2424 if (streq(name, "Id"))
2426 else if (streq(name, "LoadState"))
2428 else if (streq(name, "ActiveState"))
2429 i->active_state = s;
2430 else if (streq(name, "SubState"))
2432 else if (streq(name, "Description"))
2434 else if (streq(name, "FragmentPath"))
2435 i->fragment_path = s;
2436 else if (streq(name, "SourcePath"))
2438 else if (streq(name, "DefaultControlGroup"))
2439 i->default_control_group = s;
2440 else if (streq(name, "StatusText"))
2442 else if (streq(name, "SysFSPath"))
2444 else if (streq(name, "Where"))
2446 else if (streq(name, "What"))
2448 else if (streq(name, "Following"))
2450 else if (streq(name, "UnitFileState"))
2451 i->unit_file_state = s;
2452 else if (streq(name, "Result"))
2459 case DBUS_TYPE_BOOLEAN: {
2462 dbus_message_iter_get_basic(iter, &b);
2464 if (streq(name, "Accept"))
2466 else if (streq(name, "NeedDaemonReload"))
2467 i->need_daemon_reload = b;
2468 else if (streq(name, "ConditionResult"))
2469 i->condition_result = b;
2474 case DBUS_TYPE_UINT32: {
2477 dbus_message_iter_get_basic(iter, &u);
2479 if (streq(name, "MainPID")) {
2481 i->main_pid = (pid_t) u;
2484 } else if (streq(name, "ControlPID"))
2485 i->control_pid = (pid_t) u;
2486 else if (streq(name, "ExecMainPID")) {
2488 i->main_pid = (pid_t) u;
2489 } else if (streq(name, "NAccepted"))
2491 else if (streq(name, "NConnections"))
2492 i->n_connections = u;
2497 case DBUS_TYPE_INT32: {
2500 dbus_message_iter_get_basic(iter, &j);
2502 if (streq(name, "ExecMainCode"))
2503 i->exit_code = (int) j;
2504 else if (streq(name, "ExecMainStatus"))
2505 i->exit_status = (int) j;
2510 case DBUS_TYPE_UINT64: {
2513 dbus_message_iter_get_basic(iter, &u);
2515 if (streq(name, "ExecMainStartTimestamp"))
2516 i->start_timestamp = (usec_t) u;
2517 else if (streq(name, "ExecMainExitTimestamp"))
2518 i->exit_timestamp = (usec_t) u;
2519 else if (streq(name, "ActiveEnterTimestamp"))
2520 i->active_enter_timestamp = (usec_t) u;
2521 else if (streq(name, "InactiveEnterTimestamp"))
2522 i->inactive_enter_timestamp = (usec_t) u;
2523 else if (streq(name, "InactiveExitTimestamp"))
2524 i->inactive_exit_timestamp = (usec_t) u;
2525 else if (streq(name, "InactiveExitTimestampMonotonic"))
2526 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2527 else if (streq(name, "ActiveExitTimestamp"))
2528 i->active_exit_timestamp = (usec_t) u;
2529 else if (streq(name, "ConditionTimestamp"))
2530 i->condition_timestamp = (usec_t) u;
2535 case DBUS_TYPE_ARRAY: {
2537 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2538 startswith(name, "Exec")) {
2539 DBusMessageIter sub;
2541 dbus_message_iter_recurse(iter, &sub);
2542 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2543 ExecStatusInfo *info;
2546 if (!(info = new0(ExecStatusInfo, 1)))
2549 if (!(info->name = strdup(name))) {
2554 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2559 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2561 dbus_message_iter_next(&sub);
2563 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2564 streq(name, "Documentation")) {
2566 DBusMessageIter sub;
2568 dbus_message_iter_recurse(iter, &sub);
2569 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2573 dbus_message_iter_get_basic(&sub, &s);
2575 l = strv_append(i->documentation, s);
2579 strv_free(i->documentation);
2580 i->documentation = l;
2582 dbus_message_iter_next(&sub);
2589 case DBUS_TYPE_STRUCT: {
2591 if (streq(name, "LoadError")) {
2592 DBusMessageIter sub;
2593 const char *n, *message;
2596 dbus_message_iter_recurse(iter, &sub);
2598 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2602 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2606 if (!isempty(message))
2607 i->load_error = message;
2617 static int print_property(const char *name, DBusMessageIter *iter) {
2621 /* This is a low-level property printer, see
2622 * print_status_info() for the nicer output */
2624 if (arg_property && !strv_find(arg_property, name))
2627 switch (dbus_message_iter_get_arg_type(iter)) {
2629 case DBUS_TYPE_STRUCT: {
2630 DBusMessageIter sub;
2631 dbus_message_iter_recurse(iter, &sub);
2633 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2636 dbus_message_iter_get_basic(&sub, &u);
2639 printf("%s=%u\n", name, (unsigned) u);
2641 printf("%s=\n", name);
2644 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2647 dbus_message_iter_get_basic(&sub, &s);
2649 if (arg_all || s[0])
2650 printf("%s=%s\n", name, s);
2653 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2654 const char *a = NULL, *b = NULL;
2656 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2657 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2659 if (arg_all || !isempty(a) || !isempty(b))
2660 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2668 case DBUS_TYPE_ARRAY:
2670 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2671 DBusMessageIter sub, sub2;
2673 dbus_message_iter_recurse(iter, &sub);
2674 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2678 dbus_message_iter_recurse(&sub, &sub2);
2680 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2681 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2682 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2684 dbus_message_iter_next(&sub);
2689 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2690 DBusMessageIter sub, sub2;
2692 dbus_message_iter_recurse(iter, &sub);
2693 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2694 const char *type, *path;
2696 dbus_message_iter_recurse(&sub, &sub2);
2698 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2699 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2700 printf("%s=%s\n", type, path);
2702 dbus_message_iter_next(&sub);
2707 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2708 DBusMessageIter sub, sub2;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 uint64_t value, next_elapse;
2715 dbus_message_iter_recurse(&sub, &sub2);
2717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2720 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2722 printf("%s={ value=%s ; next_elapse=%s }\n",
2724 format_timespan(timespan1, sizeof(timespan1), value),
2725 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2728 dbus_message_iter_next(&sub);
2733 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2734 DBusMessageIter sub, sub2;
2736 dbus_message_iter_recurse(iter, &sub);
2737 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2738 const char *controller, *attr, *value;
2740 dbus_message_iter_recurse(&sub, &sub2);
2742 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2743 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2746 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2752 dbus_message_iter_next(&sub);
2757 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2758 DBusMessageIter sub;
2760 dbus_message_iter_recurse(iter, &sub);
2761 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2762 ExecStatusInfo info;
2765 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2766 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2769 t = strv_join(info.argv, " ");
2771 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2775 yes_no(info.ignore),
2776 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2777 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2778 (unsigned) info. pid,
2779 sigchld_code_to_string(info.code),
2781 info.code == CLD_EXITED ? "" : "/",
2782 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2788 strv_free(info.argv);
2790 dbus_message_iter_next(&sub);
2799 if (generic_print_property(name, iter, arg_all) > 0)
2803 printf("%s=[unprintable]\n", name);
2808 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2809 DBusMessage *reply = NULL;
2810 const char *interface = "";
2812 DBusMessageIter iter, sub, sub2, sub3;
2813 UnitStatusInfo info;
2821 r = bus_method_call_with_reply (
2823 "org.freedesktop.systemd1",
2825 "org.freedesktop.DBus.Properties",
2829 DBUS_TYPE_STRING, &interface,
2834 if (!dbus_message_iter_init(reply, &iter) ||
2835 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2836 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2837 log_error("Failed to parse reply.");
2842 dbus_message_iter_recurse(&iter, &sub);
2849 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2852 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2853 log_error("Failed to parse reply.");
2858 dbus_message_iter_recurse(&sub, &sub2);
2860 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2861 log_error("Failed to parse reply.");
2866 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2867 log_error("Failed to parse reply.");
2872 dbus_message_iter_recurse(&sub2, &sub3);
2874 if (show_properties)
2875 r = print_property(name, &sub3);
2877 r = status_property(name, &sub3, &info);
2880 log_error("Failed to parse reply.");
2885 dbus_message_iter_next(&sub);
2890 if (!show_properties) {
2891 if (streq(verb, "help"))
2892 show_unit_help(&info);
2894 print_status_info(&info);
2897 strv_free(info.documentation);
2899 if (!streq_ptr(info.active_state, "active") &&
2900 !streq_ptr(info.active_state, "reloading") &&
2901 streq(verb, "status"))
2902 /* According to LSB: "program not running" */
2905 while ((p = info.exec)) {
2906 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2907 exec_status_info_free(p);
2912 dbus_message_unref(reply);
2917 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2918 DBusMessage *reply = NULL;
2919 const char *path = NULL;
2923 dbus_error_init(&error);
2925 r = bus_method_call_with_reply (
2927 "org.freedesktop.systemd1",
2928 "/org/freedesktop/systemd1",
2929 "org.freedesktop.systemd1.Manager",
2933 DBUS_TYPE_UINT32, &pid,
2938 if (!dbus_message_get_args(reply, &error,
2939 DBUS_TYPE_OBJECT_PATH, &path,
2940 DBUS_TYPE_INVALID)) {
2941 log_error("Failed to parse reply: %s", bus_error_message(&error));
2946 r = show_one(verb, bus, path, false, new_line);
2950 dbus_message_unref(reply);
2952 dbus_error_free(&error);
2957 static int show(DBusConnection *bus, char **args) {
2959 bool show_properties, new_line = false;
2965 show_properties = streq(args[0], "show");
2967 if (show_properties)
2968 pager_open_if_enabled();
2970 if (show_properties && strv_length(args) <= 1) {
2971 /* If not argument is specified inspect the manager
2974 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2977 STRV_FOREACH(name, args+1) {
2980 if (safe_atou32(*name, &id) < 0) {
2982 /* Interpret as unit name */
2984 n = unit_name_mangle(*name);
2985 p = unit_dbus_path_from_name(n ? n : *name);
2990 r = show_one(args[0], bus, p, show_properties, &new_line);
2996 } else if (show_properties) {
2998 /* Interpret as job id */
3001 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3004 r = show_one(args[0], bus, p, show_properties, &new_line);
3012 /* Interpret as PID */
3014 r = show_one_by_pid(args[0], bus, id, &new_line);
3023 static int dump(DBusConnection *bus, char **args) {
3024 DBusMessage *reply = NULL;
3029 dbus_error_init(&error);
3031 pager_open_if_enabled();
3033 r = bus_method_call_with_reply (
3035 "org.freedesktop.systemd1",
3036 "/org/freedesktop/systemd1",
3037 "org.freedesktop.systemd1.Manager",
3045 if (!dbus_message_get_args(reply, &error,
3046 DBUS_TYPE_STRING, &text,
3047 DBUS_TYPE_INVALID)) {
3048 log_error("Failed to parse reply: %s", bus_error_message(&error));
3053 fputs(text, stdout);
3057 dbus_message_unref(reply);
3059 dbus_error_free(&error);
3064 static int snapshot(DBusConnection *bus, char **args) {
3065 DBusMessage *reply = NULL;
3068 dbus_bool_t cleanup = FALSE;
3069 DBusMessageIter iter, sub;