Coverage Report

Created: 2022-04-19 08:24

/src/systemd/src/systemctl/systemctl-show.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include <sys/mount.h>
4
5
#include "af-list.h"
6
#include "bus-error.h"
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"
22
#include "list.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"
32
#include "special.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"
41
#include "utf8.h"
42
43
0
static OutputFlags get_output_flags(void) {
44
0
        return
45
0
                FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
46
0
                (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
47
0
                colors_enabled() * OUTPUT_COLOR |
48
0
                !arg_quiet * OUTPUT_WARN_CUTOFF;
49
0
}
50
51
typedef struct ExecStatusInfo {
52
        char *name;
53
54
        char *path;
55
        char **argv;
56
57
        bool ignore;
58
59
        usec_t start_timestamp;
60
        usec_t exit_timestamp;
61
        pid_t pid;
62
        int code;
63
        int status;
64
65
        ExecCommandFlags flags;
66
67
        LIST_FIELDS(struct ExecStatusInfo, exec);
68
} ExecStatusInfo;
69
70
0
static void exec_status_info_free(ExecStatusInfo *i) {
71
0
        assert(i);
72
73
0
        free(i->name);
74
0
        free(i->path);
75
0
        strv_free(i->argv);
76
0
        free(i);
77
0
}
78
79
0
static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i, bool is_ex_prop) {
80
0
        _cleanup_strv_free_ char **ex_opts = NULL;
81
0
        uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
82
0
        const char *path;
83
0
        uint32_t pid;
84
0
        int32_t code, status;
85
0
        int ignore, r;
86
87
0
        assert(m);
88
0
        assert(i);
89
90
0
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, is_ex_prop ? "sasasttttuii" : "sasbttttuii");
91
0
        if (r < 0)
92
0
                return bus_log_parse_error(r);
93
0
        if (r == 0)
94
0
                return 0;
95
96
0
        r = sd_bus_message_read(m, "s", &path);
97
0
        if (r < 0)
98
0
                return bus_log_parse_error(r);
99
100
0
        i->path = strdup(path);
101
0
        if (!i->path)
102
0
                return log_oom();
103
104
0
        r = sd_bus_message_read_strv(m, &i->argv);
105
0
        if (r < 0)
106
0
                return bus_log_parse_error(r);
107
108
0
        r = is_ex_prop ? sd_bus_message_read_strv(m, &ex_opts) : sd_bus_message_read(m, "b", &ignore);
109
0
        if (r < 0)
110
0
                return bus_log_parse_error(r);
111
112
0
        r = sd_bus_message_read(m,
113
0
                                "ttttuii",
114
0
                                &start_timestamp, &start_timestamp_monotonic,
115
0
                                &exit_timestamp, &exit_timestamp_monotonic,
116
0
                                &pid,
117
0
                                &code, &status);
118
0
        if (r < 0)
119
0
                return bus_log_parse_error(r);
120
121
0
        if (is_ex_prop) {
122
0
                r = exec_command_flags_from_strv(ex_opts, &i->flags);
123
0
                if (r < 0)
124
0
                        return log_error_errno(r, "Failed to convert strv to ExecCommandFlags: %m");
125
126
0
                i->ignore = FLAGS_SET(i->flags, EXEC_COMMAND_IGNORE_FAILURE);
127
0
        } else
128
0
                i->ignore = ignore;
129
130
0
        i->start_timestamp = (usec_t) start_timestamp;
131
0
        i->exit_timestamp = (usec_t) exit_timestamp;
132
0
        i->pid = (pid_t) pid;
133
0
        i->code = code;
134
0
        i->status = status;
135
136
0
        r = sd_bus_message_exit_container(m);
137
0
        if (r < 0)
138
0
                return bus_log_parse_error(r);
139
140
0
        return 1;
141
0
}
142
143
typedef struct UnitCondition {
144
        char *name;
145
        char *param;
146
        bool trigger;
147
        bool negate;
148
        int tristate;
149
150
        LIST_FIELDS(struct UnitCondition, conditions);
151
} UnitCondition;
152
153
0
static UnitCondition* unit_condition_free(UnitCondition *c) {
154
0
        if (!c)
155
0
                return NULL;
156
157
0
        free(c->name);
158
0
        free(c->param);
159
0
        return mfree(c);
160
0
}
161
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
162
163
typedef struct UnitStatusInfo {
164
        const char *id;
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;
171
172
        const char *description;
173
        const char *following;
174
175
        char **documentation;
176
177
        const char *fragment_path;
178
        const char *source_path;
179
        const char *control_group;
180
181
        char **dropin_paths;
182
183
        char **triggered_by;
184
        char **triggers;
185
186
        const char *load_error;
187
        const char *result;
188
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;
194
195
        uint64_t runtime_max_sec;
196
197
        bool need_daemon_reload;
198
        bool transient;
199
200
        /* Service */
201
        pid_t main_pid;
202
        pid_t control_pid;
203
        const char *status_text;
204
        const char *pid_file;
205
        bool running:1;
206
        int status_errno;
207
208
        usec_t start_timestamp;
209
        usec_t exit_timestamp;
210
211
        int exit_code, exit_status;
212
213
        const char *log_namespace;
214
215
        usec_t condition_timestamp;
216
        bool condition_result;
217
        LIST_HEAD(UnitCondition, conditions);
218
219
        usec_t assert_timestamp;
220
        bool assert_result;
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;
227
228
        /* Socket */
229
        unsigned n_accepted;
230
        unsigned n_connections;
231
        unsigned n_refused;
232
        bool accept;
233
234
        /* Pairs of type, path */
235
        char **listen;
236
237
        /* Device */
238
        const char *sysfs_path;
239
240
        /* Mount, Automount */
241
        const char *where;
242
243
        /* Swap */
244
        const char *what;
245
246
        /* CGroup */
247
        uint64_t memory_current;
248
        uint64_t memory_min;
249
        uint64_t memory_low;
250
        uint64_t memory_high;
251
        uint64_t memory_max;
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;
257
        uint64_t tasks_max;
258
        uint64_t ip_ingress_bytes;
259
        uint64_t ip_egress_bytes;
260
        uint64_t io_read_bytes;
261
        uint64_t io_write_bytes;
262
263
        uint64_t default_memory_min;
264
        uint64_t default_memory_low;
265
266
        LIST_HEAD(ExecStatusInfo, exec);
267
} UnitStatusInfo;
268
269
0
static void unit_status_info_free(UnitStatusInfo *info) {
270
0
        ExecStatusInfo *p;
271
0
        UnitCondition *c;
272
273
0
        strv_free(info->documentation);
274
0
        strv_free(info->dropin_paths);
275
0
        strv_free(info->triggered_by);
276
0
        strv_free(info->triggers);
277
0
        strv_free(info->listen);
278
279
0
        while ((c = info->conditions)) {
280
0
                LIST_REMOVE(conditions, info->conditions, c);
281
0
                unit_condition_free(c);
282
0
        }
283
284
0
        while ((p = info->exec)) {
285
0
                LIST_REMOVE(exec, info->exec, p);
286
0
                exec_status_info_free(p);
287
0
        }
288
0
}
289
290
0
static void format_active_state(const char *active_state, const char **active_on, const char **active_off) {
291
0
        if (streq_ptr(active_state, "failed")) {
292
0
                *active_on = ansi_highlight_red();
293
0
                *active_off = ansi_normal();
294
0
        } else if (STRPTR_IN_SET(active_state, "active", "reloading")) {
295
0
                *active_on = ansi_highlight_green();
296
0
                *active_off = ansi_normal();
297
0
        } else
298
0
                *active_on = *active_off = "";
299
0
}
300
301
0
static void format_enable_state(const char *enable_state, const char **enable_on, const char **enable_off) {
302
0
        assert(enable_on);
303
0
        assert(enable_off);
304
305
0
        if (streq_ptr(enable_state, "disabled")) {
306
0
                *enable_on = ansi_highlight_yellow();
307
0
                *enable_off = ansi_normal();
308
0
        } else if (streq_ptr(enable_state, "enabled")) {
309
0
                *enable_on = ansi_highlight_green();
310
0
                *enable_off = ansi_normal();
311
0
        } else
312
0
                *enable_on = *enable_off = "";
313
0
}
314
315
static void print_status_info(
316
                sd_bus *bus,
317
                UnitStatusInfo *i,
318
0
                bool *ellipsized) {
319
320
0
        const char *active_on, *active_off, *on, *off, *ss, *fs;
321
0
        const char *enable_on, *enable_off, *enable_vendor_on, *enable_vendor_off;
322
0
        _cleanup_free_ char *formatted_path = NULL;
323
0
        usec_t timestamp;
324
0
        const char *path;
325
0
        int r;
326
327
0
        assert(i);
328
329
        /* This shows pretty information about a unit. See print_property() for a low-level property
330
         * printer */
331
332
0
        format_active_state(i->active_state, &active_on, &active_off);
333
0
        format_enable_state(i->unit_file_state, &enable_on, &enable_off);
334
0
        format_enable_state(i->unit_file_preset, &enable_vendor_on, &enable_vendor_off);
335
336
0
        const SpecialGlyph glyph = unit_active_state_to_glyph(unit_active_state_from_string(i->active_state));
337
338
0
        printf("%s%s%s %s", active_on, special_glyph(glyph), active_off, strna(i->id));
339
340
0
        if (i->description && !streq_ptr(i->id, i->description))
341
0
                printf(" - %s", i->description);
342
343
0
        printf("\n");
344
345
0
        if (i->following)
346
0
                printf("    Follows: unit currently follows state of %s\n", i->following);
347
348
0
        if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) {
349
0
                on = ansi_highlight_red();
350
0
                off = ansi_normal();
351
0
        } else
352
0
                on = off = "";
353
354
0
        path = i->source_path ?: i->fragment_path;
355
0
        if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0)
356
0
                path = formatted_path;
357
358
0
        if (!isempty(i->load_error))
359
0
                printf("     Loaded: %s%s%s (Reason: %s)\n",
360
0
                       on, strna(i->load_state), off, i->load_error);
361
0
        else if (path && !isempty(i->unit_file_state)) {
362
0
                bool show_preset = !isempty(i->unit_file_preset) &&
363
0
                        show_preset_for_state(unit_file_state_from_string(i->unit_file_state));
364
365
0
                printf("     Loaded: %s%s%s (%s; %s%s%s%s%s%s%s)\n",
366
0
                       on, strna(i->load_state), off,
367
0
                       path,
368
0
                       enable_on, i->unit_file_state, enable_off,
369
0
                       show_preset ? "; vendor preset: " : "",
370
0
                       enable_vendor_on, show_preset ? i->unit_file_preset : "", enable_vendor_off);
371
372
0
        } else if (path)
373
0
                printf("     Loaded: %s%s%s (%s)\n",
374
0
                       on, strna(i->load_state), off, path);
375
0
        else
376
0
                printf("     Loaded: %s%s%s\n",
377
0
                       on, strna(i->load_state), off);
378
379
0
        if (i->transient)
380
0
                printf("  Transient: yes\n");
