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
;
314 /* This shows pretty information about a unit. See print_property() for a low-level property
317 format_active_state(i
->active_state
, &active_on
, &active_off
);
319 const SpecialGlyph glyph
= unit_active_state_to_glyph(unit_active_state_from_string(i
->active_state
));
321 printf("%s%s%s %s", active_on
, special_glyph(glyph
), active_off
, strna(i
->id
));
323 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
324 printf(" - %s", i
->description
);
329 printf(" Follows: unit currently follows state of %s\n", i
->following
);
331 if (STRPTR_IN_SET(i
->load_state
, "error", "not-found", "bad-setting")) {
332 on
= ansi_highlight_red();
337 path
= i
->source_path
?: i
->fragment_path
;
338 if (path
&& terminal_urlify_path(path
, NULL
, &formatted_path
) >= 0)
339 path
= formatted_path
;
341 if (!isempty(i
->load_error
))
342 printf(" Loaded: %s%s%s (Reason: %s)\n",
343 on
, strna(i
->load_state
), off
, i
->load_error
);
344 else if (path
&& !isempty(i
->unit_file_state
)) {
345 bool show_preset
= !isempty(i
->unit_file_preset
) &&
346 show_preset_for_state(unit_file_state_from_string(i
->unit_file_state
));
348 printf(" Loaded: %s%s%s (%s; %s%s%s)\n",
349 on
, strna(i
->load_state
), off
,
352 show_preset
? "; vendor preset: " : "",
353 show_preset
? i
->unit_file_preset
: "");
356 printf(" Loaded: %s%s%s (%s)\n",
357 on
, strna(i
->load_state
), off
, path
);
359 printf(" Loaded: %s%s%s\n",
360 on
, strna(i
->load_state
), off
);
363 printf(" Transient: yes\n");
365 if (!strv_isempty(i
->dropin_paths
)) {
366 _cleanup_free_
char *dir
= NULL
;
369 STRV_FOREACH(dropin
, i
->dropin_paths
) {
370 _cleanup_free_
char *dropin_formatted
= NULL
;
379 dir
= dirname_malloc(*dropin
);
387 special_glyph(SPECIAL_GLYPH_TREE_RIGHT
));
390 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
392 if (terminal_urlify_path(*dropin
, basename(*dropin
), &dropin_formatted
) >= 0)
393 df
= dropin_formatted
;
397 printf("%s%s", df
, last
? "\n" : ", ");
401 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
403 printf(" Active: %s%s (%s)%s",
404 active_on
, strna(i
->active_state
), ss
, active_off
);
406 printf(" Active: %s%s%s",
407 active_on
, strna(i
->active_state
), active_off
);
409 fs
= !isempty(i
->freezer_state
) && !streq(i
->freezer_state
, "running") ? i
->freezer_state
: NULL
;
411 printf(" %s(%s)%s", ansi_highlight_yellow(), fs
, ansi_normal());
413 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
414 printf(" (Result: %s)", i
->result
);
416 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
417 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
418 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
419 i
->active_exit_timestamp
;
421 if (timestamp_is_set(timestamp
)) {
422 printf(" since %s; %s\n",
423 FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
),
424 FORMAT_TIMESTAMP_RELATIVE(timestamp
));
425 if (streq_ptr(i
->active_state
, "active") && i
->runtime_max_sec
< USEC_INFINITY
) {
426 usec_t until_timestamp
;
428 until_timestamp
= usec_add(timestamp
, i
->runtime_max_sec
);
429 printf(" Until: %s; %s\n",
430 FORMAT_TIMESTAMP_STYLE(until_timestamp
, arg_timestamp_style
),
431 FORMAT_TIMESTAMP_RELATIVE(until_timestamp
));
434 if (!endswith(i
->id
, ".target") &&
435 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") &&
436 timestamp_is_set(i
->active_enter_timestamp
) &&
437 timestamp_is_set(i
->active_exit_timestamp
) &&
438 i
->active_exit_timestamp
>= i
->active_enter_timestamp
) {
442 duration
= i
->active_exit_timestamp
- i
->active_enter_timestamp
;
443 printf(" Duration: %s\n", FORMAT_TIMESPAN(duration
, MSEC_PER_SEC
));
448 STRV_FOREACH(t
, i
->triggered_by
) {
449 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
451 (void) get_state_one_unit(bus
, *t
, &state
);
452 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
454 printf("%s %s%s%s %s\n",
455 t
== i
->triggered_by
? "TriggeredBy:" : " ",
456 on
, special_glyph(unit_active_state_to_glyph(state
)), off
,
460 if (endswith(i
->id
, ".timer")) {
461 dual_timestamp nw
, next
= {i
->next_elapse_real
, i
->next_elapse_monotonic
};
464 dual_timestamp_get(&nw
);
465 next_elapse
= calc_next_elapse(&nw
, &next
);
467 if (timestamp_is_set(next_elapse
))
468 printf(" Trigger: %s; %s\n",
469 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
),
470 FORMAT_TIMESTAMP_RELATIVE(next_elapse
));
472 printf(" Trigger: n/a\n");
475 STRV_FOREACH(t
, i
->triggers
) {
476 UnitActiveState state
= _UNIT_ACTIVE_STATE_INVALID
;
478 (void) get_state_one_unit(bus
, *t
, &state
);
479 format_active_state(unit_active_state_to_string(state
), &on
, &off
);
481 printf("%s %s%s%s %s\n",
482 t
== i
->triggers
? " Triggers:" : " ",
483 on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
,
487 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
490 printf(" Condition: start %scondition failed%s at %s; %s\n",
491 ansi_highlight_yellow(), ansi_normal(),
492 FORMAT_TIMESTAMP_STYLE(i
->condition_timestamp
, arg_timestamp_style
),
493 FORMAT_TIMESTAMP_RELATIVE(i
->condition_timestamp
));
495 LIST_FOREACH(conditions
, c
, i
->conditions
)
499 LIST_FOREACH(conditions
, c
, i
->conditions
)
501 printf(" %s %s=%s%s%s was not met\n",
502 --n
? special_glyph(SPECIAL_GLYPH_TREE_BRANCH
) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT
),
504 c
->trigger
? "|" : "",
505 c
->negate
? "!" : "",
509 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
510 printf(" Assert: start %sassertion failed%s at %s; %s\n",
511 ansi_highlight_red(), ansi_normal(),
512 FORMAT_TIMESTAMP_STYLE(i
->assert_timestamp
, arg_timestamp_style
),
513 FORMAT_TIMESTAMP_RELATIVE(i
->assert_timestamp
));
514 if (i
->failed_assert_trigger
)
515 printf(" none of the trigger assertions were met\n");
516 else if (i
->failed_assert
)
517 printf(" %s=%s%s was not met\n",
519 i
->failed_assert_negate
? "!" : "",
520 i
->failed_assert_parameter
);
524 printf(" Device: %s\n", i
->sysfs_path
);
526 printf(" Where: %s\n", i
->where
);
528 printf(" What: %s\n", i
->what
);
530 STRV_FOREACH(t
, i
->documentation
) {
531 _cleanup_free_
char *formatted
= NULL
;
534 if (terminal_urlify(*t
, NULL
, &formatted
) >= 0)
539 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", q
);
542 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
543 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
546 printf(" Accepted: %u; Connected: %u;", i
->n_accepted
, i
->n_connections
);
548 printf(" Refused: %u", i
->n_refused
);
552 LIST_FOREACH(exec
, p
, i
->exec
) {
553 _cleanup_free_
char *argv
= NULL
;
556 /* Only show exited processes here */
560 /* Don't print ExecXYZEx= properties here since it will appear as a
561 * duplicate of the non-Ex= variant. */
562 if (endswith(p
->name
, "Ex"))
565 argv
= strv_join(p
->argv
, " ");
566 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
568 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
570 on
= ansi_highlight_red();
575 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
577 if (p
->code
== CLD_EXITED
) {
580 printf("status=%i", p
->status
);
582 c
= exit_status_to_string(p
->status
, EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
587 printf("signal=%s", signal_to_string(p
->status
));
589 printf(")%s\n", off
);
591 if (i
->main_pid
== p
->pid
&&
592 i
->start_timestamp
== p
->start_timestamp
&&
593 i
->exit_timestamp
== p
->start_timestamp
)
594 /* Let's not show this twice */
597 if (p
->pid
== i
->control_pid
)
601 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
602 if (i
->main_pid
> 0) {
603 printf(" Main PID: "PID_FMT
, i
->main_pid
);
607 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
608 _cleanup_free_
char *comm
= NULL
;
610 (void) get_process_comm(i
->main_pid
, &comm
);
612 printf(" (%s)", comm
);
615 } else if (i
->exit_code
> 0) {
616 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
618 if (i
->exit_code
== CLD_EXITED
) {
621 printf("status=%i", i
->exit_status
);
623 c
= exit_status_to_string(i
->exit_status
,
624 EXIT_STATUS_LIBC
| EXIT_STATUS_SYSTEMD
);
629 printf("signal=%s", signal_to_string(i
->exit_status
));
634 if (i
->control_pid
> 0) {
635 _cleanup_free_
char *c
= NULL
;
638 fputs("; Control PID: ", stdout
);
640 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
642 printf(PID_FMT
, i
->control_pid
);
644 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
645 (void) get_process_comm(i
->control_pid
, &c
);
655 printf(" Status: \"%s\"\n", i
->status_text
);
656 if (i
->status_errno
> 0)
657 printf(" Error: %i (%s)\n", i
->status_errno
, strerror_safe(i
->status_errno
));
659 if (i
->ip_ingress_bytes
!= UINT64_MAX
&& i
->ip_egress_bytes
!= UINT64_MAX
)
660 printf(" IP: %s in, %s out\n",
661 FORMAT_BYTES(i
->ip_ingress_bytes
),
662 FORMAT_BYTES(i
->ip_egress_bytes
));
664 if (i
->io_read_bytes
!= UINT64_MAX
&& i
->io_write_bytes
!= UINT64_MAX
)
665 printf(" IO: %s read, %s written\n",
666 FORMAT_BYTES(i
->io_read_bytes
),
667 FORMAT_BYTES(i
->io_write_bytes
));
669 if (i
->tasks_current
!= UINT64_MAX
) {
670 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
672 if (i
->tasks_max
!= UINT64_MAX
)
673 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
678 if (i
->memory_current
!= UINT64_MAX
) {
679 printf(" Memory: %s", FORMAT_BYTES(i
->memory_current
));
681 if (i
->memory_min
> 0 || i
->memory_low
> 0 ||
682 i
->memory_high
!= CGROUP_LIMIT_MAX
|| i
->memory_max
!= CGROUP_LIMIT_MAX
||
683 i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
684 i
->memory_available
!= CGROUP_LIMIT_MAX
||
685 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
686 const char *prefix
= "";
689 if (i
->memory_min
> 0) {
690 printf("%smin: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_min
));
693 if (i
->memory_low
> 0) {
694 printf("%slow: %s", prefix
, FORMAT_BYTES_CGROUP_PROTECTION(i
->memory_low
));
697 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
698 printf("%shigh: %s", prefix
, FORMAT_BYTES(i
->memory_high
));
701 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
702 printf("%smax: %s", prefix
, FORMAT_BYTES(i
->memory_max
));
705 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
706 printf("%sswap max: %s", prefix
, FORMAT_BYTES(i
->memory_swap_max
));
709 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
710 printf("%slimit: %s", prefix
, FORMAT_BYTES(i
->memory_limit
));
713 if (i
->memory_available
!= CGROUP_LIMIT_MAX
) {
714 printf("%savailable: %s", prefix
, FORMAT_BYTES(i
->memory_available
));
722 if (i
->cpu_usage_nsec
!= UINT64_MAX
)
723 printf(" CPU: %s\n", FORMAT_TIMESPAN(i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
725 if (i
->control_group
) {
726 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
727 static const char prefix
[] = " ";
730 printf(" CGroup: %s\n", i
->control_group
);
732 c
= LESS_BY(columns(), strlen(prefix
));
734 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
735 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
739 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
742 extra
[k
++] = i
->main_pid
;
744 if (i
->control_pid
> 0)
745 extra
[k
++] = i
->control_pid
;
747 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
749 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
750 i
->id
, bus_error_message(&error
, r
));
753 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
754 show_journal_by_unit(
760 i
->inactive_exit_timestamp_monotonic
,
763 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
764 SD_JOURNAL_LOCAL_ONLY
,
765 arg_scope
== UNIT_FILE_SYSTEM
,
768 if (i
->need_daemon_reload
)
769 warn_unit_file_changed(i
->id
);
772 static void show_unit_help(UnitStatusInfo
*i
) {
775 if (!i
->documentation
) {
776 log_info("Documentation for %s not known.", i
->id
);
780 STRV_FOREACH(p
, i
->documentation
)
781 if (startswith(*p
, "man:"))
782 show_man_page(*p
+ 4, false);
784 log_info("Can't show: %s", *p
);
787 static int map_main_pid(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
788 UnitStatusInfo
*i
= userdata
;
792 r
= sd_bus_message_read(m
, "u", &u
);
796 i
->main_pid
= (pid_t
) u
;
802 static int map_load_error(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
803 const char *message
, **p
= userdata
;
806 r
= sd_bus_message_read(m
, "(ss)", NULL
, &message
);
810 if (!isempty(message
))
816 static int map_listen(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
817 const char *type
, *path
;
818 char ***p
= userdata
;
821 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
825 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
827 r
= strv_extend(p
, type
);
831 r
= strv_extend(p
, path
);
838 r
= sd_bus_message_exit_container(m
);
845 static int map_conditions(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
846 UnitStatusInfo
*i
= userdata
;
847 const char *cond
, *param
;
852 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
856 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
857 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
859 c
= new(UnitCondition
, 1);
863 *c
= (UnitCondition
) {
864 .name
= strdup(cond
),
865 .param
= strdup(param
),
871 if (!c
->name
|| !c
->param
)
874 LIST_PREPEND(conditions
, i
->conditions
, TAKE_PTR(c
));
879 r
= sd_bus_message_exit_container(m
);
886 static int map_asserts(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
887 UnitStatusInfo
*i
= userdata
;
888 const char *cond
, *param
;
893 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
897 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
898 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
899 i
->failed_assert
= cond
;
900 i
->failed_assert_trigger
= trigger
;
901 i
->failed_assert_negate
= negate
;
902 i
->failed_assert_parameter
= param
;
908 r
= sd_bus_message_exit_container(m
);
915 static int map_exec(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
916 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
917 ExecStatusInfo
*last
;
918 UnitStatusInfo
*i
= userdata
;
919 bool is_ex_prop
= endswith(member
, "Ex");
922 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
926 info
= new0(ExecStatusInfo
, 1);
930 LIST_FIND_TAIL(exec
, i
->exec
, last
);
932 while ((r
= exec_status_info_deserialize(m
, info
, is_ex_prop
)) > 0) {
934 info
->name
= strdup(member
);
938 LIST_INSERT_AFTER(exec
, i
->exec
, last
, info
);
941 info
= new0(ExecStatusInfo
, 1);
948 r
= sd_bus_message_exit_container(m
);
955 static int print_property(const char *name
, const char *expected_value
, sd_bus_message
*m
, BusPrintPropertyFlags flags
) {
957 const char *contents
;
963 /* This is a low-level property printer, see print_status_info() for the nicer output */
965 r
= sd_bus_message_peek_type(m
, &bus_type
, &contents
);
971 case SD_BUS_TYPE_INT32
:
972 if (endswith(name
, "ActionExitStatus")) {
975 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
979 if (i
>= 0 && i
<= 255)
980 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIi32
, i
);
981 else if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
))
982 bus_print_property_value(name
, expected_value
, flags
, "[not set]");
985 } else if (streq(name
, "NUMAPolicy")) {
988 r
= sd_bus_message_read_basic(m
, bus_type
, &i
);
992 bus_print_property_valuef(name
, expected_value
, flags
, "%s", strna(mpol_to_string(i
)));
998 case SD_BUS_TYPE_UINT64
:
999 if (endswith(name
, "Timestamp")) {
1002 r
= sd_bus_message_read_basic(m
, bus_type
, ×tamp
);
1006 bus_print_property_value(name
, expected_value
, flags
, FORMAT_TIMESTAMP_STYLE(timestamp
, arg_timestamp_style
));
1012 case SD_BUS_TYPE_STRUCT
:
1014 if (contents
[0] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
1017 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
1019 return bus_log_parse_error(r
);
1022 bus_print_property_valuef(name
, expected_value
, flags
, "%"PRIu32
, u
);
1024 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1028 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
1031 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
1033 return bus_log_parse_error(r
);
1035 bus_print_property_value(name
, expected_value
, flags
, s
);
1039 } else if (contents
[0] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
1040 const char *a
= NULL
, *b
= NULL
;
1042 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
1044 return bus_log_parse_error(r
);
1046 if (!isempty(a
) || !isempty(b
))
1047 bus_print_property_valuef(name
, expected_value
, flags
, "%s \"%s\"", strempty(a
), strempty(b
));
1049 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1053 } else if (STR_IN_SET(name
, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces", "RestrictFileSystems")) {
1054 _cleanup_strv_free_
char **l
= NULL
;
1057 r
= sd_bus_message_enter_container(m
, 'r', "bas");
1059 return bus_log_parse_error(r
);
1061 r
= sd_bus_message_read(m
, "b", &allow_list
);
1063 return bus_log_parse_error(r
);
1065 r
= sd_bus_message_read_strv(m
, &l
);
1067 return bus_log_parse_error(r
);
1069 r
= sd_bus_message_exit_container(m
);
1071 return bus_log_parse_error(r
);
1073 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || allow_list
|| !strv_isempty(l
)) {
1076 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1077 fputs(name
, stdout
);
1084 STRV_FOREACH(i
, l
) {
1092 fputc('\n', stdout
);
1097 } else if (STR_IN_SET(name
, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
1101 r
= sd_bus_message_read(m
, "(bs)", &ignore
, &s
);
1103 return bus_log_parse_error(r
);
1106 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s", ignore
? "-" : "", s
);
1108 bus_print_property_value(name
, expected_value
, flags
, NULL
);
1112 } else if (endswith(name
, "ExitStatus") && streq(contents
, "aiai")) {
1113 const int32_t *status
, *signal
;
1114 size_t n_status
, n_signal
;
1116 r
= sd_bus_message_enter_container(m
, 'r', "aiai");
1118 return bus_log_parse_error(r
);
1120 r
= sd_bus_message_read_array(m
, 'i', (const void **) &status
, &n_status
);
1122 return bus_log_parse_error(r
);
1124 r
= sd_bus_message_read_array(m
, 'i', (const void **) &signal
, &n_signal
);
1126 return bus_log_parse_error(r
);
1128 r
= sd_bus_message_exit_container(m
);
1130 return bus_log_parse_error(r
);
1132 n_status
/= sizeof(int32_t);
1133 n_signal
/= sizeof(int32_t);
1135 if (FLAGS_SET(flags
, BUS_PRINT_PROPERTY_SHOW_EMPTY
) || n_status
> 0 || n_signal
> 0) {
1138 if (!FLAGS_SET(flags
, BUS_PRINT_PROPERTY_ONLY_VALUE
)) {
1139 fputs(name
, stdout
);
1143 for (size_t i
= 0; i
< n_status
; i
++) {
1149 printf("%"PRIi32
, status
[i
]);
1152 for (size_t i
= 0; i
< n_signal
; i
++) {
1155 str
= signal_to_string((int) signal
[i
]);
1165 printf("%"PRIi32
, status
[i
]);
1168 fputc('\n', stdout
);
1175 case SD_BUS_TYPE_ARRAY
:
1177 if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
1181 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
1183 return bus_log_parse_error(r
);
1185 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
1186 bus_print_property_valuef(name
, expected_value
, flags
, "%s (ignore_errors=%s)", path
, yes_no(ignore
));
1188 return bus_log_parse_error(r
);
1190 r
= sd_bus_message_exit_container(m
);
1192 return bus_log_parse_error(r
);
1196 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
1197 const char *type
, *path
;
1199 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1201 return bus_log_parse_error(r
);
1203 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1204 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1206 return bus_log_parse_error(r
);
1208 r
= sd_bus_message_exit_container(m
);
1210 return bus_log_parse_error(r
);
1214 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
1215 const char *type
, *path
;
1217 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1219 return bus_log_parse_error(r
);
1221 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
1222 bus_print_property_valuef(name
, expected_value
, flags
, "%s (%s)", path
, type
);
1224 return bus_log_parse_error(r
);
1226 r
= sd_bus_message_exit_container(m
);
1228 return bus_log_parse_error(r
);
1232 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersMonotonic")) {
1234 uint64_t v
, next_elapse
;
1236 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
1238 return bus_log_parse_error(r
);
1240 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &v
, &next_elapse
)) > 0)
1241 bus_print_property_valuef(name
, expected_value
, flags
,
1242 "{ %s=%s ; next_elapse=%s }",
1244 strna(FORMAT_TIMESPAN(v
, 0)),
1245 strna(FORMAT_TIMESPAN(next_elapse
, 0)));
1247 return bus_log_parse_error(r
);
1249 r
= sd_bus_message_exit_container(m
);
1251 return bus_log_parse_error(r
);
1255 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "TimersCalendar")) {
1256 const char *base
, *spec
;
1257 uint64_t next_elapse
;
1259 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1261 return bus_log_parse_error(r
);
1263 while ((r
= sd_bus_message_read(m
, "(sst)", &base
, &spec
, &next_elapse
)) > 0)
1264 bus_print_property_valuef(name
, expected_value
, flags
,
1265 "{ %s=%s ; next_elapse=%s }", base
, spec
,
1266 FORMAT_TIMESTAMP_STYLE(next_elapse
, arg_timestamp_style
));
1268 return bus_log_parse_error(r
);
1270 r
= sd_bus_message_exit_container(m
);
1272 return bus_log_parse_error(r
);
1276 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
1277 ExecStatusInfo info
= {};
1278 bool is_ex_prop
= endswith(name
, "Ex");
1280 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, is_ex_prop
? "(sasasttttuii)" : "(sasbttttuii)");
1282 return bus_log_parse_error(r
);
1284 while ((r
= exec_status_info_deserialize(m
, &info
, is_ex_prop
)) > 0) {
1285 _cleanup_strv_free_
char **optv
= NULL
;
1286 _cleanup_free_
char *tt
= NULL
, *o
= NULL
;
1288 tt
= strv_join(info
.argv
, " ");
1291 r
= exec_command_flags_to_strv(info
.flags
, &optv
);
1293 return log_error_errno(r
, "Failed to convert ExecCommandFlags to strv: %m");
1295 o
= strv_join(optv
, " ");
1297 bus_print_property_valuef(name
, expected_value
, flags
,
1298 "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1302 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1303 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1305 sigchld_code_to_string(info
.code
),
1307 info
.code
== CLD_EXITED
? "" : "/",
1308 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1310 bus_print_property_valuef(name
, expected_value
, flags
,
1311 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
1314 yes_no(info
.ignore
),
1315 strna(FORMAT_TIMESTAMP_STYLE(info
.start_timestamp
, arg_timestamp_style
)),
1316 strna(FORMAT_TIMESTAMP_STYLE(info
.exit_timestamp
, arg_timestamp_style
)),
1318 sigchld_code_to_string(info
.code
),
1320 info
.code
== CLD_EXITED
? "" : "/",
1321 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
1324 strv_free(info
.argv
);
1328 r
= sd_bus_message_exit_container(m
);
1330 return bus_log_parse_error(r
);
1334 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
1335 const char *path
, *rwm
;
1337 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1339 return bus_log_parse_error(r
);
1341 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
1342 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
), strna(rwm
));
1344 return bus_log_parse_error(r
);
1346 r
= sd_bus_message_exit_container(m
);
1348 return bus_log_parse_error(r
);
1352 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1353 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
1357 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1359 return bus_log_parse_error(r
);
1361 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
1362 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), weight
);
1364 return bus_log_parse_error(r
);
1366 r
= sd_bus_message_exit_container(m
);
1368 return bus_log_parse_error(r
);
1372 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1373 (cgroup_io_limit_type_from_string(name
) >= 0 ||
1374 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
1378 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1380 return bus_log_parse_error(r
);
1382 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
1383 bus_print_property_valuef(name
, expected_value
, flags
, "%s %"PRIu64
, strna(path
), bandwidth
);
1385 return bus_log_parse_error(r
);
1387 r
= sd_bus_message_exit_container(m
);
1389 return bus_log_parse_error(r
);
1393 } else if (contents
[0] == SD_BUS_TYPE_STRUCT_BEGIN
&&
1394 streq(name
, "IODeviceLatencyTargetUSec")) {
1398 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
1400 return bus_log_parse_error(r
);
1402 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &target
)) > 0)
1403 bus_print_property_valuef(name
, expected_value
, flags
, "%s %s", strna(path
),
1404 FORMAT_TIMESPAN(target
, 1));
1406 return bus_log_parse_error(r
);
1408 r
= sd_bus_message_exit_container(m
);
1410 return bus_log_parse_error(r
);
1414 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&& STR_IN_SET(name
, "StandardInputData", "RootHashSignature")) {
1415 _cleanup_free_
char *h
= NULL
;
1420 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
1422 return bus_log_parse_error(r
);
1424 n
= base64mem(p
, sz
, &h
);
1428 bus_print_property_value(name
, expected_value
, flags
, h
);
1432 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1433 _cleanup_free_
char *addresses
= NULL
;
1435 r
= sd_bus_message_enter_container(m
, 'a', "(iayu)");
1437 return bus_log_parse_error(r
);
1440 _cleanup_free_
char *str
= NULL
;
1446 r
= sd_bus_message_enter_container(m
, 'r', "iayu");
1448 return bus_log_parse_error(r
);
1452 r
= sd_bus_message_read(m
, "i", &family
);
1454 return bus_log_parse_error(r
);
1456 r
= sd_bus_message_read_array(m
, 'y', &ap
, &an
);
1458 return bus_log_parse_error(r
);
1460 r
= sd_bus_message_read(m
, "u", &prefixlen
);
1462 return bus_log_parse_error(r
);
1464 r
= sd_bus_message_exit_container(m
);
1466 return bus_log_parse_error(r
);
1468 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1471 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1474 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
) * 8)
1477 if (in_addr_prefix_to_string(family
, (const union in_addr_union
*) ap
, prefixlen
, &str
) < 0)
1480 if (!strextend_with_separator(&addresses
, " ", str
))
1484 r
= sd_bus_message_exit_container(m
);
1486 return bus_log_parse_error(r
);
1488 bus_print_property_value(name
, expected_value
, flags
, addresses
);
1492 } else if (STR_IN_SET(name
, "BindPaths", "BindReadOnlyPaths")) {
1493 _cleanup_free_
char *paths
= NULL
;
1494 const char *source
, *dest
;
1498 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssbt)");
1500 return bus_log_parse_error(r
);
1502 while ((r
= sd_bus_message_read(m
, "(ssbt)", &source
, &dest
, &ignore_enoent
, &rbind
)) > 0) {
1503 _cleanup_free_
char *str
= NULL
;
1505 if (isempty(source
))
1508 if (asprintf(&str
, "%s%s%s%s%s",
1509 ignore_enoent
? "-" : "",
1511 isempty(dest
) ? "" : ":",
1513 rbind
== MS_REC
? ":rbind" : "") < 0)
1516 if (!strextend_with_separator(&paths
, " ", str
))
1520 return bus_log_parse_error(r
);
1522 r
= sd_bus_message_exit_container(m
);
1524 return bus_log_parse_error(r
);
1526 bus_print_property_value(name
, expected_value
, flags
, paths
);
1530 } else if (streq(name
, "TemporaryFileSystem")) {
1531 _cleanup_free_
char *paths
= NULL
;
1532 const char *target
, *option
;
1534 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1536 return bus_log_parse_error(r
);
1538 while ((r
= sd_bus_message_read(m
, "(ss)", &target
, &option
)) > 0) {
1539 _cleanup_free_
char *str
= NULL
;
1541 if (isempty(target
))
1544 if (asprintf(&str
, "%s%s%s", target
, isempty(option
) ? "" : ":", strempty(option
)) < 0)
1547 if (!strextend_with_separator(&paths
, " ", str
))
1551 return bus_log_parse_error(r
);
1553 r
= sd_bus_message_exit_container(m
);
1555 return bus_log_parse_error(r
);
1557 bus_print_property_value(name
, expected_value
, flags
, paths
);
1561 } else if (streq(name
, "LogExtraFields")) {
1562 _cleanup_free_
char *fields
= NULL
;
1566 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "ay");
1568 return bus_log_parse_error(r
);
1570 while ((r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
)) > 0) {
1571 _cleanup_free_
char *str
= NULL
;
1574 if (memchr(p
, 0, sz
))
1577 eq
= memchr(p
, '=', sz
);
1581 if (!journal_field_valid(p
, eq
- (const char*) p
, false))
1584 str
= malloc(sz
+ 1);
1591 if (!utf8_is_valid(str
))
1594 if (!strextend_with_separator(&fields
, " ", str
))
1598 return bus_log_parse_error(r
);
1600 r
= sd_bus_message_exit_container(m
);
1602 return bus_log_parse_error(r
);
1604 bus_print_property_value(name
, expected_value
, flags
, fields
);
1607 } else if (contents
[0] == SD_BUS_TYPE_BYTE
&&
1609 "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes",
1610 "EffectiveCPUs", "EffectiveMemoryNodes")) {
1612 _cleanup_free_
char *affinity
= NULL
;
1613 _cleanup_(cpu_set_reset
) CPUSet set
= {};
1617 r
= sd_bus_message_read_array(m
, 'y', &a
, &n
);
1619 return bus_log_parse_error(r
);
1621 r
= cpu_set_from_dbus(a
, n
, &set
);
1623 return log_error_errno(r
, "Failed to deserialize %s: %m", name
);
1625 affinity
= cpu_set_to_range_string(&set
);
1629 bus_print_property_value(name
, expected_value
, flags
, affinity
);
1632 } else if (streq(name
, "MountImages")) {
1633 _cleanup_free_
char *paths
= NULL
;
1635 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ssba(ss))");
1637 return bus_log_parse_error(r
);
1640 _cleanup_free_
char *str
= NULL
;
1641 const char *source
, *destination
, *partition
, *mount_options
;
1644 r
= sd_bus_message_enter_container(m
, 'r', "ssba(ss)");
1646 return bus_log_parse_error(r
);
1650 r
= sd_bus_message_read(m
, "ssb", &source
, &destination
, &ignore_enoent
);
1652 return bus_log_parse_error(r
);
1654 str
= strjoin(ignore_enoent
? "-" : "",
1661 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1663 return bus_log_parse_error(r
);
1665 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1666 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1669 return bus_log_parse_error(r
);
1671 if (!strextend_with_separator(&paths
, " ", str
))
1674 r
= sd_bus_message_exit_container(m
);
1676 return bus_log_parse_error(r
);
1678 r
= sd_bus_message_exit_container(m
);
1680 return bus_log_parse_error(r
);
1683 r
= sd_bus_message_exit_container(m
);
1685 return bus_log_parse_error(r
);
1687 bus_print_property_value(name
, expected_value
, flags
, paths
);
1691 } else if (streq(name
, "ExtensionImages")) {
1692 _cleanup_free_
char *paths
= NULL
;
1694 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sba(ss))");
1696 return bus_log_parse_error(r
);
1699 _cleanup_free_
char *str
= NULL
;
1700 const char *source
, *partition
, *mount_options
;
1703 r
= sd_bus_message_enter_container(m
, 'r', "sba(ss)");
1705 return bus_log_parse_error(r
);
1709 r
= sd_bus_message_read(m
, "sb", &source
, &ignore_enoent
);
1711 return bus_log_parse_error(r
);
1713 str
= strjoin(ignore_enoent
? "-" : "", source
);
1717 r
= sd_bus_message_enter_container(m
, 'a', "(ss)");
1719 return bus_log_parse_error(r
);
1721 while ((r
= sd_bus_message_read(m
, "(ss)", &partition
, &mount_options
)) > 0)
1722 if (!strextend_with_separator(&str
, ":", partition
, mount_options
))
1725 return bus_log_parse_error(r
);
1727 if (!strextend_with_separator(&paths
, " ", str
))
1730 r
= sd_bus_message_exit_container(m
);
1732 return bus_log_parse_error(r
);
1734 r
= sd_bus_message_exit_container(m
);
1736 return bus_log_parse_error(r
);
1739 r
= sd_bus_message_exit_container(m
);
1741 return bus_log_parse_error(r
);
1743 bus_print_property_value(name
, expected_value
, flags
, paths
);
1747 } else if (streq(name
, "BPFProgram")) {
1750 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
1752 return bus_log_parse_error(r
);
1754 while ((r
= sd_bus_message_read(m
, "(ss)", &a
, &p
)) > 0)
1755 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1757 return bus_log_parse_error(r
);
1759 r
= sd_bus_message_exit_container(m
);
1761 return bus_log_parse_error(r
);
1764 } else if (STR_IN_SET(name
, "SocketBindAllow", "SocketBindDeny")) {
1765 uint16_t nr_ports
, port_min
;
1766 int32_t af
, ip_protocol
;
1768 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(iiqq)");
1770 return bus_log_parse_error(r
);
1771 while ((r
= sd_bus_message_read(m
, "(iiqq)", &af
, &ip_protocol
, &nr_ports
, &port_min
)) > 0) {
1772 const char *family
, *colon1
, *protocol
= "", *colon2
= "";
1774 family
= strempty(af_to_ipv4_ipv6(af
));
1775 colon1
= isempty(family
) ? "" : ":";
1777 if (ip_protocol
!= 0) {
1778 protocol
= ip_protocol_to_tcp_udp(ip_protocol
);
1783 bus_print_property_valuef(name
, expected_value
, flags
, "%s%s%s%sany",
1784 family
, colon1
, protocol
, colon2
);
1785 else if (nr_ports
== 1)
1786 bus_print_property_valuef(
1787 name
, expected_value
, flags
, "%s%s%s%s%hu",
1788 family
, colon1
, protocol
, colon2
, port_min
);
1790 bus_print_property_valuef(
1791 name
, expected_value
, flags
, "%s%s%s%s%hu-%hu",
1792 family
, colon1
, protocol
, colon2
, port_min
,
1793 (uint16_t) (port_min
+ nr_ports
- 1));
1796 return bus_log_parse_error(r
);
1798 r
= sd_bus_message_exit_container(m
);
1800 return bus_log_parse_error(r
);
1803 } else if (STR_IN_SET(name
, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
1805 uint64_t symlink_flags
;
1807 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sst)");
1809 return bus_log_parse_error(r
);
1811 while ((r
= sd_bus_message_read(m
, "(sst)", &a
, &p
, &symlink_flags
)) > 0)
1812 bus_print_property_valuef(name
, expected_value
, flags
, "%s:%s", a
, p
);
1814 return bus_log_parse_error(r
);
1816 r
= sd_bus_message_exit_container(m
);
1818 return bus_log_parse_error(r
);
1829 typedef enum SystemctlShowMode
{
1830 SYSTEMCTL_SHOW_PROPERTIES
,
1831 SYSTEMCTL_SHOW_STATUS
,
1832 SYSTEMCTL_SHOW_HELP
,
1833 _SYSTEMCTL_SHOW_MODE_MAX
,
1834 _SYSTEMCTL_SHOW_MODE_INVALID
= -EINVAL
,
1835 } SystemctlShowMode
;
1837 static const char* const systemctl_show_mode_table
[_SYSTEMCTL_SHOW_MODE_MAX
] = {
1838 [SYSTEMCTL_SHOW_PROPERTIES
] = "show",
1839 [SYSTEMCTL_SHOW_STATUS
] = "status",
1840 [SYSTEMCTL_SHOW_HELP
] = "help",
1843 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode
, SystemctlShowMode
);
1845 static int show_one(
1849 SystemctlShowMode show_mode
,
1853 static const struct bus_properties_map property_map
[] = {
1854 { "LoadState", "s", NULL
, offsetof(UnitStatusInfo
, load_state
) },
1855 { "ActiveState", "s", NULL
, offsetof(UnitStatusInfo
, active_state
) },
1856 { "FreezerState", "s", NULL
, offsetof(UnitStatusInfo
, freezer_state
) },
1857 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1860 { "Id", "s", NULL
, offsetof(UnitStatusInfo
, id
) },
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 { "SubState", "s", NULL
, offsetof(UnitStatusInfo
, sub_state
) },
1865 { "UnitFileState", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_state
) },
1866 { "UnitFilePreset", "s", NULL
, offsetof(UnitStatusInfo
, unit_file_preset
) },
1867 { "Description", "s", NULL
, offsetof(UnitStatusInfo
, description
) },
1868 { "Following", "s", NULL
, offsetof(UnitStatusInfo
, following
) },
1869 { "Documentation", "as", NULL
, offsetof(UnitStatusInfo
, documentation
) },
1870 { "FragmentPath", "s", NULL
, offsetof(UnitStatusInfo
, fragment_path
) },
1871 { "SourcePath", "s", NULL
, offsetof(UnitStatusInfo
, source_path
) },
1872 { "ControlGroup", "s", NULL
, offsetof(UnitStatusInfo
, control_group
) },
1873 { "DropInPaths", "as", NULL
, offsetof(UnitStatusInfo
, dropin_paths
) },
1874 { "LoadError", "(ss)", map_load_error
, offsetof(UnitStatusInfo
, load_error
) },
1875 { "Result", "s", NULL
, offsetof(UnitStatusInfo
, result
) },
1876 { "TriggeredBy", "as", NULL
, offsetof(UnitStatusInfo
, triggered_by
) },
1877 { "Triggers", "as", NULL
, offsetof(UnitStatusInfo
, triggers
) },
1878 { "InactiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp
) },
1879 { "InactiveExitTimestampMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, inactive_exit_timestamp_monotonic
) },
1880 { "ActiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_enter_timestamp
) },
1881 { "ActiveExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, active_exit_timestamp
) },
1882 { "RuntimeMaxUSec", "t", NULL
, offsetof(UnitStatusInfo
, runtime_max_sec
) },
1883 { "InactiveEnterTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, inactive_enter_timestamp
) },
1884 { "NeedDaemonReload", "b", NULL
, offsetof(UnitStatusInfo
, need_daemon_reload
) },
1885 { "Transient", "b", NULL
, offsetof(UnitStatusInfo
, transient
) },
1886 { "ExecMainPID", "u", NULL
, offsetof(UnitStatusInfo
, main_pid
) },
1887 { "MainPID", "u", map_main_pid
, 0 },
1888 { "ControlPID", "u", NULL
, offsetof(UnitStatusInfo
, control_pid
) },
1889 { "StatusText", "s", NULL
, offsetof(UnitStatusInfo
, status_text
) },
1890 { "PIDFile", "s", NULL
, offsetof(UnitStatusInfo
, pid_file
) },
1891 { "StatusErrno", "i", NULL
, offsetof(UnitStatusInfo
, status_errno
) },
1892 { "ExecMainStartTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, start_timestamp
) },
1893 { "ExecMainExitTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, exit_timestamp
) },
1894 { "ExecMainCode", "i", NULL
, offsetof(UnitStatusInfo
, exit_code
) },
1895 { "ExecMainStatus", "i", NULL
, offsetof(UnitStatusInfo
, exit_status
) },
1896 { "LogNamespace", "s", NULL
, offsetof(UnitStatusInfo
, log_namespace
) },
1897 { "ConditionTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, condition_timestamp
) },
1898 { "ConditionResult", "b", NULL
, offsetof(UnitStatusInfo
, condition_result
) },
1899 { "Conditions", "a(sbbsi)", map_conditions
, 0 },
1900 { "AssertTimestamp", "t", NULL
, offsetof(UnitStatusInfo
, assert_timestamp
) },
1901 { "AssertResult", "b", NULL
, offsetof(UnitStatusInfo
, assert_result
) },
1902 { "Asserts", "a(sbbsi)", map_asserts
, 0 },
1903 { "NextElapseUSecRealtime", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_real
) },
1904 { "NextElapseUSecMonotonic", "t", NULL
, offsetof(UnitStatusInfo
, next_elapse_monotonic
) },
1905 { "NAccepted", "u", NULL
, offsetof(UnitStatusInfo
, n_accepted
) },
1906 { "NConnections", "u", NULL
, offsetof(UnitStatusInfo
, n_connections
) },
1907 { "NRefused", "u", NULL
, offsetof(UnitStatusInfo
, n_refused
) },
1908 { "Accept", "b", NULL
, offsetof(UnitStatusInfo
, accept
) },
1909 { "Listen", "a(ss)", map_listen
, offsetof(UnitStatusInfo
, listen
) },
1910 { "SysFSPath", "s", NULL
, offsetof(UnitStatusInfo
, sysfs_path
) },
1911 { "Where", "s", NULL
, offsetof(UnitStatusInfo
, where
) },
1912 { "What", "s", NULL
, offsetof(UnitStatusInfo
, what
) },
1913 { "MemoryCurrent", "t", NULL
, offsetof(UnitStatusInfo
, memory_current
) },
1914 { "MemoryAvailable", "t", NULL
, offsetof(UnitStatusInfo
, memory_available
) },
1915 { "DefaultMemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_min
) },
1916 { "DefaultMemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, default_memory_low
) },
1917 { "MemoryMin", "t", NULL
, offsetof(UnitStatusInfo
, memory_min
) },
1918 { "MemoryLow", "t", NULL
, offsetof(UnitStatusInfo
, memory_low
) },
1919 { "MemoryHigh", "t", NULL
, offsetof(UnitStatusInfo
, memory_high
) },
1920 { "MemoryMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_max
) },
1921 { "MemorySwapMax", "t", NULL
, offsetof(UnitStatusInfo
, memory_swap_max
) },
1922 { "MemoryLimit", "t", NULL
, offsetof(UnitStatusInfo
, memory_limit
) },
1923 { "CPUUsageNSec", "t", NULL
, offsetof(UnitStatusInfo
, cpu_usage_nsec
) },
1924 { "TasksCurrent", "t", NULL
, offsetof(UnitStatusInfo
, tasks_current
) },
1925 { "TasksMax", "t", NULL
, offsetof(UnitStatusInfo
, tasks_max
) },
1926 { "IPIngressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_ingress_bytes
) },
1927 { "IPEgressBytes", "t", NULL
, offsetof(UnitStatusInfo
, ip_egress_bytes
) },
1928 { "IOReadBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_read_bytes
) },
1929 { "IOWriteBytes", "t", NULL
, offsetof(UnitStatusInfo
, io_write_bytes
) },
1930 { "ExecCondition", "a(sasbttttuii)", map_exec
, 0 },
1931 { "ExecConditionEx", "a(sasasttttuii)", map_exec
, 0 },
1932 { "ExecStartPre", "a(sasbttttuii)", map_exec
, 0 },
1933 { "ExecStartPreEx", "a(sasasttttuii)", map_exec
, 0 },
1934 { "ExecStart", "a(sasbttttuii)", map_exec
, 0 },
1935 { "ExecStartEx", "a(sasasttttuii)", map_exec
, 0 },
1936 { "ExecStartPost", "a(sasbttttuii)", map_exec
, 0 },
1937 { "ExecStartPostEx", "a(sasasttttuii)", map_exec
, 0 },
1938 { "ExecReload", "a(sasbttttuii)", map_exec
, 0 },
1939 { "ExecReloadEx", "a(sasasttttuii)", map_exec
, 0 },
1940 { "ExecStopPre", "a(sasbttttuii)", map_exec
, 0 },
1941 { "ExecStop", "a(sasbttttuii)", map_exec
, 0 },
1942 { "ExecStopEx", "a(sasasttttuii)", map_exec
, 0 },
1943 { "ExecStopPost", "a(sasbttttuii)", map_exec
, 0 },
1944 { "ExecStopPostEx", "a(sasasttttuii)", map_exec
, 0 },
1948 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1949 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1950 _cleanup_set_free_ Set
*found_properties
= NULL
;
1951 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
1952 .memory_current
= UINT64_MAX
,
1953 .memory_high
= CGROUP_LIMIT_MAX
,
1954 .memory_max
= CGROUP_LIMIT_MAX
,
1955 .memory_swap_max
= CGROUP_LIMIT_MAX
,
1956 .memory_limit
= UINT64_MAX
,
1957 .memory_available
= CGROUP_LIMIT_MAX
,
1958 .cpu_usage_nsec
= UINT64_MAX
,
1959 .tasks_current
= UINT64_MAX
,
1960 .tasks_max
= UINT64_MAX
,
1961 .ip_ingress_bytes
= UINT64_MAX
,
1962 .ip_egress_bytes
= UINT64_MAX
,
1963 .io_read_bytes
= UINT64_MAX
,
1964 .io_write_bytes
= UINT64_MAX
,
1971 log_debug("Showing one %s", path
);
1973 r
= bus_map_all_properties(
1975 "org.freedesktop.systemd1",
1977 show_mode
== SYSTEMCTL_SHOW_STATUS
? status_map
: property_map
,
1978 BUS_MAP_BOOLEAN_AS_BOOL
,
1983 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
1985 if (unit
&& streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
1986 log_full(show_mode
== SYSTEMCTL_SHOW_PROPERTIES
? LOG_DEBUG
: LOG_ERR
,
1987 "Unit %s could not be found.", unit
);
1989 if (show_mode
== SYSTEMCTL_SHOW_STATUS
)
1990 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
1991 if (show_mode
== SYSTEMCTL_SHOW_HELP
)
2000 if (show_mode
== SYSTEMCTL_SHOW_STATUS
) {
2001 print_status_info(bus
, &info
, ellipsized
);
2003 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
2004 return EXIT_PROGRAM_NOT_RUNNING
;
2006 return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
2008 } else if (show_mode
== SYSTEMCTL_SHOW_HELP
) {
2009 show_unit_help(&info
);
2013 r
= sd_bus_message_rewind(reply
, true);
2015 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
2017 r
= bus_message_print_all_properties(reply
, print_property
, arg_properties
, arg_print_flags
, &found_properties
);
2019 return bus_log_parse_error(r
);
2021 STRV_FOREACH(pp
, arg_properties
)
2022 if (!set_contains(found_properties
, *pp
))
2023 log_debug("Property %s does not exist.", *pp
);
2028 static int get_unit_dbus_path_by_pid(
2033 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2034 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2038 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitByPID", &error
, &reply
, "u", pid
);
2040 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
2042 r
= sd_bus_message_read(reply
, "o", &u
);
2044 return bus_log_parse_error(r
);
2054 static int show_all(
2059 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2060 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
2064 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
2068 pager_open(arg_pager_flags
);
2072 typesafe_qsort(unit_infos
, c
, unit_info_compare
);
2074 for (const UnitInfo
*u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
2075 _cleanup_free_
char *p
= NULL
;
2077 p
= unit_dbus_path_from_name(u
->id
);
2081 r
= show_one(bus
, p
, u
->id
, SYSTEMCTL_SHOW_STATUS
, new_line
, ellipsized
);
2084 if (r
> 0 && ret
== 0)
2091 static int show_system_status(sd_bus
*bus
) {
2092 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2093 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
2094 static const char prefix
[] = " ";
2095 _cleanup_free_
char *hn
= NULL
;
2096 const char *on
, *off
;
2100 hn
= gethostname_malloc();
2104 r
= bus_map_all_properties(
2106 "org.freedesktop.systemd1",
2107 "/org/freedesktop/systemd1",
2108 machine_info_property_map
,
2114 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
2116 if (streq_ptr(mi
.state
, "degraded")) {
2117 on
= ansi_highlight_red();
2118 off
= ansi_normal();
2119 } else if (streq_ptr(mi
.state
, "running")) {
2120 on
= ansi_highlight_green();
2121 off
= ansi_normal();
2123 on
= ansi_highlight_yellow();
2124 off
= ansi_normal();
2127 printf("%s%s%s %s\n", on
, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE
), off
, arg_host
?: hn
);
2129 printf(" State: %s%s%s\n",
2130 on
, strna(mi
.state
), off
);
2132 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
2133 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
2135 printf(" Since: %s; %s\n",
2136 FORMAT_TIMESTAMP_STYLE(mi
.timestamp
, arg_timestamp_style
),
2137 FORMAT_TIMESTAMP_RELATIVE(mi
.timestamp
));
2139 printf(" CGroup: %s\n", empty_to_root(mi
.control_group
));
2141 c
= LESS_BY(columns(), strlen(prefix
));
2143 r
= unit_show_processes(bus
, SPECIAL_ROOT_SLICE
, mi
.control_group
, prefix
, c
, get_output_flags(), &error
);
2144 if (r
== -EBADR
&& arg_transport
== BUS_TRANSPORT_LOCAL
) /* Compatibility for really old systemd versions */
2145 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
2147 log_warning_errno(r
, "Failed to dump process list for '%s', ignoring: %s",
2148 arg_host
?: hn
, bus_error_message(&error
, r
));
2153 int verb_show(int argc
, char *argv
[], void *userdata
) {
2154 bool new_line
= false, ellipsized
= false;
2155 SystemctlShowMode show_mode
;
2161 show_mode
= systemctl_show_mode_from_string(argv
[0]);
2163 return log_error_errno(show_mode
, "Invalid argument '%s'.", argv
[0]);
2165 if (show_mode
== SYSTEMCTL_SHOW_HELP
&& argc
<= 1)
2166 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
2167 "'help' command expects one or more unit names.\n"
2168 "(Alternatively, help for systemctl itself may be shown with --help)");
2170 r
= acquire_bus(BUS_MANAGER
, &bus
);
2174 pager_open(arg_pager_flags
);
2176 /* If no argument is specified inspect the manager itself */
2177 if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
&& argc
<= 1)
2178 return show_one(bus
, "/org/freedesktop/systemd1", NULL
, show_mode
, &new_line
, &ellipsized
);
2180 if (show_mode
== SYSTEMCTL_SHOW_STATUS
&& argc
<= 1) {
2182 show_system_status(bus
);
2186 ret
= show_all(bus
, &new_line
, &ellipsized
);
2188 _cleanup_free_
char **patterns
= NULL
;
2190 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2191 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
2194 if (safe_atou32(*name
, &id
) < 0) {
2195 if (strv_push(&patterns
, *name
) < 0)
2199 } else if (show_mode
== SYSTEMCTL_SHOW_PROPERTIES
) {
2200 /* Interpret as job id */
2201 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
2205 /* Interpret as PID */
2206 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
2212 r
= unit_name_from_dbus_path(path
, &unit
);
2217 r
= show_one(bus
, path
, unit
, show_mode
, &new_line
, &ellipsized
);
2220 if (r
> 0 && ret
== 0)
2224 if (!strv_isempty(patterns
)) {
2225 _cleanup_strv_free_
char **names
= NULL
;
2227 r
= expand_unit_names(bus
, patterns
, NULL
, &names
, NULL
);
2229 return log_error_errno(r
, "Failed to expand names: %m");
2231 r
= maybe_extend_with_unit_dependencies(bus
, &names
);
2235 STRV_FOREACH(name
, names
) {
2236 _cleanup_free_
char *path
= NULL
;
2238 path
= unit_dbus_path_from_name(*name
);
2242 r
= show_one(bus
, path
, *name
, show_mode
, &new_line
, &ellipsized
);
2245 if (r
> 0 && ret
== 0)
2251 if (ellipsized
&& !arg_quiet
)
2252 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");