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
);
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
);
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
)) {
285 LIST_REMOVE(exec
, info
->exec
, 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 print_status_info(
306 const char *active_on
, *active_off
, *on
, *off
, *ss
, *fs
;
307 _cleanup_free_
char *formatted_path
= NULL
;
316 /* This shows pretty information about a unit. See print_property() for a low-level property
319 format_active_state(i
->active_state
, &active_on
, &active_off
);
321 const SpecialGlyph glyph
= unit_active_state_to_glyph(unit_active_state_from_string(i
->active_state
));
323 printf("%s%s%s %s", active_on
, special_glyph(glyph
), active_off
, strna(i
->id
));
325 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
326 printf(" - %s", i
->description
);
331 printf(" Follows: unit currently follows state of %s\n", i
->following
);
333 if (STRPTR_IN_SET(i
->load_state
, "error", "not-found", "bad-setting")) {
334 on
= ansi_highlight_red();
339 path
= i
->source_path
?: i
->fragment_path
;
340 if (path
&& terminal_urlify_path(path
, NULL
, &formatted_path
) >= 0)
341 path
= formatted_path
;
343 if (!isempty(i
->load_error
))
344 printf(" Loaded: %s%s%s (Reason: %s)\n",
345 on
, strna(i
->load_state
), off
, i
->load_error
);
346 else if (path
&& !isempty(i
->unit_file_state
)) {
347 bool show_preset
= !isempty(i
->unit_file_preset
) &&
348 show_preset_for_state(unit_file_state_from_string(i
->unit_file_state
));
350 printf(" Loaded: %s%s%s (%s; %s%s%s)\n",
351 on
, strna(i
->load_state
), off
,
354 show_preset
? "; vendor preset: " : "",
355 show_preset
? i
->unit_file_preset
: "");
358 printf(" Loaded: %s%s%s (%s)\n",
359 on
, strna(i
->load_state
), off
, path
);
361 printf(" Loaded: %s%s%s\n",
362 on
, strna(i
->load_state
), off
);
365 printf(" Transient: yes\n");
367 if (!strv_isempty(i
->dropin_paths
)) {
368 _cleanup_free_
char *dir
= NULL
;
372 STRV_FOREACH(dropin
, i
->dropin_paths
) {
373 _cleanup_free_
char *dropin_formatted
= NULL
;
382 dir
= dirname_malloc(*dropin
);
390 special_glyph(SPECIAL_GLYPH_TREE_RIGHT
));
393 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
395 if (terminal_urlify_path(*dropin
, basename(*dropin
), &dropin_formatted
) >= 0)
396 df
= dropin_formatted
;
400 printf("%s%s", df
, last
? "\n" : ", ");
404 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
406 printf(" Active: %s%s (%s)%s",
407 active_on
, strna(i
->active_state
), ss
, active_off
);
409 printf(" Active: %s%s%s",
410 active_on
, strna(i
->active_state
), active_off
);
412 fs
= !isempty(i
->freezer_state
) && !streq(i
->freezer_state
, "running") ? i
->freezer_state
: NULL
;
414 printf(" %s(%s)%s", ansi_highlight_yellow(), fs
, ansi_normal());
416 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
417 printf(" (Result: %s)", i
->result
);
419 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
420 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
421 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
422 i
->active_exit_timestamp
;
424 if (timestamp_is_set(timestamp
)) {
425 printf(" since %s; %s\n",
426 FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
),
427 FORMAT_TIMESTAMP_RELATIVE(timestamp
));
428 if (streq_ptr(i
->active_state
, "active") && i
->runtime_max_sec
< USEC_INFINITY
) {
429 usec_t until_timestamp
;
431 until_timestamp
= usec_add(timestamp
, i
->runtime_max_sec
);
432 printf(" Until: %s; %s\n",
433 FORMAT_TIMESTAMP_STYLE(until_timestamp
, arg_timestamp_style
),
434 FORMAT_TIMESTAMP_RELATIVE(until_timestamp
));
437 if (!endswith(i
->id
, ".target") &&
438 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") &&
439 timestamp_is_set(i
->active_enter_timestamp
) &&
440 timestamp_is_set(i
->active_exit_timestamp
) &&
441 i
->active_exit_timestamp
>= i
->active_enter_timestamp
) {
445 duration
= i
->active_exit_timestamp
- i
->active_enter_timestamp
;
446 printf(" Duration: %s\n", FORMAT_TIMESPAN(duration
, MSEC_PER_SEC
));
451 STRV_FOREACH(t
, i
->triggered_by
) {
452 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
454 (void) get_state_one_unit(bus
, *t
, &state
);
455 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
457 printf("%s %s%s%s %s\n",
458 t
== i
->triggered_by
? "TriggeredBy:" : " ",
459 on
, special_glyph(unit_active_state_to_glyph(state
)), off
,
463 if (endswith(i
->id
, ".timer")) {
464 dual_timestamp nw
, next
= {i
->next_elapse_real
, i
->next_elapse_monotonic
};
467 dual_timestamp_get(&nw
);
468 next_elapse
= calc_next_elapse(&nw
, &next
);
470 if (timestamp_is_set(next_elapse
))
471 printf(" Trigger: %s; %s\n",
472 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
),
473 FORMAT_TIMESTAMP_RELATIVE(next_elapse
));
475 printf(" Trigger: n/a\n");
478 STRV_FOREACH(t
, i
->triggers
) {
479 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
481 (void) get_state_one_unit(bus
, *t
, &state
);
482 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
484 printf("%s %s%s%s %s\n",
485 t
== i
->triggers
? " Triggers:" : " ",
486 on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
,
490 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
494 printf(" Condition: start %scondition failed%s at %s; %s\n",
495 ansi_highlight_yellow(), ansi_normal(),
496 FORMAT_TIMESTAMP_STYLE(i
->condition_timestamp
, arg_timestamp_style
),
497 FORMAT_TIMESTAMP_RELATIVE(i
->condition_timestamp
));
499 LIST_FOREACH(conditions
, c
, i
->conditions
)
503 LIST_FOREACH(conditions
, c
, i
->conditions
)
505 printf(" %s %s=%s%s%s was not met\n",
506 --n
? special_glyph(SPECIAL_GLYPH_TREE_BRANCH
) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT
),
508 c
->trigger
? "|" : "",
509 c
->negate
? "!" : "",
513 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
514 printf(" Assert: start %sassertion failed%s at %s; %s\n",
515 ansi_highlight_red(), ansi_normal(),
516 FORMAT_TIMESTAMP_STYLE(i
->assert_timestamp
, arg_timestamp_style
),
517 FORMAT_TIMESTAMP_RELATIVE(i
->assert_timestamp
));
518 if (i
->failed_assert_trigger
)
519 printf(" none of the trigger assertions were met\n");
520 else if (i
->failed_assert
)
521 printf(" %s=%s%s was not met\n",
523 i
->failed_assert_negate
? "!" : "",
524 i
->failed_assert_parameter
);
528 printf(" Device: %s\n", i
->sysfs_path
);
530 printf(" Where: %s\n", i
->where
);
532 printf(" What: %s\n", i
->what
);
534 STRV_FOREACH(t
, i
->documentation
) {
535 _cleanup_free_
char *formatted
= NULL
;
538 if (terminal_urlify(*t
, NULL
, &formatted
) >= 0)
543 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", q
);
546 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
547 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
550 printf(" Accepted: %u; Connected: %u;", i
->n_accepted
, i
->n_connections
);
552 printf(" Refused: %u", i
->n_refused
);
556 LIST_FOREACH(exec
, p
, i
->exec
) {
557 _cleanup_free_
char *argv
= NULL
;
560 /* Only show exited processes here */
564 /* Don't print ExecXYZEx= properties here since it will appear as a
565 * duplicate of the non-Ex= variant. */
566 if (endswith(p
->name
, "Ex"))
569 argv
= strv_join(p
->argv
, " ");
570 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
572 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
574 on
= ansi_highlight_red();
579 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
581 if (p
->code
== CLD_EXITED
) {
584 printf("status=%i", p
->status
);
586 c
= exit_status_to_string(p
->status
, EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
591 printf("signal=%s", signal_to_string(p
->status
));
593 printf(")%s\n", off
);
595 if (i
->main_pid
== p
->pid
&&
596 i
->start_timestamp
== p
->start_timestamp
&&
597 i
->exit_timestamp
== p
->start_timestamp
)
598 /* Let's not show this twice */
601 if (p
->pid
== i
->control_pid
)
605 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
606 if (i
->main_pid
> 0) {
607 printf(" Main PID: "PID_FMT
, i
->main_pid
);
611 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
612 _cleanup_free_
char *comm
= NULL
;
614 (void) get_process_comm(i
->main_pid
, &comm
);
616 printf(" (%s)", comm
);
619 } else if (i
->exit_code
> 0) {
620 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
622 if (i
->exit_code
== CLD_EXITED
) {
625 printf("status=%i", i
->exit_status
);
627 c
= exit_status_to_string(i
->exit_status
,
628 EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
633 printf("signal=%s", signal_to_string(i
->exit_status
));
638 if (i
->control_pid
> 0) {
639 _cleanup_free_
char *c
= NULL
;
642 fputs("; Control PID: ", stdout
);
644 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
646 printf(PID_FMT
, i
->control_pid
);
648 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
649 (void) get_process_comm(i
->control_pid
, &c
);
659 printf(" Status: \"%s\"\n", i
->status_text
);
660 if (i
->status_errno
> 0)
661 printf(" Error: %i (%s)\n", i
->status_errno
, strerror_safe(i
->status_errno
));
663 if (i
->ip_ingress_bytes
!= UINT64_MAX
&& i
->ip_egress_bytes
!= UINT64_MAX
)
664 printf(" IP: %s in, %s out\n",
665 FORMAT_BYTES(i
->ip_ingress_bytes
),
666 FORMAT_BYTES(i
->ip_egress_bytes
));
668 if (i
->io_read_bytes
!= UINT64_MAX
&& i
->io_write_bytes
!= UINT64_MAX
)
669 printf(" IO: %s read, %s written\n",
670 FORMAT_BYTES(i
->io_read_bytes
),
671 FORMAT_BYTES(i
->io_write_bytes
));
673 if (i
->tasks_current
!= UINT64_MAX
) {
674 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
676 if (i
->tasks_max
!= UINT64_MAX
)
677 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
682 if (i
->memory_current
!= UINT64_MAX
) {
683 printf(" Memory: %s", FORMAT_BYTES(i
->memory_current
));
685 if (i
->memory_min
> 0 || i
->memory_low
> 0 ||
686 i
->memory_high
!= CGROUP_LIMIT_MAX
|| i
->memory_max
!= CGROUP_LIMIT_MAX
||
687 i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
688 i
->memory_available
!= CGROUP_LIMIT_MAX
||
689 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
690 const char *prefix
= "";
693 if (i
->memory_min
> 0) {
694 printf("%smin: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_min
));
697 if (i
->memory_low
> 0) {
698 printf("%slow: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_low
));
701 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
702 printf("%shigh: %s", prefix
, FORMAT_BYTES(i
->memory_high
));
705 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
706 printf("%smax: %s", prefix
, FORMAT_BYTES(i
->memory_max
));
709 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
710 printf("%sswap max: %s", prefix
, FORMAT_BYTES(i
->memory_swap_max
));
713 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
714 printf("%slimit: %s", prefix
, FORMAT_BYTES(i
->memory_limit
));
717 if (i
->memory_available
!= CGROUP_LIMIT_MAX
) {
718 printf("%savailable: %s", prefix
, FORMAT_BYTES(i
->memory_available
));
726 if (i
->cpu_usage_nsec
!= UINT64_MAX
)
727 printf(" CPU: %s\n", FORMAT_TIMESPAN(i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
729 if (i
->control_group
) {
730 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
731 static const char prefix
[] = " ";
734 printf(" CGroup: %s\n", i
->control_group
);
736 c
= LESS_BY(columns(), strlen(prefix
));
738 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
739 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
743 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
746 extra
[k
++] = i
->main_pid
;
748 if (i
->control_pid
> 0)
749 extra
[k
++] = i
->control_pid
;
751 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
753 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
754 i
->id
, bus_error_message(&error
, r
));
757 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
758 show_journal_by_unit(
764 i
->inactive_exit_timestamp_monotonic
,
767 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
768 SD_JOURNAL_LOCAL_ONLY
,
769 arg_scope
== UNIT_FILE_SYSTEM
,
772 if (i
->need_daemon_reload
)
773 warn_unit_file_changed(i
->id
);
776 static void show_unit_help(UnitStatusInfo
*i
) {
781 if (!i
->documentation
) {
782 log_info("Documentation for %s not known.", i
->id
);
786 STRV_FOREACH(p
, i
->documentation
)
787 if (startswith(*p
, "man:"))
788 show_man_page(*p
+ 4, false);
790 log_info("Can't show: %s", *p
);
793 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
794 UnitStatusInfo
*i
= userdata
;
798 r
= sd_bus_message_read(m
, "u", &u
);
802 i
->main_pid
= (pid_t
) u
;
808 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
809 const char *message
, **p
= userdata
;
812 r
= sd_bus_message_read(m
, "(ss)", NULL
, &message
);
816 if (!isempty(message
))
822 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
823 const char *type
, *path
;
824 char ***p
= userdata
;
827 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
831 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
833 r
= strv_extend(p
, type
);
837 r
= strv_extend(p
, path
);
844 r
= sd_bus_message_exit_container(m
);
851 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
852 UnitStatusInfo
*i
= userdata
;
853 const char *cond
, *param
;
858 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
862 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
863 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
865 c
= new(UnitCondition
, 1);
869 *c
= (UnitCondition
) {
870 .name
= strdup(cond
),
871 .param
= strdup(param
),
877 if (!c
->name
|| !c
->param
)
880 LIST_PREPEND(conditions
, i
->conditions
, TAKE_PTR(c
));
885 r
= sd_bus_message_exit_container(m
);
892 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
893 UnitStatusInfo
*i
= userdata
;
894 const char *cond
, *param
;
899 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
903 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
904 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
905 i
->failed_assert
= cond
;
906 i
->failed_assert_trigger
= trigger
;
907 i
->failed_assert_negate
= negate
;
908 i
->failed_assert_parameter
= param
;
914 r
= sd_bus_message_exit_container(m
);
921 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
922 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
923 ExecStatusInfo
*last
;
924 UnitStatusInfo
*i
= userdata
;
925 bool is_ex_prop
= endswith(member
, "Ex");
928 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
932 info
= new0(ExecStatusInfo
, 1);
936 LIST_FIND_TAIL(exec
, i
->exec
, last
);
938 while ((r
= exec_status_info_deserialize(m
, info
, is_ex_prop
)) > 0) {
940 info
->name
= strdup(member
);
944 LIST_INSERT_AFTER(exec
, i
->exec
, last
, info
);
947 info
= new0(ExecStatusInfo
, 1);
954 r
= sd_bus_message_exit_container(m
);
961 static int print_property(const char *name
, const char *expected_value
, sd_bus_message
*m
, BusPrintPropertyFlags flags
) {
963 const char *contents
;
969 /* This is a low-level property printer, see print_status_info() for the nicer output */
971 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
977 case SD_BUS_TYPE_INT32
:
978 if (endswith(name
, "ActionExitStatus")) {
981 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
985 if (i
>= 0 && i
<= 255)
986 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIi32
, i
);
987 else if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
))
988 bus_print_property_value(name
, expected_value
, flags
, "[not set]");
991 } else if (streq(name
, "NUMAPolicy")) {
994 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
998 bus_print_property_valuef(name
, expected_value
, flags
, "%s", strna(mpol_to_string(i
)));
1004 case SD_BUS_TYPE_UINT64
:
1005 if (endswith(name
, "Timestamp")) {
1008 r
= sd_bus_message_read_basic(m
, bus_type
, ×tamp
);
1012 bus_print_property_value(name
, expected_value
, flags
, FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
));
1018 case SD_BUS_TYPE_STRUCT
:
1020 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
1023 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
1025 return bus_log_parse_error(r
);
1028 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIu32
, u
);
1030 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1034 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
1037 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
1039 return bus_log_parse_error(r
);
1041 bus_print_property_value(name
, expected_value
, flags
, s
);
1045 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
1046 const char *a
= NULL
, *b
= NULL
;
1048 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
1050 return bus_log_parse_error(r
);
1052 if (!isempty(a
) || !isempty(b
))
1053 bus_print_property_valuef(name
, expected_value
, flags
, "%s \"%s\"", strempty(a
), strempty(b
));
1055 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1059 } else if (STR_IN_SET(name
, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces", "RestrictFileSystems")) {
1060 _cleanup_strv_free_
char **l
= NULL
;
1063 r
= sd_bus_message_enter_container(m
, 'r', "bas");
1065 return bus_log_parse_error(r
);
1067 r
= sd_bus_message_read(m
, "b", &allow_list
);
1069 return bus_log_parse_error(r
);
1071 r
= sd_bus_message_read_strv(m
, &l
);
1073 return bus_log_parse_error(r
);
1075 r
= sd_bus_message_exit_container(m
);
1077 return bus_log_parse_error(r
);
1079 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || allow_list
|| !strv_isempty(l
)) {
1083 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1084 fputs(name
, stdout
);
1091 STRV_FOREACH(i
, l
) {
1099 fputc('\n', stdout
);
1104 } else if (STR_IN_SET(name
, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
1108 r
= sd_bus_message_read(m
, "(bs)", &ignore
, &s
);
1110 return bus_log_parse_error(r
);
1113 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s", ignore
? "-" : "", s
);
1115 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1119 } else if (endswith(name
, "ExitStatus") && streq(contents
, "aiai")) {
1120 const int32_t *status
, *signal
;
1121 size_t n_status
, n_signal
;
1123 r
= sd_bus_message_enter_container(m
, 'r', "aiai");
1125 return bus_log_parse_error(r
);
1127 r
= sd_bus_message_read_array(m
, 'i', (const void **) &status
, &n_status
);
1129 return bus_log_parse_error(r
);
1131 r
= sd_bus_message_read_array(m
, 'i', (const void **) &signal
, &n_signal
);
1133 return bus_log_parse_error(r
);
1135 r
= sd_bus_message_exit_container(m
);
1137 return bus_log_parse_error(r
);
1139 n_status
/= sizeof(int32_t);
1140 n_signal
/= sizeof(int32_t);
1142 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || n_status
> 0 || n_signal
> 0) {
1145 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1146 fputs(name
, stdout
);
1150 for (size_t i
= 0; i
< n_status
; i
++) {
1156 printf("%"PRIi32
, status
[i
]);
1159 for (size_t i
= 0; i
< n_signal
; i
++) {
1162 str
= signal_to_string((int) signal
[i
]);
1172 printf("%"PRIi32
, status
[i
]);
1175 fputc('\n', stdout
);
1182 case SD_BUS_TYPE_ARRAY
:
1184 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
1188 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
1190 return bus_log_parse_error(r
);
1192 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
1193 bus_print_property_valuef(name
, expected_value
, flags
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
1195 return bus_log_parse_error(r
);
1197 r
= sd_bus_message_exit_container(m
);
1199 return bus_log_parse_error(r
);
1203 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
1204 const char *type
, *path
;
1206 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1208 return bus_log_parse_error(r
);
1210 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1211 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1213 return bus_log_parse_error(r
);
1215 r
= sd_bus_message_exit_container(m
);
1217 return bus_log_parse_error(r
);
1221 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
1222 const char *type
, *path
;
1224 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1226 return bus_log_parse_error(r
);
1228 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1229 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1231 return bus_log_parse_error(r
);
1233 r
= sd_bus_message_exit_container(m
);
1235 return bus_log_parse_error(r
);
1239 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
1241 uint64_t v
, next_elapse
;
1243 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
1245 return bus_log_parse_error(r
);
1247 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0)
1248 bus_print_property_valuef(name
, expected_value
, flags
,
1249 "{ %s=%s ; next_elapse=%s }",
1251 strna(FORMAT_TIMESPAN(v
, 0)),
1252 strna(FORMAT_TIMESPAN(next_elapse
, 0)));
1254 return bus_log_parse_error(r
);
1256 r
= sd_bus_message_exit_container(m
);
1258 return bus_log_parse_error(r
);
1262 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
1263 const char *base
, *spec
;
1264 uint64_t next_elapse
;
1266 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1268 return bus_log_parse_error(r
);
1270 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0)
1271 bus_print_property_valuef(name
, expected_value
, flags
,
1272 "{ %s=%s ; next_elapse=%s }", base
, spec
,
1273 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
));
1275 return bus_log_parse_error(r
);
1277 r
= sd_bus_message_exit_container(m
);
1279 return bus_log_parse_error(r
);
1283 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
1284 ExecStatusInfo info
= {};
1285 bool is_ex_prop
= endswith(name
, "Ex");
1287 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
1289 return bus_log_parse_error(r
);
1291 while ((r
= exec_status_info_deserialize(m
, &info
, is_ex_prop
)) > 0) {
1292 _cleanup_strv_free_
char **optv
= NULL
;
1293 _cleanup_free_
char *tt
= NULL
, *o
= NULL
;
1295 tt
= strv_join(info
.argv
, " ");
1298 r
= exec_command_flags_to_strv(info
.flags
, &optv
);
1300 return log_error_errno(r
, "Failed to convert ExecCommandFlags to strv: %m");
1302 o
= strv_join(optv
, " ");
1304 bus_print_property_valuef(name
, expected_value
, flags
,
1305 "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1309 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1310 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1312 sigchld_code_to_string(info
.code
),
1314 info
.code
== CLD_EXITED
? "" : "/",
1315 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1317 bus_print_property_valuef(name
, expected_value
, flags
,
1318 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1321 yes_no(info
.ignore
),
1322 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1323 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1325 sigchld_code_to_string(info
.code
),
1327 info
.code
== CLD_EXITED
? "" : "/",
1328 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1331 strv_free(info
.argv
);
1335 r
= sd_bus_message_exit_container(m
);
1337 return bus_log_parse_error(r
);
1341 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
1342 const char *path
, *rwm
;
1344 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1346 return bus_log_parse_error(r
);
1348 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
1349 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
), strna(rwm
));
1351 return bus_log_parse_error(r
);
1353 r
= sd_bus_message_exit_container(m
);
1355 return bus_log_parse_error(r
);
1359 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1360 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
1364 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1366 return bus_log_parse_error(r
);
1368 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
1369 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), weight
);
1371 return bus_log_parse_error(r
);
1373 r
= sd_bus_message_exit_container(m
);
1375 return bus_log_parse_error(r
);
1379 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1380 (cgroup_io_limit_type_from_string(name
) >= 0 ||
1381 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
1385 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1387 return bus_log_parse_error(r
);
1389 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
1390 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), bandwidth
);
1392 return bus_log_parse_error(r
);
1394 r
= sd_bus_message_exit_container(m
);
1396 return bus_log_parse_error(r
);
1400 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1401 streq(name
, "IODeviceLatencyTargetUSec")) {
1405 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1407 return bus_log_parse_error(r
);
1409 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &target
)) > 0)
1410 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
),
1411 FORMAT_TIMESPAN(target
, 1));
1413 return bus_log_parse_error(r
);
1415 r
= sd_bus_message_exit_container(m
);
1417 return bus_log_parse_error(r
);
1421 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& STR_IN_SET(name
, "StandardInputData", "RootHashSignature")) {
1422 _cleanup_free_
char *h
= NULL
;
1427 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
1429 return bus_log_parse_error(r
);
1431 n
= base64mem(p
, sz
, &h
);
1435 bus_print_property_value(name
, expected_value
, flags
, h
);
1439 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1440 _cleanup_free_
char *addresses
= NULL
;
1442 r
= sd_bus_message_enter_container(m
, 'a', "(iayu)");
1444 return bus_log_parse_error(r
);
1447 _cleanup_free_
char *str
= NULL
;
1453 r
= sd_bus_message_enter_container(m
, 'r', "iayu");
1455 return bus_log_parse_error(r
);
1459 r
= sd_bus_message_read(m
, "i", &family
);
1461 return bus_log_parse_error(r
);
1463 r
= sd_bus_message_read_array(m
, 'y', &ap
, &an
);
1465 return bus_log_parse_error(r
);
1467 r
= sd_bus_message_read(m
, "u", &prefixlen
);
1469 return bus_log_parse_error(r
);
1471 r
= sd_bus_message_exit_container(m
);
1473 return bus_log_parse_error(r
);
1475 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1478 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1481 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
) * 8)
1484 if (in_addr_prefix_to_string(family
, (const union in_addr_union
*) ap
, prefixlen
, &str
) < 0)
1487 if (!strextend_with_separator(&addresses
, " ", str
))
1491 r
= sd_bus_message_exit_container(m
);
1493 return bus_log_parse_error(r
);
1495 bus_print_property_value(name
, expected_value
, flags
, addresses
);
1499 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
1500 _cleanup_free_
char *paths
= NULL
;
1501 const char *source
, *dest
;
1505 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssbt)");
1507 return bus_log_parse_error(r
);
1509 while ((r
= sd_bus_message_read(m
, "(ssbt)", &source
, &dest
, &ignore_enoent
, &rbind
)) > 0) {
1510 _cleanup_free_
char *str
= NULL
;
1512 if (isempty(source
))
1515 if (asprintf(&str
, "%s%s%s%s%s",
1516 ignore_enoent
? "-" : "",
1518 isempty(dest
) ? "" : ":",
1520 rbind
== MS_REC
? ":rbind" : "") < 0)
1523 if (!strextend_with_separator(&paths
, " ", str
))
1527 return bus_log_parse_error(r
);
1529 r
= sd_bus_message_exit_container(m
);
1531 return bus_log_parse_error(r
);
1533 bus_print_property_value(name
, expected_value
, flags
, paths
);
1537 } else if (streq(name
, "TemporaryFileSystem")) {
1538 _cleanup_free_
char *paths
= NULL
;
1539 const char *target
, *option
;
1541 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1543 return bus_log_parse_error(r
);
1545 while ((r
= sd_bus_message_read(m
, "(ss)", &target
, &option
)) > 0) {
1546 _cleanup_free_
char *str
= NULL
;
1548 if (isempty(target
))
1551 if (asprintf(&str
, "%s%s%s", target
, isempty(option
) ? "" : ":", strempty(option
)) < 0)
1554 if (!strextend_with_separator(&paths
, " ", str
))
1558 return bus_log_parse_error(r
);
1560 r
= sd_bus_message_exit_container(m
);
1562 return bus_log_parse_error(r
);
1564 bus_print_property_value(name
, expected_value
, flags
, paths
);
1568 } else if (streq(name
, "LogExtraFields")) {
1569 _cleanup_free_
char *fields
= NULL
;
1573 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "ay");
1575 return bus_log_parse_error(r
);
1577 while ((r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
)) > 0) {
1578 _cleanup_free_
char *str
= NULL
;
1581 if (memchr(p
, 0, sz
))
1584 eq
= memchr(p
, '=', sz
);
1588 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
1591 str
= malloc(sz
+ 1);
1598 if (!utf8_is_valid(str
))
1601 if (!strextend_with_separator(&fields
, " ", str
))
1605 return bus_log_parse_error(r
);
1607 r
= sd_bus_message_exit_container(m
);
1609 return bus_log_parse_error(r
);
1611 bus_print_property_value(name
, expected_value
, flags
, fields
);
1614 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&&
1616 "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes",
1617 "EffectiveCPUs", "EffectiveMemoryNodes")) {
1619 _cleanup_free_
char *affinity
= NULL
;
1620 _cleanup_(cpu_set_reset
) CPUSet set
= {};
1624 r
= sd_bus_message_read_array(m
, 'y', &a
, &n
);
1626 return bus_log_parse_error(r
);
1628 r
= cpu_set_from_dbus(a
, n
, &set
);
1630 return log_error_errno(r
, "Failed to deserialize %s: %m", name
);
1632 affinity
= cpu_set_to_range_string(&set
);
1636 bus_print_property_value(name
, expected_value
, flags
, affinity
);
1639 } else if (streq(name
, "MountImages")) {
1640 _cleanup_free_
char *paths
= NULL
;
1642 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssba(ss))");
1644 return bus_log_parse_error(r
);
1647 _cleanup_free_
char *str
= NULL
;
1648 const char *source
, *destination
, *partition
, *mount_options
;
1651 r
= sd_bus_message_enter_container(m
, 'r', "ssba(ss)");
1653 return bus_log_parse_error(r
);
1657 r
= sd_bus_message_read(m
, "ssb", &source
, &destination
, &ignore_enoent
);
1659 return bus_log_parse_error(r
);
1661 str
= strjoin(ignore_enoent
? "-" : "",
1668 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1670 return bus_log_parse_error(r
);
1672 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1673 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1676 return bus_log_parse_error(r
);
1678 if (!strextend_with_separator(&paths
, " ", str
))
1681 r
= sd_bus_message_exit_container(m
);
1683 return bus_log_parse_error(r
);
1685 r
= sd_bus_message_exit_container(m
);
1687 return bus_log_parse_error(r
);
1690 r
= sd_bus_message_exit_container(m
);
1692 return bus_log_parse_error(r
);
1694 bus_print_property_value(name
, expected_value
, flags
, paths
);
1698 } else if (streq(name
, "ExtensionImages")) {
1699 _cleanup_free_
char *paths
= NULL
;
1701 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sba(ss))");
1703 return bus_log_parse_error(r
);
1706 _cleanup_free_
char *str
= NULL
;
1707 const char *source
, *partition
, *mount_options
;
1710 r
= sd_bus_message_enter_container(m
, 'r', "sba(ss)");
1712 return bus_log_parse_error(r
);
1716 r
= sd_bus_message_read(m
, "sb", &source
, &ignore_enoent
);
1718 return bus_log_parse_error(r
);
1720 str
= strjoin(ignore_enoent
? "-" : "", source
);
1724 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1726 return bus_log_parse_error(r
);
1728 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1729 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1732 return bus_log_parse_error(r
);
1734 if (!strextend_with_separator(&paths
, " ", str
))
1737 r
= sd_bus_message_exit_container(m
);
1739 return bus_log_parse_error(r
);
1741 r
= sd_bus_message_exit_container(m
);
1743 return bus_log_parse_error(r
);
1746 r
= sd_bus_message_exit_container(m
);
1748 return bus_log_parse_error(r
);
1750 bus_print_property_value(name
, expected_value
, flags
, paths
);
1754 } else if (streq(name
, "BPFProgram")) {
1757 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1759 return bus_log_parse_error(r
);
1761 while ((r
= sd_bus_message_read(m
, "(ss)", &a
, &p
)) > 0)
1762 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1764 return bus_log_parse_error(r
);
1766 r
= sd_bus_message_exit_container(m
);
1768 return bus_log_parse_error(r
);
1771 } else if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1772 uint16_t nr_ports
, port_min
;
1773 int32_t af
, ip_protocol
;
1775 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(iiqq)");
1777 return bus_log_parse_error(r
);
1778 while ((r
= sd_bus_message_read(m
, "(iiqq)", &af
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1779 const char *family
, *colon1
, *protocol
= "", *colon2
= "";
1781 family
= strempty(af_to_ipv4_ipv6(af
));
1782 colon1
= isempty(family
) ? "" : ":";
1784 if (ip_protocol
!= 0) {
1785 protocol
= ip_protocol_to_tcp_udp(ip_protocol
);
1790 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s%s%sany",
1791 family
, colon1
, protocol
, colon2
);
1792 else if (nr_ports
== 1)
1793 bus_print_property_valuef(
1794 name
, expected_value
, flags
, "%s%s%s%s%hu",
1795 family
, colon1
, protocol
, colon2
, port_min
);
1797 bus_print_property_valuef(
1798 name
, expected_value
, flags
, "%s%s%s%s%hu-%hu",
1799 family
, colon1
, protocol
, colon2
, port_min
,
1800 (uint16_t) (port_min
+ nr_ports
- 1));
1803 return bus_log_parse_error(r
);
1805 r
= sd_bus_message_exit_container(m
);
1807 return bus_log_parse_error(r
);
1810 } else if (STR_IN_SET(name
, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
1812 uint64_t symlink_flags
;
1814 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1816 return bus_log_parse_error(r
);
1818 while ((r
= sd_bus_message_read(m
, "(sst)", &a
, &p
, &symlink_flags
)) > 0)
1819 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1821 return bus_log_parse_error(r
);
1823 r
= sd_bus_message_exit_container(m
);
1825 return bus_log_parse_error(r
);
1836 typedef enum SystemctlShowMode
{
1837 SYSTEMCTL_SHOW_PROPERTIES
,
1838 SYSTEMCTL_SHOW_STATUS
,
1839 SYSTEMCTL_SHOW_HELP
,
1840 _SYSTEMCTL_SHOW_MODE_MAX
,
1841 _SYSTEMCTL_SHOW_MODE_INVALID
= -EINVAL
,
1842 } SystemctlShowMode
;
1844 static const char* const systemctl_show_mode_table
[_SYSTEMCTL_SHOW_MODE_MAX
] = {
1845 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
1846 [SYSTEMCTL_SHOW_STATUS
] = "status",
1847 [SYSTEMCTL_SHOW_HELP
] = "help",
1850 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
1852 static int show_one(
1856 SystemctlShowMode show_mode
,
1860 static const struct bus_properties_map property_map
[] = {
1861 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
1862 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
1863 { "FreezerState", "s", NULL
, offsetof(UnitStatusInfo
, freezer_state
) },
1864 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1867 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
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 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
1872 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
1873 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
1874 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
1875 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
1876 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1877 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
1878 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
1879 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
1880 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
1881 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
1882 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
1883 { "TriggeredBy", "as", NULL
, offsetof(UnitStatusInfo
, triggered_by
) },
1884 { "Triggers", "as", NULL
, offsetof(UnitStatusInfo
, triggers
) },
1885 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
1886 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
1887 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
1888 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
1889 { "RuntimeMaxUSec", "t", NULL
, offsetof(UnitStatusInfo
, runtime_max_sec
) },
1890 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
1891 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
1892 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
1893 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
1894 { "MainPID", "u", map_main_pid
, 0 },
1895 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
1896 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
1897 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
1898 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
1899 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
1900 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
1901 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
1902 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
1903 { "LogNamespace", "s", NULL
, offsetof(UnitStatusInfo
, log_namespace
) },
1904 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
1905 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
1906 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
1907 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
1908 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
1909 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
1910 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
1911 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
1912 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
1913 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
1914 { "NRefused", "u", NULL
, offsetof(UnitStatusInfo
, n_refused
) },
1915 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
1916 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
1917 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
1918 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
1919 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
1920 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
1921 { "MemoryAvailable", "t", NULL
, offsetof(UnitStatusInfo
, memory_available
) },
1922 { "DefaultMemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_min
) },
1923 { "DefaultMemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_low
) },
1924 { "MemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, memory_min
) },
1925 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
1926 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
1927 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
1928 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
1929 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
1930 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
1931 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
1932 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
1933 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
1934 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
1935 { "IOReadBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_read_bytes
) },
1936 { "IOWriteBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_write_bytes
) },
1937 { "ExecCondition", "a(sasbttttuii)", map_exec
, 0 },
1938 { "ExecConditionEx", "a(sasasttttuii)", map_exec
, 0 },
1939 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
1940 { "ExecStartPreEx", "a(sasasttttuii)", map_exec
, 0 },
1941 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
1942 { "ExecStartEx", "a(sasasttttuii)", map_exec
, 0 },
1943 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
1944 { "ExecStartPostEx", "a(sasasttttuii)", map_exec
, 0 },
1945 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
1946 { "ExecReloadEx", "a(sasasttttuii)", map_exec
, 0 },
1947 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
1948 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
1949 { "ExecStopEx", "a(sasasttttuii)", map_exec
, 0 },
1950 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
1951 { "ExecStopPostEx", "a(sasasttttuii)", map_exec
, 0 },
1955 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1956 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1957 _cleanup_set_free_ Set
*found_properties
= NULL
;
1958 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
1959 .memory_current
= UINT64_MAX
,
1960 .memory_high
= CGROUP_LIMIT_MAX
,
1961 .memory_max
= CGROUP_LIMIT_MAX
,
1962 .memory_swap_max
= CGROUP_LIMIT_MAX
,
1963 .memory_limit
= UINT64_MAX
,
1964 .memory_available
= CGROUP_LIMIT_MAX
,
1965 .cpu_usage_nsec
= UINT64_MAX
,
1966 .tasks_current
= UINT64_MAX
,
1967 .tasks_max
= UINT64_MAX
,
1968 .ip_ingress_bytes
= UINT64_MAX
,
1969 .ip_egress_bytes
= UINT64_MAX
,
1970 .io_read_bytes
= UINT64_MAX
,
1971 .io_write_bytes
= UINT64_MAX
,
1979 log_debug("Showing one %s", path
);
1981 r
= bus_map_all_properties(
1983 "org.freedesktop.systemd1",
1985 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
1986 BUS_MAP_BOOLEAN_AS_BOOL
,
1991 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
1993 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
1994 log_full(show_mode
== SYSTEMCTL_SHOW_PROPERTIES
? LOG_DEBUG
: LOG_ERR
,
1995 "Unit %s could not be found.", unit
);
1997 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
1998 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
1999 if (show_mode
== SYSTEMCTL_SHOW_HELP
)
2008 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
2009 print_status_info(bus
, &info
, ellipsized
);
2011 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
2012 return EXIT_PROGRAM_NOT_RUNNING
;
2014 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
2016 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
2017 show_unit_help(&info
);
2021 r
= sd_bus_message_rewind(reply
, true);
2023 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
2025 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_print_flags
, &found_properties
);
2027 return bus_log_parse_error(r
);
2029 STRV_FOREACH(pp
, arg_properties
)
2030 if (!set_contains(found_properties
, *pp
))
2031 log_debug("Property %s does not exist.", *pp
);
2036 static int get_unit_dbus_path_by_pid(
2041 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2042 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2046 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitByPID", &error
, &reply
, "u", pid
);
2048 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
2050 r
= sd_bus_message_read(reply
, "o", &u
);
2052 return bus_log_parse_error(r
);
2062 static int show_all(
2067 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2068 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2072 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
2076 pager_open(arg_pager_flags
);
2080 typesafe_qsort(unit_infos
, c
, unit_info_compare
);
2082 for (const UnitInfo
*u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
2083 _cleanup_free_
char *p
= NULL
;
2085 p
= unit_dbus_path_from_name(u
->id
);
2089 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
2092 if (r
> 0 && ret
== 0)
2099 static int show_system_status(sd_bus
*bus
) {
2100 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2101 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
2102 static const char prefix
[] = " ";
2103 _cleanup_free_
char *hn
= NULL
;
2104 const char *on
, *off
;
2108 hn
= gethostname_malloc();
2112 r
= bus_map_all_properties(
2114 "org.freedesktop.systemd1",
2115 "/org/freedesktop/systemd1",
2116 machine_info_property_map
,
2122 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
2124 if (streq_ptr(mi
.state
, "degraded")) {
2125 on
= ansi_highlight_red();
2126 off
= ansi_normal();
2127 } else if (streq_ptr(mi
.state
, "running")) {
2128 on
= ansi_highlight_green();
2129 off
= ansi_normal();
2131 on
= ansi_highlight_yellow();
2132 off
= ansi_normal();
2135 printf("%s%s%s %s\n", on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
, arg_host
?: hn
);
2137 printf(" State: %s%s%s\n",
2138 on
, strna(mi
.state
), off
);
2140 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
2141 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
2143 printf(" Since: %s; %s\n",
2144 FORMAT_TIMESTAMP_STYLE(mi
.timestamp
, arg_timestamp_style
),
2145 FORMAT_TIMESTAMP_RELATIVE(mi
.timestamp
));
2147 printf(" CGroup: %s\n", empty_to_root(mi
.control_group
));
2149 c
= LESS_BY(columns(), strlen(prefix
));
2151 r
= unit_show_processes(bus
, SPECIAL_ROOT_SLICE
, mi
.control_group
, prefix
, c
, get_output_flags(), &error
);
2152 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) /* Compatibility for really old systemd versions */
2153 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
2155 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
2156 arg_host
?: hn
, bus_error_message(&error
, r
));
2161 int verb_show(int argc
, char *argv
[], void *userdata
) {
2162 bool new_line
= false, ellipsized
= false;
2163 SystemctlShowMode show_mode
;
2169 show_mode
= systemctl_show_mode_from_string(argv
[0]);
2171 return log_error_errno(show_mode
, "Invalid argument '%s'.", argv
[0]);
2173 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1)
2174 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2175 "'help' command expects one or more unit names.\n"
2176 "(Alternatively, help for systemctl itself may be shown with --help)");
2178 r
= acquire_bus(BUS_MANAGER
, &bus
);
2182 pager_open(arg_pager_flags
);
2184 /* If no argument is specified inspect the manager itself */
2185 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
2186 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
2188 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
2190 show_system_status(bus
);
2194 ret
= show_all(bus
, &new_line
, &ellipsized
);
2196 _cleanup_free_
char **patterns
= NULL
;
2199 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2200 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
2203 if (safe_atou32(*name
, &id
) < 0) {
2204 if (strv_push(&patterns
, *name
) < 0)
2208 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
2209 /* Interpret as job id */
2210 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
2214 /* Interpret as PID */
2215 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
2221 r
= unit_name_from_dbus_path(path
, &unit
);
2226 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
2229 if (r
> 0 && ret
== 0)
2233 if (!strv_isempty(patterns
)) {
2234 _cleanup_strv_free_
char **names
= NULL
;
2236 r
= expand_unit_names(bus
, patterns
, NULL
, &names
, NULL
);
2238 return log_error_errno(r
, "Failed to expand names: %m");
2240 r
= maybe_extend_with_unit_dependencies(bus
, &names
);
2244 STRV_FOREACH(name
, names
) {
2245 _cleanup_free_
char *path
= NULL
;
2247 path
= unit_dbus_path_from_name(*name
);
2251 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
2254 if (r
> 0 && ret
== 0)
2260 if (ellipsized
&& !arg_quiet
)
2261 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");