381
382
0
        if (!strv_isempty(i->dropin_paths)) {
383
0
                _cleanup_free_ char *dir = NULL;
384
0
                bool last = false;
385
386
0
                STRV_FOREACH(dropin, i->dropin_paths) {
387
0
                        _cleanup_free_ char *dropin_formatted = NULL;
388
0
                        const char *df;
389
390
0
                        if (!dir || last) {
391
0
                                printf(dir ? "             " :
392
0
                                             "    Drop-In: ");
393
394
0
                                dir = mfree(dir);
395
396
0
                                dir = dirname_malloc(*dropin);
397
0
                                if (!dir) {
398
0
                                        log_oom();
399
0
                                        return;
400
0
                                }
401
402
0
                                printf("%s\n"
403
0
                                       "             %s", dir,
404
0
                                       special_glyph(SPECIAL_GLYPH_TREE_RIGHT));
405
0
                        }
406
407
0
                        last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
408
409
0
                        if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0)
410
0
                                df = dropin_formatted;
411
0
                        else
412
0
                                df = *dropin;
413
414
0
                        printf("%s%s", df, last ? "\n" : ", ");
415
0
                }
416
0
        }
417
418
0
        ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
419
0
        if (ss)
420
0
                printf("     Active: %s%s (%s)%s",
421
0
                       active_on, strna(i->active_state), ss, active_off);
422
0
        else
423
0
                printf("     Active: %s%s%s",
424
0
                       active_on, strna(i->active_state), active_off);
425
426
0
        fs = !isempty(i->freezer_state) && !streq(i->freezer_state, "running") ? i->freezer_state : NULL;
427
0
        if (fs)
428
0
                printf(" %s(%s)%s", ansi_highlight_yellow(), fs, ansi_normal());
429
430
0
        if (!isempty(i->result) && !streq(i->result, "success"))
431
0
                printf(" (Result: %s)", i->result);
432
433
0
        timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
434
0
                    STRPTR_IN_SET(i->active_state, "inactive", "failed")  ? i->inactive_enter_timestamp :
435
0
                    STRPTR_IN_SET(i->active_state, "activating")          ? i->inactive_exit_timestamp :
436
0
                                                                            i->active_exit_timestamp;
437
438
0
        if (timestamp_is_set(timestamp)) {
439
0
                printf(" since %s; %s\n",
440
0
                       FORMAT_TIMESTAMP_STYLE(timestamp, arg_timestamp_style),
441
0
                       FORMAT_TIMESTAMP_RELATIVE(timestamp));
442
0
                if (streq_ptr(i->active_state, "active") && i->runtime_max_sec < USEC_INFINITY) {
443
0
                        usec_t until_timestamp;
444
445
0
                        until_timestamp = usec_add(timestamp, i->runtime_max_sec);
446
0
                        printf("      Until: %s; %s\n",
447
0
                               FORMAT_TIMESTAMP_STYLE(until_timestamp, arg_timestamp_style),
448
0
                               FORMAT_TIMESTAMP_RELATIVE(until_timestamp));
449
0
                }
450
451
0
                if (!endswith(i->id, ".target") &&
452
0
                        STRPTR_IN_SET(i->active_state, "inactive", "failed") &&
453
0
                        timestamp_is_set(i->active_enter_timestamp) &&
454
0
                        timestamp_is_set(i->active_exit_timestamp) &&
455
0
                        i->active_exit_timestamp >= i->active_enter_timestamp) {
456
457
0
                        usec_t duration;
458
459
0
                        duration = i->active_exit_timestamp - i->active_enter_timestamp;
460
0
                        printf("   Duration: %s\n", FORMAT_TIMESPAN(duration, MSEC_PER_SEC));
461
0
                }
462
0
        } else
463
0
                printf("\n");
464
465
0
        STRV_FOREACH(t, i->triggered_by) {
466
0
                UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
467
468
0
                (void) get_state_one_unit(bus, *t, &state);
469
0
                format_active_state(unit_active_state_to_string(state), &on, &off);
470
471
0
                printf("%s %s%s%s %s\n",
472
0
                       t == i->triggered_by ? "TriggeredBy:" : "            ",
473
0
                       on, special_glyph(unit_active_state_to_glyph(state)), off,
474
0
                       *t);
475
0
        }
476
477
0
        if (endswith(i->id, ".timer")) {
478
0
                dual_timestamp nw, next = {i->next_elapse_real, i->next_elapse_monotonic};
479
0
                usec_t next_elapse;
480
481
0
                dual_timestamp_get(&nw);
482
0
                next_elapse = calc_next_elapse(&nw, &next);
483
484
0
                if (timestamp_is_set(next_elapse))
485
0
                        printf("    Trigger: %s; %s\n",
486
0
                               FORMAT_TIMESTAMP_STYLE(next_elapse, arg_timestamp_style),
487
0
                               FORMAT_TIMESTAMP_RELATIVE(next_elapse));
488
0
                else
489
0
                        printf("    Trigger: n/a\n");
490
0
        }
491
492
0
        STRV_FOREACH(t, i->triggers) {
493
0
                UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
494
495
0
                (void) get_state_one_unit(bus, *t, &state);
496
0
                format_active_state(unit_active_state_to_string(state), &on, &off);
497
498
0
                printf("%s %s%s%s %s\n",
499
0
                       t == i->triggers ? "   Triggers:" : "            ",
500
0
                       on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off,
501
0
                       *t);
502
0
        }
503
504
0
        if (!i->condition_result && i->condition_timestamp > 0) {
505
0
                int n = 0;
506
507
0
                printf("  Condition: start %scondition failed%s at %s; %s\n",
508
0
                       ansi_highlight_yellow(), ansi_normal(),
509
0
                       FORMAT_TIMESTAMP_STYLE(i->condition_timestamp, arg_timestamp_style),
510
0
                       FORMAT_TIMESTAMP_RELATIVE(i->condition_timestamp));
511
512
0
                LIST_FOREACH(conditions, c, i->conditions)
513
0
                        if (c->tristate < 0)
514
0
                                n++;
515
516
0
                LIST_FOREACH(conditions, c, i->conditions)
517
0
                        if (c->tristate < 0)
518
0
                                printf("             %s %s=%s%s%s was not met\n",
519
0
                                       --n ? special_glyph(SPECIAL_GLYPH_TREE_BRANCH) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT),
520
0
                                       c->name,
521
0
                                       c->trigger ? "|" : "",
522
0
                                       c->negate ? "!" : "",
523
0
                                       c->param);
524
0
        }
525
526
0
        if (!i->assert_result && i->assert_timestamp > 0) {
527
0
                printf("     Assert: start %sassertion failed%s at %s; %s\n",
528
0
                       ansi_highlight_red(), ansi_normal(),
529
0
                       FORMAT_TIMESTAMP_STYLE(i->assert_timestamp, arg_timestamp_style),
530
0
                       FORMAT_TIMESTAMP_RELATIVE(i->assert_timestamp));
531
0
                if (i->failed_assert_trigger)
532
0
                        printf("             none of the trigger assertions were met\n");
533
0
                else if (i->failed_assert)
534
0
                        printf("             %s=%s%s was not met\n",
535
0
                               i->failed_assert,
536
0
                               i->failed_assert_negate ? "!" : "",
537
0
                               i->failed_assert_parameter);
538
0
        }
539
540
0
        if (i->sysfs_path)
541
0
                printf("     Device: %s\n", i->sysfs_path);
542
0
        if (i->where)
543
0
                printf("      Where: %s\n", i->where);
544
0
        if (i->what)
545
0
                printf("       What: %s\n", i->what);
