1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "bus-locator.h"
8 #include "bus-map-properties.h"
9 #include "bus-print-properties.h"
10 #include "bus-unit-procs.h"
11 #include "cgroup-show.h"
12 #include "cpu-set-util.h"
13 #include "errno-util.h"
14 #include "exec-util.h"
15 #include "exit-status.h"
16 #include "format-util.h"
17 #include "hexdecoct.h"
18 #include "hostname-util.h"
19 #include "in-addr-util.h"
20 #include "ip-protocol-list.h"
21 #include "journal-file.h"
23 #include "locale-util.h"
24 #include "memory-util.h"
25 #include "numa-util.h"
26 #include "parse-util.h"
27 #include "path-util.h"
28 #include "pretty-print.h"
29 #include "process-util.h"
30 #include "signal-util.h"
31 #include "sort-util.h"
33 #include "string-table.h"
34 #include "systemctl-list-machines.h"
35 #include "systemctl-list-units.h"
36 #include "systemctl-show.h"
37 #include "systemctl-sysv-compat.h"
38 #include "systemctl-util.h"
39 #include "systemctl.h"
40 #include "terminal-util.h"
43 static OutputFlags
get_output_flags(void) {
45 FLAGS_SET(arg_print_flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) * OUTPUT_SHOW_ALL
|
46 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
47 colors_enabled() * OUTPUT_COLOR
|
48 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
51 typedef struct ExecStatusInfo
{
59 usec_t start_timestamp
;
60 usec_t exit_timestamp
;
65 ExecCommandFlags flags
;
67 LIST_FIELDS(struct ExecStatusInfo
, exec_status_info_list
);
70 static void exec_status_info_free(ExecStatusInfo
*i
) {
79 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
, bool is_ex_prop
) {
80 _cleanup_strv_free_
char **ex_opts
= NULL
;
81 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
90 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, is_ex_prop
? "sasasttttuii" : "sasbttttuii");
92 return bus_log_parse_error(r
);
96 r
= sd_bus_message_read(m
, "s", &path
);
98 return bus_log_parse_error(r
);
100 i
->path
= strdup(path
);
104 r
= sd_bus_message_read_strv(m
, &i
->argv
);
106 return bus_log_parse_error(r
);
108 r
= is_ex_prop
? sd_bus_message_read_strv(m
, &ex_opts
) : sd_bus_message_read(m
, "b", &ignore
);
110 return bus_log_parse_error(r
);
112 r
= sd_bus_message_read(m
,
114 &start_timestamp
, &start_timestamp_monotonic
,
115 &exit_timestamp
, &exit_timestamp_monotonic
,
119 return bus_log_parse_error(r
);
122 r
= exec_command_flags_from_strv(ex_opts
, &i
->flags
);
124 return log_error_errno(r
, "Failed to convert strv to ExecCommandFlags: %m");
126 i
->ignore
= FLAGS_SET(i
->flags
, EXEC_COMMAND_IGNORE_FAILURE
);
130 i
->start_timestamp
= (usec_t
) start_timestamp
;
131 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
132 i
->pid
= (pid_t
) pid
;
136 r
= sd_bus_message_exit_container(m
);
138 return bus_log_parse_error(r
);
143 typedef struct UnitCondition
{
150 LIST_FIELDS(struct UnitCondition
, conditions
);
153 static UnitCondition
* unit_condition_free(UnitCondition
*c
) {
161 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
163 typedef struct UnitStatusInfo
{
165 const char *load_state
;
166 const char *active_state
;
167 const char *freezer_state
;
168 const char *sub_state
;
169 const char *unit_file_state
;
170 const char *unit_file_preset
;
172 const char *description
;
173 const char *following
;
175 char **documentation
;
177 const char *fragment_path
;
178 const char *source_path
;
179 const char *control_group
;
186 const char *load_error
;
189 usec_t inactive_exit_timestamp
;
190 usec_t inactive_exit_timestamp_monotonic
;
191 usec_t active_enter_timestamp
;
192 usec_t active_exit_timestamp
;
193 usec_t inactive_enter_timestamp
;
195 uint64_t runtime_max_sec
;
197 bool need_daemon_reload
;
203 const char *status_text
;
204 const char *pid_file
;
208 usec_t start_timestamp
;
209 usec_t exit_timestamp
;
211 int exit_code
, exit_status
;
213 const char *log_namespace
;
215 usec_t condition_timestamp
;
216 bool condition_result
;
217 LIST_HEAD(UnitCondition
, conditions
);
219 usec_t assert_timestamp
;
221 bool failed_assert_trigger
;
222 bool failed_assert_negate
;
223 const char *failed_assert
;
224 const char *failed_assert_parameter
;
225 usec_t next_elapse_real
;
226 usec_t next_elapse_monotonic
;
230 unsigned n_connections
;
234 /* Pairs of type, path */
238 const char *sysfs_path
;
240 /* Mount, Automount */
247 uint64_t memory_current
;
250 uint64_t memory_high
;
252 uint64_t memory_swap_max
;
253 uint64_t memory_limit
;
254 uint64_t memory_available
;
255 uint64_t cpu_usage_nsec
;
256 uint64_t tasks_current
;
258 uint64_t ip_ingress_bytes
;
259 uint64_t ip_egress_bytes
;
260 uint64_t io_read_bytes
;
261 uint64_t io_write_bytes
;
263 uint64_t default_memory_min
;
264 uint64_t default_memory_low
;
266 LIST_HEAD(ExecStatusInfo
, exec_status_info_list
);
269 static void unit_status_info_free(UnitStatusInfo
*info
) {
273 strv_free(info
->documentation
);
274 strv_free(info
->dropin_paths
);
275 strv_free(info
->triggered_by
);
276 strv_free(info
->triggers
);
277 strv_free(info
->listen
);
279 while ((c
= info
->conditions
)) {
280 LIST_REMOVE(conditions
, info
->conditions
, c
);
281 unit_condition_free(c
);
284 while ((p
= info
->exec_status_info_list
)) {
285 LIST_REMOVE(exec_status_info_list
, info
->exec_status_info_list
, p
);
286 exec_status_info_free(p
);
290 static void format_active_state(const char *active_state
, const char **active_on
, const char **active_off
) {
291 if (streq_ptr(active_state
, "failed")) {
292 *active_on
= ansi_highlight_red();
293 *active_off
= ansi_normal();
294 } else if (STRPTR_IN_SET(active_state
, "active", "reloading")) {
295 *active_on
= ansi_highlight_green();
296 *active_off
= ansi_normal();
298 *active_on
= *active_off
= "";
301 static void format_enable_state(const char *enable_state
, const char **enable_on
, const char **enable_off
) {
305 if (streq_ptr(enable_state
, "disabled")) {
306 *enable_on
= ansi_highlight_yellow();
307 *enable_off
= ansi_normal();
308 } else if (streq_ptr(enable_state
, "enabled")) {
309 *enable_on
= ansi_highlight_green();
310 *enable_off
= ansi_normal();
312 *enable_on
= *enable_off
= "";
315 static void print_status_info(
320 const char *active_on
, *active_off
, *on
, *off
, *ss
, *fs
;
321 const char *enable_on
, *enable_off
, *preset_on
, *preset_off
;
322 _cleanup_free_
char *formatted_path
= NULL
;
329 /* This shows pretty information about a unit. See print_property() for a low-level property
332 format_active_state(i
->active_state
, &active_on
, &active_off
);
333 format_enable_state(i
->unit_file_state
, &enable_on
, &enable_off
);
334 format_enable_state(i
->unit_file_preset
, &preset_on
, &preset_off
);
336 const SpecialGlyph glyph
= unit_active_state_to_glyph(unit_active_state_from_string(i
->active_state
));
338 printf("%s%s%s %s", active_on
, special_glyph(glyph
), active_off
, strna(i
->id
));
340 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
341 printf(" - %s", i
->description
);
346 printf(" Follows: unit currently follows state of %s\n", i
->following
);
348 if (STRPTR_IN_SET(i
->load_state
, "error", "not-found", "bad-setting")) {
349 on
= ansi_highlight_red();
354 path
= i
->source_path
?: i
->fragment_path
;
355 if (path
&& terminal_urlify_path(path
, NULL
, &formatted_path
) >= 0)
356 path
= formatted_path
;
358 if (!isempty(i
->load_error
))
359 printf(" Loaded: %s%s%s (Reason: %s)\n",
360 on
, strna(i
->load_state
), off
, i
->load_error
);
361 else if (path
&& !isempty(i
->unit_file_state
)) {
362 bool show_preset
= !isempty(i
->unit_file_preset
) &&
363 show_preset_for_state(unit_file_state_from_string(i
->unit_file_state
));
365 printf(" Loaded: %s%s%s (%s; %s%s%s%s%s%s%s)\n",
366 on
, strna(i
->load_state
), off
,
368 enable_on
, i
->unit_file_state
, enable_off
,
369 show_preset
? "; preset: " : "",
370 preset_on
, show_preset
? i
->unit_file_preset
: "", preset_off
);
373 printf(" Loaded: %s%s%s (%s)\n",
374 on
, strna(i
->load_state
), off
, path
);
376 printf(" Loaded: %s%s%s\n",
377 on
, strna(i
->load_state
), off
);
380 printf(" Transient: yes\n");
382 if (!strv_isempty(i
->dropin_paths
)) {
383 _cleanup_free_
char *dir
= NULL
;
386 STRV_FOREACH(dropin
, i
->dropin_paths
) {
387 _cleanup_free_
char *dropin_formatted
= NULL
;
396 dir
= dirname_malloc(*dropin
);
404 special_glyph(SPECIAL_GLYPH_TREE_RIGHT
));
407 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
409 if (terminal_urlify_path(*dropin
, basename(*dropin
), &dropin_formatted
) >= 0)
410 df
= dropin_formatted
;
414 printf("%s%s", df
, last
? "\n" : ", ");
418 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
420 printf(" Active: %s%s (%s)%s",
421 active_on
, strna(i
->active_state
), ss
, active_off
);
423 printf(" Active: %s%s%s",
424 active_on
, strna(i
->active_state
), active_off
);
426 fs
= !isempty(i
->freezer_state
) && !streq(i
->freezer_state
, "running") ? i
->freezer_state
: NULL
;
428 printf(" %s(%s)%s", ansi_highlight_yellow(), fs
, ansi_normal());
430 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
431 printf(" (Result: %s)", i
->result
);
433 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
434 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
435 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
436 i
->active_exit_timestamp
;
438 if (timestamp_is_set(timestamp
)) {
439 printf(" since %s; %s\n",
440 FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
),
441 FORMAT_TIMESTAMP_RELATIVE(timestamp
));
442 if (streq_ptr(i
->active_state
, "active") && i
->runtime_max_sec
< USEC_INFINITY
) {
443 usec_t until_timestamp
;
445 until_timestamp
= usec_add(timestamp
, i
->runtime_max_sec
);
446 printf(" Until: %s; %s\n",
447 FORMAT_TIMESTAMP_STYLE(until_timestamp
, arg_timestamp_style
),
448 FORMAT_TIMESTAMP_RELATIVE(until_timestamp
));
451 if (!endswith(i
->id
, ".target") &&
452 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") &&
453 timestamp_is_set(i
->active_enter_timestamp
) &&
454 timestamp_is_set(i
->active_exit_timestamp
) &&
455 i
->active_exit_timestamp
>= i
->active_enter_timestamp
) {
459 duration
= i
->active_exit_timestamp
- i
->active_enter_timestamp
;
460 printf(" Duration: %s\n", FORMAT_TIMESPAN(duration
, MSEC_PER_SEC
));
465 STRV_FOREACH(t
, i
->triggered_by
) {
466 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
468 (void) get_state_one_unit(bus
, *t
, &state
);
469 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
471 printf("%s %s%s%s %s\n",
472 t
== i
->triggered_by
? "TriggeredBy:" : " ",
473 on
, special_glyph(unit_active_state_to_glyph(state
)), off
,
477 if (endswith(i
->id
, ".timer")) {
478 dual_timestamp nw
, next
= {i
->next_elapse_real
, i
->next_elapse_monotonic
};
481 dual_timestamp_get(&nw
);
482 next_elapse
= calc_next_elapse(&nw
, &next
);
484 if (timestamp_is_set(next_elapse
))
485 printf(" Trigger: %s; %s\n",
486 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
),
487 FORMAT_TIMESTAMP_RELATIVE(next_elapse
));
489 printf(" Trigger: n/a\n");
492 STRV_FOREACH(t
, i
->triggers
) {
493 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
495 (void) get_state_one_unit(bus
, *t
, &state
);
496 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
498 printf("%s %s%s%s %s\n",
499 t
== i
->triggers
? " Triggers:" : " ",
500 on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
,
504 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
507 printf(" Condition: start %scondition failed%s at %s; %s\n",
508 ansi_highlight_yellow(), ansi_normal(),
509 FORMAT_TIMESTAMP_STYLE(i
->condition_timestamp
, arg_timestamp_style
),
510 FORMAT_TIMESTAMP_RELATIVE(i
->condition_timestamp
));
512 LIST_FOREACH(conditions
, c
, i
->conditions
)
516 LIST_FOREACH(conditions
, c
, i
->conditions
)
518 printf(" %s %s=%s%s%s was not met\n",
519 --n
? special_glyph(SPECIAL_GLYPH_TREE_BRANCH
) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT
),
521 c
->trigger
? "|" : "",
522 c
->negate
? "!" : "",
526 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
527 printf(" Assert: start %sassertion failed%s at %s; %s\n",
528 ansi_highlight_red(), ansi_normal(),
529 FORMAT_TIMESTAMP_STYLE(i
->assert_timestamp
, arg_timestamp_style
),
530 FORMAT_TIMESTAMP_RELATIVE(i
->assert_timestamp
));
531 if (i
->failed_assert_trigger
)
532 printf(" none of the trigger assertions were met\n");
533 else if (i
->failed_assert
)
534 printf(" %s=%s%s was not met\n",
536 i
->failed_assert_negate
? "!" : "",
537 i
->failed_assert_parameter
);
541 printf(" Device: %s\n", i
->sysfs_path
);
543 printf(" Where: %s\n", i
->where
);
545 printf(" What: %s\n", i
->what
);
547 STRV_FOREACH(t
, i
->documentation
) {
548 _cleanup_free_
char *formatted
= NULL
;
551 if (terminal_urlify(*t
, NULL
, &formatted
) >= 0)
556 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", q
);
559 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
560 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
563 printf(" Accepted: %u; Connected: %u;", i
->n_accepted
, i
->n_connections
);
565 printf(" Refused: %u", i
->n_refused
);
569 LIST_FOREACH(exec_status_info_list
, p
, i
->exec_status_info_list
) {
570 _cleanup_free_
char *argv
= NULL
;
573 /* Only show exited processes here */
577 /* Don't print ExecXYZEx= properties here since it will appear as a
578 * duplicate of the non-Ex= variant. */
579 if (endswith(p
->name
, "Ex"))
582 argv
= strv_join(p
->argv
, " ");
583 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
585 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
587 on
= ansi_highlight_red();
592 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
594 if (p
->code
== CLD_EXITED
) {
597 printf("status=%i", p
->status
);
599 c
= exit_status_to_string(p
->status
, EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
604 printf("signal=%s", signal_to_string(p
->status
));
606 printf(")%s\n", off
);
608 if (i
->main_pid
== p
->pid
&&
609 i
->start_timestamp
== p
->start_timestamp
&&
610 i
->exit_timestamp
== p
->start_timestamp
)
611 /* Let's not show this twice */
614 if (p
->pid
== i
->control_pid
)
618 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
619 if (i
->main_pid
> 0) {
620 printf(" Main PID: "PID_FMT
, i
->main_pid
);
624 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
625 _cleanup_free_
char *comm
= NULL
;
627 (void) get_process_comm(i
->main_pid
, &comm
);
629 printf(" (%s)", comm
);
632 } else if (i
->exit_code
> 0) {
633 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
635 if (i
->exit_code
== CLD_EXITED
) {
638 printf("status=%i", i
->exit_status
);
640 c
= exit_status_to_string(i
->exit_status
,
641 EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
646 printf("signal=%s", signal_to_string(i
->exit_status
));
651 if (i
->control_pid
> 0) {
652 _cleanup_free_
char *c
= NULL
;
655 fputs("; Control PID: ", stdout
);
657 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
659 printf(PID_FMT
, i
->control_pid
);
661 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
662 (void) get_process_comm(i
->control_pid
, &c
);
672 printf(" Status: \"%s\"\n", i
->status_text
);
673 if (i
->status_errno
> 0)
674 printf(" Error: %i (%s)\n", i
->status_errno
, strerror_safe(i
->status_errno
));
676 if (i
->ip_ingress_bytes
!= UINT64_MAX
&& i
->ip_egress_bytes
!= UINT64_MAX
)
677 printf(" IP: %s in, %s out\n",
678 FORMAT_BYTES(i
->ip_ingress_bytes
),
679 FORMAT_BYTES(i
->ip_egress_bytes
));
681 if (i
->io_read_bytes
!= UINT64_MAX
&& i
->io_write_bytes
!= UINT64_MAX
)
682 printf(" IO: %s read, %s written\n",
683 FORMAT_BYTES(i
->io_read_bytes
),
684 FORMAT_BYTES(i
->io_write_bytes
));
686 if (i
->tasks_current
!= UINT64_MAX
) {
687 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
689 if (i
->tasks_max
!= UINT64_MAX
)
690 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
695 if (i
->memory_current
!= UINT64_MAX
) {
696 printf(" Memory: %s", FORMAT_BYTES(i
->memory_current
));
698 if (i
->memory_min
> 0 || i
->memory_low
> 0 ||
699 i
->memory_high
!= CGROUP_LIMIT_MAX
|| i
->memory_max
!= CGROUP_LIMIT_MAX
||
700 i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
701 i
->memory_available
!= CGROUP_LIMIT_MAX
||
702 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
703 const char *prefix
= "";
706 if (i
->memory_min
> 0) {
707 printf("%smin: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_min
));
710 if (i
->memory_low
> 0) {
711 printf("%slow: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_low
));
714 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
715 printf("%shigh: %s", prefix
, FORMAT_BYTES(i
->memory_high
));
718 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
719 printf("%smax: %s", prefix
, FORMAT_BYTES(i
->memory_max
));
722 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
723 printf("%sswap max: %s", prefix
, FORMAT_BYTES(i
->memory_swap_max
));
726 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
727 printf("%slimit: %s", prefix
, FORMAT_BYTES(i
->memory_limit
));
730 if (i
->memory_available
!= CGROUP_LIMIT_MAX
) {
731 printf("%savailable: %s", prefix
, FORMAT_BYTES(i
->memory_available
));
739 if (i
->cpu_usage_nsec
!= UINT64_MAX
)
740 printf(" CPU: %s\n", FORMAT_TIMESPAN(i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
742 if (i
->control_group
) {
743 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
744 static const char prefix
[] = " ";
747 printf(" CGroup: %s\n", i
->control_group
);
749 c
= LESS_BY(columns(), strlen(prefix
));
751 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
752 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
756 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
759 extra
[k
++] = i
->main_pid
;
761 if (i
->control_pid
> 0)
762 extra
[k
++] = i
->control_pid
;
764 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
766 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
767 i
->id
, bus_error_message(&error
, r
));
770 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
771 show_journal_by_unit(
777 i
->inactive_exit_timestamp_monotonic
,
780 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
781 SD_JOURNAL_LOCAL_ONLY
,
782 arg_scope
== LOOKUP_SCOPE_SYSTEM
,
785 if (i
->need_daemon_reload
)
786 warn_unit_file_changed(i
->id
);
789 static void show_unit_help(UnitStatusInfo
*i
) {
792 if (!i
->documentation
) {
793 log_info("Documentation for %s not known.", i
->id
);
797 STRV_FOREACH(p
, i
->documentation
)
798 if (startswith(*p
, "man:"))
799 show_man_page(*p
+ 4, false);
801 log_info("Can't show: %s", *p
);
804 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
805 UnitStatusInfo
*i
= userdata
;
809 r
= sd_bus_message_read(m
, "u", &u
);
813 i
->main_pid
= (pid_t
) u
;
819 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
820 const char *message
, **p
= userdata
;
823 r
= sd_bus_message_read(m
, "(ss)", NULL
, &message
);
827 if (!isempty(message
))
833 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
834 const char *type
, *path
;
835 char ***p
= userdata
;
838 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
842 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
844 r
= strv_extend(p
, type
);
848 r
= strv_extend(p
, path
);
855 r
= sd_bus_message_exit_container(m
);
862 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
863 UnitStatusInfo
*i
= userdata
;
864 const char *cond
, *param
;
869 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
873 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
874 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
876 c
= new(UnitCondition
, 1);
880 *c
= (UnitCondition
) {
881 .name
= strdup(cond
),
882 .param
= strdup(param
),
888 if (!c
->name
|| !c
->param
)
891 LIST_PREPEND(conditions
, i
->conditions
, TAKE_PTR(c
));
896 r
= sd_bus_message_exit_container(m
);
903 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
904 UnitStatusInfo
*i
= userdata
;
905 const char *cond
, *param
;
910 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
914 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
915 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
916 i
->failed_assert
= cond
;
917 i
->failed_assert_trigger
= trigger
;
918 i
->failed_assert_negate
= negate
;
919 i
->failed_assert_parameter
= param
;
925 r
= sd_bus_message_exit_container(m
);
932 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
933 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
934 ExecStatusInfo
*last
;
935 UnitStatusInfo
*i
= userdata
;
936 bool is_ex_prop
= endswith(member
, "Ex");
939 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
943 info
= new0(ExecStatusInfo
, 1);
947 LIST_FIND_TAIL(exec_status_info_list
, i
->exec_status_info_list
, last
);
949 while ((r
= exec_status_info_deserialize(m
, info
, is_ex_prop
)) > 0) {
951 info
->name
= strdup(member
);
955 LIST_INSERT_AFTER(exec_status_info_list
, i
->exec_status_info_list
, last
, info
);
958 info
= new0(ExecStatusInfo
, 1);
965 r
= sd_bus_message_exit_container(m
);
972 static int print_property(const char *name
, const char *expected_value
, sd_bus_message
*m
, BusPrintPropertyFlags flags
) {
974 const char *contents
;
980 /* This is a low-level property printer, see print_status_info() for the nicer output */
982 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
988 case SD_BUS_TYPE_INT32
:
989 if (endswith(name
, "ActionExitStatus")) {
992 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
996 if (i
>= 0 && i
<= 255)
997 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIi32
, i
);
998 else if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
))
999 bus_print_property_value(name
, expected_value
, flags
, "[not set]");
1002 } else if (streq(name
, "NUMAPolicy")) {
1005 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
1009 bus_print_property_valuef(name
, expected_value
, flags
, "%s", strna(mpol_to_string(i
)));
1015 case SD_BUS_TYPE_UINT64
:
1016 if (endswith(name
, "Timestamp")) {
1019 r
= sd_bus_message_read_basic(m
, bus_type
, ×tamp
);
1023 bus_print_property_value(name
, expected_value
, flags
, FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
));
1029 case SD_BUS_TYPE_STRUCT
:
1031 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
1034 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
1036 return bus_log_parse_error(r
);
1039 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIu32
, u
);
1041 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1045 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
1048 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
1050 return bus_log_parse_error(r
);
1052 bus_print_property_value(name
, expected_value
, flags
, s
);
1056 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
1057 const char *a
= NULL
, *b
= NULL
;
1059 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
1061 return bus_log_parse_error(r
);
1063 if (!isempty(a
) || !isempty(b
))
1064 bus_print_property_valuef(name
, expected_value
, flags
, "%s \"%s\"", strempty(a
), strempty(b
));
1066 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1070 } else if (STR_IN_SET(name
, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces", "RestrictFileSystems")) {
1071 _cleanup_strv_free_
char **l
= NULL
;
1074 r
= sd_bus_message_enter_container(m
, 'r', "bas");
1076 return bus_log_parse_error(r
);
1078 r
= sd_bus_message_read(m
, "b", &allow_list
);
1080 return bus_log_parse_error(r
);
1082 r
= sd_bus_message_read_strv(m
, &l
);
1084 return bus_log_parse_error(r
);
1086 r
= sd_bus_message_exit_container(m
);
1088 return bus_log_parse_error(r
);
1090 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || allow_list
|| !strv_isempty(l
)) {
1093 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1094 fputs(name
, stdout
);
1101 STRV_FOREACH(i
, l
) {
1109 fputc('\n', stdout
);
1114 } else if (STR_IN_SET(name
, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
1118 r
= sd_bus_message_read(m
, "(bs)", &ignore
, &s
);
1120 return bus_log_parse_error(r
);
1123 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s", ignore
? "-" : "", s
);
1125 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1129 } else if (endswith(name
, "ExitStatus") && streq(contents
, "aiai")) {
1130 const int32_t *status
, *signal
;
1131 size_t n_status
, n_signal
;
1133 r
= sd_bus_message_enter_container(m
, 'r', "aiai");
1135 return bus_log_parse_error(r
);
1137 r
= sd_bus_message_read_array(m
, 'i', (const void **) &status
, &n_status
);
1139 return bus_log_parse_error(r
);
1141 r
= sd_bus_message_read_array(m
, 'i', (const void **) &signal
, &n_signal
);
1143 return bus_log_parse_error(r
);
1145 r
= sd_bus_message_exit_container(m
);
1147 return bus_log_parse_error(r
);
1149 n_status
/= sizeof(int32_t);
1150 n_signal
/= sizeof(int32_t);
1152 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || n_status
> 0 || n_signal
> 0) {
1155 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1156 fputs(name
, stdout
);
1160 for (size_t i
= 0; i
< n_status
; i
++) {
1166 printf("%"PRIi32
, status
[i
]);
1169 for (size_t i
= 0; i
< n_signal
; i
++) {
1172 str
= signal_to_string((int) signal
[i
]);
1182 printf("%"PRIi32
, status
[i
]);
1185 fputc('\n', stdout
);
1192 case SD_BUS_TYPE_ARRAY
:
1194 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
1198 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
1200 return bus_log_parse_error(r
);
1202 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
1203 bus_print_property_valuef(name
, expected_value
, flags
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
1205 return bus_log_parse_error(r
);
1207 r
= sd_bus_message_exit_container(m
);
1209 return bus_log_parse_error(r
);
1213 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
1214 const char *type
, *path
;
1216 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1218 return bus_log_parse_error(r
);
1220 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1221 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1223 return bus_log_parse_error(r
);
1225 r
= sd_bus_message_exit_container(m
);
1227 return bus_log_parse_error(r
);
1231 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
1232 const char *type
, *path
;
1234 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1236 return bus_log_parse_error(r
);
1238 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1239 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1241 return bus_log_parse_error(r
);
1243 r
= sd_bus_message_exit_container(m
);
1245 return bus_log_parse_error(r
);
1249 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
1251 uint64_t v
, next_elapse
;
1253 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
1255 return bus_log_parse_error(r
);
1257 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0)
1258 bus_print_property_valuef(name
, expected_value
, flags
,
1259 "{ %s=%s ; next_elapse=%s }",
1261 strna(FORMAT_TIMESPAN(v
, 0)),
1262 strna(FORMAT_TIMESPAN(next_elapse
, 0)));
1264 return bus_log_parse_error(r
);
1266 r
= sd_bus_message_exit_container(m
);
1268 return bus_log_parse_error(r
);
1272 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
1273 const char *base
, *spec
;
1274 uint64_t next_elapse
;
1276 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1278 return bus_log_parse_error(r
);
1280 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0)
1281 bus_print_property_valuef(name
, expected_value
, flags
,
1282 "{ %s=%s ; next_elapse=%s }", base
, spec
,
1283 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
));
1285 return bus_log_parse_error(r
);
1287 r
= sd_bus_message_exit_container(m
);
1289 return bus_log_parse_error(r
);
1293 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
1294 ExecStatusInfo info
= {};
1295 bool is_ex_prop
= endswith(name
, "Ex");
1297 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
1299 return bus_log_parse_error(r
);
1301 while ((r
= exec_status_info_deserialize(m
, &info
, is_ex_prop
)) > 0) {
1302 _cleanup_strv_free_
char **optv
= NULL
;
1303 _cleanup_free_
char *tt
= NULL
, *o
= NULL
;
1305 tt
= strv_join(info
.argv
, " ");
1308 r
= exec_command_flags_to_strv(info
.flags
, &optv
);
1310 return log_error_errno(r
, "Failed to convert ExecCommandFlags to strv: %m");
1312 o
= strv_join(optv
, " ");
1314 bus_print_property_valuef(name
, expected_value
, flags
,
1315 "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1319 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1320 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1322 sigchld_code_to_string(info
.code
),
1324 info
.code
== CLD_EXITED
? "" : "/",
1325 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1327 bus_print_property_valuef(name
, expected_value
, flags
,
1328 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1331 yes_no(info
.ignore
),
1332 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1333 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1335 sigchld_code_to_string(info
.code
),
1337 info
.code
== CLD_EXITED
? "" : "/",
1338 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1341 strv_free(info
.argv
);
1345 r
= sd_bus_message_exit_container(m
);
1347 return bus_log_parse_error(r
);
1351 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
1352 const char *path
, *rwm
;
1354 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1356 return bus_log_parse_error(r
);
1358 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
1359 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
), strna(rwm
));
1361 return bus_log_parse_error(r
);
1363 r
= sd_bus_message_exit_container(m
);
1365 return bus_log_parse_error(r
);
1369 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1370 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
1374 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1376 return bus_log_parse_error(r
);
1378 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
1379 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), weight
);
1381 return bus_log_parse_error(r
);
1383 r
= sd_bus_message_exit_container(m
);
1385 return bus_log_parse_error(r
);
1389 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1390 (cgroup_io_limit_type_from_string(name
) >= 0 ||
1391 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
1395 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1397 return bus_log_parse_error(r
);
1399 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
1400 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), bandwidth
);
1402 return bus_log_parse_error(r
);
1404 r
= sd_bus_message_exit_container(m
);
1406 return bus_log_parse_error(r
);
1410 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1411 streq(name
, "IODeviceLatencyTargetUSec")) {
1415 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1417 return bus_log_parse_error(r
);
1419 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &target
)) > 0)
1420 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
),
1421 FORMAT_TIMESPAN(target
, 1));
1423 return bus_log_parse_error(r
);
1425 r
= sd_bus_message_exit_container(m
);
1427 return bus_log_parse_error(r
);
1431 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& STR_IN_SET(name
, "StandardInputData", "RootHashSignature")) {
1432 _cleanup_free_
char *h
= NULL
;
1437 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
1439 return bus_log_parse_error(r
);
1441 n
= base64mem(p
, sz
, &h
);
1445 bus_print_property_value(name
, expected_value
, flags
, h
);
1449 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1450 _cleanup_free_
char *addresses
= NULL
;
1452 r
= sd_bus_message_enter_container(m
, 'a', "(iayu)");
1454 return bus_log_parse_error(r
);
1462 r
= sd_bus_message_enter_container(m
, 'r', "iayu");
1464 return bus_log_parse_error(r
);
1468 r
= sd_bus_message_read(m
, "i", &family
);
1470 return bus_log_parse_error(r
);
1472 r
= sd_bus_message_read_array(m
, 'y', &ap
, &an
);
1474 return bus_log_parse_error(r
);
1476 r
= sd_bus_message_read(m
, "u", &prefixlen
);
1478 return bus_log_parse_error(r
);
1480 r
= sd_bus_message_exit_container(m
);
1482 return bus_log_parse_error(r
);
1484 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1487 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1490 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
) * 8)
1493 if (!strextend_with_separator(&addresses
, " ",
1494 IN_ADDR_PREFIX_TO_STRING(family
, ap
, prefixlen
)))
1498 r
= sd_bus_message_exit_container(m
);
1500 return bus_log_parse_error(r
);
1502 bus_print_property_value(name
, expected_value
, flags
, addresses
);
1506 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
1507 _cleanup_free_
char *paths
= NULL
;
1508 const char *source
, *dest
;
1512 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssbt)");
1514 return bus_log_parse_error(r
);
1516 while ((r
= sd_bus_message_read(m
, "(ssbt)", &source
, &dest
, &ignore_enoent
, &rbind
)) > 0) {
1517 _cleanup_free_
char *str
= NULL
;
1519 if (isempty(source
))
1522 if (asprintf(&str
, "%s%s%s%s%s",
1523 ignore_enoent
? "-" : "",
1525 isempty(dest
) ? "" : ":",
1527 rbind
== MS_REC
? ":rbind" : "") < 0)
1530 if (!strextend_with_separator(&paths
, " ", str
))
1534 return bus_log_parse_error(r
);
1536 r
= sd_bus_message_exit_container(m
);
1538 return bus_log_parse_error(r
);
1540 bus_print_property_value(name
, expected_value
, flags
, paths
);
1544 } else if (streq(name
, "TemporaryFileSystem")) {
1545 _cleanup_free_
char *paths
= NULL
;
1546 const char *target
, *option
;
1548 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1550 return bus_log_parse_error(r
);
1552 while ((r
= sd_bus_message_read(m
, "(ss)", &target
, &option
)) > 0) {
1553 _cleanup_free_
char *str
= NULL
;
1555 if (isempty(target
))
1558 if (asprintf(&str
, "%s%s%s", target
, isempty(option
) ? "" : ":", strempty(option
)) < 0)
1561 if (!strextend_with_separator(&paths
, " ", str
))
1565 return bus_log_parse_error(r
);
1567 r
= sd_bus_message_exit_container(m
);
1569 return bus_log_parse_error(r
);
1571 bus_print_property_value(name
, expected_value
, flags
, paths
);
1575 } else if (streq(name
, "LogExtraFields")) {
1576 _cleanup_free_
char *fields
= NULL
;
1580 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "ay");
1582 return bus_log_parse_error(r
);
1584 while ((r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
)) > 0) {
1585 _cleanup_free_
char *str
= NULL
;
1588 if (memchr(p
, 0, sz
))
1591 eq
= memchr(p
, '=', sz
);
1595 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
1598 str
= malloc(sz
+ 1);
1605 if (!utf8_is_valid(str
))
1608 if (!strextend_with_separator(&fields
, " ", str
))
1612 return bus_log_parse_error(r
);
1614 r
= sd_bus_message_exit_container(m
);
1616 return bus_log_parse_error(r
);
1618 bus_print_property_value(name
, expected_value
, flags
, fields
);
1621 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&&
1623 "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes",
1624 "EffectiveCPUs", "EffectiveMemoryNodes")) {
1626 _cleanup_free_
char *affinity
= NULL
;
1627 _cleanup_(cpu_set_reset
) CPUSet set
= {};
1631 r
= sd_bus_message_read_array(m
, 'y', &a
, &n
);
1633 return bus_log_parse_error(r
);
1635 r
= cpu_set_from_dbus(a
, n
, &set
);
1637 return log_error_errno(r
, "Failed to deserialize %s: %m", name
);
1639 affinity
= cpu_set_to_range_string(&set
);
1643 bus_print_property_value(name
, expected_value
, flags
, affinity
);
1646 } else if (streq(name
, "MountImages")) {
1647 _cleanup_free_
char *paths
= NULL
;
1649 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssba(ss))");
1651 return bus_log_parse_error(r
);
1654 _cleanup_free_
char *str
= NULL
;
1655 const char *source
, *destination
, *partition
, *mount_options
;
1658 r
= sd_bus_message_enter_container(m
, 'r', "ssba(ss)");
1660 return bus_log_parse_error(r
);
1664 r
= sd_bus_message_read(m
, "ssb", &source
, &destination
, &ignore_enoent
);
1666 return bus_log_parse_error(r
);
1668 str
= strjoin(ignore_enoent
? "-" : "",
1675 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1677 return bus_log_parse_error(r
);
1679 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1680 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1683 return bus_log_parse_error(r
);
1685 if (!strextend_with_separator(&paths
, " ", str
))
1688 r
= sd_bus_message_exit_container(m
);
1690 return bus_log_parse_error(r
);
1692 r
= sd_bus_message_exit_container(m
);
1694 return bus_log_parse_error(r
);
1697 r
= sd_bus_message_exit_container(m
);
1699 return bus_log_parse_error(r
);
1701 bus_print_property_value(name
, expected_value
, flags
, paths
);
1705 } else if (streq(name
, "ExtensionImages")) {
1706 _cleanup_free_
char *paths
= NULL
;
1708 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sba(ss))");
1710 return bus_log_parse_error(r
);
1713 _cleanup_free_
char *str
= NULL
;
1714 const char *source
, *partition
, *mount_options
;
1717 r
= sd_bus_message_enter_container(m
, 'r', "sba(ss)");
1719 return bus_log_parse_error(r
);
1723 r
= sd_bus_message_read(m
, "sb", &source
, &ignore_enoent
);
1725 return bus_log_parse_error(r
);
1727 str
= strjoin(ignore_enoent
? "-" : "", source
);
1731 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1733 return bus_log_parse_error(r
);
1735 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1736 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1739 return bus_log_parse_error(r
);
1741 if (!strextend_with_separator(&paths
, " ", str
))
1744 r
= sd_bus_message_exit_container(m
);
1746 return bus_log_parse_error(r
);
1748 r
= sd_bus_message_exit_container(m
);
1750 return bus_log_parse_error(r
);
1753 r
= sd_bus_message_exit_container(m
);
1755 return bus_log_parse_error(r
);
1757 bus_print_property_value(name
, expected_value
, flags
, paths
);
1761 } else if (streq(name
, "BPFProgram")) {
1764 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1766 return bus_log_parse_error(r
);
1768 while ((r
= sd_bus_message_read(m
, "(ss)", &a
, &p
)) > 0)
1769 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1771 return bus_log_parse_error(r
);
1773 r
= sd_bus_message_exit_container(m
);
1775 return bus_log_parse_error(r
);
1778 } else if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1779 uint16_t nr_ports
, port_min
;
1780 int32_t af
, ip_protocol
;
1782 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(iiqq)");
1784 return bus_log_parse_error(r
);
1785 while ((r
= sd_bus_message_read(m
, "(iiqq)", &af
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1786 const char *family
, *colon1
, *protocol
= "", *colon2
= "";
1788 family
= strempty(af_to_ipv4_ipv6(af
));
1789 colon1
= isempty(family
) ? "" : ":";
1791 if (ip_protocol
!= 0) {
1792 protocol
= ip_protocol_to_tcp_udp(ip_protocol
);
1797 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s%s%sany",
1798 family
, colon1
, protocol
, colon2
);
1799 else if (nr_ports
== 1)
1800 bus_print_property_valuef(
1801 name
, expected_value
, flags
, "%s%s%s%s%hu",
1802 family
, colon1
, protocol
, colon2
, port_min
);
1804 bus_print_property_valuef(
1805 name
, expected_value
, flags
, "%s%s%s%s%hu-%hu",
1806 family
, colon1
, protocol
, colon2
, port_min
,
1807 (uint16_t) (port_min
+ nr_ports
- 1));
1810 return bus_log_parse_error(r
);
1812 r
= sd_bus_message_exit_container(m
);
1814 return bus_log_parse_error(r
);
1817 } else if (STR_IN_SET(name
, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
1819 uint64_t symlink_flags
;
1821 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1823 return bus_log_parse_error(r
);
1825 while ((r
= sd_bus_message_read(m
, "(sst)", &a
, &p
, &symlink_flags
)) > 0)
1826 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1828 return bus_log_parse_error(r
);
1830 r
= sd_bus_message_exit_container(m
);
1832 return bus_log_parse_error(r
);
1843 typedef enum SystemctlShowMode
{
1844 SYSTEMCTL_SHOW_PROPERTIES
,
1845 SYSTEMCTL_SHOW_STATUS
,
1846 SYSTEMCTL_SHOW_HELP
,
1847 _SYSTEMCTL_SHOW_MODE_MAX
,
1848 _SYSTEMCTL_SHOW_MODE_INVALID
= -EINVAL
,
1849 } SystemctlShowMode
;
1851 static const char* const systemctl_show_mode_table
[_SYSTEMCTL_SHOW_MODE_MAX
] = {
1852 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
1853 [SYSTEMCTL_SHOW_STATUS
] = "status",
1854 [SYSTEMCTL_SHOW_HELP
] = "help",
1857 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
1859 static int show_one(
1863 SystemctlShowMode show_mode
,
1867 static const struct bus_properties_map property_map
[] = {
1868 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
1869 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
1870 { "FreezerState", "s", NULL
, offsetof(UnitStatusInfo
, freezer_state
) },
1871 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1874 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
1875 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
1876 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
1877 { "FreezerState", "s", NULL
, offsetof(UnitStatusInfo
, freezer_state
) },
1878 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
1879 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
1880 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
1881 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
1882 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
1883 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1884 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
1885 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
1886 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
1887 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
1888 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
1889 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
1890 { "TriggeredBy", "as", NULL
, offsetof(UnitStatusInfo
, triggered_by
) },
1891 { "Triggers", "as", NULL
, offsetof(UnitStatusInfo
, triggers
) },
1892 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
1893 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
1894 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
1895 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
1896 { "RuntimeMaxUSec", "t", NULL
, offsetof(UnitStatusInfo
, runtime_max_sec
) },
1897 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
1898 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
1899 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
1900 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
1901 { "MainPID", "u", map_main_pid
, 0 },
1902 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
1903 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
1904 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
1905 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
1906 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
1907 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
1908 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
1909 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
1910 { "LogNamespace", "s", NULL
, offsetof(UnitStatusInfo
, log_namespace
) },
1911 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
1912 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
1913 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
1914 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
1915 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
1916 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
1917 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
1918 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
1919 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
1920 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
1921 { "NRefused", "u", NULL
, offsetof(UnitStatusInfo
, n_refused
) },
1922 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
1923 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
1924 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
1925 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
1926 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
1927 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
1928 { "MemoryAvailable", "t", NULL
, offsetof(UnitStatusInfo
, memory_available
) },
1929 { "DefaultMemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_min
) },
1930 { "DefaultMemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_low
) },
1931 { "MemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, memory_min
) },
1932 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
1933 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
1934 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
1935 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
1936 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
1937 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
1938 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
1939 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
1940 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
1941 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
1942 { "IOReadBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_read_bytes
) },
1943 { "IOWriteBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_write_bytes
) },
1944 { "ExecCondition", "a(sasbttttuii)", map_exec
, 0 },
1945 { "ExecConditionEx", "a(sasasttttuii)", map_exec
, 0 },
1946 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
1947 { "ExecStartPreEx", "a(sasasttttuii)", map_exec
, 0 },
1948 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
1949 { "ExecStartEx", "a(sasasttttuii)", map_exec
, 0 },
1950 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
1951 { "ExecStartPostEx", "a(sasasttttuii)", map_exec
, 0 },
1952 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
1953 { "ExecReloadEx", "a(sasasttttuii)", map_exec
, 0 },
1954 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
1955 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
1956 { "ExecStopEx", "a(sasasttttuii)", map_exec
, 0 },
1957 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
1958 { "ExecStopPostEx", "a(sasasttttuii)", map_exec
, 0 },
1962 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1963 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1964 _cleanup_set_free_ Set
*found_properties
= NULL
;
1965 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
1966 .memory_current
= UINT64_MAX
,
1967 .memory_high
= CGROUP_LIMIT_MAX
,
1968 .memory_max
= CGROUP_LIMIT_MAX
,
1969 .memory_swap_max
= CGROUP_LIMIT_MAX
,
1970 .memory_limit
= UINT64_MAX
,
1971 .memory_available
= CGROUP_LIMIT_MAX
,
1972 .cpu_usage_nsec
= UINT64_MAX
,
1973 .tasks_current
= UINT64_MAX
,
1974 .tasks_max
= UINT64_MAX
,
1975 .ip_ingress_bytes
= UINT64_MAX
,
1976 .ip_egress_bytes
= UINT64_MAX
,
1977 .io_read_bytes
= UINT64_MAX
,
1978 .io_write_bytes
= UINT64_MAX
,
1985 log_debug("Showing one %s", path
);
1987 r
= bus_map_all_properties(
1989 "org.freedesktop.systemd1",
1991 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
1992 BUS_MAP_BOOLEAN_AS_BOOL
,
1997 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
1999 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
2000 log_full(show_mode
== SYSTEMCTL_SHOW_PROPERTIES
? LOG_DEBUG
: LOG_ERR
,
2001 "Unit %s could not be found.", unit
);
2003 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
2004 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
2005 if (show_mode
== SYSTEMCTL_SHOW_HELP
)
2014 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
2015 print_status_info(bus
, &info
, ellipsized
);
2017 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
2018 return EXIT_PROGRAM_NOT_RUNNING
;
2020 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
2022 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
2023 show_unit_help(&info
);
2027 r
= sd_bus_message_rewind(reply
, true);
2029 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
2031 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_print_flags
, &found_properties
);
2033 return bus_log_parse_error(r
);
2035 STRV_FOREACH(pp
, arg_properties
)
2036 if (!set_contains(found_properties
, *pp
))
2037 log_debug("Property %s does not exist.", *pp
);
2042 static int get_unit_dbus_path_by_pid(
2047 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2048 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2052 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitByPID", &error
, &reply
, "u", pid
);
2054 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
2056 r
= sd_bus_message_read(reply
, "o", &u
);
2058 return bus_log_parse_error(r
);
2068 static int show_all(
2070 SystemctlShowMode show_mode
,
2074 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2075 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2079 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
2083 pager_open(arg_pager_flags
);
2087 typesafe_qsort(unit_infos
, c
, unit_info_compare
);
2089 for (const UnitInfo
*u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
2090 _cleanup_free_
char *p
= NULL
;
2092 p
= unit_dbus_path_from_name(u
->id
);
2096 r
= show_one(bus
, p
, u
->id
, show_mode
, new_line
, ellipsized
);
2099 if (r
> 0 && ret
== 0)
2106 static int show_system_status(sd_bus
*bus
) {
2107 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2108 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
2109 static const char prefix
[] = " ";
2110 _cleanup_free_
char *hn
= NULL
;
2111 const char *on
, *off
;
2115 hn
= gethostname_malloc();
2119 r
= bus_map_all_properties(
2121 "org.freedesktop.systemd1",
2122 "/org/freedesktop/systemd1",
2123 machine_info_property_map
,
2129 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
2131 if (streq_ptr(mi
.state
, "degraded")) {
2132 on
= ansi_highlight_red();
2133 off
= ansi_normal();
2134 } else if (streq_ptr(mi
.state
, "running")) {
2135 on
= ansi_highlight_green();
2136 off
= ansi_normal();
2138 on
= ansi_highlight_yellow();
2139 off
= ansi_normal();
2142 printf("%s%s%s %s\n", on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
, arg_host
?: hn
);
2144 printf(" State: %s%s%s\n",
2145 on
, strna(mi
.state
), off
);
2147 printf(" Units: %" PRIu32
" loaded (incl. loaded aliases)\n", mi
.n_names
);
2148 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
2149 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
2151 printf(" Since: %s; %s\n",
2152 FORMAT_TIMESTAMP_STYLE(mi
.timestamp
, arg_timestamp_style
),
2153 FORMAT_TIMESTAMP_RELATIVE(mi
.timestamp
));
2155 printf(" systemd: %s\n", mi
.version
);
2157 if (!isempty(mi
.tainted
))
2158 printf(" Tainted: %s%s%s\n", ansi_highlight_yellow(), mi
.tainted
, ansi_normal());
2160 printf(" CGroup: %s\n", empty_to_root(mi
.control_group
));
2162 c
= LESS_BY(columns(), strlen(prefix
));
2164 r
= unit_show_processes(bus
, SPECIAL_ROOT_SLICE
, mi
.control_group
, prefix
, c
, get_output_flags(), &error
);
2165 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) /* Compatibility for really old systemd versions */
2166 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
2168 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
2169 arg_host
?: hn
, bus_error_message(&error
, r
));
2174 int verb_show(int argc
, char *argv
[], void *userdata
) {
2175 bool new_line
= false, ellipsized
= false;
2176 SystemctlShowMode show_mode
;
2182 show_mode
= systemctl_show_mode_from_string(argv
[0]);
2184 return log_error_errno(show_mode
, "Invalid argument '%s'.", argv
[0]);
2186 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1)
2187 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2188 "'help' command expects one or more unit names.\n"
2189 "(Alternatively, help for systemctl itself may be shown with --help)");
2191 r
= acquire_bus(BUS_MANAGER
, &bus
);
2195 pager_open(arg_pager_flags
);
2198 /* If no argument or filter is specified inspect the manager itself:
2199 * systemctl status → we show status of the manager
2200 * systemctl status --all → status of the manager + status of all units
2201 * systemctl status --state=… → status of units in listed states
2202 * systemctl status --type=… → status of units of listed types
2203 * systemctl status --failed → status of failed units, mirroring systemctl list-units --failed
2206 if (!arg_states
&& !arg_types
) {
2207 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
)
2208 r
= show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
2210 r
= show_system_status(bus
);
2217 if (arg_all
|| arg_states
|| arg_types
)
2218 ret
= show_all(bus
, show_mode
, &new_line
, &ellipsized
);
2220 _cleanup_free_
char **patterns
= NULL
;
2222 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2223 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
2226 if (safe_atou32(*name
, &id
) < 0) {
2227 if (strv_push(&patterns
, *name
) < 0)
2231 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
2232 /* Interpret as job id */
2233 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
2237 /* Interpret as PID */
2238 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
2244 r
= unit_name_from_dbus_path(path
, &unit
);
2249 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
2252 if (r
> 0 && ret
== 0)
2256 if (!strv_isempty(patterns
)) {
2257 _cleanup_strv_free_
char **names
= NULL
;
2259 r
= expand_unit_names(bus
, patterns
, NULL
, &names
, NULL
);
2261 return log_error_errno(r
, "Failed to expand names: %m");
2263 r
= maybe_extend_with_unit_dependencies(bus
, &names
);
2267 STRV_FOREACH(name
, names
) {
2268 _cleanup_free_
char *path
= NULL
;
2270 path
= unit_dbus_path_from_name(*name
);
2274 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
2277 if (r
> 0 && ret
== 0)
2283 if (ellipsized
&& !arg_quiet
)
2284 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");