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