546
547
0
        STRV_FOREACH(t, i->documentation) {
548
0
                _cleanup_free_ char *formatted = NULL;
549
0
                const char *q;
550
551
0
                if (terminal_urlify(*t, NULL, &formatted) >= 0)
552
0
                        q = formatted;
553
0
                else
554
0
                        q = *t;
555
556
0
                printf("   %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q);
557
0
        }
558
559
0
        STRV_FOREACH_PAIR(t, t2, i->listen)
560
0
                printf("   %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
561
562
0
        if (i->accept) {
563
0
                printf("   Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections);
564
0
                if (i->n_refused)
565
0
                        printf("   Refused: %u", i->n_refused);
566
0
                printf("\n");
567
0
        }
568
569
0
        LIST_FOREACH(exec, p, i->exec) {
570
0
                _cleanup_free_ char *argv = NULL;
571
0
                bool good;
572
573
                /* Only show exited processes here */
574
0
                if (p->code == 0)
575
0
                        continue;
576
577
                /* Don't print ExecXYZEx= properties here since it will appear as a
578
                 * duplicate of the non-Ex= variant. */
579
0
                if (endswith(p->name, "Ex"))
580
0
                        continue;
581
582
0
                argv = strv_join(p->argv, " ");
583
0
                printf("    Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
584
585
0
                good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
586
0
                if (!good) {
587
0
                        on = ansi_highlight_red();
588
0
                        off = ansi_normal();
589
0
                } else
590
0
                        on = off = "";
591
592
0
                printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
593
594
0
                if (p->code == CLD_EXITED) {
595
0
                        const char *c;
596
597
0
                        printf("status=%i", p->status);
598
599
0
                        c = exit_status_to_string(p->status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
600
0
                        if (c)
601
0
                                printf("/%s", c);
602
603
0
                } else
604
0
                        printf("signal=%s", signal_to_string(p->status));
605
606
0
                printf(")%s\n", off);
607
608
0
                if (i->main_pid == p->pid &&
609
0
                    i->start_timestamp == p->start_timestamp &&
610
0
                    i->exit_timestamp == p->start_timestamp)
611
                        /* Let's not show this twice */
612
0
                        i->main_pid = 0;
613
614
0
                if (p->pid == i->control_pid)
615
0
                        i->control_pid = 0;
616
0
        }
617
618
0
        if (i->main_pid > 0 || i->control_pid > 0) {
619
0
                if (i->main_pid > 0) {
620
0
                        printf("   Main PID: "PID_FMT, i->main_pid);
621
622
0
                        if (i->running) {
623
624
0
                                if (arg_transport == BUS_TRANSPORT_LOCAL) {
625
0
                                        _cleanup_free_ char *comm = NULL;
626
627
0
                                        (void) get_process_comm(i->main_pid, &comm);
628
0
                                        if (comm)
629
0
                                                printf(" (%s)", comm);
630
0
                                }
631
632
0
                        } else if (i->exit_code > 0) {
633
0
                                printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
634
635
0
                                if (i->exit_code == CLD_EXITED) {
636
0
                                        const char *c;
637
638
0
                                        printf("status=%i", i->exit_status);
639
640
0
                                        c = exit_status_to_string(i->exit_status,
641
0
                                                                  EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
642
0
                                        if (c)
643
0
                                                printf("/%s", c);
644
645
0
                                } else
646
0
                                        printf("signal=%s", signal_to_string(i->exit_status));
647
0
                                printf(")");
648
0
                        }
649
0
                }
650
651
0
                if (i->control_pid > 0) {
652
0
                        _cleanup_free_ char *c = NULL;
653
654
0
                        if (i->main_pid > 0)
655
0
                                fputs("; Control PID: ", stdout);
656
0
                        else
657
0
                                fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
658
659
0
                        printf(PID_FMT, i->control_pid);
660
661
0
                        if (arg_transport == BUS_TRANSPORT_LOCAL) {
662
0
                                (void) get_process_comm(i->control_pid, &c);
663
0
                                if (c)
664
0
                                        printf(" (%s)", c);
665
0
                        }
666
0
                }
667
668
0
                printf("\n");
669
0
        }
670
671
0
        if (i->status_text)
672
0
                printf("     Status: \"%s\"\n", i->status_text);
673
0
        if (i->status_errno > 0)
674
0
                printf("      Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno));
675
676
0
        if (i->ip_ingress_bytes != UINT64_MAX && i->ip_egress_bytes != UINT64_MAX)
677
0
                printf("         IP: %s in, %s out\n",
678
0
                       FORMAT_BYTES(i->ip_ingress_bytes),
679
0
                       FORMAT_BYTES(i->ip_egress_bytes));
680
681
0
        if (i->io_read_bytes != UINT64_MAX && i->io_write_bytes != UINT64_MAX)
682
0
                printf("         IO: %s read, %s written\n",
683
0
                        FORMAT_BYTES(i->io_read_bytes),
684
0
                        FORMAT_BYTES(i->io_write_bytes));
685
686
0
        if (i->tasks_current != UINT64_MAX) {
687
0
                printf("      Tasks: %" PRIu64, i->tasks_current);
688
689
0
                if (i->tasks_max != UINT64_MAX)
690
0
                        printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
691
0
                else
692
0
                        printf("\n");
693
0
        }
694
695
0
        if (i->memory_current != UINT64_MAX) {
696
0
                printf("     Memory: %s", FORMAT_BYTES(i->memory_current));
697
698
0
                if (i->memory_min > 0 || i->memory_low > 0 ||
699
0
                    i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
700
0
                    i->memory_swap_max != CGROUP_LIMIT_MAX ||
701
0
                    i->memory_available != CGROUP_LIMIT_MAX ||
702
0
                    i->memory_limit != CGROUP_LIMIT_MAX) {
703
0
                        const char *prefix = "";
704
705
0
                        printf(" (");
706
0
                        if (i->memory_min > 0) {
707
0
                                printf("%smin: %s", prefix, FORMAT_BYTES_CGROUP_PROTECTION(i->memory_min));
708
0
                                prefix = " ";
709
0
                        }
710
0
                        if (i->memory_low > 0) {
711
0
                                printf("%slow: %s", prefix, FORMAT_BYTES_CGROUP_PROTECTION(i->memory_low));
712
0
                                prefix = " ";
713
0
                        }
714
0
                        if (i->memory_high != CGROUP_LIMIT_MAX) {
715
0
                                printf("%shigh: %s", prefix, FORMAT_BYTES(i->memory_high));
716
0
                                prefix = " ";
717
0
                        }
718
0
                        if (i->memory_max != CGROUP_LIMIT_MAX) {
719
0
                                printf("%smax: %s", prefix, FORMAT_BYTES(i->memory_max));
720
0
                                prefix = " ";
721
0
                        }
722
0
                        if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
723
0
                                printf("%sswap max: %s", prefix, FORMAT_BYTES(i->memory_swap_max));
724
0
                                prefix = " ";
725
0
                        }
726
0
                        if (i->memory_limit != CGROUP_LIMIT_MAX) {
727
0
                                printf("%slimit: %s", prefix, FORMAT_BYTES(i->memory_limit));
728
0
                                prefix = " ";
729
0
                        }
730
0
                        if (i->memory_available != CGROUP_LIMIT_MAX) {
731
0
                                printf("%savailable: %s", prefix, FORMAT_BYTES(i->memory_available));
732
0
                                prefix = " ";
733
0
                        }
734
0
                        printf(")");
735
0
                }
736
0
                printf("\n");
737
0
        }
738
739
0
        if (i->cpu_usage_nsec != UINT64_MAX)
740
0
                printf("        CPU: %s\n", FORMAT_TIMESPAN(i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
741
742
0
        if (i->control_group) {
743
0
                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
744
0
                static const char prefix[] = "             ";
745
0
                unsigned c;
746
747
0
                printf("     CGroup: %s\n", i->control_group);
748
749
0
                c = LESS_BY(columns(), strlen(prefix));
750
751
0
                r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
752
0
                if (r == -EBADR && arg_transport == BUS_TRANSPORT_LOCAL) {
753
0
                        unsigned k = 0;
754
0
                        pid_t extra[2];
755
756
                        /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
757
758
0
                        if (i->main_pid > 0)
759
0
                                extra[k++] = i->main_pid;
760
761
0
                        if (i->control_pid > 0)
762
0
                                extra[k++] = i->control_pid;
763
764
0
                        show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
765
0
                } else if (r < 0)
766
0
                        log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
767
0
                                          i->id, bus_error_message(&error, r));
768
0
        }
769
770
0
        if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
771
0
                show_journal_by_unit(
772
0
                                stdout,
773
0
                                i->id,
774
0
                                i->log_namespace,
775
0
                                arg_output,
776
0
                                0,
777
0
                                i->inactive_exit_timestamp_monotonic,
778
0
                                arg_lines,
779
0
                                getuid(),
780
0
                                get_output_flags() | OUTPUT_BEGIN_NEWLINE,
781
0
                                SD_JOURNAL_LOCAL_ONLY,
782
0
                                arg_scope == LOOKUP_SCOPE_SYSTEM,
783
0
                                ellipsized);
784
785
0
        if (i->need_daemon_reload)
786
0
                warn_unit_file_changed(i->id);
787
0
}
788
789
0
static void show_unit_help(UnitStatusInfo *i) {
790
0
        assert(i);
791
792
0
        if (!i->documentation) {
793
0
                log_info("Documentation for %s not known.", i->id);
794
0
                return;
795
0
        }
796
797
0
        STRV_FOREACH(p, i->documentation)
798
0
                if (startswith(*p, "man:"))
799
0
                        show_man_page(*p + 4, false);
800
0
                else
801
0
                        log_info("Can't show: %s", *p);
802
0
}
803
804
0
static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
805
0
        UnitStatusInfo *i = userdata;
806
0
        uint32_t u;
807
0
        int r;
808
809
0
        r = sd_bus_message_read(m, "u", &u);
810
0
        if (r < 0)
811
0
                return r;
812
813
0
        i->main_pid = (pid_t) u;
814
0
        i->running = u > 0;
815
816
0
        return 0;
817
0
}
818
819
0
static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
820
0
        const char *message, **p = userdata;
821
0
        int r;
822
823
0
        r = sd_bus_message_read(m, "(ss)", NULL, &message);
824
0
        if (r < 0)
825
0
                return r;
826
827
0
        if (!isempty(message))
828
0
                *p = message;
829
830
0
        return 0;
831
0
}
832
833
0
static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
834
0
        const char *type, *path;
835
0
        char ***p = userdata;
836
0
        int r;
837
838
0
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
839
0
        if (r < 0)
840
0
                return r;
841
842
0
        while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
843
844
0
                r = strv_extend(p, type);
845
0
                if (r < 0)
846
0
                        return r;
847
848
0
                r = strv_extend(p, path);
849
0
                if (r < 0)
850
0
                        return r;
851
0
        }
852
0
        if (r < 0)
853
0
                return r;
854
855
0
        r = sd_bus_message_exit_container(m);
856
0
        if (r < 0)
857
0
                return r;
858
859
0
        return 0;
860
0
}
861
862
0
static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
863
0
        UnitStatusInfo *i = userdata;
864
0
        const char *cond, *param;
865
0
        int trigger, negate;
866
0
        int32_t state;
867
0
        int r;
868
869
0
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
870
0
        if (r < 0)
871
0
                return r;
872
873
0
        while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
874
0
                _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
875
876
0
                c = new(UnitCondition, 1);
877
0
                if (!c)
878
0
                        return -ENOMEM;
879
880
0
                *c = (UnitCondition) {
881
0
                        .name = strdup(cond),
882
0
                        .param = strdup(param),
883
0
                        .trigger = trigger,
884
0
                        .negate = negate,
885
0
                        .tristate = state,
886
0
                };
887
888
0
                if (!c->name || !c->param)
889
0
                        return -ENOMEM;
890
891
0
                LIST_PREPEND(conditions, i->conditions, TAKE_PTR(c));
892
0
        }
893
0
        if (r < 0)
894
0
                return r;
895
896
0
        r = sd_bus_message_exit_container(m);
897
0
        if (r < 0)
898
0
                return r;
899
900
0
        return 0;
901
0
}
902
903
0
static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
904
0
        UnitStatusInfo *i = userdata;
905
0
        const char *cond, *param;
906
0
        int trigger, negate;
907
0
        int32_t state;
908
0
        int r;
909
910
0
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
911
0
        if (r < 0)
912
0
                return r;
913
914
0
        while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
915
0
                if (state < 0 && (!trigger || !i->failed_assert)) {
916
0
                        i->failed_assert = cond;
917
0
                        i->failed_assert_trigger = trigger;
918
0
                        i->failed_assert_negate = negate;
919
0
                        i->failed_assert_parameter = param;
920
0
                }
921
0
        }
922
0
        if (r < 0)
923
0
                return r;
924
925
0
        r = sd_bus_message_exit_container(m);
926
0
        if (r < 0)
927
0
                return r;
928
929
0
        return 0;
930
0
}
931
932
0
static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
933
0
        _cleanup_free_ ExecStatusInfo *info = NULL;
934
0
        ExecStatusInfo *last;
935
0
        UnitStatusInfo *i = userdata;
936
0
        bool is_ex_prop = endswith(member, "Ex");
937
0
        int r;
938
939
0
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
940
0
        if (r < 0)
941
0
                return r;
942
943
0
        info = new0(ExecStatusInfo, 1);
944
0
        if (!info)
945
0
                return -ENOMEM;
946
947
0
        LIST_FIND_TAIL(exec, i->exec, last);
948
949
0
        while ((r = exec_status_info_deserialize(m, info, is_ex_prop)) > 0) {
950
951
0
                info->name = strdup(member);
952
0
                if (!info->name)
953
0
                        return -ENOMEM;
954
955
0
                LIST_INSERT_AFTER(exec, i->exec, last, info);
956
0
                last = info;
957
958
0
                info = new0(ExecStatusInfo, 1);
959
0
                if (!info)
960
0
                        return -ENOMEM;
961
0
        }
962
0
        if (r < 0)
963
0
                return r;
964
965
0
        r = sd_bus_message_exit_container(m);
966
0
        if (r < 0)
967
0
                return r;
968
969
0
        return 0;
970
0
}
971
972
0
static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
973
0
        char bus_type;
974
0
        const char *contents;
975
0
        int r;
976
977
0
        assert(name);
978
0
        assert(m);
979
980
        /* This is a low-level property printer, see print_status_info() for the nicer output */
981
982
0
        r = sd_bus_message_peek_type(m, &bus_type, &contents);
983
0
        if (r < 0)
984
0
                return r;
985
986
0
        switch (bus_type) {
987
988
0
        case SD_BUS_TYPE_INT32:
989
0
                if (endswith(name, "ActionExitStatus")) {
990
0
                        int32_t i;
991
992
0
                        r = sd_bus_message_read_basic(m, bus_type, &i);
993
0
                        if (r < 0)
994
0
                                return r;
995
996
0
                        if (i >= 0 && i <= 255)
997
0
                                bus_print_property_valuef(name, expected_value, flags, "%"PRIi32, i);
998
0
                        else if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY))
