]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
core: add new RestrictNamespaces= unit file setting
[thirdparty/systemd.git] / src / systemctl / systemctl.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <linux/reboot.h>
25 #include <locale.h>
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/reboot.h>
31 #include <sys/socket.h>
32 #include <unistd.h>
33
34 #include "sd-bus.h"
35 #include "sd-daemon.h"
36 #include "sd-login.h"
37
38 #include "alloc-util.h"
39 #include "bus-common-errors.h"
40 #include "bus-error.h"
41 #include "bus-message.h"
42 #include "bus-unit-util.h"
43 #include "bus-util.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
46 #include "copy.h"
47 #include "dropin.h"
48 #include "efivars.h"
49 #include "env-util.h"
50 #include "exit-status.h"
51 #include "fd-util.h"
52 #include "fileio.h"
53 #include "formats-util.h"
54 #include "fs-util.h"
55 #include "glob-util.h"
56 #include "hostname-util.h"
57 #include "initreq.h"
58 #include "install.h"
59 #include "io-util.h"
60 #include "list.h"
61 #include "locale-util.h"
62 #include "log.h"
63 #include "logs-show.h"
64 #include "macro.h"
65 #include "mkdir.h"
66 #include "pager.h"
67 #include "parse-util.h"
68 #include "path-lookup.h"
69 #include "path-util.h"
70 #include "process-util.h"
71 #include "rlimit-util.h"
72 #include "set.h"
73 #include "sigbus.h"
74 #include "signal-util.h"
75 #include "socket-util.h"
76 #include "spawn-ask-password-agent.h"
77 #include "spawn-polkit-agent.h"
78 #include "special.h"
79 #include "stat-util.h"
80 #include "strv.h"
81 #include "terminal-util.h"
82 #include "unit-name.h"
83 #include "user-util.h"
84 #include "util.h"
85 #include "utmp-wtmp.h"
86 #include "verbs.h"
87 #include "virt.h"
88
89 /* The init script exit status codes
90 0 program is running or service is OK
91 1 program is dead and /var/run pid file exists
92 2 program is dead and /var/lock lock file exists
93 3 program is not running
94 4 program or service status is unknown
95 5-99 reserved for future LSB use
96 100-149 reserved for distribution use
97 150-199 reserved for application use
98 200-254 reserved
99 */
100 enum {
101 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
102 EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
103 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
104 EXIT_PROGRAM_NOT_RUNNING = 3,
105 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
106 };
107
108 static char **arg_types = NULL;
109 static char **arg_states = NULL;
110 static char **arg_properties = NULL;
111 static bool arg_all = false;
112 static enum dependency {
113 DEPENDENCY_FORWARD,
114 DEPENDENCY_REVERSE,
115 DEPENDENCY_AFTER,
116 DEPENDENCY_BEFORE,
117 _DEPENDENCY_MAX
118 } arg_dependency = DEPENDENCY_FORWARD;
119 static const char *arg_job_mode = "replace";
120 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
121 static bool arg_wait = false;
122 static bool arg_no_block = false;
123 static bool arg_no_legend = false;
124 static bool arg_no_pager = false;
125 static bool arg_no_wtmp = false;
126 static bool arg_no_sync = false;
127 static bool arg_no_wall = false;
128 static bool arg_no_reload = false;
129 static bool arg_value = false;
130 static bool arg_show_types = false;
131 static bool arg_ignore_inhibitors = false;
132 static bool arg_dry = false;
133 static bool arg_quiet = false;
134 static bool arg_full = false;
135 static bool arg_recursive = false;
136 static int arg_force = 0;
137 static bool arg_ask_password = false;
138 static bool arg_runtime = false;
139 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
140 static char **arg_wall = NULL;
141 static const char *arg_kill_who = NULL;
142 static int arg_signal = SIGTERM;
143 static char *arg_root = NULL;
144 static usec_t arg_when = 0;
145 static enum action {
146 _ACTION_INVALID,
147 ACTION_SYSTEMCTL,
148 ACTION_HALT,
149 ACTION_POWEROFF,
150 ACTION_REBOOT,
151 ACTION_KEXEC,
152 ACTION_EXIT,
153 ACTION_SUSPEND,
154 ACTION_HIBERNATE,
155 ACTION_HYBRID_SLEEP,
156 ACTION_RUNLEVEL2,
157 ACTION_RUNLEVEL3,
158 ACTION_RUNLEVEL4,
159 ACTION_RUNLEVEL5,
160 ACTION_RESCUE,
161 ACTION_EMERGENCY,
162 ACTION_DEFAULT,
163 ACTION_RELOAD,
164 ACTION_REEXEC,
165 ACTION_RUNLEVEL,
166 ACTION_CANCEL_SHUTDOWN,
167 _ACTION_MAX
168 } arg_action = ACTION_SYSTEMCTL;
169 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
170 static const char *arg_host = NULL;
171 static unsigned arg_lines = 10;
172 static OutputMode arg_output = OUTPUT_SHORT;
173 static bool arg_plain = false;
174 static bool arg_firmware_setup = false;
175 static bool arg_now = false;
176
177 static int daemon_reload(int argc, char *argv[], void* userdata);
178 static int trivial_method(int argc, char *argv[], void *userdata);
179 static int halt_now(enum action a);
180 static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
181
182 static bool original_stdout_is_tty;
183
184 typedef enum BusFocus {
185 BUS_FULL, /* The full bus indicated via --system or --user */
186 BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */
187 _BUS_FOCUS_MAX
188 } BusFocus;
189
190 static sd_bus *busses[_BUS_FOCUS_MAX] = {};
191
192 static UnitFileFlags args_to_flags(void) {
193 return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
194 (arg_force ? UNIT_FILE_FORCE : 0);
195 }
196
197 static int acquire_bus(BusFocus focus, sd_bus **ret) {
198 int r;
199
200 assert(focus < _BUS_FOCUS_MAX);
201 assert(ret);
202
203 /* We only go directly to the manager, if we are using a local transport */
204 if (arg_transport != BUS_TRANSPORT_LOCAL)
205 focus = BUS_FULL;
206
207 if (!busses[focus]) {
208 bool user;
209
210 user = arg_scope != UNIT_FILE_SYSTEM;
211
212 if (focus == BUS_MANAGER)
213 r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
214 else
215 r = bus_connect_transport(arg_transport, arg_host, user, &busses[focus]);
216 if (r < 0)
217 return log_error_errno(r, "Failed to connect to bus: %m");
218
219 (void) sd_bus_set_allow_interactive_authorization(busses[focus], arg_ask_password);
220 }
221
222 *ret = busses[focus];
223 return 0;
224 }
225
226 static void release_busses(void) {
227 BusFocus w;
228
229 for (w = 0; w < _BUS_FOCUS_MAX; w++)
230 busses[w] = sd_bus_flush_close_unref(busses[w]);
231 }
232
233 static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
234 char *s;
235 const char **p = userdata;
236 int r;
237
238 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s);
239 if (r < 0)
240 return r;
241
242 if (!isempty(s))
243 *p = s;
244
245 return 0;
246 }
247
248 static void ask_password_agent_open_if_enabled(void) {
249
250 /* Open the password agent as a child process if necessary */
251
252 if (!arg_ask_password)
253 return;
254
255 if (arg_scope != UNIT_FILE_SYSTEM)
256 return;
257
258 if (arg_transport != BUS_TRANSPORT_LOCAL)
259 return;
260
261 ask_password_agent_open();
262 }
263
264 static void polkit_agent_open_if_enabled(void) {
265
266 /* Open the polkit agent as a child process if necessary */
267
268 if (!arg_ask_password)
269 return;
270
271 if (arg_scope != UNIT_FILE_SYSTEM)
272 return;
273
274 if (arg_transport != BUS_TRANSPORT_LOCAL)
275 return;
276
277 polkit_agent_open();
278 }
279
280 static OutputFlags get_output_flags(void) {
281 return
282 arg_all * OUTPUT_SHOW_ALL |
283 arg_full * OUTPUT_FULL_WIDTH |
284 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
285 colors_enabled() * OUTPUT_COLOR |
286 !arg_quiet * OUTPUT_WARN_CUTOFF;
287 }
288
289 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
290 assert(error);
291
292 if (!sd_bus_error_is_set(error))
293 return r;
294
295 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
296 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
297 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
298 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
299 return EXIT_NOPERMISSION;
300
301 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
302 return EXIT_NOTINSTALLED;
303
304 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
305 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
306 return EXIT_NOTIMPLEMENTED;
307
308 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
309 return EXIT_NOTCONFIGURED;
310
311 if (r != 0)
312 return r;
313
314 return EXIT_FAILURE;
315 }
316
317 static bool install_client_side(void) {
318
319 /* Decides when to execute enable/disable/... operations
320 * client-side rather than server-side. */
321
322 if (running_in_chroot() > 0)
323 return true;
324
325 if (sd_booted() <= 0)
326 return true;
327
328 if (!isempty(arg_root))
329 return true;
330
331 if (arg_scope == UNIT_FILE_GLOBAL)
332 return true;
333
334 /* Unsupported environment variable, mostly for debugging purposes */
335 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
336 return true;
337
338 return false;
339 }
340
341 static int compare_unit_info(const void *a, const void *b) {
342 const UnitInfo *u = a, *v = b;
343 const char *d1, *d2;
344 int r;
345
346 /* First, order by machine */
347 if (!u->machine && v->machine)
348 return -1;
349 if (u->machine && !v->machine)
350 return 1;
351 if (u->machine && v->machine) {
352 r = strcasecmp(u->machine, v->machine);
353 if (r != 0)
354 return r;
355 }
356
357 /* Second, order by unit type */
358 d1 = strrchr(u->id, '.');
359 d2 = strrchr(v->id, '.');
360 if (d1 && d2) {
361 r = strcasecmp(d1, d2);
362 if (r != 0)
363 return r;
364 }
365
366 /* Third, order by name */
367 return strcasecmp(u->id, v->id);
368 }
369
370 static const char* unit_type_suffix(const char *name) {
371 const char *dot;
372
373 dot = strrchr(name, '.');
374 if (!dot)
375 return "";
376
377 return dot + 1;
378 }
379
380 static bool output_show_unit(const UnitInfo *u, char **patterns) {
381 assert(u);
382
383 if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
384 return false;
385
386 if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
387 return false;
388
389 if (arg_all)
390 return true;
391
392 /* Note that '--all' is not purely a state filter, but also a
393 * filter that hides units that "follow" other units (which is
394 * used for device units that appear under different names). */
395 if (!isempty(u->following))
396 return false;
397
398 if (!strv_isempty(arg_states))
399 return true;
400
401 /* By default show all units except the ones in inactive
402 * state and with no pending job */
403 if (u->job_id > 0)
404 return true;
405
406 if (streq(u->active_state, "inactive"))
407 return false;
408
409 return true;
410 }
411
412 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
413 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len;
414 const UnitInfo *u;
415 unsigned n_shown = 0;
416 int job_count = 0;
417
418 max_id_len = strlen("UNIT");
419 load_len = strlen("LOAD");
420 active_len = strlen("ACTIVE");
421 sub_len = strlen("SUB");
422 job_len = strlen("JOB");
423 max_desc_len = strlen("DESCRIPTION");
424
425 for (u = unit_infos; u < unit_infos + c; u++) {
426 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
427 load_len = MAX(load_len, strlen(u->load_state));
428 active_len = MAX(active_len, strlen(u->active_state));
429 sub_len = MAX(sub_len, strlen(u->sub_state));
430 max_desc_len = MAX(max_desc_len, strlen(u->description));
431
432 if (u->job_id != 0) {
433 job_len = MAX(job_len, strlen(u->job_type));
434 job_count++;
435 }
436
437 if (!arg_no_legend &&
438 (streq(u->active_state, "failed") ||
439 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
440 circle_len = 2;
441 }
442
443 if (!arg_full && original_stdout_is_tty) {
444 unsigned basic_len;
445
446 id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */
447 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
448
449 if (job_count)
450 basic_len += job_len + 1;
451
452 if (basic_len < (unsigned) columns()) {
453 unsigned extra_len, incr;
454 extra_len = columns() - basic_len;
455
456 /* Either UNIT already got 25, or is fully satisfied.
457 * Grant up to 25 to DESC now. */
458 incr = MIN(extra_len, 25u);
459 desc_len = incr;
460 extra_len -= incr;
461
462 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
463 * description but not more than it needs. */
464 if (extra_len > 0) {
465 incr = MIN(max_id_len - id_len, extra_len);
466 id_len += incr;
467 desc_len += MIN(extra_len - incr, max_desc_len - desc_len);
468 }
469 }
470 } else {
471 id_len = max_id_len;
472 desc_len = max_desc_len;
473 }
474
475 for (u = unit_infos; u < unit_infos + c; u++) {
476 _cleanup_free_ char *e = NULL, *j = NULL;
477 const char *on_underline = "", *off_underline = "";
478 const char *on_loaded = "", *off_loaded = "";
479 const char *on_active = "", *off_active = "";
480 const char *on_circle = "", *off_circle = "";
481 const char *id;
482 bool circle = false, underline = false;
483
484 if (!n_shown && !arg_no_legend) {
485
486 if (circle_len > 0)
487 fputs(" ", stdout);
488
489 printf("%s%-*s %-*s %-*s %-*s ",
490 ansi_underline(),
491 id_len, "UNIT",
492 load_len, "LOAD",
493 active_len, "ACTIVE",
494 sub_len, "SUB");
495
496 if (job_count)
497 printf("%-*s ", job_len, "JOB");
498
499 printf("%-*.*s%s\n",
500 desc_len,
501 !arg_full && arg_no_pager ? (int) desc_len : -1,
502 "DESCRIPTION",
503 ansi_normal());
504 }
505
506 n_shown++;
507
508 if (u + 1 < unit_infos + c &&
509 !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
510 on_underline = ansi_underline();
511 off_underline = ansi_normal();
512 underline = true;
513 }
514
515 if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
516 on_circle = ansi_highlight_yellow();
517 off_circle = ansi_normal();
518 circle = true;
519 on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
520 off_loaded = underline ? on_underline : ansi_normal();
521 } else if (streq(u->active_state, "failed") && !arg_plain) {
522 on_circle = ansi_highlight_red();
523 off_circle = ansi_normal();
524 circle = true;
525 on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
526 off_active = underline ? on_underline : ansi_normal();
527 }
528
529 if (u->machine) {
530 j = strjoin(u->machine, ":", u->id);
531 if (!j)
532 return log_oom();
533
534 id = j;
535 } else
536 id = u->id;
537
538 if (arg_full) {
539 e = ellipsize(id, id_len, 33);
540 if (!e)
541 return log_oom();
542
543 id = e;
544 }
545
546 if (circle_len > 0)
547 printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle);
548
549 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
550 on_underline,
551 on_active, id_len, id, off_active,
552 on_loaded, load_len, u->load_state, off_loaded,
553 on_active, active_len, u->active_state,
554 sub_len, u->sub_state, off_active,
555 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
556
557 printf("%-*.*s%s\n",
558 desc_len,
559 !arg_full && arg_no_pager ? (int) desc_len : -1,
560 u->description,
561 off_underline);
562 }
563
564 if (!arg_no_legend) {
565 const char *on, *off;
566
567 if (n_shown) {
568 puts("\n"
569 "LOAD = Reflects whether the unit definition was properly loaded.\n"
570 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
571 "SUB = The low-level unit activation state, values depend on unit type.");
572 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
573 on = ansi_highlight();
574 off = ansi_normal();
575 } else {
576 on = ansi_highlight_red();
577 off = ansi_normal();
578 }
579
580 if (arg_all)
581 printf("%s%u loaded units listed.%s\n"
582 "To show all installed unit files use 'systemctl list-unit-files'.\n",
583 on, n_shown, off);
584 else
585 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
586 "To show all installed unit files use 'systemctl list-unit-files'.\n",
587 on, n_shown, off);
588 }
589
590 return 0;
591 }
592
593 static int get_unit_list(
594 sd_bus *bus,
595 const char *machine,
596 char **patterns,
597 UnitInfo **unit_infos,
598 int c,
599 sd_bus_message **_reply) {
600
601 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
602 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
603 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
604 size_t size = c;
605 int r;
606 UnitInfo u;
607 bool fallback = false;
608
609 assert(bus);
610 assert(unit_infos);
611 assert(_reply);
612
613 r = sd_bus_message_new_method_call(
614 bus,
615 &m,
616 "org.freedesktop.systemd1",
617 "/org/freedesktop/systemd1",
618 "org.freedesktop.systemd1.Manager",
619 "ListUnitsByPatterns");
620 if (r < 0)
621 return bus_log_create_error(r);
622
623 r = sd_bus_message_append_strv(m, arg_states);
624 if (r < 0)
625 return bus_log_create_error(r);
626
627 r = sd_bus_message_append_strv(m, patterns);
628 if (r < 0)
629 return bus_log_create_error(r);
630
631 r = sd_bus_call(bus, m, 0, &error, &reply);
632 if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) ||
633 sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) {
634 /* Fallback to legacy ListUnitsFiltered method */
635 fallback = true;
636 log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
637 m = sd_bus_message_unref(m);
638 sd_bus_error_free(&error);
639
640 r = sd_bus_message_new_method_call(
641 bus,
642 &m,
643 "org.freedesktop.systemd1",
644 "/org/freedesktop/systemd1",
645 "org.freedesktop.systemd1.Manager",
646 "ListUnitsFiltered");
647 if (r < 0)
648 return bus_log_create_error(r);
649
650 r = sd_bus_message_append_strv(m, arg_states);
651 if (r < 0)
652 return bus_log_create_error(r);
653
654 r = sd_bus_call(bus, m, 0, &error, &reply);
655 }
656 if (r < 0)
657 return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
658
659 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
660 if (r < 0)
661 return bus_log_parse_error(r);
662
663 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
664 u.machine = machine;
665
666 if (!output_show_unit(&u, fallback ? patterns : NULL))
667 continue;
668
669 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
670 return log_oom();
671
672 (*unit_infos)[c++] = u;
673 }
674 if (r < 0)
675 return bus_log_parse_error(r);
676
677 r = sd_bus_message_exit_container(reply);
678 if (r < 0)
679 return bus_log_parse_error(r);
680
681 *_reply = reply;
682 reply = NULL;
683
684 return c;
685 }
686
687 static void message_set_freep(Set **set) {
688 sd_bus_message *m;
689
690 while ((m = set_steal_first(*set)))
691 sd_bus_message_unref(m);
692
693 set_free(*set);
694 }
695
696 static int get_unit_list_recursive(
697 sd_bus *bus,
698 char **patterns,
699 UnitInfo **_unit_infos,
700 Set **_replies,
701 char ***_machines) {
702
703 _cleanup_free_ UnitInfo *unit_infos = NULL;
704 _cleanup_(message_set_freep) Set *replies;
705 sd_bus_message *reply;
706 int c, r;
707
708 assert(bus);
709 assert(_replies);
710 assert(_unit_infos);
711 assert(_machines);
712
713 replies = set_new(NULL);
714 if (!replies)
715 return log_oom();
716
717 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
718 if (c < 0)
719 return c;
720
721 r = set_put(replies, reply);
722 if (r < 0) {
723 sd_bus_message_unref(reply);
724 return log_oom();
725 }
726
727 if (arg_recursive) {
728 _cleanup_strv_free_ char **machines = NULL;
729 char **i;
730
731 r = sd_get_machine_names(&machines);
732 if (r < 0)
733 return log_error_errno(r, "Failed to get machine names: %m");
734
735 STRV_FOREACH(i, machines) {
736 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
737 int k;
738
739 r = sd_bus_open_system_machine(&container, *i);
740 if (r < 0) {
741 log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
742 continue;
743 }
744
745 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
746 if (k < 0)
747 return k;
748
749 c = k;
750
751 r = set_put(replies, reply);
752 if (r < 0) {
753 sd_bus_message_unref(reply);
754 return log_oom();
755 }
756 }
757
758 *_machines = machines;
759 machines = NULL;
760 } else
761 *_machines = NULL;
762
763 *_unit_infos = unit_infos;
764 unit_infos = NULL;
765
766 *_replies = replies;
767 replies = NULL;
768
769 return c;
770 }
771
772 static int list_units(int argc, char *argv[], void *userdata) {
773 _cleanup_free_ UnitInfo *unit_infos = NULL;
774 _cleanup_(message_set_freep) Set *replies = NULL;
775 _cleanup_strv_free_ char **machines = NULL;
776 sd_bus *bus;
777 int r;
778
779 r = acquire_bus(BUS_MANAGER, &bus);
780 if (r < 0)
781 return r;
782
783 pager_open(arg_no_pager, false);
784
785 r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
786 if (r < 0)
787 return r;
788
789 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
790 return output_units_list(unit_infos, r);
791 }
792
793 static int get_triggered_units(
794 sd_bus *bus,
795 const char* path,
796 char*** ret) {
797
798 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
799 int r;
800
801 assert(bus);
802 assert(path);
803 assert(ret);
804
805 r = sd_bus_get_property_strv(
806 bus,
807 "org.freedesktop.systemd1",
808 path,
809 "org.freedesktop.systemd1.Unit",
810 "Triggers",
811 &error,
812 ret);
813 if (r < 0)
814 return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r));
815
816 return 0;
817 }
818
819 static int get_listening(
820 sd_bus *bus,
821 const char* unit_path,
822 char*** listening) {
823
824 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
825 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
826 const char *type, *path;
827 int r, n = 0;
828
829 r = sd_bus_get_property(
830 bus,
831 "org.freedesktop.systemd1",
832 unit_path,
833 "org.freedesktop.systemd1.Socket",
834 "Listen",
835 &error,
836 &reply,
837 "a(ss)");
838 if (r < 0)
839 return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r));
840
841 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
842 if (r < 0)
843 return bus_log_parse_error(r);
844
845 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
846
847 r = strv_extend(listening, type);
848 if (r < 0)
849 return log_oom();
850
851 r = strv_extend(listening, path);
852 if (r < 0)
853 return log_oom();
854
855 n++;
856 }
857 if (r < 0)
858 return bus_log_parse_error(r);
859
860 r = sd_bus_message_exit_container(reply);
861 if (r < 0)
862 return bus_log_parse_error(r);
863
864 return n;
865 }
866
867 struct socket_info {
868 const char *machine;
869 const char* id;
870
871 char* type;
872 char* path;
873
874 /* Note: triggered is a list here, although it almost certainly
875 * will always be one unit. Nevertheless, dbus API allows for multiple
876 * values, so let's follow that. */
877 char** triggered;
878
879 /* The strv above is shared. free is set only in the first one. */
880 bool own_triggered;
881 };
882
883 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
884 int o;
885
886 assert(a);
887 assert(b);
888
889 if (!a->machine && b->machine)
890 return -1;
891 if (a->machine && !b->machine)
892 return 1;
893 if (a->machine && b->machine) {
894 o = strcasecmp(a->machine, b->machine);
895 if (o != 0)
896 return o;
897 }
898
899 o = strcmp(a->path, b->path);
900 if (o == 0)
901 o = strcmp(a->type, b->type);
902
903 return o;
904 }
905
906 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
907 struct socket_info *s;
908 unsigned pathlen = strlen("LISTEN"),
909 typelen = strlen("TYPE") * arg_show_types,
910 socklen = strlen("UNIT"),
911 servlen = strlen("ACTIVATES");
912 const char *on, *off;
913
914 for (s = socket_infos; s < socket_infos + cs; s++) {
915 unsigned tmp = 0;
916 char **a;
917
918 socklen = MAX(socklen, strlen(s->id));
919 if (arg_show_types)
920 typelen = MAX(typelen, strlen(s->type));
921 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
922
923 STRV_FOREACH(a, s->triggered)
924 tmp += strlen(*a) + 2*(a != s->triggered);
925 servlen = MAX(servlen, tmp);
926 }
927
928 if (cs) {
929 if (!arg_no_legend)
930 printf("%-*s %-*.*s%-*s %s\n",
931 pathlen, "LISTEN",
932 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
933 socklen, "UNIT",
934 "ACTIVATES");
935
936 for (s = socket_infos; s < socket_infos + cs; s++) {
937 _cleanup_free_ char *j = NULL;
938 const char *path;
939 char **a;
940
941 if (s->machine) {
942 j = strjoin(s->machine, ":", s->path);
943 if (!j)
944 return log_oom();
945 path = j;
946 } else
947 path = s->path;
948
949 if (arg_show_types)
950 printf("%-*s %-*s %-*s",
951 pathlen, path, typelen, s->type, socklen, s->id);
952 else
953 printf("%-*s %-*s",
954 pathlen, path, socklen, s->id);
955 STRV_FOREACH(a, s->triggered)
956 printf("%s %s",
957 a == s->triggered ? "" : ",", *a);
958 printf("\n");
959 }
960
961 on = ansi_highlight();
962 off = ansi_normal();
963 if (!arg_no_legend)
964 printf("\n");
965 } else {
966 on = ansi_highlight_red();
967 off = ansi_normal();
968 }
969
970 if (!arg_no_legend) {
971 printf("%s%u sockets listed.%s\n", on, cs, off);
972 if (!arg_all)
973 printf("Pass --all to see loaded but inactive sockets, too.\n");
974 }
975
976 return 0;
977 }
978
979 static int list_sockets(int argc, char *argv[], void *userdata) {
980 _cleanup_(message_set_freep) Set *replies = NULL;
981 _cleanup_strv_free_ char **machines = NULL;
982 _cleanup_free_ UnitInfo *unit_infos = NULL;
983 _cleanup_free_ struct socket_info *socket_infos = NULL;
984 const UnitInfo *u;
985 struct socket_info *s;
986 unsigned cs = 0;
987 size_t size = 0;
988 int r = 0, n;
989 sd_bus *bus;
990
991 r = acquire_bus(BUS_MANAGER, &bus);
992 if (r < 0)
993 return r;
994
995 pager_open(arg_no_pager, false);
996
997 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
998 if (n < 0)
999 return n;
1000
1001 for (u = unit_infos; u < unit_infos + n; u++) {
1002 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
1003 int i, c;
1004
1005 if (!endswith(u->id, ".socket"))
1006 continue;
1007
1008 r = get_triggered_units(bus, u->unit_path, &triggered);
1009 if (r < 0)
1010 goto cleanup;
1011
1012 c = get_listening(bus, u->unit_path, &listening);
1013 if (c < 0) {
1014 r = c;
1015 goto cleanup;
1016 }
1017
1018 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
1019 r = log_oom();
1020 goto cleanup;
1021 }
1022
1023 for (i = 0; i < c; i++)
1024 socket_infos[cs + i] = (struct socket_info) {
1025 .machine = u->machine,
1026 .id = u->id,
1027 .type = listening[i*2],
1028 .path = listening[i*2 + 1],
1029 .triggered = triggered,
1030 .own_triggered = i==0,
1031 };
1032
1033 /* from this point on we will cleanup those socket_infos */
1034 cs += c;
1035 free(listening);
1036 listening = triggered = NULL; /* avoid cleanup */
1037 }
1038
1039 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
1040 (__compar_fn_t) socket_info_compare);
1041
1042 output_sockets_list(socket_infos, cs);
1043
1044 cleanup:
1045 assert(cs == 0 || socket_infos);
1046 for (s = socket_infos; s < socket_infos + cs; s++) {
1047 free(s->type);
1048 free(s->path);
1049 if (s->own_triggered)
1050 strv_free(s->triggered);
1051 }
1052
1053 return r;
1054 }
1055
1056 static int get_next_elapse(
1057 sd_bus *bus,
1058 const char *path,
1059 dual_timestamp *next) {
1060
1061 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1062 dual_timestamp t;
1063 int r;
1064
1065 assert(bus);
1066 assert(path);
1067 assert(next);
1068
1069 r = sd_bus_get_property_trivial(
1070 bus,
1071 "org.freedesktop.systemd1",
1072 path,
1073 "org.freedesktop.systemd1.Timer",
1074 "NextElapseUSecMonotonic",
1075 &error,
1076 't',
1077 &t.monotonic);
1078 if (r < 0)
1079 return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r));
1080
1081 r = sd_bus_get_property_trivial(
1082 bus,
1083 "org.freedesktop.systemd1",
1084 path,
1085 "org.freedesktop.systemd1.Timer",
1086 "NextElapseUSecRealtime",
1087 &error,
1088 't',
1089 &t.realtime);
1090 if (r < 0)
1091 return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r));
1092
1093 *next = t;
1094 return 0;
1095 }
1096
1097 static int get_last_trigger(
1098 sd_bus *bus,
1099 const char *path,
1100 usec_t *last) {
1101
1102 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1103 int r;
1104
1105 assert(bus);
1106 assert(path);
1107 assert(last);
1108
1109 r = sd_bus_get_property_trivial(
1110 bus,
1111 "org.freedesktop.systemd1",
1112 path,
1113 "org.freedesktop.systemd1.Timer",
1114 "LastTriggerUSec",
1115 &error,
1116 't',
1117 last);
1118 if (r < 0)
1119 return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
1120
1121 return 0;
1122 }
1123
1124 struct timer_info {
1125 const char* machine;
1126 const char* id;
1127 usec_t next_elapse;
1128 usec_t last_trigger;
1129 char** triggered;
1130 };
1131
1132 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1133 int o;
1134
1135 assert(a);
1136 assert(b);
1137
1138 if (!a->machine && b->machine)
1139 return -1;
1140 if (a->machine && !b->machine)
1141 return 1;
1142 if (a->machine && b->machine) {
1143 o = strcasecmp(a->machine, b->machine);
1144 if (o != 0)
1145 return o;
1146 }
1147
1148 if (a->next_elapse < b->next_elapse)
1149 return -1;
1150 if (a->next_elapse > b->next_elapse)
1151 return 1;
1152
1153 return strcmp(a->id, b->id);
1154 }
1155
1156 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1157 struct timer_info *t;
1158 unsigned
1159 nextlen = strlen("NEXT"),
1160 leftlen = strlen("LEFT"),
1161 lastlen = strlen("LAST"),
1162 passedlen = strlen("PASSED"),
1163 unitlen = strlen("UNIT"),
1164 activatelen = strlen("ACTIVATES");
1165
1166 const char *on, *off;
1167
1168 assert(timer_infos || n == 0);
1169
1170 for (t = timer_infos; t < timer_infos + n; t++) {
1171 unsigned ul = 0;
1172 char **a;
1173
1174 if (t->next_elapse > 0) {
1175 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1176
1177 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1178 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1179
1180 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1181 leftlen = MAX(leftlen, strlen(trel));
1182 }
1183
1184 if (t->last_trigger > 0) {
1185 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1186
1187 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1188 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1189
1190 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1191 passedlen = MAX(passedlen, strlen(trel));
1192 }
1193
1194 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1195
1196 STRV_FOREACH(a, t->triggered)
1197 ul += strlen(*a) + 2*(a != t->triggered);
1198
1199 activatelen = MAX(activatelen, ul);
1200 }
1201
1202 if (n > 0) {
1203 if (!arg_no_legend)
1204 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1205 nextlen, "NEXT",
1206 leftlen, "LEFT",
1207 lastlen, "LAST",
1208 passedlen, "PASSED",
1209 unitlen, "UNIT",
1210 "ACTIVATES");
1211
1212 for (t = timer_infos; t < timer_infos + n; t++) {
1213 _cleanup_free_ char *j = NULL;
1214 const char *unit;
1215 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1216 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1217 char **a;
1218
1219 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1220 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1221
1222 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1223 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1224
1225 if (t->machine) {
1226 j = strjoin(t->machine, ":", t->id);
1227 if (!j)
1228 return log_oom();
1229 unit = j;
1230 } else
1231 unit = t->id;
1232
1233 printf("%-*s %-*s %-*s %-*s %-*s",
1234 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1235
1236 STRV_FOREACH(a, t->triggered)
1237 printf("%s %s",
1238 a == t->triggered ? "" : ",", *a);
1239 printf("\n");
1240 }
1241
1242 on = ansi_highlight();
1243 off = ansi_normal();
1244 if (!arg_no_legend)
1245 printf("\n");
1246 } else {
1247 on = ansi_highlight_red();
1248 off = ansi_normal();
1249 }
1250
1251 if (!arg_no_legend) {
1252 printf("%s%u timers listed.%s\n", on, n, off);
1253 if (!arg_all)
1254 printf("Pass --all to see loaded but inactive timers, too.\n");
1255 }
1256
1257 return 0;
1258 }
1259
1260 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1261 usec_t next_elapse;
1262
1263 assert(nw);
1264 assert(next);
1265
1266 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1267 usec_t converted;
1268
1269 if (next->monotonic > nw->monotonic)
1270 converted = nw->realtime + (next->monotonic - nw->monotonic);
1271 else
1272 converted = nw->realtime - (nw->monotonic - next->monotonic);
1273
1274 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1275 next_elapse = MIN(converted, next->realtime);
1276 else
1277 next_elapse = converted;
1278
1279 } else
1280 next_elapse = next->realtime;
1281
1282 return next_elapse;
1283 }
1284
1285 static int list_timers(int argc, char *argv[], void *userdata) {
1286 _cleanup_(message_set_freep) Set *replies = NULL;
1287 _cleanup_strv_free_ char **machines = NULL;
1288 _cleanup_free_ struct timer_info *timer_infos = NULL;
1289 _cleanup_free_ UnitInfo *unit_infos = NULL;
1290 struct timer_info *t;
1291 const UnitInfo *u;
1292 size_t size = 0;
1293 int n, c = 0;
1294 dual_timestamp nw;
1295 sd_bus *bus;
1296 int r = 0;
1297
1298 r = acquire_bus(BUS_MANAGER, &bus);
1299 if (r < 0)
1300 return r;
1301
1302 pager_open(arg_no_pager, false);
1303
1304 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
1305 if (n < 0)
1306 return n;
1307
1308 dual_timestamp_get(&nw);
1309
1310 for (u = unit_infos; u < unit_infos + n; u++) {
1311 _cleanup_strv_free_ char **triggered = NULL;
1312 dual_timestamp next = DUAL_TIMESTAMP_NULL;
1313 usec_t m, last = 0;
1314
1315 if (!endswith(u->id, ".timer"))
1316 continue;
1317
1318 r = get_triggered_units(bus, u->unit_path, &triggered);
1319 if (r < 0)
1320 goto cleanup;
1321
1322 r = get_next_elapse(bus, u->unit_path, &next);
1323 if (r < 0)
1324 goto cleanup;
1325
1326 get_last_trigger(bus, u->unit_path, &last);
1327
1328 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1329 r = log_oom();
1330 goto cleanup;
1331 }
1332
1333 m = calc_next_elapse(&nw, &next);
1334
1335 timer_infos[c++] = (struct timer_info) {
1336 .machine = u->machine,
1337 .id = u->id,
1338 .next_elapse = m,
1339 .last_trigger = last,
1340 .triggered = triggered,
1341 };
1342
1343 triggered = NULL; /* avoid cleanup */
1344 }
1345
1346 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1347 (__compar_fn_t) timer_info_compare);
1348
1349 output_timers_list(timer_infos, c);
1350
1351 cleanup:
1352 for (t = timer_infos; t < timer_infos + c; t++)
1353 strv_free(t->triggered);
1354
1355 return r;
1356 }
1357
1358 static int compare_unit_file_list(const void *a, const void *b) {
1359 const char *d1, *d2;
1360 const UnitFileList *u = a, *v = b;
1361
1362 d1 = strrchr(u->path, '.');
1363 d2 = strrchr(v->path, '.');
1364
1365 if (d1 && d2) {
1366 int r;
1367
1368 r = strcasecmp(d1, d2);
1369 if (r != 0)
1370 return r;
1371 }
1372
1373 return strcasecmp(basename(u->path), basename(v->path));
1374 }
1375
1376 static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) {
1377 assert(u);
1378
1379 if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
1380 return false;
1381
1382 if (!strv_isempty(arg_types)) {
1383 const char *dot;
1384
1385 dot = strrchr(u->path, '.');
1386 if (!dot)
1387 return false;
1388
1389 if (!strv_find(arg_types, dot+1))
1390 return false;
1391 }
1392
1393 if (!strv_isempty(states) &&
1394 !strv_find(states, unit_file_state_to_string(u->state)))
1395 return false;
1396
1397 return true;
1398 }
1399
1400 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1401 unsigned max_id_len, id_cols, state_cols;
1402 const UnitFileList *u;
1403
1404 max_id_len = strlen("UNIT FILE");
1405 state_cols = strlen("STATE");
1406
1407 for (u = units; u < units + c; u++) {
1408 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1409 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1410 }
1411
1412 if (!arg_full) {
1413 unsigned basic_cols;
1414
1415 id_cols = MIN(max_id_len, 25u);
1416 basic_cols = 1 + id_cols + state_cols;
1417 if (basic_cols < (unsigned) columns())
1418 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1419 } else
1420 id_cols = max_id_len;
1421
1422 if (!arg_no_legend && c > 0)
1423 printf("%s%-*s %-*s%s\n",
1424 ansi_underline(),
1425 id_cols, "UNIT FILE",
1426 state_cols, "STATE",
1427 ansi_normal());
1428
1429 for (u = units; u < units + c; u++) {
1430 _cleanup_free_ char *e = NULL;
1431 const char *on, *off, *on_underline = "", *off_underline = "";
1432 const char *id;
1433 bool underline = false;
1434
1435 if (u + 1 < units + c &&
1436 !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) {
1437 on_underline = ansi_underline();
1438 off_underline = ansi_normal();
1439 underline = true;
1440 }
1441
1442 if (IN_SET(u->state,
1443 UNIT_FILE_MASKED,
1444 UNIT_FILE_MASKED_RUNTIME,
1445 UNIT_FILE_DISABLED,
1446 UNIT_FILE_BAD))
1447 on = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
1448 else if (u->state == UNIT_FILE_ENABLED)
1449 on = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
1450 else
1451 on = on_underline;
1452 off = off_underline;
1453
1454 id = basename(u->path);
1455
1456 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1457
1458 printf("%s%-*s %s%-*s%s%s\n",
1459 on_underline,
1460 id_cols, e ? e : id,
1461 on, state_cols, unit_file_state_to_string(u->state), off,
1462 off_underline);
1463 }
1464
1465 if (!arg_no_legend)
1466 printf("\n%u unit files listed.\n", c);
1467 }
1468
1469 static int list_unit_files(int argc, char *argv[], void *userdata) {
1470 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1471 _cleanup_free_ UnitFileList *units = NULL;
1472 UnitFileList *unit;
1473 size_t size = 0;
1474 unsigned c = 0;
1475 const char *state;
1476 char *path;
1477 int r;
1478 bool fallback = false;
1479
1480 if (install_client_side()) {
1481 Hashmap *h;
1482 UnitFileList *u;
1483 Iterator i;
1484 unsigned n_units;
1485
1486 h = hashmap_new(&string_hash_ops);
1487 if (!h)
1488 return log_oom();
1489
1490 r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1));
1491 if (r < 0) {
1492 unit_file_list_free(h);
1493 return log_error_errno(r, "Failed to get unit file list: %m");
1494 }
1495
1496 n_units = hashmap_size(h);
1497
1498 units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */
1499 if (!units) {
1500 unit_file_list_free(h);
1501 return log_oom();
1502 }
1503
1504 HASHMAP_FOREACH(u, h, i) {
1505 if (!output_show_unit_file(u, NULL, NULL))
1506 continue;
1507
1508 units[c++] = *u;
1509 free(u);
1510 }
1511
1512 assert(c <= n_units);
1513 hashmap_free(h);
1514
1515 r = 0;
1516 } else {
1517 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1518 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1519 sd_bus *bus;
1520
1521 r = acquire_bus(BUS_MANAGER, &bus);
1522 if (r < 0)
1523 return r;
1524
1525 r = sd_bus_message_new_method_call(
1526 bus,
1527 &m,
1528 "org.freedesktop.systemd1",
1529 "/org/freedesktop/systemd1",
1530 "org.freedesktop.systemd1.Manager",
1531 "ListUnitFilesByPatterns");
1532 if (r < 0)
1533 return bus_log_create_error(r);
1534
1535 r = sd_bus_message_append_strv(m, arg_states);
1536 if (r < 0)
1537 return bus_log_create_error(r);
1538
1539 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
1540 if (r < 0)
1541 return bus_log_create_error(r);
1542
1543 r = sd_bus_call(bus, m, 0, &error, &reply);
1544 if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
1545 /* Fallback to legacy ListUnitFiles method */
1546 fallback = true;
1547 log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
1548 m = sd_bus_message_unref(m);
1549 sd_bus_error_free(&error);
1550
1551 r = sd_bus_message_new_method_call(
1552 bus,
1553 &m,
1554 "org.freedesktop.systemd1",
1555 "/org/freedesktop/systemd1",
1556 "org.freedesktop.systemd1.Manager",
1557 "ListUnitFiles");
1558 if (r < 0)
1559 return bus_log_create_error(r);
1560
1561 r = sd_bus_call(bus, m, 0, &error, &reply);
1562 }
1563 if (r < 0)
1564 return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r));
1565
1566 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1567 if (r < 0)
1568 return bus_log_parse_error(r);
1569
1570 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1571
1572 if (!GREEDY_REALLOC(units, size, c + 1))
1573 return log_oom();
1574
1575 units[c] = (struct UnitFileList) {
1576 path,
1577 unit_file_state_from_string(state)
1578 };
1579
1580 if (output_show_unit_file(&units[c],
1581 fallback ? arg_states : NULL,
1582 fallback ? strv_skip(argv, 1) : NULL))
1583 c++;
1584
1585 }
1586 if (r < 0)
1587 return bus_log_parse_error(r);
1588
1589 r = sd_bus_message_exit_container(reply);
1590 if (r < 0)
1591 return bus_log_parse_error(r);
1592 }
1593
1594 pager_open(arg_no_pager, false);
1595
1596 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1597 output_unit_file_list(units, c);
1598
1599 if (install_client_side())
1600 for (unit = units; unit < units + c; unit++)
1601 free(unit->path);
1602
1603 return 0;
1604 }
1605
1606 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1607 _cleanup_free_ char *n = NULL;
1608 size_t max_len = MAX(columns(),20u);
1609 size_t len = 0;
1610 int i;
1611
1612 if (!arg_plain) {
1613
1614 for (i = level - 1; i >= 0; i--) {
1615 len += 2;
1616 if (len > max_len - 3 && !arg_full) {
1617 printf("%s...\n",max_len % 2 ? "" : " ");
1618 return 0;
1619 }
1620 printf("%s", special_glyph(branches & (1 << i) ? TREE_VERTICAL : TREE_SPACE));
1621 }
1622 len += 2;
1623
1624 if (len > max_len - 3 && !arg_full) {
1625 printf("%s...\n",max_len % 2 ? "" : " ");
1626 return 0;
1627 }
1628
1629 printf("%s", special_glyph(last ? TREE_RIGHT : TREE_BRANCH));
1630 }
1631
1632 if (arg_full) {
1633 printf("%s\n", name);
1634 return 0;
1635 }
1636
1637 n = ellipsize(name, max_len-len, 100);
1638 if (!n)
1639 return log_oom();
1640
1641 printf("%s\n", n);
1642 return 0;
1643 }
1644
1645 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1646
1647 static const char *dependencies[_DEPENDENCY_MAX] = {
1648 [DEPENDENCY_FORWARD] = "Requires\0"
1649 "Requisite\0"
1650 "Wants\0"
1651 "ConsistsOf\0"
1652 "BindsTo\0",
1653 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1654 "RequisiteOf\0"
1655 "WantedBy\0"
1656 "PartOf\0"
1657 "BoundBy\0",
1658 [DEPENDENCY_AFTER] = "After\0",
1659 [DEPENDENCY_BEFORE] = "Before\0",
1660 };
1661
1662 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1663 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1664 _cleanup_strv_free_ char **ret = NULL;
1665 _cleanup_free_ char *path = NULL;
1666 int r;
1667
1668 assert(bus);
1669 assert(name);
1670 assert(deps);
1671 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1672
1673 path = unit_dbus_path_from_name(name);
1674 if (!path)
1675 return log_oom();
1676
1677 r = sd_bus_call_method(
1678 bus,
1679 "org.freedesktop.systemd1",
1680 path,
1681 "org.freedesktop.DBus.Properties",
1682 "GetAll",
1683 &error,
1684 &reply,
1685 "s", "org.freedesktop.systemd1.Unit");
1686 if (r < 0)
1687 return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1688
1689 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1690 if (r < 0)
1691 return bus_log_parse_error(r);
1692
1693 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1694 const char *prop;
1695
1696 r = sd_bus_message_read(reply, "s", &prop);
1697 if (r < 0)
1698 return bus_log_parse_error(r);
1699
1700 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1701 r = sd_bus_message_skip(reply, "v");
1702 if (r < 0)
1703 return bus_log_parse_error(r);
1704 } else {
1705
1706 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1707 if (r < 0)
1708 return bus_log_parse_error(r);
1709
1710 r = bus_message_read_strv_extend(reply, &ret);
1711 if (r < 0)
1712 return bus_log_parse_error(r);
1713
1714 r = sd_bus_message_exit_container(reply);
1715 if (r < 0)
1716 return bus_log_parse_error(r);
1717 }
1718
1719 r = sd_bus_message_exit_container(reply);
1720 if (r < 0)
1721 return bus_log_parse_error(r);
1722
1723 }
1724 if (r < 0)
1725 return bus_log_parse_error(r);
1726
1727 r = sd_bus_message_exit_container(reply);
1728 if (r < 0)
1729 return bus_log_parse_error(r);
1730
1731 *deps = ret;
1732 ret = NULL;
1733
1734 return 0;
1735 }
1736
1737 static int list_dependencies_compare(const void *_a, const void *_b) {
1738 const char **a = (const char**) _a, **b = (const char**) _b;
1739
1740 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1741 return 1;
1742 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1743 return -1;
1744
1745 return strcasecmp(*a, *b);
1746 }
1747
1748 static int list_dependencies_one(
1749 sd_bus *bus,
1750 const char *name,
1751 int level,
1752 char ***units,
1753 unsigned int branches) {
1754
1755 _cleanup_strv_free_ char **deps = NULL;
1756 char **c;
1757 int r = 0;
1758
1759 assert(bus);
1760 assert(name);
1761 assert(units);
1762
1763 r = strv_extend(units, name);
1764 if (r < 0)
1765 return log_oom();
1766
1767 r = list_dependencies_get_dependencies(bus, name, &deps);
1768 if (r < 0)
1769 return r;
1770
1771 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1772
1773 STRV_FOREACH(c, deps) {
1774 if (strv_contains(*units, *c)) {
1775 if (!arg_plain) {
1776 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1777 if (r < 0)
1778 return r;
1779 }
1780 continue;
1781 }
1782
1783 if (arg_plain)
1784 printf(" ");
1785 else {
1786 UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
1787 const char *on;
1788
1789 (void) get_state_one_unit(bus, *c, &active_state);
1790
1791 switch (active_state) {
1792 case UNIT_ACTIVE:
1793 case UNIT_RELOADING:
1794 case UNIT_ACTIVATING:
1795 on = ansi_highlight_green();
1796 break;
1797
1798 case UNIT_INACTIVE:
1799 case UNIT_DEACTIVATING:
1800 on = ansi_normal();
1801 break;
1802
1803 default:
1804 on = ansi_highlight_red();
1805 break;
1806 }
1807
1808 printf("%s%s%s ", on, special_glyph(BLACK_CIRCLE), ansi_normal());
1809 }
1810
1811 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1812 if (r < 0)
1813 return r;
1814
1815 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1816 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1817 if (r < 0)
1818 return r;
1819 }
1820 }
1821
1822 if (!arg_plain)
1823 strv_remove(*units, name);
1824
1825 return 0;
1826 }
1827
1828 static int list_dependencies(int argc, char *argv[], void *userdata) {
1829 _cleanup_strv_free_ char **units = NULL;
1830 _cleanup_free_ char *unit = NULL;
1831 const char *u;
1832 sd_bus *bus;
1833 int r;
1834
1835 if (argv[1]) {
1836 r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit);
1837 if (r < 0)
1838 return log_error_errno(r, "Failed to mangle unit name: %m");
1839
1840 u = unit;
1841 } else
1842 u = SPECIAL_DEFAULT_TARGET;
1843
1844 r = acquire_bus(BUS_MANAGER, &bus);
1845 if (r < 0)
1846 return r;
1847
1848 pager_open(arg_no_pager, false);
1849
1850 puts(u);
1851
1852 return list_dependencies_one(bus, u, 0, &units, 0);
1853 }
1854
1855 struct machine_info {
1856 bool is_host;
1857 char *name;
1858 char *state;
1859 char *control_group;
1860 uint32_t n_failed_units;
1861 uint32_t n_jobs;
1862 usec_t timestamp;
1863 };
1864
1865 static const struct bus_properties_map machine_info_property_map[] = {
1866 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1867 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1868 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1869 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1870 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1871 {}
1872 };
1873
1874 static void machine_info_clear(struct machine_info *info) {
1875 assert(info);
1876
1877 free(info->name);
1878 free(info->state);
1879 free(info->control_group);
1880 zero(*info);
1881 }
1882
1883 static void free_machines_list(struct machine_info *machine_infos, int n) {
1884 int i;
1885
1886 if (!machine_infos)
1887 return;
1888
1889 for (i = 0; i < n; i++)
1890 machine_info_clear(&machine_infos[i]);
1891
1892 free(machine_infos);
1893 }
1894
1895 static int compare_machine_info(const void *a, const void *b) {
1896 const struct machine_info *u = a, *v = b;
1897
1898 if (u->is_host != v->is_host)
1899 return u->is_host > v->is_host ? -1 : 1;
1900
1901 return strcasecmp(u->name, v->name);
1902 }
1903
1904 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1905 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
1906 int r;
1907
1908 assert(mi);
1909
1910 if (!bus) {
1911 r = sd_bus_open_system_machine(&container, mi->name);
1912 if (r < 0)
1913 return r;
1914
1915 bus = container;
1916 }
1917
1918 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1919 if (r < 0)
1920 return r;
1921
1922 return 0;
1923 }
1924
1925 static bool output_show_machine(const char *name, char **patterns) {
1926 return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
1927 }
1928
1929 static int get_machine_list(
1930 sd_bus *bus,
1931 struct machine_info **_machine_infos,
1932 char **patterns) {
1933
1934 struct machine_info *machine_infos = NULL;
1935 _cleanup_strv_free_ char **m = NULL;
1936 _cleanup_free_ char *hn = NULL;
1937 size_t sz = 0;
1938 char **i;
1939 int c = 0, r;
1940
1941 hn = gethostname_malloc();
1942 if (!hn)
1943 return log_oom();
1944
1945 if (output_show_machine(hn, patterns)) {
1946 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1947 return log_oom();
1948
1949 machine_infos[c].is_host = true;
1950 machine_infos[c].name = hn;
1951 hn = NULL;
1952
1953 get_machine_properties(bus, &machine_infos[c]);
1954 c++;
1955 }
1956
1957 r = sd_get_machine_names(&m);
1958 if (r < 0)
1959 return log_error_errno(r, "Failed to get machine list: %m");
1960
1961 STRV_FOREACH(i, m) {
1962 _cleanup_free_ char *class = NULL;
1963
1964 if (!output_show_machine(*i, patterns))
1965 continue;
1966
1967 sd_machine_get_class(*i, &class);
1968 if (!streq_ptr(class, "container"))
1969 continue;
1970
1971 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1972 free_machines_list(machine_infos, c);
1973 return log_oom();
1974 }
1975
1976 machine_infos[c].is_host = false;
1977 machine_infos[c].name = strdup(*i);
1978 if (!machine_infos[c].name) {
1979 free_machines_list(machine_infos, c);
1980 return log_oom();
1981 }
1982
1983 get_machine_properties(NULL, &machine_infos[c]);
1984 c++;
1985 }
1986
1987 *_machine_infos = machine_infos;
1988 return c;
1989 }
1990
1991 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1992 struct machine_info *m;
1993 unsigned
1994 circle_len = 0,
1995 namelen = sizeof("NAME") - 1,
1996 statelen = sizeof("STATE") - 1,
1997 failedlen = sizeof("FAILED") - 1,
1998 jobslen = sizeof("JOBS") - 1;
1999
2000 assert(machine_infos || n == 0);
2001
2002 for (m = machine_infos; m < machine_infos + n; m++) {
2003 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
2004 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
2005 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
2006 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
2007
2008 if (!arg_plain && !streq_ptr(m->state, "running"))
2009 circle_len = 2;
2010 }
2011
2012 if (!arg_no_legend) {
2013 if (circle_len > 0)
2014 fputs(" ", stdout);
2015
2016 printf("%-*s %-*s %-*s %-*s\n",
2017 namelen, "NAME",
2018 statelen, "STATE",
2019 failedlen, "FAILED",
2020 jobslen, "JOBS");
2021 }
2022
2023 for (m = machine_infos; m < machine_infos + n; m++) {
2024 const char *on_state = "", *off_state = "";
2025 const char *on_failed = "", *off_failed = "";
2026 bool circle = false;
2027
2028 if (streq_ptr(m->state, "degraded")) {
2029 on_state = ansi_highlight_red();
2030 off_state = ansi_normal();
2031 circle = true;
2032 } else if (!streq_ptr(m->state, "running")) {
2033 on_state = ansi_highlight_yellow();
2034 off_state = ansi_normal();
2035 circle = true;
2036 }
2037
2038 if (m->n_failed_units > 0) {
2039 on_failed = ansi_highlight_red();
2040 off_failed = ansi_normal();
2041 } else
2042 on_failed = off_failed = "";
2043
2044 if (circle_len > 0)
2045 printf("%s%s%s ", on_state, circle ? special_glyph(BLACK_CIRCLE) : " ", off_state);
2046
2047 if (m->is_host)
2048 printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2049 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
2050 on_state, statelen, strna(m->state), off_state,
2051 on_failed, failedlen, m->n_failed_units, off_failed,
2052 jobslen, m->n_jobs);
2053 else
2054 printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2055 namelen, strna(m->name),
2056 on_state, statelen, strna(m->state), off_state,
2057 on_failed, failedlen, m->n_failed_units, off_failed,
2058 jobslen, m->n_jobs);
2059 }
2060
2061 if (!arg_no_legend)
2062 printf("\n%u machines listed.\n", n);
2063 }
2064
2065 static int list_machines(int argc, char *argv[], void *userdata) {
2066 struct machine_info *machine_infos = NULL;
2067 sd_bus *bus;
2068 int r;
2069
2070 if (geteuid() != 0) {
2071 log_error("Must be root.");
2072 return -EPERM;
2073 }
2074
2075 r = acquire_bus(BUS_MANAGER, &bus);
2076 if (r < 0)
2077 return r;
2078
2079 r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1));
2080 if (r < 0)
2081 return r;
2082
2083 pager_open(arg_no_pager, false);
2084
2085 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
2086 output_machines_list(machine_infos, r);
2087 free_machines_list(machine_infos, r);
2088
2089 return 0;
2090 }
2091
2092 static int get_default(int argc, char *argv[], void *userdata) {
2093 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2094 _cleanup_free_ char *_path = NULL;
2095 const char *path;
2096 int r;
2097
2098 if (install_client_side()) {
2099 r = unit_file_get_default(arg_scope, arg_root, &_path);
2100 if (r < 0)
2101 return log_error_errno(r, "Failed to get default target: %m");
2102 path = _path;
2103
2104 r = 0;
2105 } else {
2106 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2107 sd_bus *bus;
2108
2109 r = acquire_bus(BUS_MANAGER, &bus);
2110 if (r < 0)
2111 return r;
2112
2113 r = sd_bus_call_method(
2114 bus,
2115 "org.freedesktop.systemd1",
2116 "/org/freedesktop/systemd1",
2117 "org.freedesktop.systemd1.Manager",
2118 "GetDefaultTarget",
2119 &error,
2120 &reply,
2121 NULL);
2122 if (r < 0)
2123 return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
2124
2125 r = sd_bus_message_read(reply, "s", &path);
2126 if (r < 0)
2127 return bus_log_parse_error(r);
2128 }
2129
2130 if (path)
2131 printf("%s\n", path);
2132
2133 return 0;
2134 }
2135
2136 static int set_default(int argc, char *argv[], void *userdata) {
2137 _cleanup_free_ char *unit = NULL;
2138 UnitFileChange *changes = NULL;
2139 unsigned n_changes = 0;
2140 int r;
2141
2142 assert(argc >= 2);
2143 assert(argv);
2144
2145 r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit);
2146 if (r < 0)
2147 return log_error_errno(r, "Failed to mangle unit name: %m");
2148
2149 if (install_client_side()) {
2150 r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
2151 unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
2152
2153 if (r > 0)
2154 r = 0;
2155 } else {
2156 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2157 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2158 sd_bus *bus;
2159
2160 polkit_agent_open_if_enabled();
2161
2162 r = acquire_bus(BUS_MANAGER, &bus);
2163 if (r < 0)
2164 return r;
2165
2166 r = sd_bus_call_method(
2167 bus,
2168 "org.freedesktop.systemd1",
2169 "/org/freedesktop/systemd1",
2170 "org.freedesktop.systemd1.Manager",
2171 "SetDefaultTarget",
2172 &error,
2173 &reply,
2174 "sb", unit, 1);
2175 if (r < 0)
2176 return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
2177
2178 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
2179 if (r < 0)
2180 goto finish;
2181
2182 /* Try to reload if enabled */
2183 if (!arg_no_reload)
2184 r = daemon_reload(argc, argv, userdata);
2185 else
2186 r = 0;
2187 }
2188
2189 finish:
2190 unit_file_changes_free(changes, n_changes);
2191
2192 return r;
2193 }
2194
2195 struct job_info {
2196 uint32_t id;
2197 const char *name, *type, *state;
2198 };
2199
2200 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2201 unsigned id_len, unit_len, type_len, state_len;
2202 const struct job_info *j;
2203 const char *on, *off;
2204 bool shorten = false;
2205
2206 assert(n == 0 || jobs);
2207
2208 if (n == 0) {
2209 if (!arg_no_legend) {
2210 on = ansi_highlight_green();
2211 off = ansi_normal();
2212
2213 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2214 }
2215 return;
2216 }
2217
2218 pager_open(arg_no_pager, false);
2219
2220 id_len = strlen("JOB");
2221 unit_len = strlen("UNIT");
2222 type_len = strlen("TYPE");
2223 state_len = strlen("STATE");
2224
2225 for (j = jobs; j < jobs + n; j++) {
2226 uint32_t id = j->id;
2227 assert(j->name && j->type && j->state);
2228
2229 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2230 unit_len = MAX(unit_len, strlen(j->name));
2231 type_len = MAX(type_len, strlen(j->type));
2232 state_len = MAX(state_len, strlen(j->state));
2233 }
2234
2235 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2236 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2237 shorten = true;
2238 }
2239
2240 if (!arg_no_legend)
2241 printf("%*s %-*s %-*s %-*s\n",
2242 id_len, "JOB",
2243 unit_len, "UNIT",
2244 type_len, "TYPE",
2245 state_len, "STATE");
2246
2247 for (j = jobs; j < jobs + n; j++) {
2248 _cleanup_free_ char *e = NULL;
2249
2250 if (streq(j->state, "running")) {
2251 on = ansi_highlight();
2252 off = ansi_normal();
2253 } else
2254 on = off = "";
2255
2256 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2257 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2258 id_len, j->id,
2259 on, unit_len, e ? e : j->name, off,
2260 type_len, j->type,
2261 on, state_len, j->state, off);
2262 }
2263
2264 if (!arg_no_legend) {
2265 on = ansi_highlight();
2266 off = ansi_normal();
2267
2268 printf("\n%s%u jobs listed%s.\n", on, n, off);
2269 }
2270 }
2271
2272 static bool output_show_job(struct job_info *job, char **patterns) {
2273 return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
2274 }
2275
2276 static int list_jobs(int argc, char *argv[], void *userdata) {
2277 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2278 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2279 const char *name, *type, *state, *job_path, *unit_path;
2280 _cleanup_free_ struct job_info *jobs = NULL;
2281 size_t size = 0;
2282 unsigned c = 0;
2283 sd_bus *bus;
2284 uint32_t id;
2285 int r;
2286 bool skipped = false;
2287
2288 r = acquire_bus(BUS_MANAGER, &bus);
2289 if (r < 0)
2290 return r;
2291
2292 r = sd_bus_call_method(
2293 bus,
2294 "org.freedesktop.systemd1",
2295 "/org/freedesktop/systemd1",
2296 "org.freedesktop.systemd1.Manager",
2297 "ListJobs",
2298 &error,
2299 &reply,
2300 NULL);
2301 if (r < 0)
2302 return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r));
2303
2304 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2305 if (r < 0)
2306 return bus_log_parse_error(r);
2307
2308 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2309 struct job_info job = { id, name, type, state };
2310
2311 if (!output_show_job(&job, strv_skip(argv, 1))) {
2312 skipped = true;
2313 continue;
2314 }
2315
2316 if (!GREEDY_REALLOC(jobs, size, c + 1))
2317 return log_oom();
2318
2319 jobs[c++] = job;
2320 }
2321 if (r < 0)
2322 return bus_log_parse_error(r);
2323
2324 r = sd_bus_message_exit_container(reply);
2325 if (r < 0)
2326 return bus_log_parse_error(r);
2327
2328 pager_open(arg_no_pager, false);
2329
2330 output_jobs_list(jobs, c, skipped);
2331 return 0;
2332 }
2333
2334 static int cancel_job(int argc, char *argv[], void *userdata) {
2335 sd_bus *bus;
2336 char **name;
2337 int r = 0;
2338
2339 if (argc <= 1)
2340 return trivial_method(argc, argv, userdata);
2341
2342 r = acquire_bus(BUS_MANAGER, &bus);
2343 if (r < 0)
2344 return r;
2345
2346 polkit_agent_open_if_enabled();
2347
2348 STRV_FOREACH(name, strv_skip(argv, 1)) {
2349 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2350 uint32_t id;
2351 int q;
2352
2353 q = safe_atou32(*name, &id);
2354 if (q < 0)
2355 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2356
2357 q = sd_bus_call_method(
2358 bus,
2359 "org.freedesktop.systemd1",
2360 "/org/freedesktop/systemd1",
2361 "org.freedesktop.systemd1.Manager",
2362 "CancelJob",
2363 &error,
2364 NULL,
2365 "u", id);
2366 if (q < 0) {
2367 log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2368 if (r == 0)
2369 r = q;
2370 }
2371 }
2372
2373 return r;
2374 }
2375
2376 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2377 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2378 const char *path;
2379 int b, r;
2380
2381 /* We ignore all errors here, since this is used to show a
2382 * warning only */
2383
2384 /* We don't use unit_dbus_path_from_name() directly since we
2385 * don't want to load the unit if it isn't loaded. */
2386
2387 r = sd_bus_call_method(
2388 bus,
2389 "org.freedesktop.systemd1",
2390 "/org/freedesktop/systemd1",
2391 "org.freedesktop.systemd1.Manager",
2392 "GetUnit",
2393 NULL,
2394 &reply,
2395 "s", unit);
2396 if (r < 0)
2397 return r;
2398
2399 r = sd_bus_message_read(reply, "o", &path);
2400 if (r < 0)
2401 return r;
2402
2403 r = sd_bus_get_property_trivial(
2404 bus,
2405 "org.freedesktop.systemd1",
2406 path,
2407 "org.freedesktop.systemd1.Unit",
2408 "NeedDaemonReload",
2409 NULL,
2410 'b', &b);
2411 if (r < 0)
2412 return r;
2413
2414 return b;
2415 }
2416
2417 static void warn_unit_file_changed(const char *name) {
2418 assert(name);
2419
2420 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2421 ansi_highlight_red(),
2422 ansi_normal(),
2423 name,
2424 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2425 }
2426
2427 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2428 char **p;
2429
2430 assert(lp);
2431 assert(unit_name);
2432 assert(unit_path);
2433
2434 STRV_FOREACH(p, lp->search_path) {
2435 _cleanup_free_ char *path;
2436
2437 path = path_join(arg_root, *p, unit_name);
2438 if (!path)
2439 return log_oom();
2440
2441 if (access(path, F_OK) == 0) {
2442 *unit_path = path;
2443 path = NULL;
2444 return 1;
2445 }
2446 }
2447
2448 return 0;
2449 }
2450
2451 static int unit_find_paths(
2452 sd_bus *bus,
2453 const char *unit_name,
2454 LookupPaths *lp,
2455 char **fragment_path,
2456 char ***dropin_paths) {
2457
2458 _cleanup_free_ char *path = NULL;
2459 _cleanup_strv_free_ char **dropins = NULL;
2460 int r;
2461
2462 /**
2463 * Finds where the unit is defined on disk. Returns 0 if the unit
2464 * is not found. Returns 1 if it is found, and sets
2465 * - the path to the unit in *path, if it exists on disk,
2466 * - and a strv of existing drop-ins in *dropins,
2467 * if the arg is not NULL and any dropins were found.
2468 */
2469
2470 assert(unit_name);
2471 assert(fragment_path);
2472 assert(lp);
2473
2474 if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
2475 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2476 _cleanup_free_ char *unit = NULL;
2477
2478 unit = unit_dbus_path_from_name(unit_name);
2479 if (!unit)
2480 return log_oom();
2481
2482 r = sd_bus_get_property_string(
2483 bus,
2484 "org.freedesktop.systemd1",
2485 unit,
2486 "org.freedesktop.systemd1.Unit",
2487 "FragmentPath",
2488 &error,
2489 &path);
2490 if (r < 0)
2491 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2492
2493 if (dropin_paths) {
2494 r = sd_bus_get_property_strv(
2495 bus,
2496 "org.freedesktop.systemd1",
2497 unit,
2498 "org.freedesktop.systemd1.Unit",
2499 "DropInPaths",
2500 &error,
2501 &dropins);
2502 if (r < 0)
2503 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2504 }
2505 } else {
2506 _cleanup_set_free_ Set *names;
2507
2508 names = set_new(NULL);
2509 if (!names)
2510 return log_oom();
2511
2512 r = set_put(names, unit_name);
2513 if (r < 0)
2514 return log_error_errno(r, "Failed to add unit name: %m");
2515
2516 r = unit_file_find_path(lp, unit_name, &path);
2517 if (r < 0)
2518 return r;
2519
2520 if (r == 0) {
2521 _cleanup_free_ char *template = NULL;
2522
2523 r = unit_name_template(unit_name, &template);
2524 if (r < 0 && r != -EINVAL)
2525 return log_error_errno(r, "Failed to determine template name: %m");
2526 if (r >= 0) {
2527 r = unit_file_find_path(lp, template, &path);
2528 if (r < 0)
2529 return r;
2530 }
2531 }
2532
2533 if (dropin_paths) {
2534 r = unit_file_find_dropin_paths(lp->search_path, NULL, names, &dropins);
2535 if (r < 0)
2536 return r;
2537 }
2538 }
2539
2540 r = 0;
2541
2542 if (!isempty(path)) {
2543 *fragment_path = path;
2544 path = NULL;
2545 r = 1;
2546 }
2547
2548 if (dropin_paths && !strv_isempty(dropins)) {
2549 *dropin_paths = dropins;
2550 dropins = NULL;
2551 r = 1;
2552 }
2553
2554 if (r == 0 && !arg_force)
2555 log_error("No files found for %s.", unit_name);
2556
2557 return r;
2558 }
2559
2560 static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
2561 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2562 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2563 _cleanup_free_ char *buf = NULL;
2564 UnitActiveState state;
2565 const char *path;
2566 int r;
2567
2568 assert(name);
2569 assert(active_state);
2570
2571 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2572 * isn't loaded. */
2573 r = sd_bus_call_method(
2574 bus,
2575 "org.freedesktop.systemd1",
2576 "/org/freedesktop/systemd1",
2577 "org.freedesktop.systemd1.Manager",
2578 "GetUnit",
2579 &error,
2580 &reply,
2581 "s", name);
2582 if (r < 0) {
2583 if (!sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2584 return log_error_errno(r, "Failed to retrieve unit: %s", bus_error_message(&error, r));
2585
2586 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2587 * considered inactive. */
2588 state = UNIT_INACTIVE;
2589
2590 } else {
2591 r = sd_bus_message_read(reply, "o", &path);
2592 if (r < 0)
2593 return bus_log_parse_error(r);
2594
2595 r = sd_bus_get_property_string(
2596 bus,
2597 "org.freedesktop.systemd1",
2598 path,
2599 "org.freedesktop.systemd1.Unit",
2600 "ActiveState",
2601 &error,
2602 &buf);
2603 if (r < 0)
2604 return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
2605
2606 state = unit_active_state_from_string(buf);
2607 if (state == _UNIT_ACTIVE_STATE_INVALID) {
2608 log_error("Invalid unit state '%s' for: %s", buf, name);
2609 return -EINVAL;
2610 }
2611 }
2612
2613 *active_state = state;
2614 return 0;
2615 }
2616
2617 static int check_triggering_units(
2618 sd_bus *bus,
2619 const char *name) {
2620
2621 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2622 _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
2623 _cleanup_strv_free_ char **triggered_by = NULL;
2624 bool print_warning_label = true;
2625 UnitActiveState active_state;
2626 char **i;
2627 int r;
2628
2629 r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n);
2630 if (r < 0)
2631 return log_error_errno(r, "Failed to mangle unit name: %m");
2632
2633 path = unit_dbus_path_from_name(n);
2634 if (!path)
2635 return log_oom();
2636
2637 r = sd_bus_get_property_string(
2638 bus,
2639 "org.freedesktop.systemd1",
2640 path,
2641 "org.freedesktop.systemd1.Unit",
2642 "LoadState",
2643 &error,
2644 &load_state);
2645 if (r < 0)
2646 return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2647
2648 if (streq(load_state, "masked"))
2649 return 0;
2650
2651 r = sd_bus_get_property_strv(
2652 bus,
2653 "org.freedesktop.systemd1",
2654 path,
2655 "org.freedesktop.systemd1.Unit",
2656 "TriggeredBy",
2657 &error,
2658 &triggered_by);
2659 if (r < 0)
2660 return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2661
2662 STRV_FOREACH(i, triggered_by) {
2663 r = get_state_one_unit(bus, *i, &active_state);
2664 if (r < 0)
2665 return r;
2666
2667 if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
2668 continue;
2669
2670 if (print_warning_label) {
2671 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2672 print_warning_label = false;
2673 }
2674
2675 log_warning(" %s", *i);
2676 }
2677
2678 return 0;
2679 }
2680
2681 static const struct {
2682 const char *verb;
2683 const char *method;
2684 } unit_actions[] = {
2685 { "start", "StartUnit" },
2686 { "stop", "StopUnit" },
2687 { "condstop", "StopUnit" },
2688 { "reload", "ReloadUnit" },
2689 { "restart", "RestartUnit" },
2690 { "try-restart", "TryRestartUnit" },
2691 { "condrestart", "TryRestartUnit" },
2692 { "reload-or-restart", "ReloadOrRestartUnit" },
2693 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2694 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2695 { "condreload", "ReloadOrTryRestartUnit" },
2696 { "force-reload", "ReloadOrTryRestartUnit" }
2697 };
2698
2699 static const char *verb_to_method(const char *verb) {
2700 uint i;
2701
2702 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2703 if (streq_ptr(unit_actions[i].verb, verb))
2704 return unit_actions[i].method;
2705
2706 return "StartUnit";
2707 }
2708
2709 static const char *method_to_verb(const char *method) {
2710 uint i;
2711
2712 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2713 if (streq_ptr(unit_actions[i].method, method))
2714 return unit_actions[i].verb;
2715
2716 return "n/a";
2717 }
2718
2719 typedef struct {
2720 sd_bus_slot *match;
2721 sd_event *event;
2722 Set *unit_paths;
2723 bool any_failed;
2724 } WaitContext;
2725
2726 static void wait_context_free(WaitContext *c) {
2727 c->match = sd_bus_slot_unref(c->match);
2728 c->event = sd_event_unref(c->event);
2729 c->unit_paths = set_free_free(c->unit_paths);
2730 }
2731
2732 static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
2733 WaitContext *c = userdata;
2734 const char *path;
2735 int r;
2736
2737 path = sd_bus_message_get_path(m);
2738 if (!set_contains(c->unit_paths, path))
2739 return 0;
2740
2741 /* Check if ActiveState changed to inactive/failed */
2742 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2743 r = sd_bus_message_skip(m, "s");
2744 if (r < 0)
2745 return bus_log_parse_error(r);
2746
2747 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
2748 if (r < 0)
2749 return bus_log_parse_error(r);
2750
2751 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
2752 const char *s;
2753
2754 r = sd_bus_message_read(m, "s", &s);
2755 if (r < 0)
2756 return bus_log_parse_error(r);
2757
2758 if (streq(s, "ActiveState")) {
2759 bool is_failed;
2760
2761 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
2762 if (r < 0)
2763 return bus_log_parse_error(r);
2764
2765 r = sd_bus_message_read(m, "s", &s);
2766 if (r < 0)
2767 return bus_log_parse_error(r);
2768
2769 is_failed = streq(s, "failed");
2770 if (streq(s, "inactive") || is_failed) {
2771 log_debug("%s became %s, dropping from --wait tracking", path, s);
2772 free(set_remove(c->unit_paths, path));
2773 c->any_failed = c->any_failed || is_failed;
2774 } else
2775 log_debug("ActiveState on %s changed to %s", path, s);
2776
2777 break; /* no need to dissect the rest of the message */
2778 } else {
2779 /* other property */
2780 r = sd_bus_message_skip(m, "v");
2781 if (r < 0)
2782 return bus_log_parse_error(r);
2783 }
2784 r = sd_bus_message_exit_container(m);
2785 if (r < 0)
2786 return bus_log_parse_error(r);
2787 }
2788 if (r < 0)
2789 return bus_log_parse_error(r);
2790
2791 if (set_isempty(c->unit_paths))
2792 sd_event_exit(c->event, EXIT_SUCCESS);
2793
2794 return 0;
2795 }
2796
2797 static int start_unit_one(
2798 sd_bus *bus,
2799 const char *method,
2800 const char *name,
2801 const char *mode,
2802 sd_bus_error *error,
2803 BusWaitForJobs *w,
2804 WaitContext *wait_context) {
2805
2806 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2807 const char *path;
2808 int r;
2809
2810 assert(method);
2811 assert(name);
2812 assert(mode);
2813 assert(error);
2814
2815 if (wait_context) {
2816 _cleanup_free_ char *unit_path = NULL;
2817 const char* mt;
2818
2819 log_debug("Watching for property changes of %s", name);
2820 r = sd_bus_call_method(
2821 bus,
2822 "org.freedesktop.systemd1",
2823 "/org/freedesktop/systemd1",
2824 "org.freedesktop.systemd1.Manager",
2825 "RefUnit",
2826 error,
2827 NULL,
2828 "s", name);
2829 if (r < 0)
2830 return log_error_errno(r, "Failed to RefUnit %s: %s", name, bus_error_message(error, r));
2831
2832 unit_path = unit_dbus_path_from_name(name);
2833 if (!unit_path)
2834 return log_oom();
2835
2836 r = set_put_strdup(wait_context->unit_paths, unit_path);
2837 if (r < 0)
2838 return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path);
2839
2840 mt = strjoina("type='signal',"
2841 "interface='org.freedesktop.DBus.Properties',"
2842 "path='", unit_path, "',"
2843 "member='PropertiesChanged'");
2844 r = sd_bus_add_match(bus, &wait_context->match, mt, on_properties_changed, wait_context);
2845 if (r < 0)
2846 return log_error_errno(r, "Failed to add match for PropertiesChanged signal: %m");
2847 }
2848
2849 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2850
2851 r = sd_bus_call_method(
2852 bus,
2853 "org.freedesktop.systemd1",
2854 "/org/freedesktop/systemd1",
2855 "org.freedesktop.systemd1.Manager",
2856 method,
2857 error,
2858 &reply,
2859 "ss", name, mode);
2860 if (r < 0) {
2861 const char *verb;
2862
2863 /* There's always a fallback possible for legacy actions. */
2864 if (arg_action != ACTION_SYSTEMCTL)
2865 return r;
2866
2867 verb = method_to_verb(method);
2868
2869 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2870
2871 if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
2872 !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
2873 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2874 arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
2875 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
2876 name[0] == '-' ? " --" : "",
2877 name);
2878
2879 return r;
2880 }
2881
2882 r = sd_bus_message_read(reply, "o", &path);
2883 if (r < 0)
2884 return bus_log_parse_error(r);
2885
2886 if (need_daemon_reload(bus, name) > 0)
2887 warn_unit_file_changed(name);
2888
2889 if (w) {
2890 log_debug("Adding %s to the set", path);
2891 r = bus_wait_for_jobs_add(w, path);
2892 if (r < 0)
2893 return log_oom();
2894 }
2895
2896 return 0;
2897 }
2898
2899 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2900 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2901 char **name;
2902 int r, i;
2903
2904 assert(bus);
2905 assert(ret);
2906
2907 STRV_FOREACH(name, names) {
2908 char *t;
2909
2910 if (suffix)
2911 r = unit_name_mangle_with_suffix(*name, UNIT_NAME_GLOB, suffix, &t);
2912 else
2913 r = unit_name_mangle(*name, UNIT_NAME_GLOB, &t);
2914 if (r < 0)
2915 return log_error_errno(r, "Failed to mangle name: %m");
2916
2917 if (string_is_glob(t))
2918 r = strv_consume(&globs, t);
2919 else
2920 r = strv_consume(&mangled, t);
2921 if (r < 0)
2922 return log_oom();
2923 }
2924
2925 /* Query the manager only if any of the names are a glob, since
2926 * this is fairly expensive */
2927 if (!strv_isempty(globs)) {
2928 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2929 _cleanup_free_ UnitInfo *unit_infos = NULL;
2930 size_t allocated, n;
2931
2932 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2933 if (r < 0)
2934 return r;
2935
2936 n = strv_length(mangled);
2937 allocated = n + 1;
2938
2939 for (i = 0; i < r; i++) {
2940 if (!GREEDY_REALLOC(mangled, allocated, n+2))
2941 return log_oom();
2942
2943 mangled[n] = strdup(unit_infos[i].id);
2944 if (!mangled[n])
2945 return log_oom();
2946
2947 mangled[++n] = NULL;
2948 }
2949 }
2950
2951 *ret = mangled;
2952 mangled = NULL; /* do not free */
2953
2954 return 0;
2955 }
2956
2957 static const struct {
2958 const char *target;
2959 const char *verb;
2960 const char *mode;
2961 } action_table[_ACTION_MAX] = {
2962 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2963 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2964 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2965 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2966 [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2967 [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2968 [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2969 [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
2970 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2971 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2972 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2973 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2974 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2975 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2976 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2977 };
2978
2979 static enum action verb_to_action(const char *verb) {
2980 enum action i;
2981
2982 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2983 if (streq_ptr(action_table[i].verb, verb))
2984 return i;
2985
2986 return _ACTION_INVALID;
2987 }
2988
2989 static int start_unit(int argc, char *argv[], void *userdata) {
2990 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2991 const char *method, *mode, *one_name, *suffix = NULL;
2992 _cleanup_strv_free_ char **names = NULL;
2993 sd_bus *bus;
2994 _cleanup_(wait_context_free) WaitContext wait_context = {};
2995 char **name;
2996 int r = 0;
2997
2998 if (arg_wait && !strstr(argv[0], "start")) {
2999 log_error("--wait may only be used with a command that starts units.");
3000 return -EINVAL;
3001 }
3002
3003 /* we cannot do sender tracking on the private bus, so we need the full
3004 * one for RefUnit to implement --wait */
3005 r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
3006 if (r < 0)
3007 return r;
3008
3009 ask_password_agent_open_if_enabled();
3010 polkit_agent_open_if_enabled();
3011
3012 if (arg_action == ACTION_SYSTEMCTL) {
3013 enum action action;
3014
3015 method = verb_to_method(argv[0]);
3016 action = verb_to_action(argv[0]);
3017
3018 if (streq(argv[0], "isolate")) {
3019 mode = "isolate";
3020 suffix = ".target";
3021 } else
3022 mode = action_table[action].mode ?: arg_job_mode;
3023
3024 one_name = action_table[action].target;
3025 } else {
3026 assert(arg_action < ELEMENTSOF(action_table));
3027 assert(action_table[arg_action].target);
3028
3029 method = "StartUnit";
3030
3031 mode = action_table[arg_action].mode;
3032 one_name = action_table[arg_action].target;
3033 }
3034
3035 if (one_name)
3036 names = strv_new(one_name, NULL);
3037 else {
3038 r = expand_names(bus, strv_skip(argv, 1), suffix, &names);
3039 if (r < 0)
3040 return log_error_errno(r, "Failed to expand names: %m");
3041 }
3042
3043 if (!arg_no_block) {
3044 r = bus_wait_for_jobs_new(bus, &w);
3045 if (r < 0)
3046 return log_error_errno(r, "Could not watch jobs: %m");
3047 }
3048
3049 if (arg_wait) {
3050 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3051
3052 wait_context.unit_paths = set_new(&string_hash_ops);
3053 if (!wait_context.unit_paths)
3054 return log_oom();
3055
3056 r = sd_bus_call_method(
3057 bus,
3058 "org.freedesktop.systemd1",
3059 "/org/freedesktop/systemd1",
3060 "org.freedesktop.systemd1.Manager",
3061 "Subscribe",
3062 &error,
3063 NULL, NULL);
3064 if (r < 0)
3065 return log_error_errno(r, "Failed to enable subscription: %s", bus_error_message(&error, r));
3066 r = sd_event_default(&wait_context.event);
3067 if (r < 0)
3068 return log_error_errno(r, "Failed to allocate event loop: %m");
3069 r = sd_bus_attach_event(bus, wait_context.event, 0);
3070 if (r < 0)
3071 return log_error_errno(r, "Failed to attach bus to event loop: %m");
3072 }
3073
3074 STRV_FOREACH(name, names) {
3075 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3076 int q;
3077
3078 q = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
3079 if (r >= 0 && q < 0)
3080 r = translate_bus_error_to_exit_status(q, &error);
3081 }
3082
3083 if (!arg_no_block) {
3084 int q, arg_count = 0;
3085 const char* extra_args[4] = {};
3086
3087 if (arg_scope != UNIT_FILE_SYSTEM)
3088 extra_args[arg_count++] = "--user";
3089
3090 assert(IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_REMOTE, BUS_TRANSPORT_MACHINE));
3091 if (arg_transport == BUS_TRANSPORT_REMOTE) {
3092 extra_args[arg_count++] = "-H";
3093 extra_args[arg_count++] = arg_host;
3094 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
3095 extra_args[arg_count++] = "-M";
3096 extra_args[arg_count++] = arg_host;
3097 }
3098
3099 q = bus_wait_for_jobs(w, arg_quiet, extra_args);
3100 if (q < 0)
3101 return q;
3102
3103 /* When stopping units, warn if they can still be triggered by
3104 * another active unit (socket, path, timer) */
3105 if (!arg_quiet && streq(method, "StopUnit"))
3106 STRV_FOREACH(name, names)
3107 check_triggering_units(bus, *name);
3108 }
3109
3110 if (r >= 0 && arg_wait) {
3111 int q;
3112 q = sd_event_loop(wait_context.event);
3113 if (q < 0)
3114 return log_error_errno(q, "Failed to run event loop: %m");
3115 if (wait_context.any_failed)
3116 r = EXIT_FAILURE;
3117 }
3118
3119 return r;
3120 }
3121
3122 static int logind_set_wall_message(void) {
3123 #ifdef HAVE_LOGIND
3124 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3125 sd_bus *bus;
3126 _cleanup_free_ char *m = NULL;
3127 int r;
3128
3129 r = acquire_bus(BUS_FULL, &bus);
3130 if (r < 0)
3131 return r;
3132
3133 m = strv_join(arg_wall, " ");
3134 if (!m)
3135 return log_oom();
3136
3137 r = sd_bus_call_method(
3138 bus,
3139 "org.freedesktop.login1",
3140 "/org/freedesktop/login1",
3141 "org.freedesktop.login1.Manager",
3142 "SetWallMessage",
3143 &error,
3144 NULL,
3145 "sb",
3146 m,
3147 !arg_no_wall);
3148
3149 if (r < 0)
3150 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
3151
3152 #endif
3153 return 0;
3154 }
3155
3156 /* Ask systemd-logind, which might grant access to unprivileged users
3157 * through PolicyKit */
3158 static int logind_reboot(enum action a) {
3159 #ifdef HAVE_LOGIND
3160 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3161 const char *method, *description;
3162 sd_bus *bus;
3163 int r;
3164
3165 r = acquire_bus(BUS_FULL, &bus);
3166 if (r < 0)
3167 return r;
3168
3169 switch (a) {
3170
3171 case ACTION_REBOOT:
3172 method = "Reboot";
3173 description = "reboot system";
3174 break;
3175
3176 case ACTION_POWEROFF:
3177 method = "PowerOff";
3178 description = "power off system";
3179 break;
3180
3181 case ACTION_SUSPEND:
3182 method = "Suspend";
3183 description = "suspend system";
3184 break;
3185
3186 case ACTION_HIBERNATE:
3187 method = "Hibernate";
3188 description = "hibernate system";
3189 break;
3190
3191 case ACTION_HYBRID_SLEEP:
3192 method = "HybridSleep";
3193 description = "put system into hybrid sleep";
3194 break;
3195
3196 default:
3197 return -EINVAL;
3198 }
3199
3200 polkit_agent_open_if_enabled();
3201 (void) logind_set_wall_message();
3202
3203 r = sd_bus_call_method(
3204 bus,
3205 "org.freedesktop.login1",
3206 "/org/freedesktop/login1",
3207 "org.freedesktop.login1.Manager",
3208 method,
3209 &error,
3210 NULL,
3211 "b", arg_ask_password);
3212 if (r < 0)
3213 return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r));
3214
3215 return 0;
3216 #else
3217 return -ENOSYS;
3218 #endif
3219 }
3220
3221 static int logind_check_inhibitors(enum action a) {
3222 #ifdef HAVE_LOGIND
3223 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3224 _cleanup_strv_free_ char **sessions = NULL;
3225 const char *what, *who, *why, *mode;
3226 uint32_t uid, pid;
3227 sd_bus *bus;
3228 unsigned c = 0;
3229 char **s;
3230 int r;
3231
3232 if (arg_ignore_inhibitors || arg_force > 0)
3233 return 0;
3234
3235 if (arg_when > 0)
3236 return 0;
3237
3238 if (geteuid() == 0)
3239 return 0;
3240
3241 if (!on_tty())
3242 return 0;
3243
3244 if (arg_transport != BUS_TRANSPORT_LOCAL)
3245 return 0;
3246
3247 r = acquire_bus(BUS_FULL, &bus);
3248 if (r < 0)
3249 return r;
3250
3251 r = sd_bus_call_method(
3252 bus,
3253 "org.freedesktop.login1",
3254 "/org/freedesktop/login1",
3255 "org.freedesktop.login1.Manager",
3256 "ListInhibitors",
3257 NULL,
3258 &reply,
3259 NULL);
3260 if (r < 0)
3261 /* If logind is not around, then there are no inhibitors... */
3262 return 0;
3263
3264 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
3265 if (r < 0)
3266 return bus_log_parse_error(r);
3267
3268 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
3269 _cleanup_free_ char *comm = NULL, *user = NULL;
3270 _cleanup_strv_free_ char **sv = NULL;
3271
3272 if (!streq(mode, "block"))
3273 continue;
3274
3275 sv = strv_split(what, ":");
3276 if (!sv)
3277 return log_oom();
3278
3279 if ((pid_t) pid < 0)
3280 return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
3281
3282 if (!strv_contains(sv,
3283 IN_SET(a,
3284 ACTION_HALT,
3285 ACTION_POWEROFF,
3286 ACTION_REBOOT,
3287 ACTION_KEXEC) ? "shutdown" : "sleep"))
3288 continue;
3289
3290 get_process_comm(pid, &comm);
3291 user = uid_to_name(uid);
3292
3293 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
3294 who, (pid_t) pid, strna(comm), strna(user), why);
3295
3296 c++;
3297 }
3298 if (r < 0)
3299 return bus_log_parse_error(r);
3300
3301 r = sd_bus_message_exit_container(reply);
3302 if (r < 0)
3303 return bus_log_parse_error(r);
3304
3305 /* Check for current sessions */
3306 sd_get_sessions(&sessions);
3307 STRV_FOREACH(s, sessions) {
3308 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
3309
3310 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
3311 continue;
3312
3313 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
3314 continue;
3315
3316 if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
3317 continue;
3318
3319 sd_session_get_tty(*s, &tty);
3320 sd_session_get_seat(*s, &seat);
3321 sd_session_get_service(*s, &service);
3322 user = uid_to_name(uid);
3323
3324 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3325 c++;
3326 }
3327
3328 if (c <= 0)
3329 return 0;
3330
3331 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3332 action_table[a].verb);
3333
3334 return -EPERM;
3335 #else
3336 return 0;
3337 #endif
3338 }
3339
3340 static int logind_prepare_firmware_setup(void) {
3341 #ifdef HAVE_LOGIND
3342 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3343 sd_bus *bus;
3344 int r;
3345
3346 r = acquire_bus(BUS_FULL, &bus);
3347 if (r < 0)
3348 return r;
3349
3350 r = sd_bus_call_method(
3351 bus,
3352 "org.freedesktop.login1",
3353 "/org/freedesktop/login1",
3354 "org.freedesktop.login1.Manager",
3355 "SetRebootToFirmwareSetup",
3356 &error,
3357 NULL,
3358 "b", true);
3359 if (r < 0)
3360 return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
3361
3362 return 0;
3363 #else
3364 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3365 return -ENOSYS;
3366 #endif
3367 }
3368
3369 static int prepare_firmware_setup(void) {
3370 int r;
3371
3372 if (!arg_firmware_setup)
3373 return 0;
3374
3375 if (arg_transport == BUS_TRANSPORT_LOCAL) {
3376
3377 r = efi_set_reboot_to_firmware(true);
3378 if (r < 0)
3379 log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3380 else
3381 return r;
3382 }
3383
3384 return logind_prepare_firmware_setup();
3385 }
3386
3387 static int set_exit_code(uint8_t code) {
3388 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3389 sd_bus *bus;
3390 int r;
3391
3392 r = acquire_bus(BUS_MANAGER, &bus);
3393 if (r < 0)
3394 return r;
3395
3396 r = sd_bus_call_method(
3397 bus,
3398 "org.freedesktop.systemd1",
3399 "/org/freedesktop/systemd1",
3400 "org.freedesktop.systemd1.Manager",
3401 "SetExitCode",
3402 &error,
3403 NULL,
3404 "y", code);
3405 if (r < 0)
3406 return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
3407
3408 return 0;
3409 }
3410
3411 static int start_special(int argc, char *argv[], void *userdata) {
3412 enum action a;
3413 int r;
3414
3415 assert(argv);
3416
3417 a = verb_to_action(argv[0]);
3418
3419 r = logind_check_inhibitors(a);
3420 if (r < 0)
3421 return r;
3422
3423 if (arg_force >= 2 && geteuid() != 0) {
3424 log_error("Must be root.");
3425 return -EPERM;
3426 }
3427
3428 r = prepare_firmware_setup();
3429 if (r < 0)
3430 return r;
3431
3432 if (a == ACTION_REBOOT && argc > 1) {
3433 r = update_reboot_parameter_and_warn(argv[1]);
3434 if (r < 0)
3435 return r;
3436
3437 } else if (a == ACTION_EXIT && argc > 1) {
3438 uint8_t code;
3439
3440 /* If the exit code is not given on the command line,
3441 * don't reset it to zero: just keep it as it might
3442 * have been set previously. */
3443
3444 r = safe_atou8(argv[1], &code);
3445 if (r < 0)
3446 return log_error_errno(r, "Invalid exit code.");
3447
3448 r = set_exit_code(code);
3449 if (r < 0)
3450 return r;
3451 }
3452
3453 if (arg_force >= 2 &&
3454 IN_SET(a,
3455 ACTION_HALT,
3456 ACTION_POWEROFF,
3457 ACTION_REBOOT))
3458 return halt_now(a);
3459
3460 if (arg_force >= 1 &&
3461 IN_SET(a,
3462 ACTION_HALT,
3463 ACTION_POWEROFF,
3464 ACTION_REBOOT,
3465 ACTION_KEXEC,
3466 ACTION_EXIT))
3467 return trivial_method(argc, argv, userdata);
3468
3469 /* First try logind, to allow authentication with polkit */
3470 if (IN_SET(a,
3471 ACTION_POWEROFF,
3472 ACTION_REBOOT,
3473 ACTION_SUSPEND,
3474 ACTION_HIBERNATE,
3475 ACTION_HYBRID_SLEEP)) {
3476 r = logind_reboot(a);
3477 if (r >= 0)
3478 return r;
3479 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
3480 /* requested operation is not supported or already in progress */
3481 return r;
3482
3483 /* On all other errors, try low-level operation */
3484 }
3485
3486 return start_unit(argc, argv, userdata);
3487 }
3488
3489 static int start_system_special(int argc, char *argv[], void *userdata) {
3490 /* Like start_special above, but raises an error when running in user mode */
3491
3492 if (arg_scope != UNIT_FILE_SYSTEM) {
3493 log_error("Bad action for %s mode.",
3494 arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
3495 return -EINVAL;
3496 }
3497
3498 return start_special(argc, argv, userdata);
3499 }
3500
3501 static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
3502 _cleanup_strv_free_ char **names = NULL;
3503 UnitActiveState active_state;
3504 sd_bus *bus;
3505 char **name;
3506 int r, i;
3507 bool found = false;
3508
3509 r = acquire_bus(BUS_MANAGER, &bus);
3510 if (r < 0)
3511 return r;
3512
3513 r = expand_names(bus, args, NULL, &names);
3514 if (r < 0)
3515 return log_error_errno(r, "Failed to expand names: %m");
3516
3517 STRV_FOREACH(name, names) {
3518 r = get_state_one_unit(bus, *name, &active_state);
3519 if (r < 0)
3520 return r;
3521
3522 if (!arg_quiet)
3523 puts(unit_active_state_to_string(active_state));
3524
3525 for (i = 0; i < nb_states; ++i)
3526 if (good_states[i] == active_state)
3527 found = true;
3528 }
3529
3530 /* use the given return code for the case that we won't find
3531 * any unit which matches the list */
3532 return found ? 0 : code;
3533 }
3534
3535 static int check_unit_active(int argc, char *argv[], void *userdata) {
3536 const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
3537 /* According to LSB: 3, "program is not running" */
3538 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
3539 }
3540
3541 static int check_unit_failed(int argc, char *argv[], void *userdata) {
3542 const UnitActiveState states[] = { UNIT_FAILED };
3543 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
3544 }
3545
3546 static int kill_unit(int argc, char *argv[], void *userdata) {
3547 _cleanup_strv_free_ char **names = NULL;
3548 char *kill_who = NULL, **name;
3549 sd_bus *bus;
3550 int r, q;
3551
3552 r = acquire_bus(BUS_MANAGER, &bus);
3553 if (r < 0)
3554 return r;
3555
3556 polkit_agent_open_if_enabled();
3557
3558 if (!arg_kill_who)
3559 arg_kill_who = "all";
3560
3561 /* --fail was specified */
3562 if (streq(arg_job_mode, "fail"))
3563 kill_who = strjoina(arg_kill_who, "-fail");
3564
3565 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
3566 if (r < 0)
3567 return log_error_errno(r, "Failed to expand names: %m");
3568
3569 STRV_FOREACH(name, names) {
3570 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3571
3572 q = sd_bus_call_method(
3573 bus,
3574 "org.freedesktop.systemd1",
3575 "/org/freedesktop/systemd1",
3576 "org.freedesktop.systemd1.Manager",
3577 "KillUnit",
3578 &error,
3579 NULL,
3580 "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
3581 if (q < 0) {
3582 log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
3583 if (r == 0)
3584 r = q;
3585 }
3586 }
3587
3588 return r;
3589 }
3590
3591 typedef struct ExecStatusInfo {
3592 char *name;
3593
3594 char *path;
3595 char **argv;
3596
3597 bool ignore;
3598
3599 usec_t start_timestamp;
3600 usec_t exit_timestamp;
3601 pid_t pid;
3602 int code;
3603 int status;
3604
3605 LIST_FIELDS(struct ExecStatusInfo, exec);
3606 } ExecStatusInfo;
3607
3608 static void exec_status_info_free(ExecStatusInfo *i) {
3609 assert(i);
3610
3611 free(i->name);
3612 free(i->path);
3613 strv_free(i->argv);
3614 free(i);
3615 }
3616
3617 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3618 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3619 const char *path;
3620 uint32_t pid;
3621 int32_t code, status;
3622 int ignore, r;
3623
3624 assert(m);
3625 assert(i);
3626
3627 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3628 if (r < 0)
3629 return bus_log_parse_error(r);
3630 else if (r == 0)
3631 return 0;
3632
3633 r = sd_bus_message_read(m, "s", &path);
3634 if (r < 0)
3635 return bus_log_parse_error(r);
3636
3637 i->path = strdup(path);
3638 if (!i->path)
3639 return log_oom();
3640
3641 r = sd_bus_message_read_strv(m, &i->argv);
3642 if (r < 0)
3643 return bus_log_parse_error(r);
3644
3645 r = sd_bus_message_read(m,
3646 "bttttuii",
3647 &ignore,
3648 &start_timestamp, &start_timestamp_monotonic,
3649 &exit_timestamp, &exit_timestamp_monotonic,
3650 &pid,
3651 &code, &status);
3652 if (r < 0)
3653 return bus_log_parse_error(r);
3654
3655 i->ignore = ignore;
3656 i->start_timestamp = (usec_t) start_timestamp;
3657 i->exit_timestamp = (usec_t) exit_timestamp;
3658 i->pid = (pid_t) pid;
3659 i->code = code;
3660 i->status = status;
3661
3662 r = sd_bus_message_exit_container(m);
3663 if (r < 0)
3664 return bus_log_parse_error(r);
3665
3666 return 1;
3667 }
3668
3669 typedef struct UnitCondition {
3670 char *name;
3671 char *param;
3672 bool trigger;
3673 bool negate;
3674 int tristate;
3675
3676 LIST_FIELDS(struct UnitCondition, conditions);
3677 } UnitCondition;
3678
3679 static void unit_condition_free(UnitCondition *c) {
3680 if (!c)
3681 return;
3682
3683 free(c->name);
3684 free(c->param);
3685 free(c);
3686 }
3687
3688 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
3689
3690 typedef struct UnitStatusInfo {
3691 const char *id;
3692 const char *load_state;
3693 const char *active_state;
3694 const char *sub_state;
3695 const char *unit_file_state;
3696 const char *unit_file_preset;
3697
3698 const char *description;
3699 const char *following;
3700
3701 char **documentation;
3702
3703 const char *fragment_path;
3704 const char *source_path;
3705 const char *control_group;
3706
3707 char **dropin_paths;
3708
3709 const char *load_error;
3710 const char *result;
3711
3712 usec_t inactive_exit_timestamp;
3713 usec_t inactive_exit_timestamp_monotonic;
3714 usec_t active_enter_timestamp;
3715 usec_t active_exit_timestamp;
3716 usec_t inactive_enter_timestamp;
3717
3718 bool need_daemon_reload;
3719 bool transient;
3720
3721 /* Service */
3722 pid_t main_pid;
3723 pid_t control_pid;
3724 const char *status_text;
3725 const char *pid_file;
3726 bool running:1;
3727 int status_errno;
3728
3729 usec_t start_timestamp;
3730 usec_t exit_timestamp;
3731
3732 int exit_code, exit_status;
3733
3734 usec_t condition_timestamp;
3735 bool condition_result;
3736 LIST_HEAD(UnitCondition, conditions);
3737
3738 usec_t assert_timestamp;
3739 bool assert_result;
3740 bool failed_assert_trigger;
3741 bool failed_assert_negate;
3742 const char *failed_assert;
3743 const char *failed_assert_parameter;
3744
3745 /* Socket */
3746 unsigned n_accepted;
3747 unsigned n_connections;
3748 bool accept;
3749
3750 /* Pairs of type, path */
3751 char **listen;
3752
3753 /* Device */
3754 const char *sysfs_path;
3755
3756 /* Mount, Automount */
3757 const char *where;
3758
3759 /* Swap */
3760 const char *what;
3761
3762 /* CGroup */
3763 uint64_t memory_current;
3764 uint64_t memory_low;
3765 uint64_t memory_high;
3766 uint64_t memory_max;
3767 uint64_t memory_swap_max;
3768 uint64_t memory_limit;
3769 uint64_t cpu_usage_nsec;
3770 uint64_t tasks_current;
3771 uint64_t tasks_max;
3772
3773 LIST_HEAD(ExecStatusInfo, exec);
3774 } UnitStatusInfo;
3775
3776 static void unit_status_info_free(UnitStatusInfo *info) {
3777 ExecStatusInfo *p;
3778 UnitCondition *c;
3779
3780 strv_free(info->documentation);
3781 strv_free(info->dropin_paths);
3782 strv_free(info->listen);
3783
3784 while ((c = info->conditions)) {
3785 LIST_REMOVE(conditions, info->conditions, c);
3786 unit_condition_free(c);
3787 }
3788
3789 while ((p = info->exec)) {
3790 LIST_REMOVE(exec, info->exec, p);
3791 exec_status_info_free(p);
3792 }
3793 }
3794
3795 static void print_status_info(
3796 sd_bus *bus,
3797 UnitStatusInfo *i,
3798 bool *ellipsized) {
3799
3800 ExecStatusInfo *p;
3801 const char *active_on, *active_off, *on, *off, *ss;
3802 usec_t timestamp;
3803 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3804 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3805 const char *path;
3806 char **t, **t2;
3807 int r;
3808
3809 assert(i);
3810
3811 /* This shows pretty information about a unit. See
3812 * print_property() for a low-level property printer */
3813
3814 if (streq_ptr(i->active_state, "failed")) {
3815 active_on = ansi_highlight_red();
3816 active_off = ansi_normal();
3817 } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) {
3818 active_on = ansi_highlight_green();
3819 active_off = ansi_normal();
3820 } else
3821 active_on = active_off = "";
3822
3823 printf("%s%s%s %s", active_on, special_glyph(BLACK_CIRCLE), active_off, strna(i->id));
3824
3825 if (i->description && !streq_ptr(i->id, i->description))
3826 printf(" - %s", i->description);
3827
3828 printf("\n");
3829
3830 if (i->following)
3831 printf(" Follow: unit currently follows state of %s\n", i->following);
3832
3833 if (streq_ptr(i->load_state, "error")) {
3834 on = ansi_highlight_red();
3835 off = ansi_normal();
3836 } else
3837 on = off = "";
3838
3839 path = i->source_path ? i->source_path : i->fragment_path;
3840
3841 if (i->load_error != 0)
3842 printf(" Loaded: %s%s%s (Reason: %s)\n",
3843 on, strna(i->load_state), off, i->load_error);
3844 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3845 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3846 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3847 else if (path && !isempty(i->unit_file_state))
3848 printf(" Loaded: %s%s%s (%s; %s)\n",
3849 on, strna(i->load_state), off, path, i->unit_file_state);
3850 else if (path)
3851 printf(" Loaded: %s%s%s (%s)\n",
3852 on, strna(i->load_state), off, path);
3853 else
3854 printf(" Loaded: %s%s%s\n",
3855 on, strna(i->load_state), off);
3856
3857 if (i->transient)
3858 printf("Transient: yes\n");
3859
3860 if (!strv_isempty(i->dropin_paths)) {
3861 _cleanup_free_ char *dir = NULL;
3862 bool last = false;
3863 char ** dropin;
3864
3865 STRV_FOREACH(dropin, i->dropin_paths) {
3866 if (! dir || last) {
3867 printf(dir ? " " : " Drop-In: ");
3868
3869 dir = mfree(dir);
3870
3871 dir = dirname_malloc(*dropin);
3872 if (!dir) {
3873 log_oom();
3874 return;
3875 }
3876
3877 printf("%s\n %s", dir,
3878 special_glyph(TREE_RIGHT));
3879 }
3880
3881 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3882
3883 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3884 }
3885 }
3886
3887 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3888 if (ss)
3889 printf(" Active: %s%s (%s)%s",
3890 active_on, strna(i->active_state), ss, active_off);
3891 else
3892 printf(" Active: %s%s%s",
3893 active_on, strna(i->active_state), active_off);
3894
3895 if (!isempty(i->result) && !streq(i->result, "success"))
3896 printf(" (Result: %s)", i->result);
3897
3898 timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
3899 STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
3900 STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
3901 i->active_exit_timestamp;
3902
3903 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3904 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3905
3906 if (s1)
3907 printf(" since %s; %s\n", s2, s1);
3908 else if (s2)
3909 printf(" since %s\n", s2);
3910 else
3911 printf("\n");
3912
3913 if (!i->condition_result && i->condition_timestamp > 0) {
3914 UnitCondition *c;
3915 int n = 0;
3916
3917 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3918 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3919
3920 printf("Condition: start %scondition failed%s at %s%s%s\n",
3921 ansi_highlight_yellow(), ansi_normal(),
3922 s2, s1 ? "; " : "", strempty(s1));
3923
3924 LIST_FOREACH(conditions, c, i->conditions)
3925 if (c->tristate < 0)
3926 n++;
3927
3928 LIST_FOREACH(conditions, c, i->conditions)
3929 if (c->tristate < 0)
3930 printf(" %s %s=%s%s%s was not met\n",
3931 --n ? special_glyph(TREE_BRANCH) : special_glyph(TREE_RIGHT),
3932 c->name,
3933 c->trigger ? "|" : "",
3934 c->negate ? "!" : "",
3935 c->param);
3936 }
3937
3938 if (!i->assert_result && i->assert_timestamp > 0) {
3939 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3940 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3941
3942 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3943 ansi_highlight_red(), ansi_normal(),
3944 s2, s1 ? "; " : "", strempty(s1));
3945 if (i->failed_assert_trigger)
3946 printf(" none of the trigger assertions were met\n");
3947 else if (i->failed_assert)
3948 printf(" %s=%s%s was not met\n",
3949 i->failed_assert,
3950 i->failed_assert_negate ? "!" : "",
3951 i->failed_assert_parameter);
3952 }
3953
3954 if (i->sysfs_path)
3955 printf(" Device: %s\n", i->sysfs_path);
3956 if (i->where)
3957 printf(" Where: %s\n", i->where);
3958 if (i->what)
3959 printf(" What: %s\n", i->what);
3960
3961 STRV_FOREACH(t, i->documentation)
3962 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3963
3964 STRV_FOREACH_PAIR(t, t2, i->listen)
3965 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3966
3967 if (i->accept)
3968 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3969
3970 LIST_FOREACH(exec, p, i->exec) {
3971 _cleanup_free_ char *argv = NULL;
3972 bool good;
3973
3974 /* Only show exited processes here */
3975 if (p->code == 0)
3976 continue;
3977
3978 argv = strv_join(p->argv, " ");
3979 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
3980
3981 good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
3982 if (!good) {
3983 on = ansi_highlight_red();
3984 off = ansi_normal();
3985 } else
3986 on = off = "";
3987
3988 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3989
3990 if (p->code == CLD_EXITED) {
3991 const char *c;
3992
3993 printf("status=%i", p->status);
3994
3995 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3996 if (c)
3997 printf("/%s", c);
3998
3999 } else
4000 printf("signal=%s", signal_to_string(p->status));
4001
4002 printf(")%s\n", off);
4003
4004 if (i->main_pid == p->pid &&
4005 i->start_timestamp == p->start_timestamp &&
4006 i->exit_timestamp == p->start_timestamp)
4007 /* Let's not show this twice */
4008 i->main_pid = 0;
4009
4010 if (p->pid == i->control_pid)
4011 i->control_pid = 0;
4012 }
4013
4014 if (i->main_pid > 0 || i->control_pid > 0) {
4015 if (i->main_pid > 0) {
4016 printf(" Main PID: "PID_FMT, i->main_pid);
4017
4018 if (i->running) {
4019 _cleanup_free_ char *comm = NULL;
4020 (void) get_process_comm(i->main_pid, &comm);
4021 if (comm)
4022 printf(" (%s)", comm);
4023 } else if (i->exit_code > 0) {
4024 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
4025
4026 if (i->exit_code == CLD_EXITED) {
4027 const char *c;
4028
4029 printf("status=%i", i->exit_status);
4030
4031 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
4032 if (c)
4033 printf("/%s", c);
4034
4035 } else
4036 printf("signal=%s", signal_to_string(i->exit_status));
4037 printf(")");
4038 }
4039 }
4040
4041 if (i->control_pid > 0) {
4042 _cleanup_free_ char *c = NULL;
4043
4044 if (i->main_pid > 0)
4045 fputs("; Control PID: ", stdout);
4046 else
4047 fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
4048
4049 printf(PID_FMT, i->control_pid);
4050
4051 (void) get_process_comm(i->control_pid, &c);
4052 if (c)
4053 printf(" (%s)", c);
4054 }
4055
4056 printf("\n");
4057 }
4058
4059 if (i->status_text)
4060 printf(" Status: \"%s\"\n", i->status_text);
4061 if (i->status_errno > 0)
4062 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
4063
4064 if (i->tasks_current != (uint64_t) -1) {
4065 printf(" Tasks: %" PRIu64, i->tasks_current);
4066
4067 if (i->tasks_max != (uint64_t) -1)
4068 printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
4069 else
4070 printf("\n");
4071 }
4072
4073 if (i->memory_current != (uint64_t) -1) {
4074 char buf[FORMAT_BYTES_MAX];
4075
4076 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
4077
4078 if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX ||
4079 i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX ||
4080 i->memory_limit != CGROUP_LIMIT_MAX) {
4081 const char *prefix = "";
4082
4083 printf(" (");
4084 if (i->memory_low > 0) {
4085 printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low));
4086 prefix = " ";
4087 }
4088 if (i->memory_high != CGROUP_LIMIT_MAX) {
4089 printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
4090 prefix = " ";
4091 }
4092 if (i->memory_max != CGROUP_LIMIT_MAX) {
4093 printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
4094 prefix = " ";
4095 }
4096 if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
4097 printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
4098 prefix = " ";
4099 }
4100 if (i->memory_limit != CGROUP_LIMIT_MAX) {
4101 printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
4102 prefix = " ";
4103 }
4104 printf(")");
4105 }
4106 printf("\n");
4107 }
4108
4109 if (i->cpu_usage_nsec != (uint64_t) -1) {
4110 char buf[FORMAT_TIMESPAN_MAX];
4111 printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
4112 }
4113
4114 if (i->control_group) {
4115 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4116 static const char prefix[] = " ";
4117 unsigned c;
4118
4119 printf(" CGroup: %s\n", i->control_group);
4120
4121 c = columns();
4122 if (c > sizeof(prefix) - 1)
4123 c -= sizeof(prefix) - 1;
4124 else
4125 c = 0;
4126
4127 r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
4128 if (r == -EBADR) {
4129 unsigned k = 0;
4130 pid_t extra[2];
4131
4132 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4133
4134 if (i->main_pid > 0)
4135 extra[k++] = i->main_pid;
4136
4137 if (i->control_pid > 0)
4138 extra[k++] = i->control_pid;
4139
4140 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
4141 } else if (r < 0)
4142 log_warning_errno(r, "Failed to dump process list, ignoring: %s", bus_error_message(&error, r));
4143 }
4144
4145 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
4146 show_journal_by_unit(
4147 stdout,
4148 i->id,
4149 arg_output,
4150 0,
4151 i->inactive_exit_timestamp_monotonic,
4152 arg_lines,
4153 getuid(),
4154 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
4155 SD_JOURNAL_LOCAL_ONLY,
4156 arg_scope == UNIT_FILE_SYSTEM,
4157 ellipsized);
4158
4159 if (i->need_daemon_reload)
4160 warn_unit_file_changed(i->id);
4161 }
4162
4163 static void show_unit_help(UnitStatusInfo *i) {
4164 char **p;
4165
4166 assert(i);
4167
4168 if (!i->documentation) {
4169 log_info("Documentation for %s not known.", i->id);
4170 return;
4171 }
4172
4173 STRV_FOREACH(p, i->documentation)
4174 if (startswith(*p, "man:"))
4175 show_man_page(*p + 4, false);
4176 else
4177 log_info("Can't show: %s", *p);
4178 }
4179
4180 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
4181 int r;
4182
4183 assert(name);
4184 assert(m);
4185 assert(i);
4186
4187 switch (contents[0]) {
4188
4189 case SD_BUS_TYPE_STRING: {
4190 const char *s;
4191
4192 r = sd_bus_message_read(m, "s", &s);
4193 if (r < 0)
4194 return bus_log_parse_error(r);
4195
4196 if (!isempty(s)) {
4197 if (streq(name, "Id"))
4198 i->id = s;
4199 else if (streq(name, "LoadState"))
4200 i->load_state = s;
4201 else if (streq(name, "ActiveState"))
4202 i->active_state = s;
4203 else if (streq(name, "SubState"))
4204 i->sub_state = s;
4205 else if (streq(name, "Description"))
4206 i->description = s;
4207 else if (streq(name, "FragmentPath"))
4208 i->fragment_path = s;
4209 else if (streq(name, "SourcePath"))
4210 i->source_path = s;
4211 #ifndef NOLEGACY
4212 else if (streq(name, "DefaultControlGroup")) {
4213 const char *e;
4214 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
4215 if (e)
4216 i->control_group = e;
4217 }
4218 #endif
4219 else if (streq(name, "ControlGroup"))
4220 i->control_group = s;
4221 else if (streq(name, "StatusText"))
4222 i->status_text = s;
4223 else if (streq(name, "PIDFile"))
4224 i->pid_file = s;
4225 else if (streq(name, "SysFSPath"))
4226 i->sysfs_path = s;
4227 else if (streq(name, "Where"))
4228 i->where = s;
4229 else if (streq(name, "What"))
4230 i->what = s;
4231 else if (streq(name, "Following"))
4232 i->following = s;
4233 else if (streq(name, "UnitFileState"))
4234 i->unit_file_state = s;
4235 else if (streq(name, "UnitFilePreset"))
4236 i->unit_file_preset = s;
4237 else if (streq(name, "Result"))
4238 i->result = s;
4239 }
4240
4241 break;
4242 }
4243
4244 case SD_BUS_TYPE_BOOLEAN: {
4245 int b;
4246
4247 r = sd_bus_message_read(m, "b", &b);
4248 if (r < 0)
4249 return bus_log_parse_error(r);
4250
4251 if (streq(name, "Accept"))
4252 i->accept = b;
4253 else if (streq(name, "NeedDaemonReload"))
4254 i->need_daemon_reload = b;
4255 else if (streq(name, "ConditionResult"))
4256 i->condition_result = b;
4257 else if (streq(name, "AssertResult"))
4258 i->assert_result = b;
4259 else if (streq(name, "Transient"))
4260 i->transient = b;
4261
4262 break;
4263 }
4264
4265 case SD_BUS_TYPE_UINT32: {
4266 uint32_t u;
4267
4268 r = sd_bus_message_read(m, "u", &u);
4269 if (r < 0)
4270 return bus_log_parse_error(r);
4271
4272 if (streq(name, "MainPID")) {
4273 if (u > 0) {
4274 i->main_pid = (pid_t) u;
4275 i->running = true;
4276 }
4277 } else if (streq(name, "ControlPID"))
4278 i->control_pid = (pid_t) u;
4279 else if (streq(name, "ExecMainPID")) {
4280 if (u > 0)
4281 i->main_pid = (pid_t) u;
4282 } else if (streq(name, "NAccepted"))
4283 i->n_accepted = u;
4284 else if (streq(name, "NConnections"))
4285 i->n_connections = u;
4286
4287 break;
4288 }
4289
4290 case SD_BUS_TYPE_INT32: {
4291 int32_t j;
4292
4293 r = sd_bus_message_read(m, "i", &j);
4294 if (r < 0)
4295 return bus_log_parse_error(r);
4296
4297 if (streq(name, "ExecMainCode"))
4298 i->exit_code = (int) j;
4299 else if (streq(name, "ExecMainStatus"))
4300 i->exit_status = (int) j;
4301 else if (streq(name, "StatusErrno"))
4302 i->status_errno = (int) j;
4303
4304 break;
4305 }
4306
4307 case SD_BUS_TYPE_UINT64: {
4308 uint64_t u;
4309
4310 r = sd_bus_message_read(m, "t", &u);
4311 if (r < 0)
4312 return bus_log_parse_error(r);
4313
4314 if (streq(name, "ExecMainStartTimestamp"))
4315 i->start_timestamp = (usec_t) u;
4316 else if (streq(name, "ExecMainExitTimestamp"))
4317 i->exit_timestamp = (usec_t) u;
4318 else if (streq(name, "ActiveEnterTimestamp"))
4319 i->active_enter_timestamp = (usec_t) u;
4320 else if (streq(name, "InactiveEnterTimestamp"))
4321 i->inactive_enter_timestamp = (usec_t) u;
4322 else if (streq(name, "InactiveExitTimestamp"))
4323 i->inactive_exit_timestamp = (usec_t) u;
4324 else if (streq(name, "InactiveExitTimestampMonotonic"))
4325 i->inactive_exit_timestamp_monotonic = (usec_t) u;
4326 else if (streq(name, "ActiveExitTimestamp"))
4327 i->active_exit_timestamp = (usec_t) u;
4328 else if (streq(name, "ConditionTimestamp"))
4329 i->condition_timestamp = (usec_t) u;
4330 else if (streq(name, "AssertTimestamp"))
4331 i->assert_timestamp = (usec_t) u;
4332 else if (streq(name, "MemoryCurrent"))
4333 i->memory_current = u;
4334 else if (streq(name, "MemoryLow"))
4335 i->memory_low = u;
4336 else if (streq(name, "MemoryHigh"))
4337 i->memory_high = u;
4338 else if (streq(name, "MemoryMax"))
4339 i->memory_max = u;
4340 else if (streq(name, "MemorySwapMax"))
4341 i->memory_swap_max = u;
4342 else if (streq(name, "MemoryLimit"))
4343 i->memory_limit = u;
4344 else if (streq(name, "TasksCurrent"))
4345 i->tasks_current = u;
4346 else if (streq(name, "TasksMax"))
4347 i->tasks_max = u;
4348 else if (streq(name, "CPUUsageNSec"))
4349 i->cpu_usage_nsec = u;
4350
4351 break;
4352 }
4353
4354 case SD_BUS_TYPE_ARRAY:
4355
4356 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4357 _cleanup_free_ ExecStatusInfo *info = NULL;
4358
4359 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4360 if (r < 0)
4361 return bus_log_parse_error(r);
4362
4363 info = new0(ExecStatusInfo, 1);
4364 if (!info)
4365 return log_oom();
4366
4367 while ((r = exec_status_info_deserialize(m, info)) > 0) {
4368
4369 info->name = strdup(name);
4370 if (!info->name)
4371 return log_oom();
4372
4373 LIST_PREPEND(exec, i->exec, info);
4374
4375 info = new0(ExecStatusInfo, 1);
4376 if (!info)
4377 return log_oom();
4378 }
4379
4380 if (r < 0)
4381 return bus_log_parse_error(r);
4382
4383 r = sd_bus_message_exit_container(m);
4384 if (r < 0)
4385 return bus_log_parse_error(r);
4386
4387 return 0;
4388
4389 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4390 const char *type, *path;
4391
4392 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4393 if (r < 0)
4394 return bus_log_parse_error(r);
4395
4396 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
4397
4398 r = strv_extend(&i->listen, type);
4399 if (r < 0)
4400 return r;
4401
4402 r = strv_extend(&i->listen, path);
4403 if (r < 0)
4404 return r;
4405 }
4406 if (r < 0)
4407 return bus_log_parse_error(r);
4408
4409 r = sd_bus_message_exit_container(m);
4410 if (r < 0)
4411 return bus_log_parse_error(r);
4412
4413 return 0;
4414
4415 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
4416
4417 r = sd_bus_message_read_strv(m, &i->dropin_paths);
4418 if (r < 0)
4419 return bus_log_parse_error(r);
4420
4421 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
4422
4423 r = sd_bus_message_read_strv(m, &i->documentation);
4424 if (r < 0)
4425 return bus_log_parse_error(r);
4426
4427 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
4428 const char *cond, *param;
4429 int trigger, negate;
4430 int32_t state;
4431
4432 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4433 if (r < 0)
4434 return bus_log_parse_error(r);
4435
4436 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4437 _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
4438
4439 log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state);
4440
4441 c = new0(UnitCondition, 1);
4442 if (!c)
4443 return log_oom();
4444
4445 c->name = strdup(cond);
4446 c->param = strdup(param);
4447 if (!c->name || !c->param)
4448 return log_oom();
4449
4450 c->trigger = trigger;
4451 c->negate = negate;
4452 c->tristate = state;
4453
4454 LIST_PREPEND(conditions, i->conditions, c);
4455 c = NULL;
4456 }
4457 if (r < 0)
4458 return bus_log_parse_error(r);
4459
4460 r = sd_bus_message_exit_container(m);
4461 if (r < 0)
4462 return bus_log_parse_error(r);
4463
4464 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
4465 const char *cond, *param;
4466 int trigger, negate;
4467 int32_t state;
4468
4469 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4470 if (r < 0)
4471 return bus_log_parse_error(r);
4472
4473 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4474 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
4475 if (state < 0 && (!trigger || !i->failed_assert)) {
4476 i->failed_assert = cond;
4477 i->failed_assert_trigger = trigger;
4478 i->failed_assert_negate = negate;
4479 i->failed_assert_parameter = param;
4480 }
4481 }
4482 if (r < 0)
4483 return bus_log_parse_error(r);
4484
4485 r = sd_bus_message_exit_container(m);
4486 if (r < 0)
4487 return bus_log_parse_error(r);
4488
4489 } else
4490 goto skip;
4491
4492 break;
4493
4494 case SD_BUS_TYPE_STRUCT_BEGIN:
4495
4496 if (streq(name, "LoadError")) {
4497 const char *n, *message;
4498
4499 r = sd_bus_message_read(m, "(ss)", &n, &message);
4500 if (r < 0)
4501 return bus_log_parse_error(r);
4502
4503 if (!isempty(message))
4504 i->load_error = message;
4505 } else
4506 goto skip;
4507
4508 break;
4509
4510 default:
4511 goto skip;
4512 }
4513
4514 return 0;
4515
4516 skip:
4517 r = sd_bus_message_skip(m, contents);
4518 if (r < 0)
4519 return bus_log_parse_error(r);
4520
4521 return 0;
4522 }
4523
4524 #define print_prop(name, fmt, ...) \
4525 do { \
4526 if (arg_value) \
4527 printf(fmt "\n", __VA_ARGS__); \
4528 else \
4529 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4530 } while(0)
4531
4532 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
4533 int r;
4534
4535 assert(name);
4536 assert(m);
4537
4538 /* This is a low-level property printer, see
4539 * print_status_info() for the nicer output */
4540
4541 if (arg_properties && !strv_find(arg_properties, name)) {
4542 /* skip what we didn't read */
4543 r = sd_bus_message_skip(m, contents);
4544 return r;
4545 }
4546
4547 switch (contents[0]) {
4548
4549 case SD_BUS_TYPE_STRUCT_BEGIN:
4550
4551 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
4552 uint32_t u;
4553
4554 r = sd_bus_message_read(m, "(uo)", &u, NULL);
4555 if (r < 0)
4556 return bus_log_parse_error(r);
4557
4558 if (u > 0)
4559 print_prop(name, "%"PRIu32, u);
4560 else if (arg_all)
4561 print_prop(name, "%s", "");
4562
4563 return 0;
4564
4565 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
4566 const char *s;
4567
4568 r = sd_bus_message_read(m, "(so)", &s, NULL);
4569 if (r < 0)
4570 return bus_log_parse_error(r);
4571
4572 if (arg_all || !isempty(s))
4573 print_prop(name, "%s", s);
4574
4575 return 0;
4576
4577 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
4578 const char *a = NULL, *b = NULL;
4579
4580 r = sd_bus_message_read(m, "(ss)", &a, &b);
4581 if (r < 0)
4582 return bus_log_parse_error(r);
4583
4584 if (arg_all || !isempty(a) || !isempty(b))
4585 print_prop(name, "%s \"%s\"", strempty(a), strempty(b));
4586
4587 return 0;
4588 } else if (streq_ptr(name, "SystemCallFilter")) {
4589 _cleanup_strv_free_ char **l = NULL;
4590 int whitelist;
4591
4592 r = sd_bus_message_enter_container(m, 'r', "bas");
4593 if (r < 0)
4594 return bus_log_parse_error(r);
4595
4596 r = sd_bus_message_read(m, "b", &whitelist);
4597 if (r < 0)
4598 return bus_log_parse_error(r);
4599
4600 r = sd_bus_message_read_strv(m, &l);
4601 if (r < 0)
4602 return bus_log_parse_error(r);
4603
4604 r = sd_bus_message_exit_container(m);
4605 if (r < 0)
4606 return bus_log_parse_error(r);
4607
4608 if (arg_all || whitelist || !strv_isempty(l)) {
4609 bool first = true;
4610 char **i;
4611
4612 if (!arg_value) {
4613 fputs(name, stdout);
4614 fputc('=', stdout);
4615 }
4616
4617 if (!whitelist)
4618 fputc('~', stdout);
4619
4620 STRV_FOREACH(i, l) {
4621 if (first)
4622 first = false;
4623 else
4624 fputc(' ', stdout);
4625
4626 fputs(*i, stdout);
4627 }
4628 fputc('\n', stdout);
4629 }
4630
4631 return 0;
4632 }
4633
4634 break;
4635
4636 case SD_BUS_TYPE_ARRAY:
4637
4638 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4639 const char *path;
4640 int ignore;
4641
4642 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4643 if (r < 0)
4644 return bus_log_parse_error(r);
4645
4646 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4647 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path, yes_no(ignore));
4648
4649 if (r < 0)
4650 return bus_log_parse_error(r);
4651
4652 r = sd_bus_message_exit_container(m);
4653 if (r < 0)
4654 return bus_log_parse_error(r);
4655
4656 return 0;
4657
4658 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4659 const char *type, *path;
4660
4661 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4662 if (r < 0)
4663 return bus_log_parse_error(r);
4664
4665 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4666 print_prop(type, "%s", path);
4667 if (r < 0)
4668 return bus_log_parse_error(r);
4669
4670 r = sd_bus_message_exit_container(m);
4671 if (r < 0)
4672 return bus_log_parse_error(r);
4673
4674 return 0;
4675
4676 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4677 const char *type, *path;
4678
4679 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4680 if (r < 0)
4681 return bus_log_parse_error(r);
4682
4683 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4684 if (arg_value)
4685 puts(path);
4686 else
4687 printf("Listen%s=%s\n", type, path);
4688 if (r < 0)
4689 return bus_log_parse_error(r);
4690
4691 r = sd_bus_message_exit_container(m);
4692 if (r < 0)
4693 return bus_log_parse_error(r);
4694
4695 return 0;
4696
4697 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4698 const char *base;
4699 uint64_t value, next_elapse;
4700
4701 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4702 if (r < 0)
4703 return bus_log_parse_error(r);
4704
4705 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4706 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4707
4708 print_prop(base, "{ value=%s ; next_elapse=%s }",
4709 format_timespan(timespan1, sizeof(timespan1), value, 0),
4710 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4711 }
4712 if (r < 0)
4713 return bus_log_parse_error(r);
4714
4715 r = sd_bus_message_exit_container(m);
4716 if (r < 0)
4717 return bus_log_parse_error(r);
4718
4719 return 0;
4720
4721 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4722 ExecStatusInfo info = {};
4723
4724 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4725 if (r < 0)
4726 return bus_log_parse_error(r);
4727
4728 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4729 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4730 _cleanup_free_ char *tt;
4731
4732 tt = strv_join(info.argv, " ");
4733
4734 print_prop(name,
4735 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
4736 strna(info.path),
4737 strna(tt),
4738 yes_no(info.ignore),
4739 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4740 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4741 info.pid,
4742 sigchld_code_to_string(info.code),
4743 info.status,
4744 info.code == CLD_EXITED ? "" : "/",
4745 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4746
4747 free(info.path);
4748 strv_free(info.argv);
4749 zero(info);
4750 }
4751
4752 r = sd_bus_message_exit_container(m);
4753 if (r < 0)
4754 return bus_log_parse_error(r);
4755
4756 return 0;
4757
4758 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4759 const char *path, *rwm;
4760
4761 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4762 if (r < 0)
4763 return bus_log_parse_error(r);
4764
4765 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4766 print_prop(name, "%s %s", strna(path), strna(rwm));
4767 if (r < 0)
4768 return bus_log_parse_error(r);
4769
4770 r = sd_bus_message_exit_container(m);
4771 if (r < 0)
4772 return bus_log_parse_error(r);
4773
4774 return 0;
4775
4776 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
4777 STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
4778 const char *path;
4779 uint64_t weight;
4780
4781 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4782 if (r < 0)
4783 return bus_log_parse_error(r);
4784
4785 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4786 print_prop(name, "%s %"PRIu64, strna(path), weight);
4787 if (r < 0)
4788 return bus_log_parse_error(r);
4789
4790 r = sd_bus_message_exit_container(m);
4791 if (r < 0)
4792 return bus_log_parse_error(r);
4793
4794 return 0;
4795
4796 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
4797 (cgroup_io_limit_type_from_string(name) >= 0 ||
4798 STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4799 const char *path;
4800 uint64_t bandwidth;
4801
4802 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4803 if (r < 0)
4804 return bus_log_parse_error(r);
4805
4806 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4807 print_prop(name, "%s %"PRIu64, strna(path), bandwidth);
4808 if (r < 0)
4809 return bus_log_parse_error(r);
4810
4811 r = sd_bus_message_exit_container(m);
4812 if (r < 0)
4813 return bus_log_parse_error(r);
4814
4815 return 0;
4816 }
4817
4818 break;
4819 }
4820
4821 r = bus_print_property(name, m, arg_value, arg_all);
4822 if (r < 0)
4823 return bus_log_parse_error(r);
4824
4825 if (r == 0) {
4826 r = sd_bus_message_skip(m, contents);
4827 if (r < 0)
4828 return bus_log_parse_error(r);
4829
4830 if (arg_all)
4831 printf("%s=[unprintable]\n", name);
4832 }
4833
4834 return 0;
4835 }
4836
4837 static int show_one(
4838 const char *verb,
4839 sd_bus *bus,
4840 const char *path,
4841 const char *unit,
4842 bool show_properties,
4843 bool *new_line,
4844 bool *ellipsized) {
4845
4846 static const struct bus_properties_map property_map[] = {
4847 { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
4848 { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) },
4849 {}
4850 };
4851
4852 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
4853 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4854 _cleanup_set_free_ Set *found_properties = NULL;
4855 _cleanup_(unit_status_info_free) UnitStatusInfo info = {
4856 .memory_current = (uint64_t) -1,
4857 .memory_high = CGROUP_LIMIT_MAX,
4858 .memory_max = CGROUP_LIMIT_MAX,
4859 .memory_swap_max = CGROUP_LIMIT_MAX,
4860 .memory_limit = (uint64_t) -1,
4861 .cpu_usage_nsec = (uint64_t) -1,
4862 .tasks_current = (uint64_t) -1,
4863 .tasks_max = (uint64_t) -1,
4864 };
4865 int r;
4866
4867 assert(path);
4868 assert(new_line);
4869
4870 log_debug("Showing one %s", path);
4871
4872 r = sd_bus_call_method(
4873 bus,
4874 "org.freedesktop.systemd1",
4875 path,
4876 "org.freedesktop.DBus.Properties",
4877 "GetAll",
4878 &error,
4879 &reply,
4880 "s", "");
4881 if (r < 0)
4882 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
4883
4884 if (unit) {
4885 r = bus_message_map_all_properties(reply, property_map, &info);
4886 if (r < 0)
4887 return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
4888
4889 if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
4890 log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG,
4891 "Unit %s could not be found.", unit);
4892
4893 if (streq(verb, "status"))
4894 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
4895
4896 if (!streq(verb, "show"))
4897 return -ENOENT;
4898 }
4899
4900 r = sd_bus_message_rewind(reply, true);
4901 if (r < 0)
4902 return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
4903 }
4904
4905 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4906 if (r < 0)
4907 return bus_log_parse_error(r);
4908
4909 if (*new_line)
4910 printf("\n");
4911
4912 *new_line = true;
4913
4914 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4915 const char *name, *contents;
4916
4917 r = sd_bus_message_read(reply, "s", &name);
4918 if (r < 0)
4919 return bus_log_parse_error(r);
4920
4921 r = sd_bus_message_peek_type(reply, NULL, &contents);
4922 if (r < 0)
4923 return bus_log_parse_error(r);
4924
4925 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4926 if (r < 0)
4927 return bus_log_parse_error(r);
4928
4929 if (show_properties) {
4930 r = set_ensure_allocated(&found_properties, &string_hash_ops);
4931 if (r < 0)
4932 return log_oom();
4933
4934 r = set_put(found_properties, name);
4935 if (r < 0 && r != EEXIST)
4936 return log_oom();
4937
4938 r = print_property(name, reply, contents);
4939 } else
4940 r = status_property(name, reply, &info, contents);
4941 if (r < 0)
4942 return r;
4943
4944 r = sd_bus_message_exit_container(reply);
4945 if (r < 0)
4946 return bus_log_parse_error(r);
4947
4948 r = sd_bus_message_exit_container(reply);
4949 if (r < 0)
4950 return bus_log_parse_error(r);
4951 }
4952 if (r < 0)
4953 return bus_log_parse_error(r);
4954
4955 r = sd_bus_message_exit_container(reply);
4956 if (r < 0)
4957 return bus_log_parse_error(r);
4958
4959 r = 0;
4960 if (show_properties) {
4961 char **pp;
4962 int not_found_level = streq(verb, "show") ? LOG_DEBUG : LOG_WARNING;
4963
4964 STRV_FOREACH(pp, arg_properties)
4965 if (!set_contains(found_properties, *pp)) {
4966 log_full(not_found_level, "Property %s does not exist.", *pp);
4967 r = -ENXIO;
4968 }
4969
4970 } else if (streq(verb, "help"))
4971 show_unit_help(&info);
4972 else if (streq(verb, "status")) {
4973 print_status_info(bus, &info, ellipsized);
4974
4975 if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
4976 r = EXIT_PROGRAM_NOT_RUNNING;
4977 else
4978 r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
4979 }
4980
4981 return r;
4982 }
4983
4984 static int get_unit_dbus_path_by_pid(
4985 sd_bus *bus,
4986 uint32_t pid,
4987 char **unit) {
4988
4989 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4990 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
4991 char *u;
4992 int r;
4993
4994 r = sd_bus_call_method(
4995 bus,
4996 "org.freedesktop.systemd1",
4997 "/org/freedesktop/systemd1",
4998 "org.freedesktop.systemd1.Manager",
4999 "GetUnitByPID",
5000 &error,
5001 &reply,
5002 "u", pid);
5003 if (r < 0)
5004 return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
5005
5006 r = sd_bus_message_read(reply, "o", &u);
5007 if (r < 0)
5008 return bus_log_parse_error(r);
5009
5010 u = strdup(u);
5011 if (!u)
5012 return log_oom();
5013
5014 *unit = u;
5015 return 0;
5016 }
5017
5018 static int show_all(
5019 const char* verb,
5020 sd_bus *bus,
5021 bool show_properties,
5022 bool *new_line,
5023 bool *ellipsized) {
5024
5025 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5026 _cleanup_free_ UnitInfo *unit_infos = NULL;
5027 const UnitInfo *u;
5028 unsigned c;
5029 int r, ret = 0;
5030
5031 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
5032 if (r < 0)
5033 return r;
5034
5035 pager_open(arg_no_pager, false);
5036
5037 c = (unsigned) r;
5038
5039 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
5040
5041 for (u = unit_infos; u < unit_infos + c; u++) {
5042 _cleanup_free_ char *p = NULL;
5043
5044 p = unit_dbus_path_from_name(u->id);
5045 if (!p)
5046 return log_oom();
5047
5048 r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
5049 if (r < 0)
5050 return r;
5051 else if (r > 0 && ret == 0)
5052 ret = r;
5053 }
5054
5055 return ret;
5056 }
5057
5058 static int show_system_status(sd_bus *bus) {
5059 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
5060 _cleanup_free_ char *hn = NULL;
5061 _cleanup_(machine_info_clear) struct machine_info mi = {};
5062 const char *on, *off;
5063 int r;
5064
5065 hn = gethostname_malloc();
5066 if (!hn)
5067 return log_oom();
5068
5069 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
5070 if (r < 0)
5071 return log_error_errno(r, "Failed to read server status: %m");
5072
5073 if (streq_ptr(mi.state, "degraded")) {
5074 on = ansi_highlight_red();
5075 off = ansi_normal();
5076 } else if (!streq_ptr(mi.state, "running")) {
5077 on = ansi_highlight_yellow();
5078 off = ansi_normal();
5079 } else
5080 on = off = "";
5081
5082 printf("%s%s%s %s\n", on, special_glyph(BLACK_CIRCLE), off, arg_host ? arg_host : hn);
5083
5084 printf(" State: %s%s%s\n",
5085 on, strna(mi.state), off);
5086
5087 printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
5088 printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
5089
5090 printf(" Since: %s; %s\n",
5091 format_timestamp(since2, sizeof(since2), mi.timestamp),
5092 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
5093
5094 printf(" CGroup: %s\n", mi.control_group ?: "/");
5095 if (IN_SET(arg_transport,
5096 BUS_TRANSPORT_LOCAL,
5097 BUS_TRANSPORT_MACHINE)) {
5098 static const char prefix[] = " ";
5099 unsigned c;
5100
5101 c = columns();
5102 if (c > sizeof(prefix) - 1)
5103 c -= sizeof(prefix) - 1;
5104 else
5105 c = 0;
5106
5107 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
5108 }
5109
5110 return 0;
5111 }
5112
5113 static int show(int argc, char *argv[], void *userdata) {
5114 bool show_properties, show_status, show_help, new_line = false;
5115 bool ellipsized = false;
5116 int r, ret = 0;
5117 sd_bus *bus;
5118
5119 assert(argv);
5120
5121 show_properties = streq(argv[0], "show");
5122 show_status = streq(argv[0], "status");
5123 show_help = streq(argv[0], "help");
5124
5125 if (show_help && argc <= 1) {
5126 log_error("This command expects one or more unit names. Did you mean --help?");
5127 return -EINVAL;
5128 }
5129
5130 r = acquire_bus(BUS_MANAGER, &bus);
5131 if (r < 0)
5132 return r;
5133
5134 pager_open(arg_no_pager, false);
5135
5136 if (show_status)
5137 /* Increase max number of open files to 16K if we can, we
5138 * might needs this when browsing journal files, which might
5139 * be split up into many files. */
5140 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
5141
5142 /* If no argument is specified inspect the manager itself */
5143 if (show_properties && argc <= 1)
5144 return show_one(argv[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
5145
5146 if (show_status && argc <= 1) {
5147
5148 show_system_status(bus);
5149 new_line = true;
5150
5151 if (arg_all)
5152 ret = show_all(argv[0], bus, false, &new_line, &ellipsized);
5153 } else {
5154 _cleanup_free_ char **patterns = NULL;
5155 char **name;
5156
5157 STRV_FOREACH(name, strv_skip(argv, 1)) {
5158 _cleanup_free_ char *path = NULL, *unit = NULL;
5159 uint32_t id;
5160
5161 if (safe_atou32(*name, &id) < 0) {
5162 if (strv_push(&patterns, *name) < 0)
5163 return log_oom();
5164
5165 continue;
5166 } else if (show_properties) {
5167 /* Interpret as job id */
5168 if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
5169 return log_oom();
5170
5171 } else {
5172 /* Interpret as PID */
5173 r = get_unit_dbus_path_by_pid(bus, id, &path);
5174 if (r < 0) {
5175 ret = r;
5176 continue;
5177 }
5178
5179 r = unit_name_from_dbus_path(path, &unit);
5180 if (r < 0)
5181 return log_oom();
5182 }
5183
5184 r = show_one(argv[0], bus, path, unit, show_properties, &new_line, &ellipsized);
5185 if (r < 0)
5186 return r;
5187 else if (r > 0 && ret == 0)
5188 ret = r;
5189 }
5190
5191 if (!strv_isempty(patterns)) {
5192 _cleanup_strv_free_ char **names = NULL;
5193
5194 r = expand_names(bus, patterns, NULL, &names);
5195 if (r < 0)
5196 return log_error_errno(r, "Failed to expand names: %m");
5197
5198 STRV_FOREACH(name, names) {
5199 _cleanup_free_ char *path;
5200
5201 path = unit_dbus_path_from_name(*name);
5202 if (!path)
5203 return log_oom();
5204
5205 r = show_one(argv[0], bus, path, *name, show_properties, &new_line, &ellipsized);
5206 if (r < 0)
5207 return r;
5208 if (r > 0 && ret == 0)
5209 ret = r;
5210 }
5211 }
5212 }
5213
5214 if (ellipsized && !arg_quiet)
5215 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5216
5217 return ret;
5218 }
5219
5220 static int cat_file(const char *filename, bool newline) {
5221 _cleanup_close_ int fd;
5222
5223 fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
5224 if (fd < 0)
5225 return -errno;
5226
5227 printf("%s%s# %s%s\n",
5228 newline ? "\n" : "",
5229 ansi_highlight_blue(),
5230 filename,
5231 ansi_normal());
5232 fflush(stdout);
5233
5234 return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false);
5235 }
5236
5237 static int cat(int argc, char *argv[], void *userdata) {
5238 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5239 _cleanup_strv_free_ char **names = NULL;
5240 char **name;
5241 sd_bus *bus;
5242 bool first = true;
5243 int r;
5244
5245 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5246 log_error("Cannot remotely cat units.");
5247 return -EINVAL;
5248 }
5249
5250 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
5251 if (r < 0)
5252 return log_error_errno(r, "Failed to determine unit paths: %m");
5253
5254 r = acquire_bus(BUS_MANAGER, &bus);
5255 if (r < 0)
5256 return r;
5257
5258 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
5259 if (r < 0)
5260 return log_error_errno(r, "Failed to expand names: %m");
5261
5262 pager_open(arg_no_pager, false);
5263
5264 STRV_FOREACH(name, names) {
5265 _cleanup_free_ char *fragment_path = NULL;
5266 _cleanup_strv_free_ char **dropin_paths = NULL;
5267 char **path;
5268
5269 r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
5270 if (r < 0)
5271 return r;
5272 else if (r == 0)
5273 return -ENOENT;
5274
5275 if (first)
5276 first = false;
5277 else
5278 puts("");
5279
5280 if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
5281 fprintf(stderr,
5282 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5283 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5284 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5285 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5286 ansi_highlight_red(),
5287 *name,
5288 ansi_highlight_red(),
5289 ansi_highlight_red(),
5290 ansi_highlight_red(),
5291 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
5292 ansi_normal());
5293
5294 if (fragment_path) {
5295 r = cat_file(fragment_path, false);
5296 if (r < 0)
5297 return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
5298 }
5299
5300 STRV_FOREACH(path, dropin_paths) {
5301 r = cat_file(*path, path == dropin_paths);
5302 if (r < 0)
5303 return log_warning_errno(r, "Failed to cat %s: %m", *path);
5304 }
5305 }
5306
5307 return 0;
5308 }
5309
5310 static int set_property(int argc, char *argv[], void *userdata) {
5311 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5312 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5313 _cleanup_free_ char *n = NULL;
5314 sd_bus *bus;
5315 int r;
5316
5317 r = acquire_bus(BUS_MANAGER, &bus);
5318 if (r < 0)
5319 return r;
5320
5321 polkit_agent_open_if_enabled();
5322
5323 r = sd_bus_message_new_method_call(
5324 bus,
5325 &m,
5326 "org.freedesktop.systemd1",
5327 "/org/freedesktop/systemd1",
5328 "org.freedesktop.systemd1.Manager",
5329 "SetUnitProperties");
5330 if (r < 0)
5331 return bus_log_create_error(r);
5332
5333 r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n);
5334 if (r < 0)
5335 return log_error_errno(r, "Failed to mangle unit name: %m");
5336
5337 r = sd_bus_message_append(m, "sb", n, arg_runtime);
5338 if (r < 0)
5339 return bus_log_create_error(r);
5340
5341 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
5342 if (r < 0)
5343 return bus_log_create_error(r);
5344
5345 r = bus_append_unit_property_assignment_many(m, strv_skip(argv, 2));
5346 if (r < 0)
5347 return r;
5348
5349 r = sd_bus_message_close_container(m);
5350 if (r < 0)
5351 return bus_log_create_error(r);
5352
5353 r = sd_bus_call(bus, m, 0, &error, NULL);
5354 if (r < 0)
5355 return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
5356
5357 return 0;
5358 }
5359
5360 static int daemon_reload(int argc, char *argv[], void *userdata) {
5361 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5362 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5363 const char *method;
5364 sd_bus *bus;
5365 int r;
5366
5367 r = acquire_bus(BUS_MANAGER, &bus);
5368 if (r < 0)
5369 return r;
5370
5371 polkit_agent_open_if_enabled();
5372
5373 switch (arg_action) {
5374
5375 case ACTION_RELOAD:
5376 method = "Reload";
5377 break;
5378
5379 case ACTION_REEXEC:
5380 method = "Reexecute";
5381 break;
5382
5383 case ACTION_SYSTEMCTL:
5384 method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
5385 /* "daemon-reload" */ "Reload";
5386 break;
5387
5388 default:
5389 assert_not_reached("Unexpected action");
5390 }
5391
5392 r = sd_bus_message_new_method_call(
5393 bus,
5394 &m,
5395 "org.freedesktop.systemd1",
5396 "/org/freedesktop/systemd1",
5397 "org.freedesktop.systemd1.Manager",
5398 method);
5399 if (r < 0)
5400 return bus_log_create_error(r);
5401
5402 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5403 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5404 * their timeout, and for everything else there's the same time budget in place. */
5405
5406 r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
5407
5408 /* On reexecution, we expect a disconnect, not a reply */
5409 if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
5410 r = 0;
5411
5412 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
5413 return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
5414
5415 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5416 * old ways of doing things, hence don't log any error in that case here. */
5417
5418 return r < 0 ? r : 0;
5419 }
5420
5421 static int trivial_method(int argc, char *argv[], void *userdata) {
5422 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5423 const char *method;
5424 sd_bus *bus;
5425 int r;
5426
5427 r = acquire_bus(BUS_MANAGER, &bus);
5428 if (r < 0)
5429 return r;
5430
5431 polkit_agent_open_if_enabled();
5432
5433 method =
5434 streq(argv[0], "clear-jobs") ||
5435 streq(argv[0], "cancel") ? "ClearJobs" :
5436 streq(argv[0], "reset-failed") ? "ResetFailed" :
5437 streq(argv[0], "halt") ? "Halt" :
5438 streq(argv[0], "reboot") ? "Reboot" :
5439 streq(argv[0], "kexec") ? "KExec" :
5440 streq(argv[0], "exit") ? "Exit" :
5441 /* poweroff */ "PowerOff";
5442
5443 r = sd_bus_call_method(
5444 bus,
5445 "org.freedesktop.systemd1",
5446 "/org/freedesktop/systemd1",
5447 "org.freedesktop.systemd1.Manager",
5448 method,
5449 &error,
5450 NULL,
5451 NULL);
5452 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
5453 return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
5454
5455 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5456 * old ways of doing things, hence don't log any error in that case here. */
5457
5458 return r < 0 ? r : 0;
5459 }
5460
5461 static int reset_failed(int argc, char *argv[], void *userdata) {
5462 _cleanup_strv_free_ char **names = NULL;
5463 sd_bus *bus;
5464 char **name;
5465 int r, q;
5466
5467 if (argc <= 1)
5468 return trivial_method(argc, argv, userdata);
5469
5470 r = acquire_bus(BUS_MANAGER, &bus);
5471 if (r < 0)
5472 return r;
5473
5474 polkit_agent_open_if_enabled();
5475
5476 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
5477 if (r < 0)
5478 return log_error_errno(r, "Failed to expand names: %m");
5479
5480 STRV_FOREACH(name, names) {
5481 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5482
5483 q = sd_bus_call_method(
5484 bus,
5485 "org.freedesktop.systemd1",
5486 "/org/freedesktop/systemd1",
5487 "org.freedesktop.systemd1.Manager",
5488 "ResetFailedUnit",
5489 &error,
5490 NULL,
5491 "s", *name);
5492 if (q < 0) {
5493 log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
5494 if (r == 0)
5495 r = q;
5496 }
5497 }
5498
5499 return r;
5500 }
5501
5502 static int show_environment(int argc, char *argv[], void *userdata) {
5503 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5504 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5505 const char *text;
5506 sd_bus *bus;
5507 int r;
5508
5509 r = acquire_bus(BUS_MANAGER, &bus);
5510 if (r < 0)
5511 return r;
5512
5513 pager_open(arg_no_pager, false);
5514
5515 r = sd_bus_get_property(
5516 bus,
5517 "org.freedesktop.systemd1",
5518 "/org/freedesktop/systemd1",
5519 "org.freedesktop.systemd1.Manager",
5520 "Environment",
5521 &error,
5522 &reply,
5523 "as");
5524 if (r < 0)
5525 return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
5526
5527 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
5528 if (r < 0)
5529 return bus_log_parse_error(r);
5530
5531 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
5532 puts(text);
5533 if (r < 0)
5534 return bus_log_parse_error(r);
5535
5536 r = sd_bus_message_exit_container(reply);
5537 if (r < 0)
5538 return bus_log_parse_error(r);
5539
5540 return 0;
5541 }
5542
5543 static int switch_root(int argc, char *argv[], void *userdata) {
5544 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5545 _cleanup_free_ char *cmdline_init = NULL;
5546 const char *root, *init;
5547 sd_bus *bus;
5548 int r;
5549
5550 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5551 log_error("Cannot switch root remotely.");
5552 return -EINVAL;
5553 }
5554
5555 if (argc < 2 || argc > 3) {
5556 log_error("Wrong number of arguments.");
5557 return -EINVAL;
5558 }
5559
5560 root = argv[1];
5561
5562 if (argc >= 3)
5563 init = argv[2];
5564 else {
5565 r = parse_env_file("/proc/cmdline", WHITESPACE,
5566 "init", &cmdline_init,
5567 NULL);
5568 if (r < 0)
5569 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5570
5571 init = cmdline_init;
5572 }
5573
5574 init = empty_to_null(init);
5575 if (init) {
5576 const char *root_systemd_path = NULL, *root_init_path = NULL;
5577
5578 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
5579 root_init_path = strjoina(root, "/", init);
5580
5581 /* If the passed init is actually the same as the
5582 * systemd binary, then let's suppress it. */
5583 if (files_same(root_init_path, root_systemd_path) > 0)
5584 init = NULL;
5585 }
5586
5587 r = acquire_bus(BUS_MANAGER, &bus);
5588 if (r < 0)
5589 return r;
5590
5591 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5592
5593 r = sd_bus_call_method(
5594 bus,
5595 "org.freedesktop.systemd1",
5596 "/org/freedesktop/systemd1",
5597 "org.freedesktop.systemd1.Manager",
5598 "SwitchRoot",
5599 &error,
5600 NULL,
5601 "ss", root, init);
5602 if (r < 0)
5603 return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
5604
5605 return 0;
5606 }
5607
5608 static int set_environment(int argc, char *argv[], void *userdata) {
5609 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5610 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5611 const char *method;
5612 sd_bus *bus;
5613 int r;
5614
5615 assert(argc > 1);
5616 assert(argv);
5617
5618 r = acquire_bus(BUS_MANAGER, &bus);
5619 if (r < 0)
5620 return r;
5621
5622 polkit_agent_open_if_enabled();
5623
5624 method = streq(argv[0], "set-environment")
5625 ? "SetEnvironment"
5626 : "UnsetEnvironment";
5627
5628 r = sd_bus_message_new_method_call(
5629 bus,
5630 &m,
5631 "org.freedesktop.systemd1",
5632 "/org/freedesktop/systemd1",
5633 "org.freedesktop.systemd1.Manager",
5634 method);
5635 if (r < 0)
5636 return bus_log_create_error(r);
5637
5638 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
5639 if (r < 0)
5640 return bus_log_create_error(r);
5641
5642 r = sd_bus_call(bus, m, 0, &error, NULL);
5643 if (r < 0)
5644 return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
5645
5646 return 0;
5647 }
5648
5649 static int import_environment(int argc, char *argv[], void *userdata) {
5650 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5651 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5652 sd_bus *bus;
5653 int r;
5654
5655 r = acquire_bus(BUS_MANAGER, &bus);
5656 if (r < 0)
5657 return r;
5658
5659 polkit_agent_open_if_enabled();
5660
5661 r = sd_bus_message_new_method_call(
5662 bus,
5663 &m,
5664 "org.freedesktop.systemd1",
5665 "/org/freedesktop/systemd1",
5666 "org.freedesktop.systemd1.Manager",
5667 "SetEnvironment");
5668 if (r < 0)
5669 return bus_log_create_error(r);
5670
5671 if (argc < 2)
5672 r = sd_bus_message_append_strv(m, environ);
5673 else {
5674 char **a, **b;
5675
5676 r = sd_bus_message_open_container(m, 'a', "s");
5677 if (r < 0)
5678 return bus_log_create_error(r);
5679
5680 STRV_FOREACH(a, strv_skip(argv, 1)) {
5681
5682 if (!env_name_is_valid(*a)) {
5683 log_error("Not a valid environment variable name: %s", *a);
5684 return -EINVAL;
5685 }
5686
5687 STRV_FOREACH(b, environ) {
5688 const char *eq;
5689
5690 eq = startswith(*b, *a);
5691 if (eq && *eq == '=') {
5692
5693 r = sd_bus_message_append(m, "s", *b);
5694 if (r < 0)
5695 return bus_log_create_error(r);
5696
5697 break;
5698 }
5699 }
5700 }
5701
5702 r = sd_bus_message_close_container(m);
5703 }
5704 if (r < 0)
5705 return bus_log_create_error(r);
5706
5707 r = sd_bus_call(bus, m, 0, &error, NULL);
5708 if (r < 0)
5709 return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
5710
5711 return 0;
5712 }
5713
5714 static int enable_sysv_units(const char *verb, char **args) {
5715 int r = 0;
5716
5717 #if defined(HAVE_SYSV_COMPAT)
5718 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5719 unsigned f = 0;
5720
5721 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5722
5723 if (arg_scope != UNIT_FILE_SYSTEM)
5724 return 0;
5725
5726 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5727 return 0;
5728
5729 if (!STR_IN_SET(verb,
5730 "enable",
5731 "disable",
5732 "is-enabled"))
5733 return 0;
5734
5735 r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
5736 if (r < 0)
5737 return r;
5738
5739 r = 0;
5740 while (args[f]) {
5741
5742 const char *argv[] = {
5743 ROOTLIBEXECDIR "/systemd-sysv-install",
5744 NULL,
5745 NULL,
5746 NULL,
5747 NULL,
5748 };
5749
5750 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5751 bool found_native = false, found_sysv;
5752 siginfo_t status;
5753 const char *name;
5754 unsigned c = 1;
5755 pid_t pid;
5756 int j;
5757
5758 name = args[f++];
5759
5760 if (!endswith(name, ".service"))
5761 continue;
5762
5763 if (path_is_absolute(name))
5764 continue;
5765
5766 j = unit_file_exists(arg_scope, &paths, name);
5767 if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
5768 return log_error_errno(j, "Failed to lookup unit file state: %m");
5769 found_native = j != 0;
5770
5771 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5772 * prefer the native unit */
5773 if (found_native && streq(verb, "is-enabled"))
5774 continue;
5775
5776 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5777 if (!p)
5778 return log_oom();
5779
5780 p[strlen(p) - strlen(".service")] = 0;
5781 found_sysv = access(p, F_OK) >= 0;
5782 if (!found_sysv)
5783 continue;
5784
5785 if (!arg_quiet) {
5786 if (found_native)
5787 log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
5788 else
5789 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
5790 }
5791
5792 if (!isempty(arg_root))
5793 argv[c++] = q = strappend("--root=", arg_root);
5794
5795 argv[c++] = verb;
5796 argv[c++] = basename(p);
5797 argv[c] = NULL;
5798
5799 l = strv_join((char**)argv, " ");
5800 if (!l)
5801 return log_oom();
5802
5803 log_info("Executing: %s", l);
5804
5805 pid = fork();
5806 if (pid < 0)
5807 return log_error_errno(errno, "Failed to fork: %m");
5808 else if (pid == 0) {
5809 /* Child */
5810
5811 (void) reset_all_signal_handlers();
5812 (void) reset_signal_mask();
5813
5814 execv(argv[0], (char**) argv);
5815 log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
5816 _exit(EXIT_FAILURE);
5817 }
5818
5819 j = wait_for_terminate(pid, &status);
5820 if (j < 0)
5821 return log_error_errno(j, "Failed to wait for child: %m");
5822
5823 if (status.si_code == CLD_EXITED) {
5824 if (streq(verb, "is-enabled")) {
5825 if (status.si_status == 0) {
5826 if (!arg_quiet)
5827 puts("enabled");
5828 r = 1;
5829 } else {
5830 if (!arg_quiet)
5831 puts("disabled");
5832 }
5833
5834 } else if (status.si_status != 0)
5835 return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
5836 } else {
5837 log_error("Unexpected waitid() result.");
5838 return -EPROTO;
5839 }
5840
5841 if (found_native)
5842 continue;
5843
5844 /* Remove this entry, so that we don't try enabling it as native unit */
5845 assert(f > 0);
5846 f--;
5847 assert(args[f] == name);
5848 strv_remove(args, name);
5849 }
5850
5851 #endif
5852 return r;
5853 }
5854
5855 static int mangle_names(char **original_names, char ***mangled_names) {
5856 char **i, **l, **name;
5857 int r;
5858
5859 l = i = new(char*, strv_length(original_names) + 1);
5860 if (!l)
5861 return log_oom();
5862
5863 STRV_FOREACH(name, original_names) {
5864
5865 /* When enabling units qualified path names are OK,
5866 * too, hence allow them explicitly. */
5867
5868 if (is_path(*name)) {
5869 *i = strdup(*name);
5870 if (!*i) {
5871 strv_free(l);
5872 return log_oom();
5873 }
5874 } else {
5875 r = unit_name_mangle(*name, UNIT_NAME_NOGLOB, i);
5876 if (r < 0) {
5877 strv_free(l);
5878 return log_error_errno(r, "Failed to mangle unit name: %m");
5879 }
5880 }
5881
5882 i++;
5883 }
5884
5885 *i = NULL;
5886 *mangled_names = l;
5887
5888 return 0;
5889 }
5890
5891 static int normalize_names(char **names, bool warn_if_path) {
5892 char **u;
5893 bool was_path = false;
5894
5895 STRV_FOREACH(u, names) {
5896 int r;
5897
5898 if (!is_path(*u))
5899 continue;
5900
5901 r = free_and_strdup(u, basename(*u));
5902 if (r < 0)
5903 return log_error_errno(r, "Failed to normalize unit file path: %m");
5904
5905 was_path = true;
5906 }
5907
5908 if (warn_if_path && was_path)
5909 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
5910
5911 return 0;
5912 }
5913
5914 static int unit_exists(const char *unit) {
5915 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5916 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5917 _cleanup_free_ char *path = NULL;
5918 static const struct bus_properties_map property_map[] = {
5919 { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
5920 { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)},
5921 {},
5922 };
5923 UnitStatusInfo info = {};
5924 sd_bus *bus;
5925 int r;
5926
5927 path = unit_dbus_path_from_name(unit);
5928 if (!path)
5929 return log_oom();
5930
5931 r = acquire_bus(BUS_MANAGER, &bus);
5932 if (r < 0)
5933 return r;
5934
5935 r = sd_bus_call_method(
5936 bus,
5937 "org.freedesktop.systemd1",
5938 path,
5939 "org.freedesktop.DBus.Properties",
5940 "GetAll",
5941 &error,
5942 &reply,
5943 "s", "");
5944 if (r < 0)
5945 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
5946
5947 r = bus_message_map_all_properties(reply, property_map, &info);
5948 if (r < 0)
5949 return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
5950
5951 return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
5952 }
5953
5954 static int enable_unit(int argc, char *argv[], void *userdata) {
5955 _cleanup_strv_free_ char **names = NULL;
5956 const char *verb = argv[0];
5957 UnitFileChange *changes = NULL;
5958 unsigned n_changes = 0;
5959 int carries_install_info = -1;
5960 bool ignore_carries_install_info = arg_quiet;
5961 int r;
5962
5963 if (!argv[1])
5964 return 0;
5965
5966 r = mangle_names(strv_skip(argv, 1), &names);
5967 if (r < 0)
5968 return r;
5969
5970 r = enable_sysv_units(verb, names);
5971 if (r < 0)
5972 return r;
5973
5974 /* If the operation was fully executed by the SysV compat, let's finish early */
5975 if (strv_isempty(names)) {
5976 if (arg_no_reload || install_client_side())
5977 return 0;
5978 return daemon_reload(argc, argv, userdata);
5979 }
5980
5981 if (streq(verb, "disable")) {
5982 r = normalize_names(names, true);
5983 if (r < 0)
5984 return r;
5985 }
5986
5987 if (install_client_side()) {
5988 UnitFileFlags flags;
5989
5990 flags = args_to_flags();
5991 if (streq(verb, "enable")) {
5992 r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
5993 carries_install_info = r;
5994 } else if (streq(verb, "disable"))
5995 r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
5996 else if (streq(verb, "reenable")) {
5997 r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
5998 carries_install_info = r;
5999 } else if (streq(verb, "link"))
6000 r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
6001 else if (streq(verb, "preset")) {
6002 r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
6003 } else if (streq(verb, "mask"))
6004 r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6005 else if (streq(verb, "unmask"))
6006 r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6007 else if (streq(verb, "revert"))
6008 r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
6009 else
6010 assert_not_reached("Unknown verb");
6011
6012 unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
6013 if (r < 0)
6014 goto finish;
6015 r = 0;
6016 } else {
6017 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6018 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6019 bool expect_carries_install_info = false;
6020 bool send_runtime = true, send_force = true, send_preset_mode = false;
6021 const char *method;
6022 sd_bus *bus;
6023
6024 if (STR_IN_SET(verb, "mask", "unmask")) {
6025 r = unit_exists(*names);
6026 if (r < 0)
6027 return r;
6028 if (r == 0)
6029 log_notice("Unit %s does not exist, proceeding anyway.", *names);
6030 }
6031
6032 r = acquire_bus(BUS_MANAGER, &bus);
6033 if (r < 0)
6034 return r;
6035
6036 polkit_agent_open_if_enabled();
6037
6038 if (streq(verb, "enable")) {
6039 method = "EnableUnitFiles";
6040 expect_carries_install_info = true;
6041 } else if (streq(verb, "disable")) {
6042 method = "DisableUnitFiles";
6043 send_force = false;
6044 } else if (streq(verb, "reenable")) {
6045 method = "ReenableUnitFiles";
6046 expect_carries_install_info = true;
6047 } else if (streq(verb, "link"))
6048 method = "LinkUnitFiles";
6049 else if (streq(verb, "preset")) {
6050
6051 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
6052 method = "PresetUnitFilesWithMode";
6053 send_preset_mode = true;
6054 } else
6055 method = "PresetUnitFiles";
6056
6057 expect_carries_install_info = true;
6058 ignore_carries_install_info = true;
6059 } else if (streq(verb, "mask"))
6060 method = "MaskUnitFiles";
6061 else if (streq(verb, "unmask")) {
6062 method = "UnmaskUnitFiles";
6063 send_force = false;
6064 } else if (streq(verb, "revert")) {
6065 method = "RevertUnitFiles";
6066 send_runtime = send_force = false;
6067 } else
6068 assert_not_reached("Unknown verb");
6069
6070 r = sd_bus_message_new_method_call(
6071 bus,
6072 &m,
6073 "org.freedesktop.systemd1",
6074 "/org/freedesktop/systemd1",
6075 "org.freedesktop.systemd1.Manager",
6076 method);
6077 if (r < 0)
6078 return bus_log_create_error(r);
6079
6080 r = sd_bus_message_append_strv(m, names);
6081 if (r < 0)
6082 return bus_log_create_error(r);
6083
6084 if (send_preset_mode) {
6085 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
6086 if (r < 0)
6087 return bus_log_create_error(r);
6088 }
6089
6090 if (send_runtime) {
6091 r = sd_bus_message_append(m, "b", arg_runtime);
6092 if (r < 0)
6093 return bus_log_create_error(r);
6094 }
6095
6096 if (send_force) {
6097 r = sd_bus_message_append(m, "b", arg_force);
6098 if (r < 0)
6099 return bus_log_create_error(r);
6100 }
6101
6102 r = sd_bus_call(bus, m, 0, &error, &reply);
6103 if (r < 0)
6104 return log_error_errno(r, "Failed to %s unit: %s", verb, bus_error_message(&error, r));
6105
6106 if (expect_carries_install_info) {
6107 r = sd_bus_message_read(reply, "b", &carries_install_info);
6108 if (r < 0)
6109 return bus_log_parse_error(r);
6110 }
6111
6112 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6113 if (r < 0)
6114 goto finish;
6115
6116 /* Try to reload if enabled */
6117 if (!arg_no_reload)
6118 r = daemon_reload(argc, argv, userdata);
6119 else
6120 r = 0;
6121 }
6122
6123 if (carries_install_info == 0 && !ignore_carries_install_info)
6124 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6125 "settings in the [Install] section, and DefaultInstance for template units).\n"
6126 "This means they are not meant to be enabled using systemctl.\n"
6127 "Possible reasons for having this kind of units are:\n"
6128 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6129 " .wants/ or .requires/ directory.\n"
6130 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6131 " a requirement dependency on it.\n"
6132 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6133 " D-Bus, udev, scripted systemctl call, ...).\n"
6134 "4) In case of template units, the unit is meant to be enabled with some\n"
6135 " instance name specified.");
6136
6137 if (arg_now && n_changes > 0 && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
6138 char *new_args[n_changes + 2];
6139 sd_bus *bus;
6140 unsigned i;
6141
6142 r = acquire_bus(BUS_MANAGER, &bus);
6143 if (r < 0)
6144 goto finish;
6145
6146 new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
6147 for (i = 0; i < n_changes; i++)
6148 new_args[i + 1] = basename(changes[i].path);
6149 new_args[i + 1] = NULL;
6150
6151 r = start_unit(strv_length(new_args), new_args, userdata);
6152 }
6153
6154 finish:
6155 unit_file_changes_free(changes, n_changes);
6156
6157 return r;
6158 }
6159
6160 static int add_dependency(int argc, char *argv[], void *userdata) {
6161 _cleanup_strv_free_ char **names = NULL;
6162 _cleanup_free_ char *target = NULL;
6163 const char *verb = argv[0];
6164 UnitFileChange *changes = NULL;
6165 unsigned n_changes = 0;
6166 UnitDependency dep;
6167 int r = 0;
6168
6169 if (!argv[1])
6170 return 0;
6171
6172 r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target);
6173 if (r < 0)
6174 return log_error_errno(r, "Failed to mangle unit name: %m");
6175
6176 r = mangle_names(strv_skip(argv, 2), &names);
6177 if (r < 0)
6178 return r;
6179
6180 if (streq(verb, "add-wants"))
6181 dep = UNIT_WANTS;
6182 else if (streq(verb, "add-requires"))
6183 dep = UNIT_REQUIRES;
6184 else
6185 assert_not_reached("Unknown verb");
6186
6187 if (install_client_side()) {
6188 r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes);
6189 unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
6190
6191 if (r > 0)
6192 r = 0;
6193 } else {
6194 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6195 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6196 sd_bus *bus;
6197
6198 r = acquire_bus(BUS_MANAGER, &bus);
6199 if (r < 0)
6200 return r;
6201
6202 polkit_agent_open_if_enabled();
6203
6204 r = sd_bus_message_new_method_call(
6205 bus,
6206 &m,
6207 "org.freedesktop.systemd1",
6208 "/org/freedesktop/systemd1",
6209 "org.freedesktop.systemd1.Manager",
6210 "AddDependencyUnitFiles");
6211 if (r < 0)
6212 return bus_log_create_error(r);
6213
6214 r = sd_bus_message_append_strv(m, names);
6215 if (r < 0)
6216 return bus_log_create_error(r);
6217
6218 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
6219 if (r < 0)
6220 return bus_log_create_error(r);
6221
6222 r = sd_bus_call(bus, m, 0, &error, &reply);
6223 if (r < 0)
6224 return log_error_errno(r, "Failed to add dependency: %s", bus_error_message(&error, r));
6225
6226 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6227 if (r < 0)
6228 goto finish;
6229
6230 if (arg_no_reload) {
6231 r = 0;
6232 goto finish;
6233 }
6234
6235 r = daemon_reload(argc, argv, userdata);
6236 }
6237
6238 finish:
6239 unit_file_changes_free(changes, n_changes);
6240
6241 return r;
6242 }
6243
6244 static int preset_all(int argc, char *argv[], void *userdata) {
6245 UnitFileChange *changes = NULL;
6246 unsigned n_changes = 0;
6247 int r;
6248
6249 if (install_client_side()) {
6250 r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes);
6251 unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
6252
6253 if (r > 0)
6254 r = 0;
6255 } else {
6256 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6257 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6258 sd_bus *bus;
6259
6260 r = acquire_bus(BUS_MANAGER, &bus);
6261 if (r < 0)
6262 return r;
6263
6264 polkit_agent_open_if_enabled();
6265
6266 r = sd_bus_call_method(
6267 bus,
6268 "org.freedesktop.systemd1",
6269 "/org/freedesktop/systemd1",
6270 "org.freedesktop.systemd1.Manager",
6271 "PresetAllUnitFiles",
6272 &error,
6273 &reply,
6274 "sbb",
6275 unit_file_preset_mode_to_string(arg_preset_mode),
6276 arg_runtime,
6277 arg_force);
6278 if (r < 0)
6279 return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
6280
6281 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6282 if (r < 0)
6283 goto finish;
6284
6285 if (arg_no_reload) {
6286 r = 0;
6287 goto finish;
6288 }
6289
6290 r = daemon_reload(argc, argv, userdata);
6291 }
6292
6293 finish:
6294 unit_file_changes_free(changes, n_changes);
6295
6296 return r;
6297 }
6298
6299 static int show_installation_targets_client_side(const char *name) {
6300 UnitFileChange *changes = NULL;
6301 unsigned n_changes = 0, i;
6302 UnitFileFlags flags;
6303 char **p;
6304 int r;
6305
6306 p = STRV_MAKE(name);
6307 flags = UNIT_FILE_DRY_RUN |
6308 (arg_runtime ? UNIT_FILE_RUNTIME : 0);
6309
6310 r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
6311 if (r < 0)
6312 return log_error_errno(r, "Failed to get file links for %s: %m", name);
6313
6314 for (i = 0; i < n_changes; i++)
6315 if (changes[i].type == UNIT_FILE_UNLINK)
6316 printf(" %s\n", changes[i].path);
6317
6318 return 0;
6319 }
6320
6321 static int show_installation_targets(sd_bus *bus, const char *name) {
6322 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6323 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6324 const char *link;
6325 int r;
6326
6327 r = sd_bus_call_method(
6328 bus,
6329 "org.freedesktop.systemd1",
6330 "/org/freedesktop/systemd1",
6331 "org.freedesktop.systemd1.Manager",
6332 "GetUnitFileLinks",
6333 &error,
6334 &reply,
6335 "sb", name, arg_runtime);
6336 if (r < 0)
6337 return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
6338
6339 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
6340 if (r < 0)
6341 return bus_log_parse_error(r);
6342
6343 while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
6344 printf(" %s\n", link);
6345
6346 if (r < 0)
6347 return bus_log_parse_error(r);
6348
6349 r = sd_bus_message_exit_container(reply);
6350 if (r < 0)
6351 return bus_log_parse_error(r);
6352
6353 return 0;
6354 }
6355
6356 static int unit_is_enabled(int argc, char *argv[], void *userdata) {
6357
6358 _cleanup_strv_free_ char **names = NULL;
6359 bool enabled;
6360 char **name;
6361 int r;
6362
6363 r = mangle_names(strv_skip(argv, 1), &names);
6364 if (r < 0)
6365 return r;
6366
6367 r = enable_sysv_units(argv[0], names);
6368 if (r < 0)
6369 return r;
6370
6371 enabled = r > 0;
6372
6373 if (install_client_side()) {
6374 STRV_FOREACH(name, names) {
6375 UnitFileState state;
6376
6377 r = unit_file_get_state(arg_scope, arg_root, *name, &state);
6378 if (r < 0)
6379 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
6380
6381 if (IN_SET(state,
6382 UNIT_FILE_ENABLED,
6383 UNIT_FILE_ENABLED_RUNTIME,
6384 UNIT_FILE_STATIC,
6385 UNIT_FILE_INDIRECT,
6386 UNIT_FILE_GENERATED))
6387 enabled = true;
6388
6389 if (!arg_quiet) {
6390 puts(unit_file_state_to_string(state));
6391 if (arg_full) {
6392 r = show_installation_targets_client_side(*name);
6393 if (r < 0)
6394 return r;
6395 }
6396 }
6397 }
6398
6399 r = 0;
6400 } else {
6401 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6402 sd_bus *bus;
6403
6404 r = acquire_bus(BUS_MANAGER, &bus);
6405 if (r < 0)
6406 return r;
6407
6408 STRV_FOREACH(name, names) {
6409 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6410 const char *s;
6411
6412 r = sd_bus_call_method(
6413 bus,
6414 "org.freedesktop.systemd1",
6415 "/org/freedesktop/systemd1",
6416 "org.freedesktop.systemd1.Manager",
6417 "GetUnitFileState",
6418 &error,
6419 &reply,
6420 "s", *name);
6421 if (r < 0)
6422 return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
6423
6424 r = sd_bus_message_read(reply, "s", &s);
6425 if (r < 0)
6426 return bus_log_parse_error(r);
6427
6428 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6429 enabled = true;
6430
6431 if (!arg_quiet) {
6432 puts(s);
6433 if (arg_full) {
6434 r = show_installation_targets(bus, *name);
6435 if (r < 0)
6436 return r;
6437 }
6438 }
6439 }
6440 }
6441
6442 return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
6443 }
6444
6445 static int is_system_running(int argc, char *argv[], void *userdata) {
6446 _cleanup_free_ char *state = NULL;
6447 sd_bus *bus;
6448 int r;
6449
6450 if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
6451 if (!arg_quiet)
6452 puts("offline");
6453 return EXIT_FAILURE;
6454 }
6455
6456 r = acquire_bus(BUS_MANAGER, &bus);
6457 if (r < 0)
6458 return r;
6459
6460 r = sd_bus_get_property_string(
6461 bus,
6462 "org.freedesktop.systemd1",
6463 "/org/freedesktop/systemd1",
6464 "org.freedesktop.systemd1.Manager",
6465 "SystemState",
6466 NULL,
6467 &state);
6468 if (r < 0) {
6469 if (!arg_quiet)
6470 puts("unknown");
6471 return 0;
6472 }
6473
6474 if (!arg_quiet)
6475 puts(state);
6476
6477 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
6478 }
6479
6480 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
6481 _cleanup_free_ char *t = NULL;
6482 int r;
6483
6484 assert(new_path);
6485 assert(original_path);
6486 assert(ret_tmp_fn);
6487
6488 r = tempfn_random(new_path, NULL, &t);
6489 if (r < 0)
6490 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
6491
6492 r = mkdir_parents(new_path, 0755);
6493 if (r < 0)
6494 return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
6495
6496 r = copy_file(original_path, t, 0, 0644, 0);
6497 if (r == -ENOENT) {
6498
6499 r = touch(t);
6500 if (r < 0)
6501 return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
6502
6503 } else if (r < 0)
6504 return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
6505
6506 *ret_tmp_fn = t;
6507 t = NULL;
6508
6509 return 0;
6510 }
6511
6512 static int get_file_to_edit(
6513 const LookupPaths *paths,
6514 const char *name,
6515 char **ret_path) {
6516
6517 _cleanup_free_ char *path = NULL, *run = NULL;
6518
6519 assert(name);
6520 assert(ret_path);
6521
6522 path = strjoin(paths->persistent_config, "/", name);
6523 if (!path)
6524 return log_oom();
6525
6526 if (arg_runtime) {
6527 run = strjoin(paths->runtime_config, "/", name);
6528 if (!run)
6529 return log_oom();
6530 }
6531
6532 if (arg_runtime) {
6533 if (access(path, F_OK) >= 0) {
6534 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path);
6535 return -EEXIST;
6536 }
6537
6538 *ret_path = run;
6539 run = NULL;
6540 } else {
6541 *ret_path = path;
6542 path = NULL;
6543 }
6544
6545 return 0;
6546 }
6547
6548 static int unit_file_create_new(
6549 const LookupPaths *paths,
6550 const char *unit_name,
6551 const char *suffix,
6552 char **ret_new_path,
6553 char **ret_tmp_path) {
6554
6555 char *tmp_new_path, *tmp_tmp_path, *ending;
6556 int r;
6557
6558 assert(unit_name);
6559 assert(ret_new_path);
6560 assert(ret_tmp_path);
6561
6562 ending = strjoina(unit_name, suffix);
6563 r = get_file_to_edit(paths, ending, &tmp_new_path);
6564 if (r < 0)
6565 return r;
6566
6567 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
6568 if (r < 0) {
6569 free(tmp_new_path);
6570 return r;
6571 }
6572
6573 *ret_new_path = tmp_new_path;
6574 *ret_tmp_path = tmp_tmp_path;
6575
6576 return 0;
6577 }
6578
6579 static int unit_file_create_copy(
6580 const LookupPaths *paths,
6581 const char *unit_name,
6582 const char *fragment_path,
6583 char **ret_new_path,
6584 char **ret_tmp_path) {
6585
6586 char *tmp_new_path, *tmp_tmp_path;
6587 int r;
6588
6589 assert(fragment_path);
6590 assert(unit_name);
6591 assert(ret_new_path);
6592 assert(ret_tmp_path);
6593
6594 r = get_file_to_edit(paths, unit_name, &tmp_new_path);
6595 if (r < 0)
6596 return r;
6597
6598 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
6599 char response;
6600
6601 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path);
6602 if (r < 0) {
6603 free(tmp_new_path);
6604 return r;
6605 }
6606 if (response != 'y') {
6607 log_warning("%s ignored", unit_name);
6608 free(tmp_new_path);
6609 return -EKEYREJECTED;
6610 }
6611 }
6612
6613 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
6614 if (r < 0) {
6615 free(tmp_new_path);
6616 return r;
6617 }
6618
6619 *ret_new_path = tmp_new_path;
6620 *ret_tmp_path = tmp_tmp_path;
6621
6622 return 0;
6623 }
6624
6625 static int run_editor(char **paths) {
6626 pid_t pid;
6627 int r;
6628
6629 assert(paths);
6630
6631 pid = fork();
6632 if (pid < 0)
6633 return log_error_errno(errno, "Failed to fork: %m");
6634
6635 if (pid == 0) {
6636 const char **args;
6637 char *editor, **editor_args = NULL;
6638 char **tmp_path, **original_path, *p;
6639 unsigned n_editor_args = 0, i = 1;
6640 size_t argc;
6641
6642 (void) reset_all_signal_handlers();
6643 (void) reset_signal_mask();
6644
6645 argc = strv_length(paths)/2 + 1;
6646
6647 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6648 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6649 * we try to execute well known editors
6650 */
6651 editor = getenv("SYSTEMD_EDITOR");
6652 if (!editor)
6653 editor = getenv("EDITOR");
6654 if (!editor)
6655 editor = getenv("VISUAL");
6656
6657 if (!isempty(editor)) {
6658 editor_args = strv_split(editor, WHITESPACE);
6659 if (!editor_args) {
6660 (void) log_oom();
6661 _exit(EXIT_FAILURE);
6662 }
6663 n_editor_args = strv_length(editor_args);
6664 argc += n_editor_args - 1;
6665 }
6666 args = newa(const char*, argc + 1);
6667
6668 if (n_editor_args > 0) {
6669 args[0] = editor_args[0];
6670 for (; i < n_editor_args; i++)
6671 args[i] = editor_args[i];
6672 }
6673
6674 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
6675 args[i] = *tmp_path;
6676 i++;
6677 }
6678 args[i] = NULL;
6679
6680 if (n_editor_args > 0)
6681 execvp(args[0], (char* const*) args);
6682
6683 FOREACH_STRING(p, "editor", "nano", "vim", "vi") {
6684 args[0] = p;
6685 execvp(p, (char* const*) args);
6686 /* We do not fail if the editor doesn't exist
6687 * because we want to try each one of them before
6688 * failing.
6689 */
6690 if (errno != ENOENT) {
6691 log_error_errno(errno, "Failed to execute %s: %m", editor);
6692 _exit(EXIT_FAILURE);
6693 }
6694 }
6695
6696 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6697 _exit(EXIT_FAILURE);
6698 }
6699
6700 r = wait_for_terminate_and_warn("editor", pid, true);
6701 if (r < 0)
6702 return log_error_errno(r, "Failed to wait for child: %m");
6703
6704 return 0;
6705 }
6706
6707 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6708 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6709 char **name;
6710 int r;
6711
6712 assert(names);
6713 assert(paths);
6714
6715 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
6716 if (r < 0)
6717 return r;
6718
6719 STRV_FOREACH(name, names) {
6720 _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL;
6721
6722 r = unit_find_paths(bus, *name, &lp, &path, NULL);
6723 if (r < 0)
6724 return r;
6725 else if (!arg_force) {
6726 if (r == 0) {
6727 log_error("Run 'systemctl edit --force %s' to create a new unit.", *name);
6728 return -ENOENT;
6729 } else if (!path) {
6730 // FIXME: support units with path==NULL (no FragmentPath)
6731 log_error("No fragment exists for %s.", *name);
6732 return -ENOENT;
6733 }
6734 }
6735
6736 if (path) {
6737 if (arg_full)
6738 r = unit_file_create_copy(&lp, *name, path, &new_path, &tmp_path);
6739 else
6740 r = unit_file_create_new(&lp, *name, ".d/override.conf", &new_path, &tmp_path);
6741 } else
6742 r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path);
6743 if (r < 0)
6744 return r;
6745
6746 r = strv_push_pair(paths, new_path, tmp_path);
6747 if (r < 0)
6748 return log_oom();
6749 new_path = tmp_path = NULL;
6750 }
6751
6752 return 0;
6753 }
6754
6755 static int edit(int argc, char *argv[], void *userdata) {
6756 _cleanup_strv_free_ char **names = NULL;
6757 _cleanup_strv_free_ char **paths = NULL;
6758 char **original, **tmp;
6759 sd_bus *bus;
6760 int r;
6761
6762 if (!on_tty()) {
6763 log_error("Cannot edit units if not on a tty.");
6764 return -EINVAL;
6765 }
6766
6767 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6768 log_error("Cannot edit units remotely.");
6769 return -EINVAL;
6770 }
6771
6772 r = acquire_bus(BUS_MANAGER, &bus);
6773 if (r < 0)
6774 return r;
6775
6776 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
6777 if (r < 0)
6778 return log_error_errno(r, "Failed to expand names: %m");
6779
6780 r = find_paths_to_edit(bus, names, &paths);
6781 if (r < 0)
6782 return r;
6783
6784 if (strv_isempty(paths))
6785 return -ENOENT;
6786
6787 r = run_editor(paths);
6788 if (r < 0)
6789 goto end;
6790
6791 STRV_FOREACH_PAIR(original, tmp, paths) {
6792 /* If the temporary file is empty we ignore it. It's
6793 * useful if the user wants to cancel its modification
6794 */
6795 if (null_or_empty_path(*tmp)) {
6796 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
6797 continue;
6798 }
6799
6800 r = rename(*tmp, *original);
6801 if (r < 0) {
6802 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
6803 goto end;
6804 }
6805 }
6806
6807 r = 0;
6808
6809 if (!arg_no_reload && !install_client_side())
6810 r = daemon_reload(argc, argv, userdata);
6811
6812 end:
6813 STRV_FOREACH_PAIR(original, tmp, paths) {
6814 (void) unlink(*tmp);
6815
6816 /* Removing empty dropin dirs */
6817 if (!arg_full) {
6818 _cleanup_free_ char *dir;
6819
6820 dir = dirname_malloc(*original);
6821 if (!dir)
6822 return log_oom();
6823
6824 /* no need to check if the dir is empty, rmdir
6825 * does nothing if it is not the case.
6826 */
6827 (void) rmdir(dir);
6828 }
6829 }
6830
6831 return r;
6832 }
6833
6834 static void systemctl_help(void) {
6835
6836 pager_open(arg_no_pager, false);
6837
6838 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6839 "Query or send control commands to the systemd manager.\n\n"
6840 " -h --help Show this help\n"
6841 " --version Show package version\n"
6842 " --system Connect to system manager\n"
6843 " --user Connect to user service manager\n"
6844 " -H --host=[USER@]HOST\n"
6845 " Operate on remote host\n"
6846 " -M --machine=CONTAINER\n"
6847 " Operate on local container\n"
6848 " -t --type=TYPE List units of a particular type\n"
6849 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6850 " -p --property=NAME Show only properties by this name\n"
6851 " -a --all Show all properties/all units currently in memory,\n"
6852 " including dead/empty ones. To list all units installed on\n"
6853 " the system, use the 'list-unit-files' command instead.\n"
6854 " -l --full Don't ellipsize unit names on output\n"
6855 " -r --recursive Show unit list of host and local containers\n"
6856 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6857 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6858 " queueing a new job\n"
6859 " --show-types When showing sockets, explicitly show their type\n"
6860 " --value When showing properties, only print the value\n"
6861 " -i --ignore-inhibitors\n"
6862 " When shutting down or sleeping, ignore inhibitors\n"
6863 " --kill-who=WHO Who to send signal to\n"
6864 " -s --signal=SIGNAL Which signal to send\n"
6865 " --now Start or stop unit in addition to enabling or disabling it\n"
6866 " -q --quiet Suppress output\n"
6867 " --wait For (re)start, wait until service stopped again\n"
6868 " --no-block Do not wait until operation finished\n"
6869 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6870 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6871 " --no-legend Do not print a legend (column headers and hints)\n"
6872 " --no-pager Do not pipe output into a pager\n"
6873 " --no-ask-password\n"
6874 " Do not ask for system passwords\n"
6875 " --global Enable/disable unit files globally\n"
6876 " --runtime Enable unit files only temporarily until next reboot\n"
6877 " -f --force When enabling unit files, override existing symlinks\n"
6878 " When shutting down, execute action immediately\n"
6879 " --preset-mode= Apply only enable, only disable, or all presets\n"
6880 " --root=PATH Enable unit files in the specified root directory\n"
6881 " -n --lines=INTEGER Number of journal entries to show\n"
6882 " -o --output=STRING Change journal output mode (short, short-precise,\n"
6883 " short-iso, short-full, short-monotonic, short-unix,\n"
6884 " verbose, export, json, json-pretty, json-sse, cat)\n"
6885 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6886 " --plain Print unit dependencies as a list instead of a tree\n\n"
6887 "Unit Commands:\n"
6888 " list-units [PATTERN...] List units currently in memory\n"
6889 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
6890 " by address\n"
6891 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
6892 " by next elapse\n"
6893 " start NAME... Start (activate) one or more units\n"
6894 " stop NAME... Stop (deactivate) one or more units\n"
6895 " reload NAME... Reload one or more units\n"
6896 " restart NAME... Start or restart one or more units\n"
6897 " try-restart NAME... Restart one or more units if active\n"
6898 " reload-or-restart NAME... Reload one or more units if possible,\n"
6899 " otherwise start or restart\n"
6900 " try-reload-or-restart NAME... If active, reload one or more units,\n"
6901 " if supported, otherwise restart\n"
6902 " isolate NAME Start one unit and stop all others\n"
6903 " kill NAME... Send signal to processes of a unit\n"
6904 " is-active PATTERN... Check whether units are active\n"
6905 " is-failed PATTERN... Check whether units are failed\n"
6906 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6907 " show [PATTERN...|JOB...] Show properties of one or more\n"
6908 " units/jobs or the manager\n"
6909 " cat PATTERN... Show files and drop-ins of one or more units\n"
6910 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6911 " help PATTERN...|PID... Show manual for one or more units\n"
6912 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6913 " units\n"
6914 " list-dependencies [NAME] Recursively show units which are required\n"
6915 " or wanted by this unit or by which this\n"
6916 " unit is required or wanted\n\n"
6917 "Unit File Commands:\n"
6918 " list-unit-files [PATTERN...] List installed unit files\n"
6919 " enable [NAME...|PATH...] Enable one or more unit files\n"
6920 " disable NAME... Disable one or more unit files\n"
6921 " reenable NAME... Reenable one or more unit files\n"
6922 " preset NAME... Enable/disable one or more unit files\n"
6923 " based on preset configuration\n"
6924 " preset-all Enable/disable all unit files based on\n"
6925 " preset configuration\n"
6926 " is-enabled NAME... Check whether unit files are enabled\n"
6927 " mask NAME... Mask one or more units\n"
6928 " unmask NAME... Unmask one or more units\n"
6929 " link PATH... Link one or more units files into\n"
6930 " the search path\n"
6931 " revert NAME... Revert one or more unit files to vendor\n"
6932 " version\n"
6933 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6934 " on specified one or more units\n"
6935 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6936 " on specified one or more units\n"
6937 " edit NAME... Edit one or more unit files\n"
6938 " get-default Get the name of the default target\n"
6939 " set-default NAME Set the default target\n\n"
6940 "Machine Commands:\n"
6941 " list-machines [PATTERN...] List local containers and host\n\n"
6942 "Job Commands:\n"
6943 " list-jobs [PATTERN...] List jobs\n"
6944 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6945 "Environment Commands:\n"
6946 " show-environment Dump environment\n"
6947 " set-environment NAME=VALUE... Set one or more environment variables\n"
6948 " unset-environment NAME... Unset one or more environment variables\n"
6949 " import-environment [NAME...] Import all or some environment variables\n\n"
6950 "Manager Lifecycle Commands:\n"
6951 " daemon-reload Reload systemd manager configuration\n"
6952 " daemon-reexec Reexecute systemd manager\n\n"
6953 "System Commands:\n"
6954 " is-system-running Check whether system is fully running\n"
6955 " default Enter system default mode\n"
6956 " rescue Enter system rescue mode\n"
6957 " emergency Enter system emergency mode\n"
6958 " halt Shut down and halt the system\n"
6959 " poweroff Shut down and power-off the system\n"
6960 " reboot [ARG] Shut down and reboot the system\n"
6961 " kexec Shut down and reboot the system with kexec\n"
6962 " exit [EXIT_CODE] Request user instance or container exit\n"
6963 " switch-root ROOT [INIT] Change to a different root file system\n"
6964 " suspend Suspend the system\n"
6965 " hibernate Hibernate the system\n"
6966 " hybrid-sleep Hibernate and suspend the system\n",
6967 program_invocation_short_name);
6968 }
6969
6970 static void halt_help(void) {
6971 printf("%s [OPTIONS...]%s\n\n"
6972 "%s the system.\n\n"
6973 " --help Show this help\n"
6974 " --halt Halt the machine\n"
6975 " -p --poweroff Switch off the machine\n"
6976 " --reboot Reboot the machine\n"
6977 " -f --force Force immediate halt/power-off/reboot\n"
6978 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6979 " -d --no-wtmp Don't write wtmp record\n"
6980 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6981 program_invocation_short_name,
6982 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6983 arg_action == ACTION_REBOOT ? "Reboot" :
6984 arg_action == ACTION_POWEROFF ? "Power off" :
6985 "Halt");
6986 }
6987
6988 static void shutdown_help(void) {
6989 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6990 "Shut down the system.\n\n"
6991 " --help Show this help\n"
6992 " -H --halt Halt the machine\n"
6993 " -P --poweroff Power-off the machine\n"
6994 " -r --reboot Reboot the machine\n"
6995 " -h Equivalent to --poweroff, overridden by --halt\n"
6996 " -k Don't halt/power-off/reboot, just send warnings\n"
6997 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6998 " -c Cancel a pending shutdown\n",
6999 program_invocation_short_name);
7000 }
7001
7002 static void telinit_help(void) {
7003 printf("%s [OPTIONS...] {COMMAND}\n\n"
7004 "Send control commands to the init daemon.\n\n"
7005 " --help Show this help\n"
7006 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7007 "Commands:\n"
7008 " 0 Power-off the machine\n"
7009 " 6 Reboot the machine\n"
7010 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7011 " 1, s, S Enter rescue mode\n"
7012 " q, Q Reload init daemon configuration\n"
7013 " u, U Reexecute init daemon\n",
7014 program_invocation_short_name);
7015 }
7016
7017 static void runlevel_help(void) {
7018 printf("%s [OPTIONS...]\n\n"
7019 "Prints the previous and current runlevel of the init system.\n\n"
7020 " --help Show this help\n",
7021 program_invocation_short_name);
7022 }
7023
7024 static void help_types(void) {
7025 int i;
7026
7027 if (!arg_no_legend)
7028 puts("Available unit types:");
7029 for (i = 0; i < _UNIT_TYPE_MAX; i++)
7030 puts(unit_type_to_string(i));
7031 }
7032
7033 static void help_states(void) {
7034 int i;
7035
7036 if (!arg_no_legend)
7037 puts("Available unit load states:");
7038 for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
7039 puts(unit_load_state_to_string(i));
7040
7041 if (!arg_no_legend)
7042 puts("\nAvailable unit active states:");
7043 for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
7044 puts(unit_active_state_to_string(i));
7045
7046 if (!arg_no_legend)
7047 puts("\nAvailable automount unit substates:");
7048 for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
7049 puts(automount_state_to_string(i));
7050
7051 if (!arg_no_legend)
7052 puts("\nAvailable busname unit substates:");
7053 for (i = 0; i < _BUSNAME_STATE_MAX; i++)
7054 puts(busname_state_to_string(i));
7055
7056 if (!arg_no_legend)
7057 puts("\nAvailable device unit substates:");
7058 for (i = 0; i < _DEVICE_STATE_MAX; i++)
7059 puts(device_state_to_string(i));
7060
7061 if (!arg_no_legend)
7062 puts("\nAvailable mount unit substates:");
7063 for (i = 0; i < _MOUNT_STATE_MAX; i++)
7064 puts(mount_state_to_string(i));
7065
7066 if (!arg_no_legend)
7067 puts("\nAvailable path unit substates:");
7068 for (i = 0; i < _PATH_STATE_MAX; i++)
7069 puts(path_state_to_string(i));
7070
7071 if (!arg_no_legend)
7072 puts("\nAvailable scope unit substates:");
7073 for (i = 0; i < _SCOPE_STATE_MAX; i++)
7074 puts(scope_state_to_string(i));
7075
7076 if (!arg_no_legend)
7077 puts("\nAvailable service unit substates:");
7078 for (i = 0; i < _SERVICE_STATE_MAX; i++)
7079 puts(service_state_to_string(i));
7080
7081 if (!arg_no_legend)
7082 puts("\nAvailable slice unit substates:");
7083 for (i = 0; i < _SLICE_STATE_MAX; i++)
7084 puts(slice_state_to_string(i));
7085
7086 if (!arg_no_legend)
7087 puts("\nAvailable socket unit substates:");
7088 for (i = 0; i < _SOCKET_STATE_MAX; i++)
7089 puts(socket_state_to_string(i));
7090
7091 if (!arg_no_legend)
7092 puts("\nAvailable swap unit substates:");
7093 for (i = 0; i < _SWAP_STATE_MAX; i++)
7094 puts(swap_state_to_string(i));
7095
7096 if (!arg_no_legend)
7097 puts("\nAvailable target unit substates:");
7098 for (i = 0; i < _TARGET_STATE_MAX; i++)
7099 puts(target_state_to_string(i));
7100
7101 if (!arg_no_legend)
7102 puts("\nAvailable timer unit substates:");
7103 for (i = 0; i < _TIMER_STATE_MAX; i++)
7104 puts(timer_state_to_string(i));
7105 }
7106
7107 static int systemctl_parse_argv(int argc, char *argv[]) {
7108
7109 enum {
7110 ARG_FAIL = 0x100,
7111 ARG_REVERSE,
7112 ARG_AFTER,
7113 ARG_BEFORE,
7114 ARG_SHOW_TYPES,
7115 ARG_IRREVERSIBLE,
7116 ARG_IGNORE_DEPENDENCIES,
7117 ARG_VALUE,
7118 ARG_VERSION,
7119 ARG_USER,
7120 ARG_SYSTEM,
7121 ARG_GLOBAL,
7122 ARG_NO_BLOCK,
7123 ARG_NO_LEGEND,
7124 ARG_NO_PAGER,
7125 ARG_NO_WALL,
7126 ARG_ROOT,
7127 ARG_NO_RELOAD,
7128 ARG_KILL_WHO,
7129 ARG_NO_ASK_PASSWORD,
7130 ARG_FAILED,
7131 ARG_RUNTIME,
7132 ARG_FORCE,
7133 ARG_PLAIN,
7134 ARG_STATE,
7135 ARG_JOB_MODE,
7136 ARG_PRESET_MODE,
7137 ARG_FIRMWARE_SETUP,
7138 ARG_NOW,
7139 ARG_MESSAGE,
7140 ARG_WAIT,
7141 };
7142
7143 static const struct option options[] = {
7144 { "help", no_argument, NULL, 'h' },
7145 { "version", no_argument, NULL, ARG_VERSION },
7146 { "type", required_argument, NULL, 't' },
7147 { "property", required_argument, NULL, 'p' },
7148 { "all", no_argument, NULL, 'a' },
7149 { "reverse", no_argument, NULL, ARG_REVERSE },
7150 { "after", no_argument, NULL, ARG_AFTER },
7151 { "before", no_argument, NULL, ARG_BEFORE },
7152 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
7153 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
7154 { "full", no_argument, NULL, 'l' },
7155 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
7156 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
7157 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
7158 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
7159 { "ignore-inhibitors", no_argument, NULL, 'i' },
7160 { "value", no_argument, NULL, ARG_VALUE },
7161 { "user", no_argument, NULL, ARG_USER },
7162 { "system", no_argument, NULL, ARG_SYSTEM },
7163 { "global", no_argument, NULL, ARG_GLOBAL },
7164 { "wait", no_argument, NULL, ARG_WAIT },
7165 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
7166 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
7167 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
7168 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7169 { "quiet", no_argument, NULL, 'q' },
7170 { "root", required_argument, NULL, ARG_ROOT },
7171 { "force", no_argument, NULL, ARG_FORCE },
7172 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
7173 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
7174 { "signal", required_argument, NULL, 's' },
7175 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
7176 { "host", required_argument, NULL, 'H' },
7177 { "machine", required_argument, NULL, 'M' },
7178 { "runtime", no_argument, NULL, ARG_RUNTIME },
7179 { "lines", required_argument, NULL, 'n' },
7180 { "output", required_argument, NULL, 'o' },
7181 { "plain", no_argument, NULL, ARG_PLAIN },
7182 { "state", required_argument, NULL, ARG_STATE },
7183 { "recursive", no_argument, NULL, 'r' },
7184 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
7185 { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
7186 { "now", no_argument, NULL, ARG_NOW },
7187 { "message", required_argument, NULL, ARG_MESSAGE },
7188 {}
7189 };
7190
7191 const char *p;
7192 int c, r;
7193
7194 assert(argc >= 0);
7195 assert(argv);
7196
7197 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7198 arg_ask_password = true;
7199
7200 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
7201
7202 switch (c) {
7203
7204 case 'h':
7205 systemctl_help();
7206 return 0;
7207
7208 case ARG_VERSION:
7209 return version();
7210
7211 case 't': {
7212 if (isempty(optarg)) {
7213 log_error("--type requires arguments.");
7214 return -EINVAL;
7215 }
7216
7217 p = optarg;
7218 for (;;) {
7219 _cleanup_free_ char *type = NULL;
7220
7221 r = extract_first_word(&p, &type, ",", 0);
7222 if (r < 0)
7223 return log_error_errno(r, "Failed to parse type: %s", optarg);
7224
7225 if (r == 0)
7226 break;
7227
7228 if (streq(type, "help")) {
7229 help_types();
7230 return 0;
7231 }
7232
7233 if (unit_type_from_string(type) >= 0) {
7234 if (strv_push(&arg_types, type) < 0)
7235 return log_oom();
7236 type = NULL;
7237 continue;
7238 }
7239
7240 /* It's much nicer to use --state= for
7241 * load states, but let's support this
7242 * in --types= too for compatibility
7243 * with old versions */
7244 if (unit_load_state_from_string(type) >= 0) {
7245 if (strv_push(&arg_states, type) < 0)
7246 return log_oom();
7247 type = NULL;
7248 continue;
7249 }
7250
7251 log_error("Unknown unit type or load state '%s'.", type);
7252 log_info("Use -t help to see a list of allowed values.");
7253 return -EINVAL;
7254 }
7255
7256 break;
7257 }
7258
7259 case 'p': {
7260 /* Make sure that if the empty property list
7261 was specified, we won't show any properties. */
7262 if (isempty(optarg) && !arg_properties) {
7263 arg_properties = new0(char*, 1);
7264 if (!arg_properties)
7265 return log_oom();
7266 } else {
7267 p = optarg;
7268 for (;;) {
7269 _cleanup_free_ char *prop = NULL;
7270
7271 r = extract_first_word(&p, &prop, ",", 0);
7272 if (r < 0)
7273 return log_error_errno(r, "Failed to parse property: %s", optarg);
7274
7275 if (r == 0)
7276 break;
7277
7278 if (strv_push(&arg_properties, prop) < 0)
7279 return log_oom();
7280
7281 prop = NULL;
7282 }
7283 }
7284
7285 /* If the user asked for a particular
7286 * property, show it to him, even if it is
7287 * empty. */
7288 arg_all = true;
7289
7290 break;
7291 }
7292
7293 case 'a':
7294 arg_all = true;
7295 break;
7296
7297 case ARG_REVERSE:
7298 arg_dependency = DEPENDENCY_REVERSE;
7299 break;
7300
7301 case ARG_AFTER:
7302 arg_dependency = DEPENDENCY_AFTER;
7303 break;
7304
7305 case ARG_BEFORE:
7306 arg_dependency = DEPENDENCY_BEFORE;
7307 break;
7308
7309 case ARG_SHOW_TYPES:
7310 arg_show_types = true;
7311 break;
7312
7313 case ARG_VALUE:
7314 arg_value = true;
7315 break;
7316
7317 case ARG_JOB_MODE:
7318 arg_job_mode = optarg;
7319 break;
7320
7321 case ARG_FAIL:
7322 arg_job_mode = "fail";
7323 break;
7324
7325 case ARG_IRREVERSIBLE:
7326 arg_job_mode = "replace-irreversibly";
7327 break;
7328
7329 case ARG_IGNORE_DEPENDENCIES:
7330 arg_job_mode = "ignore-dependencies";
7331 break;
7332
7333 case ARG_USER:
7334 arg_scope = UNIT_FILE_USER;
7335 break;
7336
7337 case ARG_SYSTEM:
7338 arg_scope = UNIT_FILE_SYSTEM;
7339 break;
7340
7341 case ARG_GLOBAL:
7342 arg_scope = UNIT_FILE_GLOBAL;
7343 break;
7344
7345 case ARG_WAIT:
7346 arg_wait = true;
7347 break;
7348
7349 case ARG_NO_BLOCK:
7350 arg_no_block = true;
7351 break;
7352
7353 case ARG_NO_LEGEND:
7354 arg_no_legend = true;
7355 break;
7356
7357 case ARG_NO_PAGER:
7358 arg_no_pager = true;
7359 break;
7360
7361 case ARG_NO_WALL:
7362 arg_no_wall = true;
7363 break;
7364
7365 case ARG_ROOT:
7366 r = parse_path_argument_and_warn(optarg, false, &arg_root);
7367 if (r < 0)
7368 return r;
7369 break;
7370
7371 case 'l':
7372 arg_full = true;
7373 break;
7374
7375 case ARG_FAILED:
7376 if (strv_extend(&arg_states, "failed") < 0)
7377 return log_oom();
7378
7379 break;
7380
7381 case 'q':
7382 arg_quiet = true;
7383 break;
7384
7385 case ARG_FORCE:
7386 arg_force++;
7387 break;
7388
7389 case 'f':
7390 arg_force++;
7391 break;
7392
7393 case ARG_NO_RELOAD:
7394 arg_no_reload = true;
7395 break;
7396
7397 case ARG_KILL_WHO:
7398 arg_kill_who = optarg;
7399 break;
7400
7401 case 's':
7402 arg_signal = signal_from_string_try_harder(optarg);
7403 if (arg_signal < 0) {
7404 log_error("Failed to parse signal string %s.", optarg);
7405 return -EINVAL;
7406 }
7407 break;
7408
7409 case ARG_NO_ASK_PASSWORD:
7410 arg_ask_password = false;
7411 break;
7412
7413 case 'H':
7414 arg_transport = BUS_TRANSPORT_REMOTE;
7415 arg_host = optarg;
7416 break;
7417
7418 case 'M':
7419 arg_transport = BUS_TRANSPORT_MACHINE;
7420 arg_host = optarg;
7421 break;
7422
7423 case ARG_RUNTIME:
7424 arg_runtime = true;
7425 break;
7426
7427 case 'n':
7428 if (safe_atou(optarg, &arg_lines) < 0) {
7429 log_error("Failed to parse lines '%s'", optarg);
7430 return -EINVAL;
7431 }
7432 break;
7433
7434 case 'o':
7435 arg_output = output_mode_from_string(optarg);
7436 if (arg_output < 0) {
7437 log_error("Unknown output '%s'.", optarg);
7438 return -EINVAL;
7439 }
7440 break;
7441
7442 case 'i':
7443 arg_ignore_inhibitors = true;
7444 break;
7445
7446 case ARG_PLAIN:
7447 arg_plain = true;
7448 break;
7449
7450 case ARG_FIRMWARE_SETUP:
7451 arg_firmware_setup = true;
7452 break;
7453
7454 case ARG_STATE: {
7455 if (isempty(optarg)) {
7456 log_error("--signal requires arguments.");
7457 return -EINVAL;
7458 }
7459
7460 p = optarg;
7461 for (;;) {
7462 _cleanup_free_ char *s = NULL;
7463
7464 r = extract_first_word(&p, &s, ",", 0);
7465 if (r < 0)
7466 return log_error_errno(r, "Failed to parse signal: %s", optarg);
7467
7468 if (r == 0)
7469 break;
7470
7471 if (streq(s, "help")) {
7472 help_states();
7473 return 0;
7474 }
7475
7476 if (strv_push(&arg_states, s) < 0)
7477 return log_oom();
7478
7479 s = NULL;
7480 }
7481 break;
7482 }
7483
7484 case 'r':
7485 if (geteuid() != 0) {
7486 log_error("--recursive requires root privileges.");
7487 return -EPERM;
7488 }
7489
7490 arg_recursive = true;
7491 break;
7492
7493 case ARG_PRESET_MODE:
7494
7495 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
7496 if (arg_preset_mode < 0) {
7497 log_error("Failed to parse preset mode: %s.", optarg);
7498 return -EINVAL;
7499 }
7500
7501 break;
7502
7503 case ARG_NOW:
7504 arg_now = true;
7505 break;
7506
7507 case ARG_MESSAGE:
7508 if (strv_extend(&arg_wall, optarg) < 0)
7509 return log_oom();
7510 break;
7511
7512 case '?':
7513 return -EINVAL;
7514
7515 default:
7516 assert_not_reached("Unhandled option");
7517 }
7518
7519 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
7520 log_error("Cannot access user instance remotely.");
7521 return -EINVAL;
7522 }
7523
7524 if (arg_wait && arg_no_block) {
7525 log_error("--wait may not be combined with --no-block.");
7526 return -EINVAL;
7527 }
7528
7529 return 1;
7530 }
7531
7532 static int halt_parse_argv(int argc, char *argv[]) {
7533
7534 enum {
7535 ARG_HELP = 0x100,
7536 ARG_HALT,
7537 ARG_REBOOT,
7538 ARG_NO_WALL
7539 };
7540
7541 static const struct option options[] = {
7542 { "help", no_argument, NULL, ARG_HELP },
7543 { "halt", no_argument, NULL, ARG_HALT },
7544 { "poweroff", no_argument, NULL, 'p' },
7545 { "reboot", no_argument, NULL, ARG_REBOOT },
7546 { "force", no_argument, NULL, 'f' },
7547 { "wtmp-only", no_argument, NULL, 'w' },
7548 { "no-wtmp", no_argument, NULL, 'd' },
7549 { "no-sync", no_argument, NULL, 'n' },
7550 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7551 {}
7552 };
7553
7554 int c, r, runlevel;
7555
7556 assert(argc >= 0);
7557 assert(argv);
7558
7559 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
7560 if (runlevel == '0' || runlevel == '6')
7561 arg_force = 2;
7562
7563 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
7564 switch (c) {
7565
7566 case ARG_HELP:
7567 halt_help();
7568 return 0;
7569
7570 case ARG_HALT:
7571 arg_action = ACTION_HALT;
7572 break;
7573
7574 case 'p':
7575 if (arg_action != ACTION_REBOOT)
7576 arg_action = ACTION_POWEROFF;
7577 break;
7578
7579 case ARG_REBOOT:
7580 arg_action = ACTION_REBOOT;
7581 break;
7582
7583 case 'f':
7584 arg_force = 2;
7585 break;
7586
7587 case 'w':
7588 arg_dry = true;
7589 break;
7590
7591 case 'd':
7592 arg_no_wtmp = true;
7593 break;
7594
7595 case 'n':
7596 arg_no_sync = true;
7597 break;
7598
7599 case ARG_NO_WALL:
7600 arg_no_wall = true;
7601 break;
7602
7603 case 'i':
7604 case 'h':
7605 /* Compatibility nops */
7606 break;
7607
7608 case '?':
7609 return -EINVAL;
7610
7611 default:
7612 assert_not_reached("Unhandled option");
7613 }
7614
7615 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
7616 r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL);
7617 if (r < 0)
7618 return r;
7619 } else if (optind < argc) {
7620 log_error("Too many arguments.");
7621 return -EINVAL;
7622 }
7623
7624 return 1;
7625 }
7626
7627 static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
7628 assert(t);
7629 assert(_u);
7630
7631 if (streq(t, "now"))
7632 *_u = 0;
7633 else if (!strchr(t, ':')) {
7634 uint64_t u;
7635
7636 if (safe_atou64(t, &u) < 0)
7637 return -EINVAL;
7638
7639 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
7640 } else {
7641 char *e = NULL;
7642 long hour, minute;
7643 struct tm tm = {};
7644 time_t s;
7645 usec_t n;
7646
7647 errno = 0;
7648 hour = strtol(t, &e, 10);
7649 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
7650 return -EINVAL;
7651
7652 minute = strtol(e+1, &e, 10);
7653 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
7654 return -EINVAL;
7655
7656 n = now(CLOCK_REALTIME);
7657 s = (time_t) (n / USEC_PER_SEC);
7658
7659 assert_se(localtime_r(&s, &tm));
7660
7661 tm.tm_hour = (int) hour;
7662 tm.tm_min = (int) minute;
7663 tm.tm_sec = 0;
7664
7665 assert_se(s = mktime(&tm));
7666
7667 *_u = (usec_t) s * USEC_PER_SEC;
7668
7669 while (*_u <= n)
7670 *_u += USEC_PER_DAY;
7671 }
7672
7673 return 0;
7674 }
7675
7676 static int shutdown_parse_argv(int argc, char *argv[]) {
7677
7678 enum {
7679 ARG_HELP = 0x100,
7680 ARG_NO_WALL
7681 };
7682
7683 static const struct option options[] = {
7684 { "help", no_argument, NULL, ARG_HELP },
7685 { "halt", no_argument, NULL, 'H' },
7686 { "poweroff", no_argument, NULL, 'P' },
7687 { "reboot", no_argument, NULL, 'r' },
7688 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
7689 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7690 {}
7691 };
7692
7693 char **wall = NULL;
7694 int c, r;
7695
7696 assert(argc >= 0);
7697 assert(argv);
7698
7699 while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0)
7700 switch (c) {
7701
7702 case ARG_HELP:
7703 shutdown_help();
7704 return 0;
7705
7706 case 'H':
7707 arg_action = ACTION_HALT;
7708 break;
7709
7710 case 'P':
7711 arg_action = ACTION_POWEROFF;
7712 break;
7713
7714 case 'r':
7715 if (kexec_loaded())
7716 arg_action = ACTION_KEXEC;
7717 else
7718 arg_action = ACTION_REBOOT;
7719 break;
7720
7721 case 'K':
7722 arg_action = ACTION_KEXEC;
7723 break;
7724
7725 case 'h':
7726 if (arg_action != ACTION_HALT)
7727 arg_action = ACTION_POWEROFF;
7728 break;
7729
7730 case 'k':
7731 arg_dry = true;
7732 break;
7733
7734 case ARG_NO_WALL:
7735 arg_no_wall = true;
7736 break;
7737
7738 case 't':
7739 case 'a':
7740 case 'f':
7741 case 'F':
7742 /* Compatibility nops */
7743 break;
7744
7745 case 'c':
7746 arg_action = ACTION_CANCEL_SHUTDOWN;
7747 break;
7748
7749 case '?':
7750 return -EINVAL;
7751
7752 default:
7753 assert_not_reached("Unhandled option");
7754 }
7755
7756 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7757 r = parse_shutdown_time_spec(argv[optind], &arg_when);
7758 if (r < 0) {
7759 log_error("Failed to parse time specification: %s", argv[optind]);
7760 return r;
7761 }
7762 } else
7763 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7764
7765 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7766 /* No time argument for shutdown cancel */
7767 wall = argv + optind;
7768 else if (argc > optind + 1)
7769 /* We skip the time argument */
7770 wall = argv + optind + 1;
7771
7772 if (wall) {
7773 arg_wall = strv_copy(wall);
7774 if (!arg_wall)
7775 return log_oom();
7776 }
7777
7778 optind = argc;
7779
7780 return 1;
7781 }
7782
7783 static int telinit_parse_argv(int argc, char *argv[]) {
7784
7785 enum {
7786 ARG_HELP = 0x100,
7787 ARG_NO_WALL
7788 };
7789
7790 static const struct option options[] = {
7791 { "help", no_argument, NULL, ARG_HELP },
7792 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7793 {}
7794 };
7795
7796 static const struct {
7797 char from;
7798 enum action to;
7799 } table[] = {
7800 { '0', ACTION_POWEROFF },
7801 { '6', ACTION_REBOOT },
7802 { '1', ACTION_RESCUE },
7803 { '2', ACTION_RUNLEVEL2 },
7804 { '3', ACTION_RUNLEVEL3 },
7805 { '4', ACTION_RUNLEVEL4 },
7806 { '5', ACTION_RUNLEVEL5 },
7807 { 's', ACTION_RESCUE },
7808 { 'S', ACTION_RESCUE },
7809 { 'q', ACTION_RELOAD },
7810 { 'Q', ACTION_RELOAD },
7811 { 'u', ACTION_REEXEC },
7812 { 'U', ACTION_REEXEC }
7813 };
7814
7815 unsigned i;
7816 int c;
7817
7818 assert(argc >= 0);
7819 assert(argv);
7820
7821 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7822 switch (c) {
7823
7824 case ARG_HELP:
7825 telinit_help();
7826 return 0;
7827
7828 case ARG_NO_WALL:
7829 arg_no_wall = true;
7830 break;
7831
7832 case '?':
7833 return -EINVAL;
7834
7835 default:
7836 assert_not_reached("Unhandled option");
7837 }
7838
7839 if (optind >= argc) {
7840 log_error("%s: required argument missing.", program_invocation_short_name);
7841 return -EINVAL;
7842 }
7843
7844 if (optind + 1 < argc) {
7845 log_error("Too many arguments.");
7846 return -EINVAL;
7847 }
7848
7849 if (strlen(argv[optind]) != 1) {
7850 log_error("Expected single character argument.");
7851 return -EINVAL;
7852 }
7853
7854 for (i = 0; i < ELEMENTSOF(table); i++)
7855 if (table[i].from == argv[optind][0])
7856 break;
7857
7858 if (i >= ELEMENTSOF(table)) {
7859 log_error("Unknown command '%s'.", argv[optind]);
7860 return -EINVAL;
7861 }
7862
7863 arg_action = table[i].to;
7864
7865 optind++;
7866
7867 return 1;
7868 }
7869
7870 static int runlevel_parse_argv(int argc, char *argv[]) {
7871
7872 enum {
7873 ARG_HELP = 0x100,
7874 };
7875
7876 static const struct option options[] = {
7877 { "help", no_argument, NULL, ARG_HELP },
7878 {}
7879 };
7880
7881 int c;
7882
7883 assert(argc >= 0);
7884 assert(argv);
7885
7886 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7887 switch (c) {
7888
7889 case ARG_HELP:
7890 runlevel_help();
7891 return 0;
7892
7893 case '?':
7894 return -EINVAL;
7895
7896 default:
7897 assert_not_reached("Unhandled option");
7898 }
7899
7900 if (optind < argc) {
7901 log_error("Too many arguments.");
7902 return -EINVAL;
7903 }
7904
7905 return 1;
7906 }
7907
7908 static int parse_argv(int argc, char *argv[]) {
7909 assert(argc >= 0);
7910 assert(argv);
7911
7912 if (program_invocation_short_name) {
7913
7914 if (strstr(program_invocation_short_name, "halt")) {
7915 arg_action = ACTION_HALT;
7916 return halt_parse_argv(argc, argv);
7917 } else if (strstr(program_invocation_short_name, "poweroff")) {
7918 arg_action = ACTION_POWEROFF;
7919 return halt_parse_argv(argc, argv);
7920 } else if (strstr(program_invocation_short_name, "reboot")) {
7921 if (kexec_loaded())
7922 arg_action = ACTION_KEXEC;
7923 else
7924 arg_action = ACTION_REBOOT;
7925 return halt_parse_argv(argc, argv);
7926 } else if (strstr(program_invocation_short_name, "shutdown")) {
7927 arg_action = ACTION_POWEROFF;
7928 return shutdown_parse_argv(argc, argv);
7929 } else if (strstr(program_invocation_short_name, "init")) {
7930
7931 if (sd_booted() > 0) {
7932 arg_action = _ACTION_INVALID;
7933 return telinit_parse_argv(argc, argv);
7934 } else {
7935 /* Hmm, so some other init system is
7936 * running, we need to forward this
7937 * request to it. For now we simply
7938 * guess that it is Upstart. */
7939
7940 execv(TELINIT, argv);
7941
7942 log_error("Couldn't find an alternative telinit implementation to spawn.");
7943 return -EIO;
7944 }
7945
7946 } else if (strstr(program_invocation_short_name, "runlevel")) {
7947 arg_action = ACTION_RUNLEVEL;
7948 return runlevel_parse_argv(argc, argv);
7949 }
7950 }
7951
7952 arg_action = ACTION_SYSTEMCTL;
7953 return systemctl_parse_argv(argc, argv);
7954 }
7955
7956 #ifdef HAVE_SYSV_COMPAT
7957 _pure_ static int action_to_runlevel(void) {
7958
7959 static const char table[_ACTION_MAX] = {
7960 [ACTION_HALT] = '0',
7961 [ACTION_POWEROFF] = '0',
7962 [ACTION_REBOOT] = '6',
7963 [ACTION_RUNLEVEL2] = '2',
7964 [ACTION_RUNLEVEL3] = '3',
7965 [ACTION_RUNLEVEL4] = '4',
7966 [ACTION_RUNLEVEL5] = '5',
7967 [ACTION_RESCUE] = '1'
7968 };
7969
7970 assert(arg_action < _ACTION_MAX);
7971
7972 return table[arg_action];
7973 }
7974 #endif
7975
7976 static int talk_initctl(void) {
7977 #ifdef HAVE_SYSV_COMPAT
7978 struct init_request request = {
7979 .magic = INIT_MAGIC,
7980 .sleeptime = 0,
7981 .cmd = INIT_CMD_RUNLVL
7982 };
7983
7984 _cleanup_close_ int fd = -1;
7985 char rl;
7986 int r;
7987
7988 rl = action_to_runlevel();
7989 if (!rl)
7990 return 0;
7991
7992 request.runlevel = rl;
7993
7994 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7995 if (fd < 0) {
7996 if (errno == ENOENT)
7997 return 0;
7998
7999 return log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
8000 }
8001
8002 r = loop_write(fd, &request, sizeof(request), false);
8003 if (r < 0)
8004 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
8005
8006 return 1;
8007 #else
8008 return 0;
8009 #endif
8010 }
8011
8012 static int systemctl_main(int argc, char *argv[]) {
8013
8014 static const Verb verbs[] = {
8015 { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units },
8016 { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
8017 { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets },
8018 { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers },
8019 { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs },
8020 { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines },
8021 { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, trivial_method },
8022 { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job },
8023 { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8024 { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8025 { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
8026 { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8027 { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8028 { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8029 { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8030 { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */
8031 { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8032 { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */
8033 { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
8034 { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */
8035 { "isolate", 2, 2, VERB_NOCHROOT, start_unit },
8036 { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit },
8037 { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
8038 { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
8039 { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed },
8040 { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8041 { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat },
8042 { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8043 { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8044 { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
8045 { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
8046 { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment },
8047 { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
8048 { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
8049 { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment },
8050 { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8051 { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8052 { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_system_special },
8053 { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8054 { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8055 { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8056 { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8057 { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special },
8058 { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8059 { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8060 { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special },
8061 { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed },
8062 { "enable", 2, VERB_ANY, 0, enable_unit },
8063 { "disable", 2, VERB_ANY, 0, enable_unit },
8064 { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
8065 { "reenable", 2, VERB_ANY, 0, enable_unit },
8066 { "preset", 2, VERB_ANY, 0, enable_unit },
8067 { "preset-all", VERB_ANY, 1, 0, preset_all },
8068 { "mask", 2, VERB_ANY, 0, enable_unit },
8069 { "unmask", 2, VERB_ANY, 0, enable_unit },
8070 { "link", 2, VERB_ANY, 0, enable_unit },
8071 { "revert", 2, VERB_ANY, 0, enable_unit },
8072 { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root },
8073 { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies },
8074 { "set-default", 2, 2, 0, set_default },
8075 { "get-default", VERB_ANY, 1, 0, get_default },
8076 { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property },
8077 { "is-system-running", VERB_ANY, 1, 0, is_system_running },
8078 { "add-wants", 3, VERB_ANY, 0, add_dependency },
8079 { "add-requires", 3, VERB_ANY, 0, add_dependency },
8080 { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit },
8081 {}
8082 };
8083
8084 return dispatch_verb(argc, argv, verbs, NULL);
8085 }
8086
8087 static int reload_with_fallback(void) {
8088
8089 /* First, try systemd via D-Bus. */
8090 if (daemon_reload(0, NULL, NULL) >= 0)
8091 return 0;
8092
8093 /* Nothing else worked, so let's try signals */
8094 assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
8095
8096 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
8097 return log_error_errno(errno, "kill() failed: %m");
8098
8099 return 0;
8100 }
8101
8102 static int start_with_fallback(void) {
8103
8104 /* First, try systemd via D-Bus. */
8105 if (start_unit(0, NULL, NULL) >= 0)
8106 return 0;
8107
8108 /* Nothing else worked, so let's try /dev/initctl */
8109 if (talk_initctl() > 0)
8110 return 0;
8111
8112 log_error("Failed to talk to init daemon.");
8113 return -EIO;
8114 }
8115
8116 static int halt_now(enum action a) {
8117 int r;
8118
8119 /* The kernel will automaticall flush ATA disks and suchlike
8120 * on reboot(), but the file systems need to be synce'd
8121 * explicitly in advance. */
8122 if (!arg_no_sync)
8123 (void) sync();
8124
8125 /* Make sure C-A-D is handled by the kernel from this point
8126 * on... */
8127 (void) reboot(RB_ENABLE_CAD);
8128
8129 switch (a) {
8130
8131 case ACTION_HALT:
8132 log_info("Halting.");
8133 (void) reboot(RB_HALT_SYSTEM);
8134 return -errno;
8135
8136 case ACTION_POWEROFF:
8137 log_info("Powering off.");
8138 (void) reboot(RB_POWER_OFF);
8139 return -errno;
8140
8141 case ACTION_KEXEC:
8142 case ACTION_REBOOT: {
8143 _cleanup_free_ char *param = NULL;
8144
8145 r = read_one_line_file("/run/systemd/reboot-param", &param);
8146 if (r < 0)
8147 log_warning_errno(r, "Failed to read reboot parameter file: %m");
8148
8149 if (!isempty(param)) {
8150 log_info("Rebooting with argument '%s'.", param);
8151 (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
8152 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
8153 }
8154
8155 log_info("Rebooting.");
8156 (void) reboot(RB_AUTOBOOT);
8157 return -errno;
8158 }
8159
8160 default:
8161 assert_not_reached("Unknown action.");
8162 }
8163 }
8164
8165 static int logind_schedule_shutdown(void) {
8166
8167 #ifdef HAVE_LOGIND
8168 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8169 char date[FORMAT_TIMESTAMP_MAX];
8170 const char *action;
8171 sd_bus *bus;
8172 int r;
8173
8174 r = acquire_bus(BUS_FULL, &bus);
8175 if (r < 0)
8176 return r;
8177
8178 switch (arg_action) {
8179 case ACTION_HALT:
8180 action = "halt";
8181 break;
8182 case ACTION_POWEROFF:
8183 action = "poweroff";
8184 break;
8185 case ACTION_KEXEC:
8186 action = "kexec";
8187 break;
8188 case ACTION_EXIT:
8189 action = "exit";
8190 break;
8191 case ACTION_REBOOT:
8192 default:
8193 action = "reboot";
8194 break;
8195 }
8196
8197 if (arg_dry)
8198 action = strjoina("dry-", action);
8199
8200 (void) logind_set_wall_message();
8201
8202 r = sd_bus_call_method(
8203 bus,
8204 "org.freedesktop.login1",
8205 "/org/freedesktop/login1",
8206 "org.freedesktop.login1.Manager",
8207 "ScheduleShutdown",
8208 &error,
8209 NULL,
8210 "st",
8211 action,
8212 arg_when);
8213 if (r < 0)
8214 return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
8215
8216 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
8217 return 0;
8218 #else
8219 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8220 return -ENOSYS;
8221 #endif
8222 }
8223
8224 static int halt_main(void) {
8225 int r;
8226
8227 r = logind_check_inhibitors(arg_action);
8228 if (r < 0)
8229 return r;
8230
8231 if (arg_when > 0)
8232 return logind_schedule_shutdown();
8233
8234 if (geteuid() != 0) {
8235 if (arg_dry || arg_force > 0) {
8236 log_error("Must be root.");
8237 return -EPERM;
8238 }
8239
8240 /* Try logind if we are a normal user and no special
8241 * mode applies. Maybe PolicyKit allows us to shutdown
8242 * the machine. */
8243 if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) {
8244 r = logind_reboot(arg_action);
8245 if (r >= 0)
8246 return r;
8247 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
8248 /* requested operation is not
8249 * supported on the local system or
8250 * already in progress */
8251 return r;
8252 /* on all other errors, try low-level operation */
8253 }
8254 }
8255
8256 if (!arg_dry && !arg_force)
8257 return start_with_fallback();
8258
8259 assert(geteuid() == 0);
8260
8261 if (!arg_no_wtmp) {
8262 if (sd_booted() > 0)
8263 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8264 else {
8265 r = utmp_put_shutdown();
8266 if (r < 0)
8267 log_warning_errno(r, "Failed to write utmp record: %m");
8268 }
8269 }
8270
8271 if (arg_dry)
8272 return 0;
8273
8274 r = halt_now(arg_action);
8275 return log_error_errno(r, "Failed to reboot: %m");
8276 }
8277
8278 static int runlevel_main(void) {
8279 int r, runlevel, previous;
8280
8281 r = utmp_get_runlevel(&runlevel, &previous);
8282 if (r < 0) {
8283 puts("unknown");
8284 return r;
8285 }
8286
8287 printf("%c %c\n",
8288 previous <= 0 ? 'N' : previous,
8289 runlevel <= 0 ? 'N' : runlevel);
8290
8291 return 0;
8292 }
8293
8294 static int logind_cancel_shutdown(void) {
8295 #ifdef HAVE_LOGIND
8296 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8297 sd_bus *bus;
8298 int r;
8299
8300 r = acquire_bus(BUS_FULL, &bus);
8301 if (r < 0)
8302 return r;
8303
8304 (void) logind_set_wall_message();
8305
8306 r = sd_bus_call_method(
8307 bus,
8308 "org.freedesktop.login1",
8309 "/org/freedesktop/login1",
8310 "org.freedesktop.login1.Manager",
8311 "CancelScheduledShutdown",
8312 &error,
8313 NULL, NULL);
8314 if (r < 0)
8315 return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
8316
8317 return 0;
8318 #else
8319 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8320 return -ENOSYS;
8321 #endif
8322 }
8323
8324 int main(int argc, char*argv[]) {
8325 int r;
8326
8327 setlocale(LC_ALL, "");
8328 log_parse_environment();
8329 log_open();
8330 sigbus_install();
8331
8332 /* Explicitly not on_tty() to avoid setting cached value.
8333 * This becomes relevant for piping output which might be
8334 * ellipsized. */
8335 original_stdout_is_tty = isatty(STDOUT_FILENO);
8336
8337 r = parse_argv(argc, argv);
8338 if (r <= 0)
8339 goto finish;
8340
8341 if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
8342 log_info("Running in chroot, ignoring request.");
8343 r = 0;
8344 goto finish;
8345 }
8346
8347 /* systemctl_main() will print an error message for the bus
8348 * connection, but only if it needs to */
8349
8350 switch (arg_action) {
8351
8352 case ACTION_SYSTEMCTL:
8353 r = systemctl_main(argc, argv);
8354 break;
8355
8356 case ACTION_HALT:
8357 case ACTION_POWEROFF:
8358 case ACTION_REBOOT:
8359 case ACTION_KEXEC:
8360 r = halt_main();
8361 break;
8362
8363 case ACTION_RUNLEVEL2:
8364 case ACTION_RUNLEVEL3:
8365 case ACTION_RUNLEVEL4:
8366 case ACTION_RUNLEVEL5:
8367 case ACTION_RESCUE:
8368 case ACTION_EMERGENCY:
8369 case ACTION_DEFAULT:
8370 r = start_with_fallback();
8371 break;
8372
8373 case ACTION_RELOAD:
8374 case ACTION_REEXEC:
8375 r = reload_with_fallback();
8376 break;
8377
8378 case ACTION_CANCEL_SHUTDOWN:
8379 r = logind_cancel_shutdown();
8380 break;
8381
8382 case ACTION_RUNLEVEL:
8383 r = runlevel_main();
8384 break;
8385
8386 case _ACTION_INVALID:
8387 default:
8388 assert_not_reached("Unknown action");
8389 }
8390
8391 finish:
8392 release_busses();
8393
8394 pager_close();
8395 ask_password_agent_close();
8396 polkit_agent_close();
8397
8398 strv_free(arg_types);
8399 strv_free(arg_states);
8400 strv_free(arg_properties);
8401
8402 strv_free(arg_wall);
8403 free(arg_root);
8404
8405 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8406 return r < 0 ? EXIT_FAILURE : r;
8407 }