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