999
0
                                bus_print_property_value(name, expected_value, flags, "[not set]");
1000
1001
0
                        return 1;
1002
0
                } else if (streq(name, "NUMAPolicy")) {
1003
0
                        int32_t i;
1004
1005
0
                        r = sd_bus_message_read_basic(m, bus_type, &i);
1006
0
                        if (r < 0)
1007
0
                                return r;
1008
1009
0
                        bus_print_property_valuef(name, expected_value, flags, "%s", strna(mpol_to_string(i)));
1010
1011
0
                        return 1;
1012
0
                }
1013
0
                break;
1014
1015
0
        case SD_BUS_TYPE_UINT64:
1016
0
                if (endswith(name, "Timestamp")) {
1017
0
                        uint64_t timestamp;
1018
1019
0
                        r = sd_bus_message_read_basic(m, bus_type, &timestamp);
1020
0
                        if (r < 0)
1021
0
                                return r;
1022
1023
0
                        bus_print_property_value(name, expected_value, flags, FORMAT_TIMESTAMP_STYLE(timestamp, arg_timestamp_style));
1024
1025
0
                        return 1;
1026
0
                }
1027
0
                break;
1028
1029
0
        case SD_BUS_TYPE_STRUCT:
1030
1031
0
                if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
1032
0
                        uint32_t u;
1033
1034
0
                        r = sd_bus_message_read(m, "(uo)", &u, NULL);
1035
0
                        if (r < 0)
1036
0
                                return bus_log_parse_error(r);
1037
1038
0
                        if (u > 0)
1039
0
                                bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
1040
0
                        else
1041
0
                                bus_print_property_value(name, expected_value, flags, NULL);
1042
1043
0
                        return 1;
1044
1045
0
                } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
1046
0
                        const char *s;
1047
1048
0
                        r = sd_bus_message_read(m, "(so)", &s, NULL);
1049
0
                        if (r < 0)
1050
0
                                return bus_log_parse_error(r);
1051
1052
0
                        bus_print_property_value(name, expected_value, flags, s);
1053
1054
0
                        return 1;
1055
1056
0
                } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
1057
0
                        const char *a = NULL, *b = NULL;
1058
1059
0
                        r = sd_bus_message_read(m, "(ss)", &a, &b);
1060
0
                        if (r < 0)
1061
0
                                return bus_log_parse_error(r);
1062
1063
0
                        if (!isempty(a) || !isempty(b))
1064
0
                                bus_print_property_valuef(name, expected_value, flags, "%s \"%s\"", strempty(a), strempty(b));
1065
0
                        else
1066
0
                                bus_print_property_value(name, expected_value, flags, NULL);
1067
1068
0
                        return 1;
1069
1070
0
                } else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies", "RestrictNetworkInterfaces", "RestrictFileSystems")) {
1071
0
                        _cleanup_strv_free_ char **l = NULL;
1072
0
                        int allow_list;
1073
1074
0
                        r = sd_bus_message_enter_container(m, 'r', "bas");
1075
0
                        if (r < 0)
1076
0
                                return bus_log_parse_error(r);
1077
1078
0
                        r = sd_bus_message_read(m, "b", &allow_list);
1079
0
                        if (r < 0)
1080
0
                                return bus_log_parse_error(r);
1081
1082
0
                        r = sd_bus_message_read_strv(m, &l);
1083
0
                        if (r < 0)
1084
0
                                return bus_log_parse_error(r);
1085
1086
0
                        r = sd_bus_message_exit_container(m);
1087
0
                        if (r < 0)
1088
0
                                return bus_log_parse_error(r);
1089
1090
0
                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || allow_list || !strv_isempty(l)) {
1091
0
                                bool first = true;
1092
1093
0
                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE)) {
1094
0
                                        fputs(name, stdout);
1095
0
                                        fputc('=', stdout);
1096
0
                                }
1097
1098
0
                                if (!allow_list)
1099
0
                                        fputc('~', stdout);
1100
1101
0
                                STRV_FOREACH(i, l) {
1102
0
                                        if (first)
1103
0
                                                first = false;
1104
0
                                        else
1105
0
                                                fputc(' ', stdout);
1106
1107
0
                                        fputs(*i, stdout);
1108
0
                                }
1109
0
                                fputc('\n', stdout);
1110
0
                        }
1111
1112
0
                        return 1;
1113
1114
0
                } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
1115
0
                        int ignore;
1116
0
                        const char *s;
1117
1118
0
                        r = sd_bus_message_read(m, "(bs)", &ignore, &s);
1119
0
                        if (r < 0)
1120
0
                                return bus_log_parse_error(r);
1121
1122
0
                        if (!isempty(s))
1123
0
                                bus_print_property_valuef(name, expected_value, flags, "%s%s", ignore ? "-" : "", s);
1124
0
                        else
1125
0
                                bus_print_property_value(name, expected_value, flags, NULL);
1126
1127
0
                        return 1;
1128
1129
0
                } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
1130
0
                        const int32_t *status, *signal;
1131
0
                        size_t n_status, n_signal;
1132
1133
0
                        r = sd_bus_message_enter_container(m, 'r', "aiai");
1134
0
                        if (r < 0)
1135
0
                                return bus_log_parse_error(r);
1136
1137
0
                        r = sd_bus_message_read_array(m, 'i', (const void **) &status, &n_status);
1138
0
                        if (r < 0)
1139
0
                                return bus_log_parse_error(r);
1140
1141
0
                        r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &n_signal);
1142
0
                        if (r < 0)
1143
0
                                return bus_log_parse_error(r);
1144
1145
0
                        r = sd_bus_message_exit_container(m);
1146
0
                        if (r < 0)
1147
0
                                return bus_log_parse_error(r);
1148
1149
0
                        n_status /= sizeof(int32_t);
1150
0
                        n_signal /= sizeof(int32_t);
1151
1152
0
                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n_status > 0 || n_signal > 0) {
1153
0
                                bool first = true;
1154
1155
0
                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE)) {
1156
0
                                        fputs(name, stdout);
1157
0
                                        fputc('=', stdout);
1158
0
                                }
1159
1160
0
                                for (size_t i = 0; i < n_status; i++) {
1161
0
                                        if (first)
1162
0
                                                first = false;
1163
0
                                        else
1164
0
                                                fputc(' ', stdout);
1165
1166
0
                                        printf("%"PRIi32, status[i]);
1167
0
                                }
1168
1169
0
                                for (size_t i = 0; i < n_signal; i++) {
1170
0
                                        const char *str;
1171
1172
0
                                        str = signal_to_string((int) signal[i]);
1173
1174
0
                                        if (first)
1175
0
                                                first = false;
1176
0
                                        else
1177
0
                                                fputc(' ', stdout);
1178
1179
0
                                        if (str)
1180
0
                                                fputs(str, stdout);
1181
0
                                        else
1182
0
                                                printf("%"PRIi32, status[i]);
1183
0
                                }
1184
1185
0
                                fputc('\n', stdout);
1186
0
                        }
1187
0
                        return 1;
1188
0
                }
1189
1190
0
                break;
1191
1192
0
        case SD_BUS_TYPE_ARRAY:
1193
1194
0
                if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
1195
0
                        const char *path;
1196
0
                        int ignore;
1197
1198
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
1199
0
                        if (r < 0)
1200
0
                                return bus_log_parse_error(r);
1201
1202
0
                        while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
1203
0
                                bus_print_property_valuef(name, expected_value, flags, "%s (ignore_errors=%s)", path, yes_no(ignore));
1204
0
                        if (r < 0)
1205
0
                                return bus_log_parse_error(r);
1206
1207
0
                        r = sd_bus_message_exit_container(m);
1208
0
                        if (r < 0)
1209
0
                                return bus_log_parse_error(r);
1210
1211
0
                        return 1;
1212
1213
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
1214
0
                        const char *type, *path;
1215
1216
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
1217
0
                        if (r < 0)
1218
0
                                return bus_log_parse_error(r);
1219
1220
0
                        while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
1221
0
                                bus_print_property_valuef(name, expected_value, flags, "%s (%s)", path, type);
1222
0
                        if (r < 0)
1223
0
                                return bus_log_parse_error(r);
1224
1225
0
                        r = sd_bus_message_exit_container(m);
1226
0
                        if (r < 0)
1227
0
                                return bus_log_parse_error(r);
1228
1229
0
                        return 1;
1230
1231
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
1232
0
                        const char *type, *path;
1233
1234
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
1235
0
                        if (r < 0)
1236
0
                                return bus_log_parse_error(r);
1237
1238
0
                        while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
1239
0
                                bus_print_property_valuef(name, expected_value, flags, "%s (%s)", path, type);
1240
0
                        if (r < 0)
1241
0
                                return bus_log_parse_error(r);
1242
1243
0
                        r = sd_bus_message_exit_container(m);
1244
0
                        if (r < 0)
1245
0
                                return bus_log_parse_error(r);
1246
1247
0
                        return 1;
1248
1249
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
1250
0
                        const char *base;
1251
0
                        uint64_t v, next_elapse;
1252
1253
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
1254
0
                        if (r < 0)
1255
0
                                return bus_log_parse_error(r);
1256
1257
0
                        while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0)
1258
0
                                bus_print_property_valuef(name, expected_value, flags,
1259
0
                                                          "{ %s=%s ; next_elapse=%s }",
1260
0
                                                          base,
1261
0
                                                          strna(FORMAT_TIMESPAN(v, 0)),
1262
0
                                                          strna(FORMAT_TIMESPAN(next_elapse, 0)));
1263
0
                        if (r < 0)
1264
0
                                return bus_log_parse_error(r);
1265
1266
0
                        r = sd_bus_message_exit_container(m);
1267
0
                        if (r < 0)
1268
0
                                return bus_log_parse_error(r);
1269
1270
0
                        return 1;
1271
1272
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
1273
0
                        const char *base, *spec;
1274
0
                        uint64_t next_elapse;
1275
1276
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)");
1277
0
                        if (r < 0)
1278
0
                                return bus_log_parse_error(r);
1279
1280
0
                        while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0)
1281
0
                                bus_print_property_valuef(name, expected_value, flags,
1282
0
                                                          "{ %s=%s ; next_elapse=%s }", base, spec,
1283
0
                                                          FORMAT_TIMESTAMP_STYLE(next_elapse, arg_timestamp_style));
1284
0
                        if (r < 0)
1285
0
                                return bus_log_parse_error(r);
1286
1287
0
                        r = sd_bus_message_exit_container(m);
1288
0
                        if (r < 0)
1289
0
                                return bus_log_parse_error(r);
1290
1291
0
                        return 1;
1292
1293
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
1294
0
                        ExecStatusInfo info = {};
1295
0
                        bool is_ex_prop = endswith(name, "Ex");
1296
1297
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)");
1298
0
                        if (r < 0)
1299
0
                                return bus_log_parse_error(r);
1300
1301
0
                        while ((r = exec_status_info_deserialize(m, &info, is_ex_prop)) > 0) {
1302
0
                                _cleanup_strv_free_ char **optv = NULL;
1303
0
                                _cleanup_free_ char *tt = NULL, *o = NULL;
1304
1305
0
                                tt = strv_join(info.argv, " ");
1306
1307
0
                                if (is_ex_prop) {
1308
0
                                        r = exec_command_flags_to_strv(info.flags, &optv);
1309
0
                                        if (r < 0)
1310
0
                                                return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m");
1311
1312
0
                                        o = strv_join(optv, " ");
1313
1314
0
                                        bus_print_property_valuef(name, expected_value, flags,
1315
0
                                                                  "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
1316
0
                                                                  strna(info.path),
1317
0
                                                                  strna(tt),
1318
0
                                                                  strna(o),
1319
0
                                                                  strna(FORMAT_TIMESTAMP_STYLE(info.start_timestamp, arg_timestamp_style)),
1320
0
                                                                  strna(FORMAT_TIMESTAMP_STYLE(info.exit_timestamp, arg_timestamp_style)),
1321
0
                                                                  info.pid,
1322
0
                                                                  sigchld_code_to_string(info.code),
1323
0
                                                                  info.status,
1324
0
                                                                  info.code == CLD_EXITED ? "" : "/",
1325
0
                                                                  strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
1326
0
                                } else
1327
0
                                        bus_print_property_valuef(name, expected_value, flags,
1328
0
                                                                  "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
1329
0
                                                                  strna(info.path),
1330
0
                                                                  strna(tt),
1331
0
                                                                  yes_no(info.ignore),
1332
0
                                                                  strna(FORMAT_TIMESTAMP_STYLE(info.start_timestamp, arg_timestamp_style)),
1333
0
                                                                  strna(FORMAT_TIMESTAMP_STYLE(info.exit_timestamp, arg_timestamp_style)),
1334
0
                                                                  info.pid,
1335
0
                                                                  sigchld_code_to_string(info.code),
1336
0
                                                                  info.status,
1337
0
                                                                  info.code == CLD_EXITED ? "" : "/",
1338
0
                                                                  strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
1339
1340
0
                                free(info.path);
1341
0
                                strv_free(info.argv);
1342
0
                                zero(info);
1343
0
                        }
1344
1345
0
                        r = sd_bus_message_exit_container(m);
1346
0
                        if (r < 0)
1347
0
                                return bus_log_parse_error(r);
1348
1349
0
                        return 1;
1350
1351
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
1352
0
                        const char *path, *rwm;
1353
1354
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
1355
0
                        if (r < 0)
1356
0
                                return bus_log_parse_error(r);
1357
1358
0
                        while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
1359
0
                                bus_print_property_valuef(name, expected_value, flags, "%s %s", strna(path), strna(rwm));
1360
0
                        if (r < 0)
1361
0
                                return bus_log_parse_error(r);
1362
1363
0
                        r = sd_bus_message_exit_container(m);
1364
0
                        if (r < 0)
1365
0
                                return bus_log_parse_error(r);
1366
1367
0
                        return 1;
1368
1369
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
1370
0
                           STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
1371
0
                        const char *path;
1372
0
                        uint64_t weight;
1373
1374
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
1375
0
                        if (r < 0)
1376
0
                                return bus_log_parse_error(r);
1377
1378
0
                        while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
1379
0
                                bus_print_property_valuef(name, expected_value, flags, "%s %"PRIu64, strna(path), weight);
1380
0
                        if (r < 0)
1381
0
                                return bus_log_parse_error(r);
1382
1383
0
                        r = sd_bus_message_exit_container(m);
1384
0
                        if (r < 0)
1385
0
                                return bus_log_parse_error(r);
1386
1387
0
                        return 1;
1388
1389
0
                } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
1390
0
                           (cgroup_io_limit_type_from_string(name) >= 0 ||
1391
0
                            STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
1392
0
                        const char *path;
1393
0
                        uint64_t bandwidth;
1394
1395
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
1396
0
                        if (r < 0)
1397
0
                                return bus_log_parse_error(r);
1398
1399
0
                        while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
1400
0
                                bus_print_property_valuef(name, expected_value, flags, "%s %"PRIu64, strna(path), bandwidth);
1401
0
                        if (r < 0)
1402
0
                                return bus_log_parse_error(r);
1403
1404
0
                        r = sd_bus_message_exit_container(m);
1405
0
                        if (r < 0)
1406
0
                                return bus_log_parse_error(r);
1407
1408
0
                        return 1;
1409
1410
0
                }  else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
1411
0
                            streq(name, "IODeviceLatencyTargetUSec")) {
1412
0
                        const char *path;
1413
0
                        uint64_t target;
1414
1415
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
1416
0
                        if (r < 0)
1417
0
                                return bus_log_parse_error(r);
1418
1419
0
                        while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
1420
0
                                bus_print_property_valuef(name, expected_value, flags, "%s %s", strna(path),
1421
0
                                                          FORMAT_TIMESPAN(target, 1));
1422
0
                        if (r < 0)
1423
0
                                return bus_log_parse_error(r);
1424
1425
0
                        r = sd_bus_message_exit_container(m);
1426
0
                        if (r < 0)
1427
0
                                return bus_log_parse_error(r);
1428
1429
0
                        return 1;
1430
1431
0
                } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "StandardInputData", "RootHashSignature")) {
1432
0
                        _cleanup_free_ char *h = NULL;
1433
0
                        const void *p;
1434
0
                        size_t sz;
1435
0
                        ssize_t n;
1436
1437
0
                        r = sd_bus_message_read_array(m, 'y', &p, &sz);
1438
0
                        if (r < 0)
1439
0
                                return bus_log_parse_error(r);
1440
1441
0
                        n = base64mem(p, sz, &h);
1442
0
                        if (n < 0)
1443
0
                                return log_oom();
1444
1445
0
                        bus_print_property_value(name, expected_value, flags, h);
1446
1447
0
                        return 1;
1448
1449
0
                } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1450
0
                        _cleanup_free_ char *addresses = NULL;
1451
1452
0
                        r = sd_bus_message_enter_container(m, 'a', "(iayu)");
1453
0
                        if (r < 0)
1454
0
                                return bus_log_parse_error(r);
1455
1456
0
                        for (;;) {
1457
0
                                _cleanup_free_ char *str = NULL;
1458
0
                                uint32_t prefixlen;
1459
0
                                int32_t family;
1460
0
                                const void *ap;
1461
0
                                size_t an;
1462
1463
0
                                r = sd_bus_message_enter_container(m, 'r', "iayu");
1464
0
                                if (r < 0)
1465
0
                                        return bus_log_parse_error(r);
1466
0
                                if (r == 0)
1467
0
                                        break;
1468
1469
0
                                r = sd_bus_message_read(m, "i", &family);
1470
0
                                if (r < 0)
1471
0
                                        return bus_log_parse_error(r);
1472
1473
0
                                r = sd_bus_message_read_array(m, 'y', &ap, &an);
1474
0
                                if (r < 0)
1475
0
                                        return bus_log_parse_error(r);
1476
1477
0
                                r = sd_bus_message_read(m, "u", &prefixlen);
1478
0
                                if (r < 0)
1479
0
                                        return bus_log_parse_error(r);
1480
1481
0
                                r = sd_bus_message_exit_container(m);
1482
0
                                if (r < 0)
1483
0
                                        return bus_log_parse_error(r);
1484
1485
0
                                if (!IN_SET(family, AF_INET, AF_INET6))
1486
0
                                        continue;
1487
1488
0
                                if (an != FAMILY_ADDRESS_SIZE(family))
1489
0
                                        continue;
1490
1491
0
                                if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
1492
0
                                        continue;
1493
1494
0
                                if (in_addr_prefix_to_string(family, (const union in_addr_union*) ap, prefixlen, &str) < 0)
1495
0
                                        continue;
1496
1497
0
                                if (!strextend_with_separator(&addresses, " ", str))
1498
0
                                        return log_oom();
1499
0
                        }
1500
1501
0
                        r = sd_bus_message_exit_container(m);
1502
0
                        if (r < 0)
1503
0
                                return bus_log_parse_error(r);
1504
1505
0
                        bus_print_property_value(name, expected_value, flags, addresses);
1506
1507
0
                        return 1;
1508
1509
0
                } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
1510
0
                        _cleanup_free_ char *paths = NULL;
1511
0
                        const char *source, *dest;
1512
0
                        int ignore_enoent;
1513
0
                        uint64_t rbind;
1514
1515
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
1516
0
                        if (r < 0)
1517
0
                                return bus_log_parse_error(r);
1518
1519
0
                        while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
1520
0
                                _cleanup_free_ char *str = NULL;
1521
1522
0
                                if (isempty(source))
1523
0
                                        continue;
1524
1525
0
                                if (asprintf(&str, "%s%s%s%s%s",
1526
0
                                             ignore_enoent ? "-" : "",
1527
0
                                             source,
1528
0
                                             isempty(dest) ? "" : ":",
1529
0
                                             strempty(dest),
1530
0
                                             rbind == MS_REC ? ":rbind" : "") < 0)
1531
0
                                        return log_oom();
1532
1533
0
                                if (!strextend_with_separator(&paths, " ", str))
1534
0
                                        return log_oom();
1535
0
                        }
1536
0
                        if (r < 0)
1537
0
                                return bus_log_parse_error(r);
1538
1539
0
                        r = sd_bus_message_exit_container(m);
1540
0
                        if (r < 0)
1541
0
                                return bus_log_parse_error(r);
1542
1543
0
                        bus_print_property_value(name, expected_value, flags, paths);
1544
1545
0
                        return 1;
1546
1547
0
                } else if (streq(name, "TemporaryFileSystem")) {
1548
0
                        _cleanup_free_ char *paths = NULL;
1549
0
                        const char *target, *option;
1550
1551
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
1552
0
                        if (r < 0)
1553
0
                                return bus_log_parse_error(r);
1554
1555
0
                        while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
1556
0
                                _cleanup_free_ char *str = NULL;
1557
1558
0
                                if (isempty(target))
1559
0
                                        continue;
1560
1561
0
                                if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
1562
0
                                        return log_oom();
1563
1564
0
                                if (!strextend_with_separator(&paths, " ", str))
1565
0
                                        return log_oom();
1566
0
                        }
1567
0
                        if (r < 0)
1568
0
                                return bus_log_parse_error(r);
1569
1570
0
                        r = sd_bus_message_exit_container(m);
1571
0
                        if (r < 0)
1572
0
                                return bus_log_parse_error(r);
1573
1574
0
                        bus_print_property_value(name, expected_value, flags, paths);
1575
1576
0
                        return 1;
1577
1578
0
                } else if (streq(name, "LogExtraFields")) {
1579
0
                        _cleanup_free_ char *fields = NULL;
1580
0
                        const void *p;
1581
0
                        size_t sz;
1582
1583
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
1584
0
                        if (r < 0)
1585
0
                                return bus_log_parse_error(r);
1586
1587
0
                        while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
1588
0
                                _cleanup_free_ char *str = NULL;
1589
0
                                const char *eq;
1590
1591
0
                                if (memchr(p, 0, sz))
1592
0
                                        continue;
1593
1594
0
                                eq = memchr(p, '=', sz);
1595
0
                                if (!eq)
1596
0
                                        continue;
1597
1598
0
                                if (!journal_field_valid(p, eq - (const char*) p, false))
1599
0
                                        continue;
1600
1601
0
                                str = malloc(sz + 1);
1602
0
                                if (!str)
1603
0
                                        return log_oom();
1604
1605
0
                                memcpy(str, p, sz);
1606
0
                                str[sz] = '\0';
1607
1608
0
                                if (!utf8_is_valid(str))
1609
0
                                        continue;
1610
1611
0
                                if (!strextend_with_separator(&fields, " ", str))
1612
0
                                        return log_oom();
1613
0
                        }
1614
0
                        if (r < 0)
1615
0
                                return bus_log_parse_error(r);
1616
1617
0
                        r = sd_bus_message_exit_container(m);
1618
0
                        if (r < 0)
1619
0
                                return bus_log_parse_error(r);
1620
1621
0
                        bus_print_property_value(name, expected_value, flags, fields);
1622
1623
0
                        return 1;
1624
0
                } else if (contents[0] == SD_BUS_TYPE_BYTE &&
1625
0
                           STR_IN_SET(name,
1626
0
                                      "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes",
1627
0
                                      "EffectiveCPUs", "EffectiveMemoryNodes")) {
1628
1629
0
                        _cleanup_free_ char *affinity = NULL;
1630
0
                        _cleanup_(cpu_set_reset) CPUSet set = {};
1631
0
                        const void *a;
1632
0
                        size_t n;
1633
1634
0
                        r = sd_bus_message_read_array(m, 'y', &a, &n);
1635
0
                        if (r < 0)
1636
0
                                return bus_log_parse_error(r);
1637
1638
0
                        r = cpu_set_from_dbus(a, n, &set);
1639
0
                        if (r < 0)
1640
0
                                return log_error_errno(r, "Failed to deserialize %s: %m", name);
1641
1642
0
                        affinity = cpu_set_to_range_string(&set);
1643
0
                        if (!affinity)
1644
0
                                return log_oom();
1645
1646
0
                        bus_print_property_value(name, expected_value, flags, affinity);
1647
1648
0
                        return 1;
1649
0
                } else if (streq(name, "MountImages")) {
1650
0
                        _cleanup_free_ char *paths = NULL;
1651
1652
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssba(ss))");
1653
0
                        if (r < 0)
1654
0
                                return bus_log_parse_error(r);
1655
1656
0
                        for (;;) {
1657
0
                                _cleanup_free_ char *str = NULL;
1658
0
                                const char *source, *destination, *partition, *mount_options;
1659
0
                                int ignore_enoent;
1660
1661
0
                                r = sd_bus_message_enter_container(m, 'r', "ssba(ss)");
1662
0
                                if (r < 0)
1663
0
                                        return bus_log_parse_error(r);
1664
0
                                if (r == 0)
1665
0
                                        break;
1666
1667
0
                                r = sd_bus_message_read(m, "ssb", &source, &destination, &ignore_enoent);
1668
0
                                if (r < 0)
1669
0
                                        return bus_log_parse_error(r);
1670
1671
0
                                str = strjoin(ignore_enoent ? "-" : "",
1672
0
                                              source,
1673
0
                                              ":",
1674
0
                                              destination);
1675
0
                                if (!str)
1676
0
                                        return log_oom();
1677
1678
0
                                r = sd_bus_message_enter_container(m, 'a', "(ss)");
1679
0
                                if (r < 0)
1680
0
                                        return bus_log_parse_error(r);
1681
1682
0
                                while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0)
1683
0
                                        if (!strextend_with_separator(&str, ":", partition, mount_options))
1684
0
                                                return log_oom();
1685
0
                                if (r < 0)
1686
0
                                        return bus_log_parse_error(r);
1687
1688
0
                                if (!strextend_with_separator(&paths, " ", str))
1689
0
                                        return log_oom();
1690
1691
0
                                r = sd_bus_message_exit_container(m);
1692
0
                                if (r < 0)
1693
0
                                        return bus_log_parse_error(r);
1694
1695
0
                                r = sd_bus_message_exit_container(m);
1696
0
                                if (r < 0)
1697
0
                                        return bus_log_parse_error(r);
1698
0
                        }
1699
1700
0
                        r = sd_bus_message_exit_container(m);
1701
0
                        if (r < 0)
1702
0
                                return bus_log_parse_error(r);
1703
1704
0
                        bus_print_property_value(name, expected_value, flags, paths);
1705
1706
0
                        return 1;
1707
1708
0
                } else if (streq(name, "ExtensionImages")) {
1709
0
                        _cleanup_free_ char *paths = NULL;
1710
1711
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sba(ss))");
1712
0
                        if (r < 0)
1713
0
                                return bus_log_parse_error(r);
1714
1715
0
                        for (;;) {
1716
0
                                _cleanup_free_ char *str = NULL;
1717
0
                                const char *source, *partition, *mount_options;
1718
0
                                int ignore_enoent;
1719
1720
0
                                r = sd_bus_message_enter_container(m, 'r', "sba(ss)");
1721
0
                                if (r < 0)
1722
0
                                        return bus_log_parse_error(r);
1723
0
                                if (r == 0)
1724
0
                                        break;
1725
1726
0
                                r = sd_bus_message_read(m, "sb", &source, &ignore_enoent);
1727
0
                                if (r < 0)
1728
0
                                        return bus_log_parse_error(r);
1729
1730
0
                                str = strjoin(ignore_enoent ? "-" : "", source);
1731
0
                                if (!str)
1732
0
                                        return log_oom();
1733
1734
0
                                r = sd_bus_message_enter_container(m, 'a', "(ss)");
1735
0
                                if (r < 0)
1736
0
                                        return bus_log_parse_error(r);
1737
1738
0
                                while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0)
1739
0
                                        if (!strextend_with_separator(&str, ":", partition, mount_options))
1740
0
                                                return log_oom();
1741
0
                                if (r < 0)
1742
0
                                        return bus_log_parse_error(r);
1743
1744
0
                                if (!strextend_with_separator(&paths, " ", str))
1745
0
                                        return log_oom();
1746
1747
0
                                r = sd_bus_message_exit_container(m);
1748
0
                                if (r < 0)
1749
0
                                        return bus_log_parse_error(r);
1750
1751
0
                                r = sd_bus_message_exit_container(m);
1752
0
                                if (r < 0)
1753
0
                                        return bus_log_parse_error(r);
1754
0
                        }
1755
1756
0
                        r = sd_bus_message_exit_container(m);
1757
0
                        if (r < 0)
1758
0
                                return bus_log_parse_error(r);
1759
1760
0
                        bus_print_property_value(name, expected_value, flags, paths);
1761
1762
0
                        return 1;
1763
1764
0
                } else if (streq(name, "BPFProgram")) {
1765
0
                        const char *a, *p;
1766
1767
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
1768
0
                        if (r < 0)
1769
0
                                return bus_log_parse_error(r);
1770
1771
0
                        while ((r = sd_bus_message_read(m, "(ss)", &a, &p)) > 0)
1772
0
                                bus_print_property_valuef(name, expected_value, flags, "%s:%s", a, p);
1773
0
                        if (r < 0)
1774
0
                                return bus_log_parse_error(r);
1775
1776
0
                        r = sd_bus_message_exit_container(m);
1777
0
                        if (r < 0)
1778
0
                                return bus_log_parse_error(r);
1779
1780
0
                        return 1;
1781
0
                } else if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
1782
0
                        uint16_t nr_ports, port_min;
1783
0
                        int32_t af, ip_protocol;
1784
1785
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(iiqq)");
1786
0
                        if (r < 0)
1787
0
                                return bus_log_parse_error(r);
1788
0
                        while ((r = sd_bus_message_read(m, "(iiqq)", &af, &ip_protocol, &nr_ports, &port_min)) > 0) {
1789
0
                                const char *family, *colon1, *protocol = "", *colon2 = "";
1790
1791
0
                                family = strempty(af_to_ipv4_ipv6(af));
1792
0
                                colon1 = isempty(family) ? "" : ":";
1793
1794
0
                                if (ip_protocol != 0) {
1795
0
                                        protocol = ip_protocol_to_tcp_udp(ip_protocol);
1796
0
                                        colon2 = "";
1797
0
                                }
1798
1799
0
                                if (nr_ports == 0)
1800
0
                                        bus_print_property_valuef(name, expected_value, flags, "%s%s%s%sany",
1801
0
                                                        family, colon1, protocol, colon2);
1802
0
                                else if (nr_ports == 1)
1803
0
                                        bus_print_property_valuef(
1804
0
                                                        name, expected_value, flags, "%s%s%s%s%hu",
1805
0
                                                        family, colon1, protocol, colon2, port_min);
1806
0
                                else
1807
0
                                        bus_print_property_valuef(
1808
0
                                                        name, expected_value, flags, "%s%s%s%s%hu-%hu",
1809
0
                                                        family, colon1, protocol, colon2, port_min,
1810
0
                                                        (uint16_t) (port_min + nr_ports - 1));
1811
0
                        }
1812
0
                        if (r < 0)
1813
0
                                return bus_log_parse_error(r);
1814
1815
0
                        r = sd_bus_message_exit_container(m);
1816
0
                        if (r < 0)
1817
0
                                return bus_log_parse_error(r);
1818
1819
0
                        return 1;
1820
0
                } else if (STR_IN_SET(name, "StateDirectorySymlink", "RuntimeDirectorySymlink", "CacheDirectorySymlink", "LogsDirectorySymlink")) {
1821
0
                        const char *a, *p;
1822
0
                        uint64_t symlink_flags;
1823
1824
0
                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)");
1825
0
                        if (r < 0)
1826
0
                                return bus_log_parse_error(r);
1827
1828
0
                        while ((r = sd_bus_message_read(m, "(sst)", &a, &p, &symlink_flags)) > 0)
1829
0
                                bus_print_property_valuef(name, expected_value, flags, "%s:%s", a, p);
1830
0
                        if (r < 0)
1831
0
                                return bus_log_parse_error(r);
1832
1833
0
                        r = sd_bus_message_exit_container(m);
1834
0
                        if (r < 0)
1835
0
                                return bus_log_parse_error(r);
1836
1837
0
                        return 1;
1838
0
                }
1839
1840
0
                break;
1841
0
        }
1842
1843
0
        return 0;
1844
0
}
1845
1846
typedef enum SystemctlShowMode{
1847
        SYSTEMCTL_SHOW_PROPERTIES,
1848
        SYSTEMCTL_SHOW_STATUS,
1849
        SYSTEMCTL_SHOW_HELP,
1850
        _SYSTEMCTL_SHOW_MODE_MAX,
1851
        _SYSTEMCTL_SHOW_MODE_INVALID = -EINVAL,
1852
} SystemctlShowMode;
1853
1854
static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = {
1855
        [SYSTEMCTL_SHOW_PROPERTIES] = "show",
1856
        [SYSTEMCTL_SHOW_STATUS] = "status",
1857
        [SYSTEMCTL_SHOW_HELP] = "help",
1858
};
1859
1860
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
1861
1862
static int show_one(
1863
                sd_bus *bus,
1864
                const char *path,
1865
                const char *unit,
1866
                SystemctlShowMode show_mode,
1867
                bool *new_line,
1868
0
                bool *ellipsized) {
1869
1870
0
        static const struct bus_properties_map property_map[] = {
1871
0
                { "LoadState",                      "s",               NULL,           offsetof(UnitStatusInfo, load_state)                        },
1872
0
                { "ActiveState",                    "s",               NULL,           offsetof(UnitStatusInfo, active_state)                      },
1873
0
                { "FreezerState",                   "s",               NULL,           offsetof(UnitStatusInfo, freezer_state)                     },
1874
0
                { "Documentation",                  "as",              NULL,           offsetof(UnitStatusInfo, documentation)                     },
1875
0
                {}
1876
0
        }, status_map[] = {
1877
0
                { "Id",                             "s",               NULL,           offsetof(UnitStatusInfo, id)                                },
1878
0
                { "LoadState",                      "s",               NULL,           offsetof(UnitStatusInfo, load_state)                        },
1879
0
                { "ActiveState",                    "s",               NULL,           offsetof(UnitStatusInfo, active_state)                      },
1880
0
                { "FreezerState",                   "s",               NULL,           offsetof(UnitStatusInfo, freezer_state)                     },
1881
0
                { "SubState",                       "s",               NULL,           offsetof(UnitStatusInfo, sub_state)                         },
1882
0
                { "UnitFileState",                  "s",               NULL,           offsetof(UnitStatusInfo, unit_file_state)                   },
1883
0
                { "UnitFilePreset",                 "s",               NULL,           offsetof(UnitStatusInfo, unit_file_preset)                  },
1884
0
                { "Description",                    "s",               NULL,           offsetof(UnitStatusInfo, description)                       },
1885
0
                { "Following",                      "s",               NULL,           offsetof(UnitStatusInfo, following)                         },
1886
0
                { "Documentation",                  "as",              NULL,           offsetof(UnitStatusInfo, documentation)                     },
1887
0
                { "FragmentPath",                   "s",               NULL,           offsetof(UnitStatusInfo, fragment_path)                     },
1888
0
                { "SourcePath",                     "s",               NULL,           offsetof(UnitStatusInfo, source_path)                       },
1889
0
                { "ControlGroup",                   "s",               NULL,           offsetof(UnitStatusInfo, control_group)                     },
1890
0
                { "DropInPaths",                    "as",              NULL,           offsetof(UnitStatusInfo, dropin_paths)                      },
1891
0
                { "LoadError",                      "(ss)",            map_load_error, offsetof(UnitStatusInfo, load_error)                        },
1892
0
                { "Result",                         "s",               NULL,           offsetof(UnitStatusInfo, result)                            },
1893
0
                { "TriggeredBy",                    "as",              NULL,           offsetof(UnitStatusInfo, triggered_by)                      },
1894
0
                { "Triggers",                       "as",              NULL,           offsetof(UnitStatusInfo, triggers)                          },
1895
0
                { "InactiveExitTimestamp",          "t",               NULL,           offsetof(UnitStatusInfo, inactive_exit_timestamp)           },
1896
0
                { "InactiveExitTimestampMonotonic", "t",               NULL,           offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
1897
0
                { "ActiveEnterTimestamp",           "t",               NULL,           offsetof(UnitStatusInfo, active_enter_timestamp)            },
1898
0
                { "ActiveExitTimestamp",            "t",               NULL,           offsetof(UnitStatusInfo, active_exit_timestamp)             },
1899
0
                { "RuntimeMaxUSec",                 "t",               NULL,           offsetof(UnitStatusInfo, runtime_max_sec)                   },
1900
0
                { "InactiveEnterTimestamp",         "t",               NULL,           offsetof(UnitStatusInfo, inactive_enter_timestamp)          },
1901
0
                { "NeedDaemonReload",               "b",               NULL,           offsetof(UnitStatusInfo, need_daemon_reload)                },
1902
0
                { "Transient",                      "b",               NULL,           offsetof(UnitStatusInfo, transient)                         },
1903
0
                { "ExecMainPID",                    "u",               NULL,           offsetof(UnitStatusInfo, main_pid)                          },
1904
0
                { "MainPID",                        "u",               map_main_pid,   0                                                           },
1905
0
                { "ControlPID",                     "u",               NULL,           offsetof(UnitStatusInfo, control_pid)                       },
1906
0
                { "StatusText",                     "s",               NULL,           offsetof(UnitStatusInfo, status_text)                       },
1907
0
                { "PIDFile",                        "s",               NULL,           offsetof(UnitStatusInfo, pid_file)                          },
1908
0
                { "StatusErrno",                    "i",               NULL,           offsetof(UnitStatusInfo, status_errno)                      },
1909
0
                { "ExecMainStartTimestamp",         "t",               NULL,           offsetof(UnitStatusInfo, start_timestamp)                   },
1910
0
                { "ExecMainExitTimestamp",          "t",               NULL,           offsetof(UnitStatusInfo, exit_timestamp)                    },
1911
0
                { "ExecMainCode",                   "i",               NULL,           offsetof(UnitStatusInfo, exit_code)                         },
1912
0
                { "ExecMainStatus",                 "i",               NULL,           offsetof(UnitStatusInfo, exit_status)                       },
1913
0
                { "LogNamespace",                   "s",               NULL,           offsetof(UnitStatusInfo, log_namespace)                     },
1914
0
                { "ConditionTimestamp",             "t",               NULL,           offsetof(UnitStatusInfo, condition_timestamp)               },
1915
0
                { "ConditionResult",                "b",               NULL,           offsetof(UnitStatusInfo, condition_result)                  },
1916
0
                { "Conditions",                     "a(sbbsi)",        map_conditions, 0                                                           },
1917
0
                { "AssertTimestamp",                "t",               NULL,           offsetof(UnitStatusInfo, assert_timestamp)                  },
1918
0
                { "AssertResult",                   "b",               NULL,           offsetof(UnitStatusInfo, assert_result)                     },
1919
0
                { "Asserts",                        "a(sbbsi)",        map_asserts,    0                                                           },
1920
0
                { "NextElapseUSecRealtime",         "t",               NULL,           offsetof(UnitStatusInfo, next_elapse_real)                  },
1921
0
                { "NextElapseUSecMonotonic",        "t",               NULL,           offsetof(UnitStatusInfo, next_elapse_monotonic)             },
1922
0
                { "NAccepted",                      "u",               NULL,           offsetof(UnitStatusInfo, n_accepted)                        },
1923
0
                { "NConnections",                   "u",               NULL,           offsetof(UnitStatusInfo, n_connections)                     },
1924
0
                { "NRefused",                       "u",               NULL,           offsetof(UnitStatusInfo, n_refused)                         },
1925
0
                { "Accept",                         "b",               NULL,           offsetof(UnitStatusInfo, accept)                            },
1926
0
                { "Listen",                         "a(ss)",           map_listen,     offsetof(UnitStatusInfo, listen)                            },
1927
0
                { "SysFSPath",                      "s",               NULL,           offsetof(UnitStatusInfo, sysfs_path)                        },
1928
0
                { "Where",                          "s",               NULL,           offsetof(UnitStatusInfo, where)                             },
1929
0
                { "What",                           "s",               NULL,           offsetof(UnitStatusInfo, what)                              },
1930
0
                { "MemoryCurrent",                  "t",               NULL,           offsetof(UnitStatusInfo, memory_current)                    },
1931
0
                { "MemoryAvailable",                "t",               NULL,           offsetof(UnitStatusInfo, memory_available)                  },
1932
0
                { "DefaultMemoryMin",               "t",               NULL,           offsetof(UnitStatusInfo, default_memory_min)                },
1933
0
                { "DefaultMemoryLow",               "t",               NULL,           offsetof(UnitStatusInfo, default_memory_low)                },
1934
0
                { "MemoryMin",                      "t",               NULL,           offsetof(UnitStatusInfo, memory_min)                        },
1935
0
                { "MemoryLow",                      "t",               NULL,           offsetof(UnitStatusInfo, memory_low)                        },
1936
0
                { "MemoryHigh",                     "t",               NULL,           offsetof(UnitStatusInfo, memory_high)                       },
1937
0
                { "MemoryMax",                      "t",               NULL,           offsetof(UnitStatusInfo, memory_max)                        },
1938
0
                { "MemorySwapMax",                  "t",               NULL,           offsetof(UnitStatusInfo, memory_swap_max)                   },
1939
0
                { "MemoryLimit",                    "t",               NULL,           offsetof(UnitStatusInfo, memory_limit)                      },
1940
0
                { "CPUUsageNSec",                   "t",               NULL,           offsetof(UnitStatusInfo, cpu_usage_nsec)                    },
1941
0
                { "TasksCurrent",                   "t",               NULL,           offsetof(UnitStatusInfo, tasks_current)                     },
1942
0
                { "TasksMax",                       "t",               NULL,           offsetof(UnitStatusInfo, tasks_max)                         },
1943
0
                { "IPIngressBytes",                 "t",               NULL,           offsetof(UnitStatusInfo, ip_ingress_bytes)                  },
1944
0
                { "IPEgressBytes",                  "t",               NULL,           offsetof(UnitStatusInfo, ip_egress_bytes)                   },
1945
0
                { "IOReadBytes",                    "t",               NULL,           offsetof(UnitStatusInfo, io_read_bytes)                     },
1946
0
                { "IOWriteBytes",                   "t",               NULL,           offsetof(UnitStatusInfo, io_write_bytes)                    },
1947
0
                { "ExecCondition",                  "a(sasbttttuii)",  map_exec,       0                                                           },
1948
0
                { "ExecConditionEx",                "a(sasasttttuii)", map_exec,       0                                                           },
1949
0
                { "ExecStartPre",                   "a(sasbttttuii)",  map_exec,       0                                                           },
1950
0
                { "ExecStartPreEx",                 "a(sasasttttuii)", map_exec,       0                                                           },
1951
0
                { "ExecStart",                      "a(sasbttttuii)",  map_exec,       0                                                           },
1952
0
                { "ExecStartEx",                    "a(sasasttttuii)", map_exec,       0                                                           },
1953
0
                { "ExecStartPost",                  "a(sasbttttuii)",  map_exec,       0                                                           },
1954
0
                { "ExecStartPostEx",                "a(sasasttttuii)", map_exec,       0                                                           },
1955
0
                { "ExecReload",                     "a(sasbttttuii)",  map_exec,       0                                                           },
1956
0
                { "ExecReloadEx",                   "a(sasasttttuii)", map_exec,       0                                                           },
1957
0
                { "ExecStopPre",                    "a(sasbttttuii)",  map_exec,       0                                                           },
1958
0
                { "ExecStop",                       "a(sasbttttuii)",  map_exec,       0                                                           },
1959
0
                { "ExecStopEx",                     "a(sasasttttuii)", map_exec,       0                                                           },
1960
0
                { "ExecStopPost",                   "a(sasbttttuii)",  map_exec,       0                                                           },
1961
0
                { "ExecStopPostEx",                 "a(sasasttttuii)", map_exec,       0                                                           },
1962
0
                {}
1963
0
        };
1964
1965
0
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1966
0
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1967
0
        _cleanup_set_free_ Set *found_properties = NULL;
1968
0
        _cleanup_(unit_status_info_free) UnitStatusInfo info = {
1969
0
                .memory_current = UINT64_MAX,
1970
0
                .memory_high = CGROUP_LIMIT_MAX,
1971
0
                .memory_max = CGROUP_LIMIT_MAX,
1972
0
                .memory_swap_max = CGROUP_LIMIT_MAX,
1973
0
                .memory_limit = UINT64_MAX,
1974
0
                .memory_available = CGROUP_LIMIT_MAX,
1975
0
                .cpu_usage_nsec = UINT64_MAX,
1976
0
                .tasks_current = UINT64_MAX,
1977
0
                .tasks_max = UINT64_MAX,
1978
0
                .ip_ingress_bytes = UINT64_MAX,
1979
0
                .ip_egress_bytes = UINT64_MAX,
1980
0
                .io_read_bytes = UINT64_MAX,
1981
0
                .io_write_bytes = UINT64_MAX,
1982
0
        };
1983
0
        int r;
1984
1985
0
        assert(path);
1986
0
        assert(new_line);
1987
1988
0
        log_debug("Showing one %s", path);
1989
1990
0
        r = bus_map_all_properties(
1991
0
                        bus,
1992
0
                        "org.freedesktop.systemd1",
1993
0
                        path,
1994
0
                        show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
1995
0
                        BUS_MAP_BOOLEAN_AS_BOOL,
1996
0
                        &error,
1997
0
                        &reply,
1998
0
                        &info);
1999
0
        if (r < 0)
2000
0
                return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
2001
2002
0
        if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
2003
0
                log_full(show_mode == SYSTEMCTL_SHOW_PROPERTIES ? LOG_DEBUG : LOG_ERR,
2004
0
                         "Unit %s could not be found.", unit);
2005
2006
0
                if (show_mode == SYSTEMCTL_SHOW_STATUS)
2007
0
                        return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
2008
0
                if (show_mode == SYSTEMCTL_SHOW_HELP)
2009
0
                        return -ENOENT;
2010
0
        }
2011
2012
0
        if (*new_line)
2013
0
                printf("\n");
2014
2015
0
        *new_line = true;
2016
2017
0
        if (show_mode == SYSTEMCTL_SHOW_STATUS) {
2018
0
                print_status_info(bus, &info, ellipsized);
2019
2020
0
                if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
2021
0
                        return EXIT_PROGRAM_NOT_RUNNING;
2022
2023
0
                return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
2024
2025
0
        } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
2026
0
                show_unit_help(&info);
2027
0
                return 0;
2028
0
        }
2029
2030
0
        r = sd_bus_message_rewind(reply, true);
2031
0
        if (r < 0)
2032
0
                return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
2033
2034
0
        r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_print_flags, &found_properties);
2035
0
        if (r < 0)
2036
0
                return bus_log_parse_error(r);
2037
2038
0
        STRV_FOREACH(pp, arg_properties)
2039
0
                if (!set_contains(found_properties, *pp))
2040
0
                        log_debug("Property %s does not exist.", *pp);
2041
2042
0
        return 0;
2043
0
}
2044
2045
static int get_unit_dbus_path_by_pid(
2046
                sd_bus *bus,
2047
                uint32_t pid,
2048
0
                char **unit) {
2049
2050
0
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2051
0
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2052
0
        char *u;
2053
0
        int r;
2054
2055
0
        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", pid);
2056
0
        if (r < 0)
2057
0
                return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
2058
2059
0
        r = sd_bus_message_read(reply, "o", &u);
2060
0
        if (r < 0)
2061
0
                return bus_log_parse_error(r);
2062
2063
0
        u = strdup(u);
2064
0
        if (!u)
2065
0
                return log_oom();
2066
2067
0
        *unit = u;
2068
0
        return 0;
2069
0
}
2070
2071
static int show_all(
2072
                sd_bus *bus,
2073
                bool *new_line,
2074
0
                bool *ellipsized) {
2075
2076
0
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2077
0
        _cleanup_free_ UnitInfo *unit_infos = NULL;
2078
0
        unsigned c;
2079
0
        int r, ret = 0;
2080
2081
0
        r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
2082
0
        if (r < 0)
2083
0
                return r;
2084
2085
0
        pager_open(arg_pager_flags);
2086
2087
0
        c = (unsigned) r;
2088
2089
0
        typesafe_qsort(unit_infos, c, unit_info_compare);
2090
2091
0
        for (const UnitInfo *u = unit_infos; u < unit_infos + c; u++) {
2092
0
                _cleanup_free_ char *p = NULL;
2093
2094
0
                p = unit_dbus_path_from_name(u->id);
2095
0
                if (!p)
2096
0
                        return log_oom();
2097
2098
0
                r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
2099
0
                if (r < 0)
2100
0
                        return r;
2101
0
                if (r > 0 && ret == 0)
2102
0
                        ret = r;
2103
0
        }
2104
2105
0
        return ret;
2106
0
}
2107
2108
0
static int show_system_status(sd_bus *bus) {
2109
0
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2110
0
        _cleanup_(machine_info_clear) struct machine_info mi = {};
2111
0
        static const char prefix[] = "           ";
2112
0
        _cleanup_free_ char *hn = NULL;
2113
0
        const char *on, *off;
2114
0
        unsigned c;
2115
0
        int r;
2116
2117
0
        hn = gethostname_malloc();
2118
0
        if (!hn)
2119
0
                return log_oom();
2120
2121
0
        r = bus_map_all_properties(
2122
0
                        bus,
2123
0
                        "org.freedesktop.systemd1",
2124
0
                        "/org/freedesktop/systemd1",
2125
0
                        machine_info_property_map,
2126
0
                        BUS_MAP_STRDUP,
2127
0
                        &error,
2128
0
                        NULL,
2129
0
                        &mi);
2130
0
        if (r < 0)
2131
0
                return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
2132
2133
0
        if (streq_ptr(mi.state, "degraded")) {
2134
0
                on = ansi_highlight_red();
2135
0
                off = ansi_normal();
2136
0
        } else if (streq_ptr(mi.state, "running")) {
2137
0
                on = ansi_highlight_green();
2138
0
                off = ansi_normal();
2139
0
        } else {
2140
0
                on = ansi_highlight_yellow();
2141
0
                off = ansi_normal();
2142
0
        }
2143
2144
0
        printf("%s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, arg_host ?: hn);
2145
2146
0
        printf("    State: %s%s%s\n",
2147
0
               on, strna(mi.state), off);
2148
2149
0
        printf("    Units: %" PRIu32 " loaded (incl. loaded aliases)\n", mi.n_names);
2150
0
        printf("     Jobs: %" PRIu32 " queued\n", mi.n_jobs);
2151
0
        printf("   Failed: %" PRIu32 " units\n", mi.n_failed_units);
2152
2153
0
        printf("    Since: %s; %s\n",
2154
0
               FORMAT_TIMESTAMP_STYLE(mi.timestamp, arg_timestamp_style),
2155
0
               FORMAT_TIMESTAMP_RELATIVE(mi.timestamp));
2156
2157
0
        printf("  systemd: %s\n", mi.version);
2158
2159
0
        if (!isempty(mi.tainted))
2160
0
                printf("  Tainted: %s%s%s\n", ansi_highlight_yellow(), mi.tainted, ansi_normal());
2161
2162
0
        printf("   CGroup: %s\n", empty_to_root(mi.control_group));
2163
2164
0
        c = LESS_BY(columns(), strlen(prefix));
2165
2166
0
        r = unit_show_processes(bus, SPECIAL_ROOT_SLICE, mi.control_group, prefix, c, get_output_flags(), &error);
2167
0
        if (r == -EBADR && arg_transport == BUS_TRANSPORT_LOCAL) /* Compatibility for really old systemd versions */
2168
0
                show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
2169
0
        else if (r < 0)
2170
0
                log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s",
2171
0
                                  arg_host ?: hn, bus_error_message(&error, r));
2172
2173
0
        return 0;
2174
0
}
2175
2176
0
int verb_show(int argc, char *argv[], void *userdata) {
2177
0
        bool new_line = false, ellipsized = false;
2178
0
        SystemctlShowMode show_mode;
2179
0
        int r, ret = 0;
2180
0
        sd_bus *bus;
2181
2182
0
        assert(argv);
2183
2184
0
        show_mode = systemctl_show_mode_from_string(argv[0]);
2185
0
        if (show_mode < 0)
2186
0
                return log_error_errno(show_mode, "Invalid argument '%s'.", argv[0]);
2187
2188
0
        if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1)
2189
0
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2190
0
                                       "'help' command expects one or more unit names.\n"
2191
0
                                       "(Alternatively, help for systemctl itself may be shown with --help)");
2192
2193
0
        r = acquire_bus(BUS_MANAGER, &bus);
2194
0
        if (r < 0)
2195
0
                return r;
2196
2197
0
        pager_open(arg_pager_flags);
2198
2199
        /* If no argument is specified inspect the manager itself */
2200
0
        if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
2201
0
                return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
2202
2203
0
        if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
2204
2205
0
                show_system_status(bus);
2206
0
                new_line = true;
2207
2208
0
                if (arg_all)
2209
0
                        ret = show_all(bus, &new_line, &ellipsized);
2210
0
        } else {
2211
0
                _cleanup_free_ char **patterns = NULL;
2212
2213
0
                STRV_FOREACH(name, strv_skip(argv, 1)) {
2214
0
                        _cleanup_free_ char *path = NULL, *unit = NULL;
2215
0
                        uint32_t id;
2216
2217
0
                        if (safe_atou32(*name, &id) < 0) {
2218
0
                                if (strv_push(&patterns, *name) < 0)
2219
0
                                        return log_oom();
2220
2221
0
                                continue;
2222
0
                        } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
2223
                                /* Interpret as job id */
2224
0
                                if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
2225
0
                                        return log_oom();
2226
2227
0
                        } else {
2228
                                /* Interpret as PID */
2229
0
                                r = get_unit_dbus_path_by_pid(bus, id, &path);
2230
0
                                if (r < 0) {
2231
0
                                        ret = r;
2232
0
                                        continue;
2233
0
                                }
2234
2235
0
                                r = unit_name_from_dbus_path(path, &unit);
2236
0
                                if (r < 0)
2237
0
                                        return log_oom();
2238
0
                        }
2239
2240
0
                        r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
2241
0
                        if (r < 0)
2242
0
                                return r;
2243
0
                        if (r > 0 && ret == 0)
2244
0
                                ret = r;
2245
0
                }
2246
2247
0
                if (!strv_isempty(patterns)) {
2248
0
                        _cleanup_strv_free_ char **names = NULL;
2249
2250
0
                        r = expand_unit_names(bus, patterns, NULL, &names, NULL);
2251
0
                        if (r < 0)
2252
0
                                return log_error_errno(r, "Failed to expand names: %m");
2253
2254
0
                        r = maybe_extend_with_unit_dependencies(bus, &names);
2255
0
                        if (r < 0)
2256
0
                                return r;
2257
2258
0
                        STRV_FOREACH(name, names) {
2259
0
                                _cleanup_free_ char *path = NULL;
2260
2261
0
                                path = unit_dbus_path_from_name(*name);
2262
0
                                if (!path)
2263
0
                                        return log_oom();
2264
2265
0
                                r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
2266
0
                                if (r < 0)
2267
0
                                        return r;
2268
0
                                if (r > 0 && ret == 0)
2269
0
                                        ret = r;
2270
0
                        }
2271
0
                }
2272
0
        }
2273
2274
0
        if (ellipsized && !arg_quiet)
2275
0
                printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
2276
2277
0
        return ret;
2278
0
}