]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
0e833ab538ba1e91f4891100ae03dd4a9fe76843
[thirdparty/systemd.git] / src / systemctl / systemctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
26 #include <stdio.h>
27 #include <getopt.h>
28 #include <locale.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <termios.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <stddef.h>
39 #include <sys/prctl.h>
40
41 #include "sd-daemon.h"
42 #include "sd-shutdown.h"
43 #include "sd-login.h"
44 #include "sd-bus.h"
45 #include "log.h"
46 #include "util.h"
47 #include "macro.h"
48 #include "set.h"
49 #include "utmp-wtmp.h"
50 #include "special.h"
51 #include "initreq.h"
52 #include "path-util.h"
53 #include "strv.h"
54 #include "cgroup-show.h"
55 #include "cgroup-util.h"
56 #include "list.h"
57 #include "path-lookup.h"
58 #include "conf-parser.h"
59 #include "exit-status.h"
60 #include "bus-errors.h"
61 #include "build.h"
62 #include "unit-name.h"
63 #include "pager.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
66 #include "install.h"
67 #include "logs-show.h"
68 #include "path-util.h"
69 #include "socket-util.h"
70 #include "fileio.h"
71 #include "bus-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74
75 static char **arg_types = NULL;
76 static char **arg_states = NULL;
77 static char **arg_properties = NULL;
78 static bool arg_all = false;
79 static bool original_stdout_is_tty;
80 static enum dependency {
81 DEPENDENCY_FORWARD,
82 DEPENDENCY_REVERSE,
83 DEPENDENCY_AFTER,
84 DEPENDENCY_BEFORE,
85 } arg_dependency = DEPENDENCY_FORWARD;
86 static const char *arg_job_mode = "replace";
87 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
88 static bool arg_no_block = false;
89 static bool arg_no_legend = false;
90 static bool arg_no_pager = false;
91 static bool arg_no_wtmp = false;
92 static bool arg_no_wall = false;
93 static bool arg_no_reload = false;
94 static bool arg_show_types = false;
95 static bool arg_ignore_inhibitors = false;
96 static bool arg_dry = false;
97 static bool arg_quiet = false;
98 static bool arg_full = false;
99 static int arg_force = 0;
100 static bool arg_ask_password = true;
101 static bool arg_runtime = false;
102 static char **arg_wall = NULL;
103 static const char *arg_kill_who = NULL;
104 static int arg_signal = SIGTERM;
105 static const char *arg_root = NULL;
106 static usec_t arg_when = 0;
107 static enum action {
108 _ACTION_INVALID,
109 ACTION_SYSTEMCTL,
110 ACTION_HALT,
111 ACTION_POWEROFF,
112 ACTION_REBOOT,
113 ACTION_KEXEC,
114 ACTION_EXIT,
115 ACTION_SUSPEND,
116 ACTION_HIBERNATE,
117 ACTION_HYBRID_SLEEP,
118 ACTION_RUNLEVEL2,
119 ACTION_RUNLEVEL3,
120 ACTION_RUNLEVEL4,
121 ACTION_RUNLEVEL5,
122 ACTION_RESCUE,
123 ACTION_EMERGENCY,
124 ACTION_DEFAULT,
125 ACTION_RELOAD,
126 ACTION_REEXEC,
127 ACTION_RUNLEVEL,
128 ACTION_CANCEL_SHUTDOWN,
129 _ACTION_MAX
130 } arg_action = ACTION_SYSTEMCTL;
131 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
132 static char *arg_host = NULL;
133 static unsigned arg_lines = 10;
134 static OutputMode arg_output = OUTPUT_SHORT;
135 static bool arg_plain = false;
136
137 static int daemon_reload(sd_bus *bus, char **args);
138 static int halt_now(enum action a);
139
140 static void pager_open_if_enabled(void) {
141
142 if (arg_no_pager)
143 return;
144
145 pager_open(false);
146 }
147
148 static void ask_password_agent_open_if_enabled(void) {
149
150 /* Open the password agent as a child process if necessary */
151
152 if (!arg_ask_password)
153 return;
154
155 if (arg_scope != UNIT_FILE_SYSTEM)
156 return;
157
158 if (arg_transport != BUS_TRANSPORT_LOCAL)
159 return;
160
161 ask_password_agent_open();
162 }
163
164 #ifdef HAVE_LOGIND
165 static void polkit_agent_open_if_enabled(void) {
166
167 /* Open the polkit agent as a child process if necessary */
168
169 if (!arg_ask_password)
170 return;
171
172 if (arg_scope != UNIT_FILE_SYSTEM)
173 return;
174
175 if (arg_transport != BUS_TRANSPORT_LOCAL)
176 return;
177
178 polkit_agent_open();
179 }
180 #endif
181
182 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
183 assert(error);
184
185 if (!sd_bus_error_is_set(error))
186 return r;
187
188 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
189 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
190 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
191 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
192 return EXIT_NOPERMISSION;
193
194 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
195 return EXIT_NOTINSTALLED;
196
197 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
198 sd_bus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
199 return EXIT_NOTIMPLEMENTED;
200
201 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
202 return EXIT_NOTCONFIGURED;
203
204 if (r != 0)
205 return r;
206
207 return EXIT_FAILURE;
208 }
209
210 static void warn_wall(enum action a) {
211 static const char *table[_ACTION_MAX] = {
212 [ACTION_HALT] = "The system is going down for system halt NOW!",
213 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
214 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
215 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
216 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
217 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
218 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
219 };
220
221 if (arg_no_wall)
222 return;
223
224 if (arg_wall) {
225 _cleanup_free_ char *p;
226
227 p = strv_join(arg_wall, " ");
228 if (!p) {
229 log_oom();
230 return;
231 }
232
233 if (*p) {
234 utmp_wall(p, NULL);
235 return;
236 }
237 }
238
239 if (!table[a])
240 return;
241
242 utmp_wall(table[a], NULL);
243 }
244
245 static bool avoid_bus(void) {
246
247 if (running_in_chroot() > 0)
248 return true;
249
250 if (sd_booted() <= 0)
251 return true;
252
253 if (!isempty(arg_root))
254 return true;
255
256 if (arg_scope == UNIT_FILE_GLOBAL)
257 return true;
258
259 return false;
260 }
261
262 static int compare_unit_info(const void *a, const void *b) {
263 const UnitInfo *u = a, *v = b;
264 const char *d1, *d2;
265
266 d1 = strrchr(u->id, '.');
267 d2 = strrchr(v->id, '.');
268
269 if (d1 && d2) {
270 int r;
271
272 r = strcasecmp(d1, d2);
273 if (r != 0)
274 return r;
275 }
276
277 return strcasecmp(u->id, v->id);
278 }
279
280 static bool output_show_unit(const UnitInfo *u) {
281 const char *dot;
282
283 if (!strv_isempty(arg_states))
284 return
285 strv_contains(arg_states, u->load_state) ||
286 strv_contains(arg_states, u->sub_state) ||
287 strv_contains(arg_states, u->active_state);
288
289 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
290 strv_find(arg_types, dot+1))) &&
291 (arg_all || !(streq(u->active_state, "inactive")
292 || u->following[0]) || u->job_id > 0);
293 }
294
295 static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
296 unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
297 const UnitInfo *u;
298 unsigned n_shown = 0;
299 int job_count = 0;
300
301 max_id_len = sizeof("UNIT")-1;
302 load_len = sizeof("LOAD")-1;
303 active_len = sizeof("ACTIVE")-1;
304 sub_len = sizeof("SUB")-1;
305 job_len = sizeof("JOB")-1;
306 desc_len = 0;
307
308 for (u = unit_infos; u < unit_infos + c; u++) {
309 if (!output_show_unit(u))
310 continue;
311
312 max_id_len = MAX(max_id_len, strlen(u->id));
313 load_len = MAX(load_len, strlen(u->load_state));
314 active_len = MAX(active_len, strlen(u->active_state));
315 sub_len = MAX(sub_len, strlen(u->sub_state));
316
317 if (u->job_id != 0) {
318 job_len = MAX(job_len, strlen(u->job_type));
319 job_count++;
320 }
321 }
322
323 if (!arg_full && original_stdout_is_tty) {
324 unsigned basic_len;
325
326 id_len = MIN(max_id_len, 25u);
327 basic_len = 5 + id_len + 5 + active_len + sub_len;
328
329 if (job_count)
330 basic_len += job_len + 1;
331
332 if (basic_len < (unsigned) columns()) {
333 unsigned extra_len, incr;
334 extra_len = columns() - basic_len;
335
336 /* Either UNIT already got 25, or is fully satisfied.
337 * Grant up to 25 to DESC now. */
338 incr = MIN(extra_len, 25u);
339 desc_len += incr;
340 extra_len -= incr;
341
342 /* split the remaining space between UNIT and DESC,
343 * but do not give UNIT more than it needs. */
344 if (extra_len > 0) {
345 incr = MIN(extra_len / 2, max_id_len - id_len);
346 id_len += incr;
347 desc_len += extra_len - incr;
348 }
349 }
350 } else
351 id_len = max_id_len;
352
353 for (u = unit_infos; u < unit_infos + c; u++) {
354 _cleanup_free_ char *e = NULL;
355 const char *on_loaded, *off_loaded, *on = "";
356 const char *on_active, *off_active, *off = "";
357
358 if (!output_show_unit(u))
359 continue;
360
361 if (!n_shown && !arg_no_legend) {
362 printf("%-*s %-*s %-*s %-*s ",
363 id_len, "UNIT",
364 load_len, "LOAD",
365 active_len, "ACTIVE",
366 sub_len, "SUB");
367
368 if (job_count)
369 printf("%-*s ", job_len, "JOB");
370
371 if (!arg_full && arg_no_pager)
372 printf("%.*s\n", desc_len, "DESCRIPTION");
373 else
374 printf("%s\n", "DESCRIPTION");
375 }
376
377 n_shown++;
378
379 if (streq(u->load_state, "error") ||
380 streq(u->load_state, "not-found")) {
381 on_loaded = on = ansi_highlight_red();
382 off_loaded = off = ansi_highlight_off();
383 } else
384 on_loaded = off_loaded = "";
385
386 if (streq(u->active_state, "failed")) {
387 on_active = on = ansi_highlight_red();
388 off_active = off = ansi_highlight_off();
389 } else
390 on_active = off_active = "";
391
392 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
393
394 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
395 on, id_len, e ? e : u->id, off,
396 on_loaded, load_len, u->load_state, off_loaded,
397 on_active, active_len, u->active_state,
398 sub_len, u->sub_state, off_active,
399 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
400
401 if (desc_len > 0)
402 printf("%.*s\n", desc_len, u->description);
403 else
404 printf("%s\n", u->description);
405 }
406
407 if (!arg_no_legend) {
408 const char *on, *off;
409
410 if (n_shown) {
411 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
412 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
413 "SUB = The low-level unit activation state, values depend on unit type.\n");
414 if (job_count)
415 printf("JOB = Pending job for the unit.\n");
416 puts("");
417 on = ansi_highlight();
418 off = ansi_highlight_off();
419 } else {
420 on = ansi_highlight_red();
421 off = ansi_highlight_off();
422 }
423
424 if (arg_all)
425 printf("%s%u loaded units listed.%s\n"
426 "To show all installed unit files use 'systemctl list-unit-files'.\n",
427 on, n_shown, off);
428 else
429 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n",
431 on, n_shown, off);
432 }
433 }
434
435 static int get_unit_list(
436 sd_bus *bus,
437 sd_bus_message **_reply,
438 UnitInfo **_unit_infos) {
439
440 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
441 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
442 _cleanup_free_ UnitInfo *unit_infos = NULL;
443 size_t size = 0;
444 int r, c = 0;
445 UnitInfo u;
446
447 assert(bus);
448 assert(_reply);
449 assert(_unit_infos);
450
451 r = sd_bus_call_method(
452 bus,
453 "org.freedesktop.systemd1",
454 "/org/freedesktop/systemd1",
455 "org.freedesktop.systemd1.Manager",
456 "ListUnits",
457 &error,
458 &reply,
459 NULL);
460 if (r < 0) {
461 log_error("Failed to list units: %s", bus_error_message(&error, r));
462 return r;
463 }
464
465 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
466 if (r < 0)
467 return bus_log_parse_error(r);
468
469 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
470
471 if (!GREEDY_REALLOC(unit_infos, size, c+1))
472 return log_oom();
473
474 unit_infos[c++] = u;
475 }
476 if (r < 0)
477 return bus_log_parse_error(r);
478
479 r = sd_bus_message_exit_container(reply);
480 if (r < 0)
481 return bus_log_parse_error(r);
482
483 *_reply = reply;
484 reply = NULL;
485
486 *_unit_infos = unit_infos;
487 unit_infos = NULL;
488
489 return c;
490 }
491
492 static int list_units(sd_bus *bus, char **args) {
493 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
494 _cleanup_free_ UnitInfo *unit_infos = NULL;
495 int r;
496
497 pager_open_if_enabled();
498
499 r = get_unit_list(bus, &reply, &unit_infos);
500 if (r < 0)
501 return r;
502
503 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
504 output_units_list(unit_infos, r);
505
506 return 0;
507 }
508
509 static int get_triggered_units(
510 sd_bus *bus,
511 const char* path,
512 char*** ret) {
513
514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
515 int r;
516
517 r = sd_bus_get_property_strv(
518 bus,
519 "org.freedesktop.systemd1",
520 path,
521 "org.freedesktop.systemd1.Unit",
522 "Triggers",
523 &error,
524 ret);
525
526 if (r < 0)
527 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
528
529 return 0;
530 }
531
532 static int get_listening(
533 sd_bus *bus,
534 const char* unit_path,
535 char*** listening) {
536
537 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
538 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
539 const char *type, *path;
540 int r, n = 0;
541
542 r = sd_bus_get_property(
543 bus,
544 "org.freedesktop.systemd1",
545 unit_path,
546 "org.freedesktop.systemd1.Socket",
547 "Listen",
548 &error,
549 &reply,
550 "a(ss)");
551 if (r < 0) {
552 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
553 return r;
554 }
555
556 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
557 if (r < 0)
558 return bus_log_parse_error(r);
559
560 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
561
562 r = strv_extend(listening, type);
563 if (r < 0)
564 return log_oom();
565
566 r = strv_extend(listening, path);
567 if (r < 0)
568 return log_oom();
569
570 n++;
571 }
572 if (r < 0)
573 return bus_log_parse_error(r);
574
575 r = sd_bus_message_exit_container(reply);
576 if (r < 0)
577 return bus_log_parse_error(r);
578
579 return n;
580 }
581
582 struct socket_info {
583 const char* id;
584
585 char* type;
586 char* path;
587
588 /* Note: triggered is a list here, although it almost certainly
589 * will always be one unit. Nevertheless, dbus API allows for multiple
590 * values, so let's follow that.*/
591 char** triggered;
592
593 /* The strv above is shared. free is set only in the first one. */
594 bool own_triggered;
595 };
596
597 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
598 int o;
599
600 assert(a);
601 assert(b);
602
603 o = strcmp(a->path, b->path);
604 if (o == 0)
605 o = strcmp(a->type, b->type);
606
607 return o;
608 }
609
610 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
611 struct socket_info *s;
612 unsigned pathlen = sizeof("LISTEN") - 1,
613 typelen = (sizeof("TYPE") - 1) * arg_show_types,
614 socklen = sizeof("UNIT") - 1,
615 servlen = sizeof("ACTIVATES") - 1;
616 const char *on, *off;
617
618 for (s = socket_infos; s < socket_infos + cs; s++) {
619 unsigned tmp = 0;
620 char **a;
621
622 socklen = MAX(socklen, strlen(s->id));
623 if (arg_show_types)
624 typelen = MAX(typelen, strlen(s->type));
625 pathlen = MAX(pathlen, strlen(s->path));
626
627 STRV_FOREACH(a, s->triggered)
628 tmp += strlen(*a) + 2*(a != s->triggered);
629 servlen = MAX(servlen, tmp);
630 }
631
632 if (cs) {
633 if (!arg_no_legend)
634 printf("%-*s %-*.*s%-*s %s\n",
635 pathlen, "LISTEN",
636 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
637 socklen, "UNIT",
638 "ACTIVATES");
639
640 for (s = socket_infos; s < socket_infos + cs; s++) {
641 char **a;
642
643 if (arg_show_types)
644 printf("%-*s %-*s %-*s",
645 pathlen, s->path, typelen, s->type, socklen, s->id);
646 else
647 printf("%-*s %-*s",
648 pathlen, s->path, socklen, s->id);
649 STRV_FOREACH(a, s->triggered)
650 printf("%s %s",
651 a == s->triggered ? "" : ",", *a);
652 printf("\n");
653 }
654
655 on = ansi_highlight();
656 off = ansi_highlight_off();
657 if (!arg_no_legend)
658 printf("\n");
659 } else {
660 on = ansi_highlight_red();
661 off = ansi_highlight_off();
662 }
663
664 if (!arg_no_legend) {
665 printf("%s%u sockets listed.%s\n", on, cs, off);
666 if (!arg_all)
667 printf("Pass --all to see loaded but inactive sockets, too.\n");
668 }
669
670 return 0;
671 }
672
673 static int list_sockets(sd_bus *bus, char **args) {
674 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
675 _cleanup_free_ UnitInfo *unit_infos = NULL;
676 struct socket_info *socket_infos = NULL;
677 const UnitInfo *u;
678 struct socket_info *s;
679 unsigned cs = 0;
680 size_t size = 0;
681 int r = 0, n;
682
683 pager_open_if_enabled();
684
685 n = get_unit_list(bus, &reply, &unit_infos);
686 if (n < 0)
687 return n;
688
689 for (u = unit_infos; u < unit_infos + n; u++) {
690 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
691 int i, c;
692
693 if (!output_show_unit(u))
694 continue;
695
696 if (!endswith(u->id, ".socket"))
697 continue;
698
699 r = get_triggered_units(bus, u->unit_path, &triggered);
700 if (r < 0)
701 goto cleanup;
702
703 c = get_listening(bus, u->unit_path, &listening);
704 if (c < 0) {
705 r = c;
706 goto cleanup;
707 }
708
709 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
710 r = log_oom();
711 goto cleanup;
712 }
713
714 for (i = 0; i < c; i++)
715 socket_infos[cs + i] = (struct socket_info) {
716 .id = u->id,
717 .type = listening[i*2],
718 .path = listening[i*2 + 1],
719 .triggered = triggered,
720 .own_triggered = i==0,
721 };
722
723 /* from this point on we will cleanup those socket_infos */
724 cs += c;
725 free(listening);
726 listening = triggered = NULL; /* avoid cleanup */
727 }
728
729 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
730 (__compar_fn_t) socket_info_compare);
731
732 output_sockets_list(socket_infos, cs);
733
734 cleanup:
735 assert(cs == 0 || socket_infos);
736 for (s = socket_infos; s < socket_infos + cs; s++) {
737 free(s->type);
738 free(s->path);
739 if (s->own_triggered)
740 strv_free(s->triggered);
741 }
742 free(socket_infos);
743
744 return r;
745 }
746
747 static int get_next_elapse(
748 sd_bus *bus,
749 const char *path,
750 dual_timestamp *next) {
751
752 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
753 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
754 dual_timestamp t;
755 int r;
756
757 assert(bus);
758 assert(path);
759 assert(next);
760
761 r = sd_bus_get_property_trivial(
762 bus,
763 "org.freedesktop.systemd1",
764 path,
765 "org.freedesktop.systemd1.Timer",
766 "NextElapseUSecMonotonic",
767 &error,
768 't',
769 &t.monotonic);
770 if (r < 0) {
771 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
772 return r;
773 }
774
775 r = sd_bus_get_property_trivial(
776 bus,
777 "org.freedesktop.systemd1",
778 path,
779 "org.freedesktop.systemd1.Timer",
780 "NextElapseUSecRealtime",
781 &error,
782 't',
783 &t.realtime);
784 if (r < 0) {
785 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
786 return r;
787 }
788
789 *next = t;
790 return 0;
791 }
792
793 struct timer_info {
794 const char* id;
795 usec_t next_elapse;
796 char** triggered;
797 };
798
799 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
800 assert(a);
801 assert(b);
802
803 if (a->next_elapse < b->next_elapse)
804 return -1;
805 if (a->next_elapse > b->next_elapse)
806 return 1;
807
808 return strcmp(a->id, b->id);
809 }
810
811 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
812 struct timer_info *t;
813 unsigned
814 nextlen = sizeof("NEXT") - 1,
815 leftlen = sizeof("LEFT") - 1,
816 unitlen = sizeof("UNIT") - 1,
817 activatelen = sizeof("ACTIVATES") - 1;
818
819 const char *on, *off;
820
821 assert(timer_infos || n == 0);
822
823 for (t = timer_infos; t < timer_infos + n; t++) {
824 unsigned ul = 0;
825 char **a;
826
827 if (t->next_elapse > 0) {
828 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
829
830 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
831 nextlen = MAX(nextlen, strlen(tstamp) + 1);
832
833 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
834 leftlen = MAX(leftlen, strlen(trel));
835 }
836
837 unitlen = MAX(unitlen, strlen(t->id));
838
839 STRV_FOREACH(a, t->triggered)
840 ul += strlen(*a) + 2*(a != t->triggered);
841 activatelen = MAX(activatelen, ul);
842 }
843
844 if (n > 0) {
845 if (!arg_no_legend)
846 printf("%-*s %-*s %-*s %s\n",
847 nextlen, "NEXT",
848 leftlen, "LEFT",
849 unitlen, "UNIT",
850 "ACTIVATES");
851
852 for (t = timer_infos; t < timer_infos + n; t++) {
853 char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
854 char **a;
855
856 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
857 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
858
859 printf("%-*s %-*s %-*s",
860 nextlen, tstamp, leftlen, trel, unitlen, t->id);
861
862 STRV_FOREACH(a, t->triggered)
863 printf("%s %s",
864 a == t->triggered ? "" : ",", *a);
865 printf("\n");
866 }
867
868 on = ansi_highlight();
869 off = ansi_highlight_off();
870 if (!arg_no_legend)
871 printf("\n");
872 } else {
873 on = ansi_highlight_red();
874 off = ansi_highlight_off();
875 }
876
877 if (!arg_no_legend) {
878 printf("%s%u timers listed.%s\n", on, n, off);
879 if (!arg_all)
880 printf("Pass --all to see loaded but inactive timers, too.\n");
881 }
882
883 return 0;
884 }
885
886 static int list_timers(sd_bus *bus, char **args) {
887
888 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
889 _cleanup_free_ struct timer_info *timer_infos = NULL;
890 _cleanup_free_ UnitInfo *unit_infos = NULL;
891 struct timer_info *t;
892 const UnitInfo *u;
893 size_t size = 0;
894 int n, c = 0;
895 dual_timestamp nw;
896 int r = 0;
897
898 pager_open_if_enabled();
899
900 n = get_unit_list(bus, &reply, &unit_infos);
901 if (n < 0)
902 return n;
903
904 dual_timestamp_get(&nw);
905
906 for (u = unit_infos; u < unit_infos + n; u++) {
907 _cleanup_strv_free_ char **triggered = NULL;
908 dual_timestamp next;
909 usec_t m;
910
911 if (!output_show_unit(u))
912 continue;
913
914 if (!endswith(u->id, ".timer"))
915 continue;
916
917 r = get_triggered_units(bus, u->unit_path, &triggered);
918 if (r < 0)
919 goto cleanup;
920
921 r = get_next_elapse(bus, u->unit_path, &next);
922 if (r < 0)
923 goto cleanup;
924
925 if (next.monotonic != (usec_t) -1 && next.monotonic > 0) {
926 usec_t converted;
927
928 if (next.monotonic > nw.monotonic)
929 converted = nw.realtime + (next.monotonic - nw.monotonic);
930 else
931 converted = nw.realtime - (nw.monotonic - next.monotonic);
932
933 if (next.realtime != (usec_t) -1 && next.realtime > 0)
934 m = MIN(converted, next.realtime);
935 else
936 m = converted;
937 } else
938 m = next.realtime;
939
940 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
941 r = log_oom();
942 goto cleanup;
943 }
944
945 timer_infos[c++] = (struct timer_info) {
946 .id = u->id,
947 .next_elapse = m,
948 .triggered = triggered,
949 };
950
951 triggered = NULL; /* avoid cleanup */
952 }
953
954 qsort_safe(timer_infos, c, sizeof(struct timer_info),
955 (__compar_fn_t) timer_info_compare);
956
957 output_timers_list(timer_infos, c);
958
959 cleanup:
960 for (t = timer_infos; t < timer_infos + c; t++)
961 strv_free(t->triggered);
962
963 return r;
964 }
965
966 static int compare_unit_file_list(const void *a, const void *b) {
967 const char *d1, *d2;
968 const UnitFileList *u = a, *v = b;
969
970 d1 = strrchr(u->path, '.');
971 d2 = strrchr(v->path, '.');
972
973 if (d1 && d2) {
974 int r;
975
976 r = strcasecmp(d1, d2);
977 if (r != 0)
978 return r;
979 }
980
981 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
982 }
983
984 static bool output_show_unit_file(const UnitFileList *u) {
985 const char *dot;
986
987 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
988 }
989
990 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
991 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
992 const UnitFileList *u;
993
994 max_id_len = sizeof("UNIT FILE")-1;
995 state_cols = sizeof("STATE")-1;
996
997 for (u = units; u < units + c; u++) {
998 if (!output_show_unit_file(u))
999 continue;
1000
1001 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
1002 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1003 }
1004
1005 if (!arg_full) {
1006 unsigned basic_cols;
1007
1008 id_cols = MIN(max_id_len, 25u);
1009 basic_cols = 1 + id_cols + state_cols;
1010 if (basic_cols < (unsigned) columns())
1011 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1012 } else
1013 id_cols = max_id_len;
1014
1015 if (!arg_no_legend)
1016 printf("%-*s %-*s\n",
1017 id_cols, "UNIT FILE",
1018 state_cols, "STATE");
1019
1020 for (u = units; u < units + c; u++) {
1021 _cleanup_free_ char *e = NULL;
1022 const char *on, *off;
1023 const char *id;
1024
1025 if (!output_show_unit_file(u))
1026 continue;
1027
1028 n_shown++;
1029
1030 if (u->state == UNIT_FILE_MASKED ||
1031 u->state == UNIT_FILE_MASKED_RUNTIME ||
1032 u->state == UNIT_FILE_DISABLED ||
1033 u->state == UNIT_FILE_INVALID) {
1034 on = ansi_highlight_red();
1035 off = ansi_highlight_off();
1036 } else if (u->state == UNIT_FILE_ENABLED) {
1037 on = ansi_highlight_green();
1038 off = ansi_highlight_off();
1039 } else
1040 on = off = "";
1041
1042 id = path_get_file_name(u->path);
1043
1044 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1045
1046 printf("%-*s %s%-*s%s\n",
1047 id_cols, e ? e : id,
1048 on, state_cols, unit_file_state_to_string(u->state), off);
1049 }
1050
1051 if (!arg_no_legend)
1052 printf("\n%u unit files listed.\n", n_shown);
1053 }
1054
1055 static int list_unit_files(sd_bus *bus, char **args) {
1056 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1057 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1058 _cleanup_free_ UnitFileList *units = NULL;
1059 unsigned c = 0;
1060 const char *state;
1061 char *path;
1062 int r;
1063
1064 pager_open_if_enabled();
1065
1066 if (avoid_bus()) {
1067 Hashmap *h;
1068 UnitFileList *u;
1069 Iterator i;
1070 unsigned n_units;
1071
1072 h = hashmap_new(string_hash_func, string_compare_func);
1073 if (!h)
1074 return log_oom();
1075
1076 r = unit_file_get_list(arg_scope, arg_root, h);
1077 if (r < 0) {
1078 unit_file_list_free(h);
1079 log_error("Failed to get unit file list: %s", strerror(-r));
1080 return r;
1081 }
1082
1083 n_units = hashmap_size(h);
1084 units = new(UnitFileList, n_units);
1085 if (!units) {
1086 unit_file_list_free(h);
1087 return log_oom();
1088 }
1089
1090 HASHMAP_FOREACH(u, h, i) {
1091 memcpy(units + c++, u, sizeof(UnitFileList));
1092 free(u);
1093 }
1094
1095 assert(c == n_units);
1096 hashmap_free(h);
1097 } else {
1098 size_t size = 0;
1099
1100 r = sd_bus_call_method(
1101 bus,
1102 "org.freedesktop.systemd1",
1103 "/org/freedesktop/systemd1",
1104 "org.freedesktop.systemd1.Manager",
1105 "ListUnitFiles",
1106 &error,
1107 &reply,
1108 NULL);
1109 if (r < 0) {
1110 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1111 return r;
1112 }
1113
1114 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1115 if (r < 0)
1116 return bus_log_parse_error(r);
1117
1118 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1119
1120 if (!GREEDY_REALLOC(units, size, c + 1))
1121 return log_oom();
1122
1123 units[c++] = (struct UnitFileList) {
1124 path,
1125 unit_file_state_from_string(state)
1126 };
1127 }
1128 if (r < 0)
1129 return bus_log_parse_error(r);
1130
1131 r = sd_bus_message_exit_container(reply);
1132 if (r < 0)
1133 return bus_log_parse_error(r);
1134 }
1135
1136 if (c > 0) {
1137 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1138 output_unit_file_list(units, c);
1139 }
1140
1141 return 0;
1142 }
1143
1144 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1145 _cleanup_free_ char *n = NULL;
1146 size_t max_len = MAX(columns(),20u);
1147 size_t len = 0;
1148 int i;
1149
1150 if (!arg_plain) {
1151
1152 for (i = level - 1; i >= 0; i--) {
1153 len += 2;
1154 if(len > max_len - 3 && !arg_full) {
1155 printf("%s...\n",max_len % 2 ? "" : " ");
1156 return 0;
1157 }
1158 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1159 }
1160 len += 2;
1161
1162 if(len > max_len - 3 && !arg_full) {
1163 printf("%s...\n",max_len % 2 ? "" : " ");
1164 return 0;
1165 }
1166
1167 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1168 }
1169
1170 if (arg_full){
1171 printf("%s\n", name);
1172 return 0;
1173 }
1174
1175 n = ellipsize(name, max_len-len, 100);
1176 if(!n)
1177 return log_oom();
1178
1179 printf("%s\n", n);
1180 return 0;
1181 }
1182
1183 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1184
1185 static const char *dependencies[] = {
1186 [DEPENDENCY_FORWARD] = "Requires\0"
1187 "RequiresOverridable\0"
1188 "Requisite\0"
1189 "RequisiteOverridable\0"
1190 "Wants\0",
1191 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1192 "RequiredByOverridable\0"
1193 "WantedBy\0"
1194 "PartOf\0",
1195 [DEPENDENCY_AFTER] = "After\0",
1196 [DEPENDENCY_BEFORE] = "Before\0",
1197 };
1198
1199 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1200 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1201 _cleanup_strv_free_ char **ret = NULL;
1202 _cleanup_free_ char *path = NULL;
1203 int r;
1204
1205 assert(bus);
1206 assert(name);
1207 assert(deps);
1208 assert(arg_dependency < ELEMENTSOF(dependencies));
1209
1210 path = unit_dbus_path_from_name(name);
1211 if (!path)
1212 return log_oom();
1213
1214 r = sd_bus_call_method(
1215 bus,
1216 "org.freedesktop.systemd1",
1217 path,
1218 "org.freedesktop.DBus.Properties",
1219 "GetAll",
1220 &error,
1221 &reply,
1222 "s", "org.freedesktop.systemd1.Unit");
1223 if (r < 0) {
1224 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1225 return r;
1226 }
1227
1228 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1229 if (r < 0)
1230 return bus_log_parse_error(r);
1231
1232 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1233 const char *prop;
1234
1235 r = sd_bus_message_read(reply, "s", &prop);
1236 if (r < 0)
1237 return bus_log_parse_error(r);
1238
1239 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1240 r = sd_bus_message_skip(reply, "v");
1241 if (r < 0)
1242 return bus_log_parse_error(r);
1243 } else {
1244
1245 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1246 if (r < 0)
1247 return bus_log_parse_error(r);
1248
1249 r = bus_message_read_strv_extend(reply, &ret);
1250 if (r < 0)
1251 return bus_log_parse_error(r);
1252
1253 r = sd_bus_message_exit_container(reply);
1254 if (r < 0)
1255 return bus_log_parse_error(r);
1256 }
1257
1258 r = sd_bus_message_exit_container(reply);
1259 if (r < 0)
1260 return bus_log_parse_error(r);
1261
1262 }
1263 if (r < 0)
1264 return bus_log_parse_error(r);
1265
1266 r = sd_bus_message_exit_container(reply);
1267 if (r < 0)
1268 return bus_log_parse_error(r);
1269
1270 *deps = ret;
1271 ret = NULL;
1272
1273 return 0;
1274 }
1275
1276 static int list_dependencies_compare(const void *_a, const void *_b) {
1277 const char **a = (const char**) _a, **b = (const char**) _b;
1278
1279 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1280 return 1;
1281 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1282 return -1;
1283
1284 return strcasecmp(*a, *b);
1285 }
1286
1287 static int list_dependencies_one(
1288 sd_bus *bus,
1289 const char *name,
1290 int level,
1291 char ***units,
1292 unsigned int branches) {
1293
1294 _cleanup_strv_free_ char **deps = NULL, **u;
1295 char **c;
1296 int r = 0;
1297
1298 assert(bus);
1299 assert(name);
1300 assert(units);
1301
1302 u = strv_append(*units, name);
1303 if (!u)
1304 return log_oom();
1305
1306 r = list_dependencies_get_dependencies(bus, name, &deps);
1307 if (r < 0)
1308 return r;
1309
1310 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1311
1312 STRV_FOREACH(c, deps) {
1313 if (strv_contains(u, *c)) {
1314 if (!arg_plain) {
1315 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1316 if (r < 0)
1317 return r;
1318 }
1319 continue;
1320 }
1321
1322 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1323 if (r < 0)
1324 return r;
1325
1326 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1327 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1328 if(r < 0)
1329 return r;
1330 }
1331 }
1332
1333 if (arg_plain) {
1334 strv_free(*units);
1335 *units = u;
1336 u = NULL;
1337 }
1338
1339 return 0;
1340 }
1341
1342 static int list_dependencies(sd_bus *bus, char **args) {
1343 _cleanup_strv_free_ char **units = NULL;
1344 _cleanup_free_ char *unit = NULL;
1345 const char *u;
1346
1347 assert(bus);
1348
1349 if (args[1]) {
1350 unit = unit_name_mangle(args[1]);
1351 if (!unit)
1352 return log_oom();
1353 u = unit;
1354 } else
1355 u = SPECIAL_DEFAULT_TARGET;
1356
1357 pager_open_if_enabled();
1358
1359 puts(u);
1360
1361 return list_dependencies_one(bus, u, 0, &units, 0);
1362 }
1363
1364 static int get_default(sd_bus *bus, char **args) {
1365 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1366 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1367 _cleanup_free_ char *_path = NULL;
1368 const char *path;
1369 int r;
1370
1371 if (!bus || avoid_bus()) {
1372 r = unit_file_get_default(arg_scope, arg_root, &_path);
1373 if (r < 0) {
1374 log_error("Failed to get default target: %s", strerror(-r));
1375 return r;
1376 }
1377 path = _path;
1378
1379 } else {
1380 r = sd_bus_call_method(
1381 bus,
1382 "org.freedesktop.systemd1",
1383 "/org/freedesktop/systemd1",
1384 "org.freedesktop.systemd1.Manager",
1385 "GetDefaultTarget",
1386 &error,
1387 &reply,
1388 NULL);
1389 if (r < 0) {
1390 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1391 return r;
1392 }
1393
1394 r = sd_bus_message_read(reply, "s", &path);
1395 if (r < 0)
1396 return bus_log_parse_error(r);
1397 }
1398
1399 if (path)
1400 printf("%s\n", path);
1401
1402 return 0;
1403 }
1404
1405 struct job_info {
1406 uint32_t id;
1407 const char *name, *type, *state;
1408 };
1409
1410 static void output_jobs_list(const struct job_info* jobs, unsigned n) {
1411 unsigned id_len, unit_len, type_len, state_len;
1412 const struct job_info *j;
1413 const char *on, *off;
1414 bool shorten = false;
1415
1416 assert(n == 0 || jobs);
1417
1418 if (n == 0) {
1419 on = ansi_highlight_green();
1420 off = ansi_highlight_off();
1421
1422 printf("%sNo jobs running.%s\n", on, off);
1423 return;
1424 }
1425
1426 pager_open_if_enabled();
1427
1428 id_len = sizeof("JOB")-1;
1429 unit_len = sizeof("UNIT")-1;
1430 type_len = sizeof("TYPE")-1;
1431 state_len = sizeof("STATE")-1;
1432
1433 for (j = jobs; j < jobs + n; j++) {
1434 uint32_t id = j->id;
1435 assert(j->name && j->type && j->state);
1436
1437 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1438 unit_len = MAX(unit_len, strlen(j->name));
1439 type_len = MAX(type_len, strlen(j->type));
1440 state_len = MAX(state_len, strlen(j->state));
1441 }
1442
1443 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1444 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1445 shorten = true;
1446 }
1447
1448 printf("%*s %-*s %-*s %-*s\n",
1449 id_len, "JOB",
1450 unit_len, "UNIT",
1451 type_len, "TYPE",
1452 state_len, "STATE");
1453
1454 for (j = jobs; j < jobs + n; j++) {
1455 _cleanup_free_ char *e = NULL;
1456
1457 if (streq(j->state, "running")) {
1458 on = ansi_highlight();
1459 off = ansi_highlight_off();
1460 } else
1461 on = off = "";
1462
1463 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1464 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1465 id_len, j->id,
1466 on, unit_len, e ? e : j->name, off,
1467 type_len, j->type,
1468 on, state_len, j->state, off);
1469 }
1470
1471 on = ansi_highlight();
1472 off = ansi_highlight_off();
1473
1474 printf("\n%s%u jobs listed%s.\n", on, n, off);
1475 }
1476
1477 static int list_jobs(sd_bus *bus, char **args) {
1478 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1479 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1480 const char *name, *type, *state, *job_path, *unit_path;
1481 _cleanup_free_ struct job_info *jobs = NULL;
1482 size_t size = 0;
1483 unsigned c = 0;
1484 uint32_t id;
1485 int r;
1486
1487 r = sd_bus_call_method(
1488 bus,
1489 "org.freedesktop.systemd1",
1490 "/org/freedesktop/systemd1",
1491 "org.freedesktop.systemd1.Manager",
1492 "ListJobs",
1493 &error,
1494 &reply,
1495 NULL);
1496 if (r < 0) {
1497 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
1498 return r;
1499 }
1500
1501 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
1502 if (r < 0)
1503 return bus_log_parse_error(r);
1504
1505 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
1506
1507 if (!GREEDY_REALLOC(jobs, size, c + 1))
1508 return log_oom();
1509
1510 jobs[c++] = (struct job_info) {
1511 id,
1512 name,
1513 type,
1514 state
1515 };
1516 }
1517 if (r < 0)
1518 return bus_log_parse_error(r);
1519
1520 r = sd_bus_message_exit_container(reply);
1521 if (r < 0)
1522 return bus_log_parse_error(r);
1523
1524 output_jobs_list(jobs, c);
1525 return r;
1526 }
1527
1528 static int cancel_job(sd_bus *bus, char **args) {
1529 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1530 char **name;
1531
1532 assert(args);
1533
1534 if (strv_length(args) <= 1)
1535 return daemon_reload(bus, args);
1536
1537 STRV_FOREACH(name, args+1) {
1538 uint32_t id;
1539 int r;
1540
1541 r = safe_atou32(*name, &id);
1542 if (r < 0) {
1543 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
1544 return r;
1545 }
1546
1547 r = sd_bus_call_method(
1548 bus,
1549 "org.freedesktop.systemd1",
1550 "/org/freedesktop/systemd1",
1551 "org.freedesktop.systemd1.Manager",
1552 "CancelJob",
1553 &error,
1554 NULL,
1555 "u", id);
1556 if (r < 0) {
1557 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
1558 return r;
1559 }
1560 }
1561
1562 return 0;
1563 }
1564
1565 static int need_daemon_reload(sd_bus *bus, const char *unit) {
1566 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1567 _cleanup_free_ char *n = NULL;
1568 const char *path;
1569 int b, r;
1570
1571 /* We ignore all errors here, since this is used to show a
1572 * warning only */
1573
1574 n = unit_name_mangle(unit);
1575 if (!n)
1576 return -ENOMEM;
1577
1578 /* We don't use unit_dbus_path_from_name() directly since we
1579 * don't want to load the unit if it isn't loaded. */
1580
1581 r = sd_bus_call_method(
1582 bus,
1583 "org.freedesktop.systemd1",
1584 "/org/freedesktop/systemd1",
1585 "org.freedesktop.systemd1.Manager",
1586 "GetUnit",
1587 NULL,
1588 &reply,
1589 "s", n);
1590 if (r < 0)
1591 return r;
1592
1593 r = sd_bus_message_read(reply, "o", &path);
1594 if (r < 0)
1595 return r;
1596
1597 r = sd_bus_get_property_trivial(
1598 bus,
1599 "org.freedesktop.systemd1",
1600 path,
1601 "org.freedesktop.systemd1.Unit",
1602 "NeedDaemonReload",
1603 NULL,
1604 'b', &b);
1605 if (r < 0)
1606 return r;
1607
1608 return b;
1609 }
1610
1611 typedef struct WaitData {
1612 Set *set;
1613
1614 char *name;
1615 char *result;
1616 } WaitData;
1617
1618 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data) {
1619 WaitData *d = data;
1620
1621 assert(bus);
1622 assert(m);
1623 assert(d);
1624
1625 log_debug("Got D-Bus request: %s.%s() on %s",
1626 sd_bus_message_get_interface(m),
1627 sd_bus_message_get_member(m),
1628 sd_bus_message_get_path(m));
1629
1630 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1631 log_error("Warning! D-Bus connection terminated.");
1632 sd_bus_close(bus);
1633 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1634 uint32_t id;
1635 const char *path, *result, *unit;
1636 char *ret;
1637 int r;
1638
1639 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1640 if (r >= 0) {
1641 ret = set_remove(d->set, (char*) path);
1642 if (!ret)
1643 return 0;
1644
1645 free(ret);
1646
1647 if (!isempty(result))
1648 d->result = strdup(result);
1649
1650 if (!isempty(unit))
1651 d->name = strdup(unit);
1652
1653 return 0;
1654 }
1655 #ifndef NOLEGACY
1656 r = sd_bus_message_read(m, "uos", &id, &path, &result);
1657 if (r >= 0) {
1658 ret = set_remove(d->set, (char*) path);
1659 if (!ret)
1660 return 0;
1661
1662 free(ret);
1663
1664 if (*result)
1665 d->result = strdup(result);
1666
1667 return 0;
1668 }
1669 #endif
1670
1671 log_error("Failed to parse message.");
1672 }
1673
1674 return 0;
1675 }
1676
1677 static int enable_wait_for_jobs(sd_bus *bus) {
1678 int r;
1679
1680 assert(bus);
1681
1682 r = sd_bus_add_match(
1683 bus,
1684 "type='signal',"
1685 "sender='org.freedesktop.systemd1',"
1686 "interface='org.freedesktop.systemd1.Manager',"
1687 "member='JobRemoved',"
1688 "path='/org/freedesktop/systemd1'",
1689 NULL, NULL);
1690 if (r < 0) {
1691 log_error("Failed to add match");
1692 return -EIO;
1693 }
1694
1695 /* This is slightly dirty, since we don't undo the match registrations. */
1696 return 0;
1697 }
1698
1699 static int wait_for_jobs(sd_bus *bus, Set *s) {
1700 WaitData d = { .set = s };
1701 int r;
1702
1703 assert(bus);
1704 assert(s);
1705
1706 r = sd_bus_add_filter(bus, wait_filter, &d);
1707 if (r < 0)
1708 return log_oom();
1709
1710 while (!set_isempty(s)) {
1711 for(;;) {
1712 r = sd_bus_process(bus, NULL);
1713 if (r < 0)
1714 return r;
1715 if (r > 0)
1716 break;
1717 r = sd_bus_wait(bus, (uint64_t) -1);
1718 if (r < 0)
1719 return r;
1720 }
1721
1722 if (!d.result)
1723 goto free_name;
1724
1725 if (!arg_quiet) {
1726 if (streq(d.result, "timeout"))
1727 log_error("Job for %s timed out.", strna(d.name));
1728 else if (streq(d.result, "canceled"))
1729 log_error("Job for %s canceled.", strna(d.name));
1730 else if (streq(d.result, "dependency"))
1731 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1732 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1733 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1734 }
1735
1736 if (streq_ptr(d.result, "timeout"))
1737 r = -ETIME;
1738 else if (streq_ptr(d.result, "canceled"))
1739 r = -ECANCELED;
1740 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1741 r = -EIO;
1742
1743 free(d.result);
1744 d.result = NULL;
1745
1746 free_name:
1747 free(d.name);
1748 d.name = NULL;
1749 }
1750
1751 return sd_bus_remove_filter(bus, wait_filter, &d);
1752 }
1753
1754 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
1755 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1756 _cleanup_free_ char *n = NULL, *state = NULL;
1757 const char *path;
1758 int r;
1759
1760 assert(name);
1761
1762 n = unit_name_mangle(name);
1763 if (!n)
1764 return log_oom();
1765
1766 /* We don't use unit_dbus_path_from_name() directly since we
1767 * don't want to load the unit if it isn't loaded. */
1768
1769 r = sd_bus_call_method(
1770 bus,
1771 "org.freedesktop.systemd1",
1772 "/org/freedesktop/systemd1",
1773 "org.freedesktop.systemd1.Manager",
1774 "GetUnit",
1775 NULL,
1776 &reply,
1777 "s", n);
1778 if (r < 0) {
1779 if (!quiet)
1780 puts("unknown");
1781 return 0;
1782 }
1783
1784 r = sd_bus_message_read(reply, "o", &path);
1785 if (r < 0)
1786 return bus_log_parse_error(r);
1787
1788 r = sd_bus_get_property_string(
1789 bus,
1790 "org.freedesktop.systemd1",
1791 path,
1792 "org.freedesktop.systemd1.Unit",
1793 "ActiveState",
1794 NULL,
1795 &state);
1796 if (r < 0) {
1797 if (!quiet)
1798 puts("unknown");
1799 return 0;
1800 }
1801
1802 if (!quiet)
1803 puts(state);
1804
1805 return nulstr_contains(good_states, state);
1806 }
1807
1808 static int check_triggering_units(
1809 sd_bus *bus,
1810 const char *name) {
1811
1812 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1813 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
1814 _cleanup_strv_free_ char **triggered_by = NULL;
1815 bool print_warning_label = true;
1816 char **i;
1817 int r;
1818
1819 n = unit_name_mangle(name);
1820 if (!n)
1821 return log_oom();
1822
1823 path = unit_dbus_path_from_name(n);
1824 if (!path)
1825 return log_oom();
1826
1827 r = sd_bus_get_property_string(
1828 bus,
1829 "org.freedesktop.systemd1",
1830 path,
1831 "org.freedesktop.systemd1.Unit",
1832 "LoadState",
1833 &error,
1834 &state);
1835 if (r < 0) {
1836 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
1837 return r;
1838 }
1839
1840 if (streq(state, "masked"))
1841 return 0;
1842
1843 r = sd_bus_get_property_strv(
1844 bus,
1845 "org.freedesktop.systemd1",
1846 path,
1847 "org.freedesktop.systemd1.Unit",
1848 "TriggeredBy",
1849 &error,
1850 &triggered_by);
1851 if (r < 0) {
1852 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
1853 return r;
1854 }
1855
1856 STRV_FOREACH(i, triggered_by) {
1857 r = check_one_unit(bus, *i, "active\0reloading\0", true);
1858 if (r < 0) {
1859 log_error("Failed to check unit: %s", strerror(-r));
1860 return r;
1861 }
1862
1863 if (r == 0)
1864 continue;
1865
1866 if (print_warning_label) {
1867 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
1868 print_warning_label = false;
1869 }
1870
1871 log_warning(" %s", *i);
1872 }
1873
1874 return 0;
1875 }
1876
1877 static int start_unit_one(
1878 sd_bus *bus,
1879 const char *method,
1880 const char *name,
1881 const char *mode,
1882 sd_bus_error *error,
1883 Set *s) {
1884
1885 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1886 _cleanup_free_ char *n;
1887 const char *path;
1888 int r;
1889
1890 assert(method);
1891 assert(name);
1892 assert(mode);
1893 assert(error);
1894
1895 n = unit_name_mangle(name);
1896 if (!n)
1897 return log_oom();
1898
1899 r = sd_bus_call_method(
1900 bus,
1901 "org.freedesktop.systemd1",
1902 "/org/freedesktop/systemd1",
1903 "org.freedesktop.systemd1.Manager",
1904 method,
1905 error,
1906 &reply,
1907 "ss", n, mode);
1908 if (r < 0) {
1909 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1910 /* There's always a fallback possible for
1911 * legacy actions. */
1912 return -EADDRNOTAVAIL;
1913
1914 log_error("Failed to start %s: %s", name, bus_error_message(error, r));
1915 return r;
1916 }
1917
1918 r = sd_bus_message_read(reply, "o", &path);
1919 if (r < 0)
1920 return bus_log_parse_error(r);
1921
1922 if (need_daemon_reload(bus, n) > 0)
1923 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
1924 n, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
1925
1926 if (s) {
1927 char *p;
1928
1929 p = strdup(path);
1930 if (!p)
1931 return log_oom();
1932
1933 r = set_consume(s, p);
1934 if (r < 0)
1935 return log_oom();
1936 }
1937
1938 return 0;
1939 }
1940
1941 static const struct {
1942 const char *target;
1943 const char *verb;
1944 const char *mode;
1945 } action_table[_ACTION_MAX] = {
1946 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1947 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1948 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1949 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1950 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1951 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1952 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1953 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1954 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1955 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1956 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1957 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1958 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1959 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1960 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1961 };
1962
1963 static enum action verb_to_action(const char *verb) {
1964 enum action i;
1965
1966 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
1967 if (streq_ptr(action_table[i].verb, verb))
1968 return i;
1969
1970 return _ACTION_INVALID;
1971 }
1972
1973 static int start_unit(sd_bus *bus, char **args) {
1974 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1975 _cleanup_set_free_free_ Set *s = NULL;
1976 const char *method, *mode, *one_name;
1977 char **name;
1978 int r;
1979
1980 assert(bus);
1981
1982 ask_password_agent_open_if_enabled();
1983
1984 if (arg_action == ACTION_SYSTEMCTL) {
1985 enum action action;
1986 method =
1987 streq(args[0], "stop") ||
1988 streq(args[0], "condstop") ? "StopUnit" :
1989 streq(args[0], "reload") ? "ReloadUnit" :
1990 streq(args[0], "restart") ? "RestartUnit" :
1991
1992 streq(args[0], "try-restart") ||
1993 streq(args[0], "condrestart") ? "TryRestartUnit" :
1994
1995 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1996
1997 streq(args[0], "reload-or-try-restart") ||
1998 streq(args[0], "condreload") ||
1999 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2000 "StartUnit";
2001 action = verb_to_action(args[0]);
2002
2003 mode = streq(args[0], "isolate") ? "isolate" :
2004 action_table[action].mode ?: arg_job_mode;
2005
2006 one_name = action_table[action].target;
2007 } else {
2008 assert(arg_action < ELEMENTSOF(action_table));
2009 assert(action_table[arg_action].target);
2010
2011 method = "StartUnit";
2012
2013 mode = action_table[arg_action].mode;
2014 one_name = action_table[arg_action].target;
2015 }
2016
2017 if (!arg_no_block) {
2018 r = enable_wait_for_jobs(bus);
2019 if (r < 0) {
2020 log_error("Could not watch jobs: %s", strerror(-r));
2021 return r;
2022 }
2023
2024 s = set_new(string_hash_func, string_compare_func);
2025 if (!s)
2026 return log_oom();
2027 }
2028
2029 if (one_name) {
2030 r = start_unit_one(bus, method, one_name, mode, &error, s);
2031 if (r < 0)
2032 r = translate_bus_error_to_exit_status(r, &error);
2033 } else {
2034 r = 0;
2035
2036 STRV_FOREACH(name, args+1) {
2037 int q;
2038
2039 q = start_unit_one(bus, method, *name, mode, &error, s);
2040 if (q < 0) {
2041 r = translate_bus_error_to_exit_status(r, &error);
2042 sd_bus_error_free(&error);
2043 }
2044 }
2045 }
2046
2047 if (!arg_no_block) {
2048 int q;
2049
2050 q = wait_for_jobs(bus, s);
2051 if (q < 0)
2052 return q;
2053
2054 /* When stopping units, warn if they can still be triggered by
2055 * another active unit (socket, path, timer) */
2056 if (!arg_quiet && streq(method, "StopUnit")) {
2057 if (one_name)
2058 check_triggering_units(bus, one_name);
2059 else
2060 STRV_FOREACH(name, args+1)
2061 check_triggering_units(bus, *name);
2062 }
2063 }
2064
2065 return r;
2066 }
2067
2068 /* Ask systemd-logind, which might grant access to unprivileged users
2069 * through PolicyKit */
2070 static int reboot_with_logind(sd_bus *bus, enum action a) {
2071 #ifdef HAVE_LOGIND
2072 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2073 const char *method;
2074 int r;
2075
2076 if (!bus)
2077 return -EIO;
2078
2079 polkit_agent_open_if_enabled();
2080
2081 switch (a) {
2082
2083 case ACTION_REBOOT:
2084 method = "Reboot";
2085 break;
2086
2087 case ACTION_POWEROFF:
2088 method = "PowerOff";
2089 break;
2090
2091 case ACTION_SUSPEND:
2092 method = "Suspend";
2093 break;
2094
2095 case ACTION_HIBERNATE:
2096 method = "Hibernate";
2097 break;
2098
2099 case ACTION_HYBRID_SLEEP:
2100 method = "HybridSleep";
2101 break;
2102
2103 default:
2104 return -EINVAL;
2105 }
2106
2107 r = sd_bus_call_method(
2108 bus,
2109 "org.freedesktop.login1",
2110 "/org/freedesktop/login1",
2111 "org.freedesktop.login1.Manager",
2112 method,
2113 &error,
2114 NULL,
2115 "b", true);
2116 if (r < 0)
2117 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2118
2119 return r;
2120 #else
2121 return -ENOSYS;
2122 #endif
2123 }
2124
2125 static int check_inhibitors(sd_bus *bus, enum action a) {
2126 #ifdef HAVE_LOGIND
2127 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2128 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2129 _cleanup_strv_free_ char **sessions = NULL;
2130 const char *what, *who, *why, *mode;
2131 uint32_t uid, pid;
2132 unsigned c = 0;
2133 char **s;
2134 int r;
2135
2136 if (!bus)
2137 return 0;
2138
2139 if (arg_ignore_inhibitors || arg_force > 0)
2140 return 0;
2141
2142 if (arg_when > 0)
2143 return 0;
2144
2145 if (geteuid() == 0)
2146 return 0;
2147
2148 if (!on_tty())
2149 return 0;
2150
2151 r = sd_bus_call_method(
2152 bus,
2153 "org.freedesktop.login1",
2154 "/org/freedesktop/login1",
2155 "org.freedesktop.login1.Manager",
2156 "ListInhibitors",
2157 NULL,
2158 &reply,
2159 NULL);
2160 if (r < 0)
2161 /* If logind is not around, then there are no inhibitors... */
2162 return 0;
2163
2164 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2165 if (r < 0)
2166 return bus_log_parse_error(r);
2167
2168 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2169 _cleanup_free_ char *comm = NULL, *user = NULL;
2170 _cleanup_strv_free_ char **sv = NULL;
2171
2172 if (!streq(mode, "block"))
2173 continue;
2174
2175 sv = strv_split(what, ":");
2176 if (!sv)
2177 return log_oom();
2178
2179 if (!strv_contains(sv,
2180 a == ACTION_HALT ||
2181 a == ACTION_POWEROFF ||
2182 a == ACTION_REBOOT ||
2183 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2184 continue;
2185
2186 get_process_comm(pid, &comm);
2187 user = uid_to_name(uid);
2188
2189 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2190 who, (unsigned long) pid, strna(comm), strna(user), why);
2191
2192 c++;
2193 }
2194 if (r < 0)
2195 return bus_log_parse_error(r);
2196
2197 r = sd_bus_message_exit_container(reply);
2198 if (r < 0)
2199 return bus_log_parse_error(r);
2200
2201 /* Check for current sessions */
2202 sd_get_sessions(&sessions);
2203 STRV_FOREACH(s, sessions) {
2204 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2205
2206 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2207 continue;
2208
2209 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2210 continue;
2211
2212 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2213 continue;
2214
2215 sd_session_get_tty(*s, &tty);
2216 sd_session_get_seat(*s, &seat);
2217 sd_session_get_service(*s, &service);
2218 user = uid_to_name(uid);
2219
2220 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2221 c++;
2222 }
2223
2224 if (c <= 0)
2225 return 0;
2226
2227 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2228 action_table[a].verb);
2229
2230 return -EPERM;
2231 #else
2232 return 0;
2233 #endif
2234 }
2235
2236 static int start_special(sd_bus *bus, char **args) {
2237 enum action a;
2238 int r;
2239
2240 assert(args);
2241
2242 a = verb_to_action(args[0]);
2243
2244 r = check_inhibitors(bus, a);
2245 if (r < 0)
2246 return r;
2247
2248 if (arg_force >= 2 && geteuid() != 0) {
2249 log_error("Must be root.");
2250 return -EPERM;
2251 }
2252
2253 if (arg_force >= 2 &&
2254 (a == ACTION_HALT ||
2255 a == ACTION_POWEROFF ||
2256 a == ACTION_REBOOT))
2257 return halt_now(a);
2258
2259 if (arg_force >= 1 &&
2260 (a == ACTION_HALT ||
2261 a == ACTION_POWEROFF ||
2262 a == ACTION_REBOOT ||
2263 a == ACTION_KEXEC ||
2264 a == ACTION_EXIT))
2265 return daemon_reload(bus, args);
2266
2267 /* first try logind, to allow authentication with polkit */
2268 if (geteuid() != 0 &&
2269 (a == ACTION_POWEROFF ||
2270 a == ACTION_REBOOT ||
2271 a == ACTION_SUSPEND ||
2272 a == ACTION_HIBERNATE ||
2273 a == ACTION_HYBRID_SLEEP)) {
2274 r = reboot_with_logind(bus, a);
2275 if (r >= 0)
2276 return r;
2277 }
2278
2279 r = start_unit(bus, args);
2280 if (r == EXIT_SUCCESS)
2281 warn_wall(a);
2282
2283 return r;
2284 }
2285
2286 static int check_unit_active(sd_bus *bus, char **args) {
2287 char **name;
2288 int r = 3; /* According to LSB: "program is not running" */
2289
2290 assert(bus);
2291 assert(args);
2292
2293 STRV_FOREACH(name, args+1) {
2294 int state;
2295
2296 state = check_one_unit(bus, *name, "active\0reloading\0", arg_quiet);
2297 if (state < 0)
2298 return state;
2299 if (state > 0)
2300 r = 0;
2301 }
2302
2303 return r;
2304 }
2305
2306 static int check_unit_failed(sd_bus *bus, char **args) {
2307 char **name;
2308 int r = 1;
2309
2310 assert(bus);
2311 assert(args);
2312
2313 STRV_FOREACH(name, args+1) {
2314 int state;
2315
2316 state = check_one_unit(bus, *name, "failed\0", arg_quiet);
2317 if (state < 0)
2318 return state;
2319 if (state > 0)
2320 r = 0;
2321 }
2322
2323 return r;
2324 }
2325
2326 static int kill_unit(sd_bus *bus, char **args) {
2327 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2328 char **name;
2329 int r = 0;
2330
2331 assert(bus);
2332 assert(args);
2333
2334 if (!arg_kill_who)
2335 arg_kill_who = "all";
2336
2337 STRV_FOREACH(name, args+1) {
2338 _cleanup_free_ char *n = NULL;
2339
2340 n = unit_name_mangle(*name);
2341 if (!n)
2342 return log_oom();
2343
2344 r = sd_bus_call_method(
2345 bus,
2346 "org.freedesktop.systemd1",
2347 "/org/freedesktop/systemd1",
2348 "org.freedesktop.systemd1.Manager",
2349 "KillUnit",
2350 &error,
2351 NULL,
2352 "ssi", n, arg_kill_who, arg_signal);
2353 if (r < 0) {
2354 log_error("Failed to kill unit %s: %s", n, bus_error_message(&error, r));
2355 return r;
2356 }
2357 }
2358
2359 return 0;
2360 }
2361
2362 typedef struct ExecStatusInfo {
2363 char *name;
2364
2365 char *path;
2366 char **argv;
2367
2368 bool ignore;
2369
2370 usec_t start_timestamp;
2371 usec_t exit_timestamp;
2372 pid_t pid;
2373 int code;
2374 int status;
2375
2376 LIST_FIELDS(struct ExecStatusInfo, exec);
2377 } ExecStatusInfo;
2378
2379 static void exec_status_info_free(ExecStatusInfo *i) {
2380 assert(i);
2381
2382 free(i->name);
2383 free(i->path);
2384 strv_free(i->argv);
2385 free(i);
2386 }
2387
2388 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2389 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2390 const char *path;
2391 uint32_t pid;
2392 int32_t code, status;
2393 int ignore, r;
2394
2395 assert(m);
2396 assert(i);
2397
2398 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
2399 if (r < 0)
2400 return bus_log_parse_error(r);
2401 else if (r == 0)
2402 return 0;
2403
2404 r = sd_bus_message_read(m, "s", &path);
2405 if (r < 0)
2406 return bus_log_parse_error(r);
2407
2408 i->path = strdup(path);
2409 if (!i->path)
2410 return log_oom();
2411
2412 r = sd_bus_message_read_strv(m, &i->argv);
2413 if (r < 0)
2414 return bus_log_parse_error(r);
2415
2416 r = sd_bus_message_read(m,
2417 "bttttuii",
2418 &ignore,
2419 &start_timestamp, &start_timestamp_monotonic,
2420 &exit_timestamp, &exit_timestamp_monotonic,
2421 &pid,
2422 &code, &status);
2423 if (r < 0)
2424 return bus_log_parse_error(r);
2425
2426 i->ignore = ignore;
2427 i->start_timestamp = (usec_t) start_timestamp;
2428 i->exit_timestamp = (usec_t) exit_timestamp;
2429 i->pid = (pid_t) pid;
2430 i->code = code;
2431 i->status = status;
2432
2433 r = sd_bus_message_exit_container(m);
2434 if (r < 0)
2435 return bus_log_parse_error(r);
2436
2437 return 1;
2438 }
2439
2440 typedef struct UnitStatusInfo {
2441 const char *id;
2442 const char *load_state;
2443 const char *active_state;
2444 const char *sub_state;
2445 const char *unit_file_state;
2446
2447 const char *description;
2448 const char *following;
2449
2450 char **documentation;
2451
2452 const char *fragment_path;
2453 const char *source_path;
2454 const char *control_group;
2455
2456 char **dropin_paths;
2457
2458 const char *load_error;
2459 const char *result;
2460
2461 usec_t inactive_exit_timestamp;
2462 usec_t inactive_exit_timestamp_monotonic;
2463 usec_t active_enter_timestamp;
2464 usec_t active_exit_timestamp;
2465 usec_t inactive_enter_timestamp;
2466
2467 bool need_daemon_reload;
2468
2469 /* Service */
2470 pid_t main_pid;
2471 pid_t control_pid;
2472 const char *status_text;
2473 const char *pid_file;
2474 bool running:1;
2475
2476 usec_t start_timestamp;
2477 usec_t exit_timestamp;
2478
2479 int exit_code, exit_status;
2480
2481 usec_t condition_timestamp;
2482 bool condition_result;
2483 bool failed_condition_trigger;
2484 bool failed_condition_negate;
2485 const char *failed_condition;
2486 const char *failed_condition_param;
2487
2488 /* Socket */
2489 unsigned n_accepted;
2490 unsigned n_connections;
2491 bool accept;
2492
2493 /* Pairs of type, path */
2494 char **listen;
2495
2496 /* Device */
2497 const char *sysfs_path;
2498
2499 /* Mount, Automount */
2500 const char *where;
2501
2502 /* Swap */
2503 const char *what;
2504
2505 LIST_HEAD(ExecStatusInfo, exec);
2506 } UnitStatusInfo;
2507
2508 static void print_status_info(
2509 UnitStatusInfo *i,
2510 bool *ellipsized) {
2511
2512 ExecStatusInfo *p;
2513 const char *on, *off, *ss;
2514 usec_t timestamp;
2515 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2516 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2517 const char *path;
2518 int flags =
2519 arg_all * OUTPUT_SHOW_ALL |
2520 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2521 on_tty() * OUTPUT_COLOR |
2522 !arg_quiet * OUTPUT_WARN_CUTOFF |
2523 arg_full * OUTPUT_FULL_WIDTH;
2524 char **t, **t2;
2525
2526 assert(i);
2527
2528 /* This shows pretty information about a unit. See
2529 * print_property() for a low-level property printer */
2530
2531 printf("%s", strna(i->id));
2532
2533 if (i->description && !streq_ptr(i->id, i->description))
2534 printf(" - %s", i->description);
2535
2536 printf("\n");
2537
2538 if (i->following)
2539 printf(" Follow: unit currently follows state of %s\n", i->following);
2540
2541 if (streq_ptr(i->load_state, "error")) {
2542 on = ansi_highlight_red();
2543 off = ansi_highlight_off();
2544 } else
2545 on = off = "";
2546
2547 path = i->source_path ? i->source_path : i->fragment_path;
2548
2549 if (i->load_error)
2550 printf(" Loaded: %s%s%s (Reason: %s)\n",
2551 on, strna(i->load_state), off, i->load_error);
2552 else if (path && i->unit_file_state)
2553 printf(" Loaded: %s%s%s (%s; %s)\n",
2554 on, strna(i->load_state), off, path, i->unit_file_state);
2555 else if (path)
2556 printf(" Loaded: %s%s%s (%s)\n",
2557 on, strna(i->load_state), off, path);
2558 else
2559 printf(" Loaded: %s%s%s\n",
2560 on, strna(i->load_state), off);
2561
2562 if (!strv_isempty(i->dropin_paths)) {
2563 _cleanup_free_ char *dir = NULL;
2564 bool last = false;
2565 char ** dropin;
2566
2567 STRV_FOREACH(dropin, i->dropin_paths) {
2568 if (! dir || last) {
2569 printf(dir ? " " : " Drop-In: ");
2570
2571 free(dir);
2572 dir = NULL;
2573
2574 if (path_get_parent(*dropin, &dir) < 0) {
2575 log_oom();
2576 return;
2577 }
2578
2579 printf("%s\n %s", dir,
2580 draw_special_char(DRAW_TREE_RIGHT));
2581 }
2582
2583 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2584
2585 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2586 }
2587 }
2588
2589 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2590
2591 if (streq_ptr(i->active_state, "failed")) {
2592 on = ansi_highlight_red();
2593 off = ansi_highlight_off();
2594 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2595 on = ansi_highlight_green();
2596 off = ansi_highlight_off();
2597 } else
2598 on = off = "";
2599
2600 if (ss)
2601 printf(" Active: %s%s (%s)%s",
2602 on, strna(i->active_state), ss, off);
2603 else
2604 printf(" Active: %s%s%s",
2605 on, strna(i->active_state), off);
2606
2607 if (!isempty(i->result) && !streq(i->result, "success"))
2608 printf(" (Result: %s)", i->result);
2609
2610 timestamp = (streq_ptr(i->active_state, "active") ||
2611 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2612 (streq_ptr(i->active_state, "inactive") ||
2613 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2614 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2615 i->active_exit_timestamp;
2616
2617 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2618 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2619
2620 if (s1)
2621 printf(" since %s; %s\n", s2, s1);
2622 else if (s2)
2623 printf(" since %s\n", s2);
2624 else
2625 printf("\n");
2626
2627 if (!i->condition_result && i->condition_timestamp > 0) {
2628 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2629 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2630
2631 printf(" start condition failed at %s%s%s\n",
2632 s2, s1 ? "; " : "", s1 ? s1 : "");
2633 if (i->failed_condition_trigger)
2634 printf(" none of the trigger conditions were met\n");
2635 else if (i->failed_condition)
2636 printf(" %s=%s%s was not met\n",
2637 i->failed_condition,
2638 i->failed_condition_negate ? "!" : "",
2639 i->failed_condition_param);
2640 }
2641
2642 if (i->sysfs_path)
2643 printf(" Device: %s\n", i->sysfs_path);
2644 if (i->where)
2645 printf(" Where: %s\n", i->where);
2646 if (i->what)
2647 printf(" What: %s\n", i->what);
2648
2649 STRV_FOREACH(t, i->documentation)
2650 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2651
2652 STRV_FOREACH_PAIR(t, t2, i->listen)
2653 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2654
2655 if (i->accept)
2656 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2657
2658 LIST_FOREACH(exec, p, i->exec) {
2659 _cleanup_free_ char *argv = NULL;
2660 bool good;
2661
2662 /* Only show exited processes here */
2663 if (p->code == 0)
2664 continue;
2665
2666 argv = strv_join(p->argv, " ");
2667 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2668
2669 good = is_clean_exit_lsb(p->code, p->status, NULL);
2670 if (!good) {
2671 on = ansi_highlight_red();
2672 off = ansi_highlight_off();
2673 } else
2674 on = off = "";
2675
2676 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2677
2678 if (p->code == CLD_EXITED) {
2679 const char *c;
2680
2681 printf("status=%i", p->status);
2682
2683 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2684 if (c)
2685 printf("/%s", c);
2686
2687 } else
2688 printf("signal=%s", signal_to_string(p->status));
2689
2690 printf(")%s\n", off);
2691
2692 if (i->main_pid == p->pid &&
2693 i->start_timestamp == p->start_timestamp &&
2694 i->exit_timestamp == p->start_timestamp)
2695 /* Let's not show this twice */
2696 i->main_pid = 0;
2697
2698 if (p->pid == i->control_pid)
2699 i->control_pid = 0;
2700 }
2701
2702 if (i->main_pid > 0 || i->control_pid > 0) {
2703 if (i->main_pid > 0) {
2704 printf(" Main PID: %u", (unsigned) i->main_pid);
2705
2706 if (i->running) {
2707 _cleanup_free_ char *comm = NULL;
2708 get_process_comm(i->main_pid, &comm);
2709 if (comm)
2710 printf(" (%s)", comm);
2711 } else if (i->exit_code > 0) {
2712 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2713
2714 if (i->exit_code == CLD_EXITED) {
2715 const char *c;
2716
2717 printf("status=%i", i->exit_status);
2718
2719 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2720 if (c)
2721 printf("/%s", c);
2722
2723 } else
2724 printf("signal=%s", signal_to_string(i->exit_status));
2725 printf(")");
2726 }
2727
2728 if (i->control_pid > 0)
2729 printf(";");
2730 }
2731
2732 if (i->control_pid > 0) {
2733 _cleanup_free_ char *c = NULL;
2734
2735 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2736
2737 get_process_comm(i->control_pid, &c);
2738 if (c)
2739 printf(" (%s)", c);
2740 }
2741
2742 printf("\n");
2743 }
2744
2745 if (i->status_text)
2746 printf(" Status: \"%s\"\n", i->status_text);
2747
2748 if (i->control_group &&
2749 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2750 unsigned c;
2751
2752 printf(" CGroup: %s\n", i->control_group);
2753
2754 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
2755 unsigned k = 0;
2756 pid_t extra[2];
2757 char prefix[] = " ";
2758
2759 c = columns();
2760 if (c > sizeof(prefix) - 1)
2761 c -= sizeof(prefix) - 1;
2762 else
2763 c = 0;
2764
2765 if (i->main_pid > 0)
2766 extra[k++] = i->main_pid;
2767
2768 if (i->control_pid > 0)
2769 extra[k++] = i->control_pid;
2770
2771 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2772 c, false, extra, k, flags);
2773 }
2774 }
2775
2776 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
2777 printf("\n");
2778 show_journal_by_unit(stdout,
2779 i->id,
2780 arg_output,
2781 0,
2782 i->inactive_exit_timestamp_monotonic,
2783 arg_lines,
2784 getuid(),
2785 flags,
2786 arg_scope == UNIT_FILE_SYSTEM,
2787 ellipsized);
2788 }
2789
2790 if (i->need_daemon_reload)
2791 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2792 ansi_highlight_red(),
2793 ansi_highlight_off(),
2794 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2795 }
2796
2797 static void show_unit_help(UnitStatusInfo *i) {
2798 char **p;
2799
2800 assert(i);
2801
2802 if (!i->documentation) {
2803 log_info("Documentation for %s not known.", i->id);
2804 return;
2805 }
2806
2807 STRV_FOREACH(p, i->documentation) {
2808
2809 if (startswith(*p, "man:")) {
2810 const char *args[4] = { "man", NULL, NULL, NULL };
2811 _cleanup_free_ char *page = NULL, *section = NULL;
2812 char *e = NULL;
2813 pid_t pid;
2814 size_t k;
2815
2816 k = strlen(*p);
2817
2818 if ((*p)[k-1] == ')')
2819 e = strrchr(*p, '(');
2820
2821 if (e) {
2822 page = strndup((*p) + 4, e - *p - 4);
2823 section = strndup(e + 1, *p + k - e - 2);
2824 if (!page || !section) {
2825 log_oom();
2826 return;
2827 }
2828
2829 args[1] = section;
2830 args[2] = page;
2831 } else
2832 args[1] = *p + 4;
2833
2834 pid = fork();
2835 if (pid < 0) {
2836 log_error("Failed to fork: %m");
2837 continue;
2838 }
2839
2840 if (pid == 0) {
2841 /* Child */
2842 execvp(args[0], (char**) args);
2843 log_error("Failed to execute man: %m");
2844 _exit(EXIT_FAILURE);
2845 }
2846
2847 wait_for_terminate(pid, NULL);
2848 } else
2849 log_info("Can't show: %s", *p);
2850 }
2851 }
2852
2853 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
2854 int r;
2855
2856 assert(name);
2857 assert(m);
2858 assert(i);
2859
2860 switch (contents[0]) {
2861
2862 case SD_BUS_TYPE_STRING: {
2863 const char *s;
2864
2865 r = sd_bus_message_read(m, "s", &s);
2866 if (r < 0)
2867 return bus_log_parse_error(r);
2868
2869 if (!isempty(s)) {
2870 if (streq(name, "Id"))
2871 i->id = s;
2872 else if (streq(name, "LoadState"))
2873 i->load_state = s;
2874 else if (streq(name, "ActiveState"))
2875 i->active_state = s;
2876 else if (streq(name, "SubState"))
2877 i->sub_state = s;
2878 else if (streq(name, "Description"))
2879 i->description = s;
2880 else if (streq(name, "FragmentPath"))
2881 i->fragment_path = s;
2882 else if (streq(name, "SourcePath"))
2883 i->source_path = s;
2884 #ifndef NOLEGACY
2885 else if (streq(name, "DefaultControlGroup")) {
2886 const char *e;
2887 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2888 if (e)
2889 i->control_group = e;
2890 }
2891 #endif
2892 else if (streq(name, "ControlGroup"))
2893 i->control_group = s;
2894 else if (streq(name, "StatusText"))
2895 i->status_text = s;
2896 else if (streq(name, "PIDFile"))
2897 i->pid_file = s;
2898 else if (streq(name, "SysFSPath"))
2899 i->sysfs_path = s;
2900 else if (streq(name, "Where"))
2901 i->where = s;
2902 else if (streq(name, "What"))
2903 i->what = s;
2904 else if (streq(name, "Following"))
2905 i->following = s;
2906 else if (streq(name, "UnitFileState"))
2907 i->unit_file_state = s;
2908 else if (streq(name, "Result"))
2909 i->result = s;
2910 }
2911
2912 break;
2913 }
2914
2915 case SD_BUS_TYPE_BOOLEAN: {
2916 int b;
2917
2918 r = sd_bus_message_read(m, "b", &b);
2919 if (r < 0)
2920 return bus_log_parse_error(r);
2921
2922 if (streq(name, "Accept"))
2923 i->accept = b;
2924 else if (streq(name, "NeedDaemonReload"))
2925 i->need_daemon_reload = b;
2926 else if (streq(name, "ConditionResult"))
2927 i->condition_result = b;
2928
2929 break;
2930 }
2931
2932 case SD_BUS_TYPE_UINT32: {
2933 uint32_t u;
2934
2935 r = sd_bus_message_read(m, "u", &u);
2936 if (r < 0)
2937 return bus_log_parse_error(r);
2938
2939 if (streq(name, "MainPID")) {
2940 if (u > 0) {
2941 i->main_pid = (pid_t) u;
2942 i->running = true;
2943 }
2944 } else if (streq(name, "ControlPID"))
2945 i->control_pid = (pid_t) u;
2946 else if (streq(name, "ExecMainPID")) {
2947 if (u > 0)
2948 i->main_pid = (pid_t) u;
2949 } else if (streq(name, "NAccepted"))
2950 i->n_accepted = u;
2951 else if (streq(name, "NConnections"))
2952 i->n_connections = u;
2953
2954 break;
2955 }
2956
2957 case SD_BUS_TYPE_INT32: {
2958 int32_t j;
2959
2960 r = sd_bus_message_read(m, "i", &j);
2961 if (r < 0)
2962 return bus_log_parse_error(r);
2963
2964 if (streq(name, "ExecMainCode"))
2965 i->exit_code = (int) j;
2966 else if (streq(name, "ExecMainStatus"))
2967 i->exit_status = (int) j;
2968
2969 break;
2970 }
2971
2972 case SD_BUS_TYPE_UINT64: {
2973 uint64_t u;
2974
2975 r = sd_bus_message_read(m, "t", &u);
2976 if (r < 0)
2977 return bus_log_parse_error(r);
2978
2979 if (streq(name, "ExecMainStartTimestamp"))
2980 i->start_timestamp = (usec_t) u;
2981 else if (streq(name, "ExecMainExitTimestamp"))
2982 i->exit_timestamp = (usec_t) u;
2983 else if (streq(name, "ActiveEnterTimestamp"))
2984 i->active_enter_timestamp = (usec_t) u;
2985 else if (streq(name, "InactiveEnterTimestamp"))
2986 i->inactive_enter_timestamp = (usec_t) u;
2987 else if (streq(name, "InactiveExitTimestamp"))
2988 i->inactive_exit_timestamp = (usec_t) u;
2989 else if (streq(name, "InactiveExitTimestampMonotonic"))
2990 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2991 else if (streq(name, "ActiveExitTimestamp"))
2992 i->active_exit_timestamp = (usec_t) u;
2993 else if (streq(name, "ConditionTimestamp"))
2994 i->condition_timestamp = (usec_t) u;
2995
2996 break;
2997 }
2998
2999 case SD_BUS_TYPE_ARRAY:
3000
3001 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3002 _cleanup_free_ ExecStatusInfo *info = NULL;
3003
3004 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3005 if (r < 0)
3006 return bus_log_parse_error(r);
3007
3008 info = new0(ExecStatusInfo, 1);
3009 if (!info)
3010 return log_oom();
3011
3012 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3013
3014 info->name = strdup(name);
3015 if (!info->name)
3016 log_oom();
3017
3018 LIST_PREPEND(exec, i->exec, info);
3019
3020 info = new0(ExecStatusInfo, 1);
3021 if (!info)
3022 log_oom();
3023 }
3024
3025 if (r < 0)
3026 return bus_log_parse_error(r);
3027
3028 r = sd_bus_message_exit_container(m);
3029 if (r < 0)
3030 return bus_log_parse_error(r);
3031
3032 return 0;
3033
3034 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3035 const char *type, *path;
3036
3037 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3038 if (r < 0)
3039 return bus_log_parse_error(r);
3040
3041 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3042
3043 r = strv_extend(&i->listen, type);
3044 if (r < 0)
3045 return r;
3046
3047 r = strv_extend(&i->listen, path);
3048 if (r < 0)
3049 return r;
3050 }
3051 if (r < 0)
3052 return bus_log_parse_error(r);
3053
3054 r = sd_bus_message_exit_container(m);
3055 if (r < 0)
3056 return bus_log_parse_error(r);
3057
3058 return 0;
3059
3060 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3061
3062 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3063 if (r < 0)
3064 return bus_log_parse_error(r);
3065
3066 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3067
3068 r = sd_bus_message_read_strv(m, &i->documentation);
3069 if (r < 0)
3070 return bus_log_parse_error(r);
3071
3072 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3073 const char *cond, *param;
3074 int trigger, negate;
3075 int32_t state;
3076
3077 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3078 if (r < 0)
3079 return bus_log_parse_error(r);
3080
3081 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3082 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3083 if (state < 0 && (!trigger || !i->failed_condition)) {
3084 i->failed_condition = cond;
3085 i->failed_condition_trigger = trigger;
3086 i->failed_condition_negate = negate;
3087 i->failed_condition_param = param;
3088 }
3089 }
3090 if (r < 0)
3091 return bus_log_parse_error(r);
3092
3093 r = sd_bus_message_exit_container(m);
3094 if (r < 0)
3095 return bus_log_parse_error(r);
3096
3097 } else
3098 goto skip;
3099
3100 break;
3101
3102 case SD_BUS_TYPE_STRUCT_BEGIN:
3103
3104 if (streq(name, "LoadError")) {
3105 const char *n, *message;
3106
3107 r = sd_bus_message_read(m, "(ss)", &n, &message);
3108 if (r < 0)
3109 return bus_log_parse_error(r);
3110
3111 if (!isempty(message))
3112 i->load_error = message;
3113 } else
3114 goto skip;
3115
3116 break;
3117
3118 default:
3119 goto skip;
3120 }
3121
3122 return 0;
3123
3124 skip:
3125 r = sd_bus_message_skip(m, contents);
3126 if (r < 0)
3127 return bus_log_parse_error(r);
3128
3129 return 0;
3130 }
3131
3132 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3133 int r;
3134
3135 assert(name);
3136 assert(m);
3137
3138 /* This is a low-level property printer, see
3139 * print_status_info() for the nicer output */
3140
3141 if (arg_properties && !strv_find(arg_properties, name)) {
3142 /* skip what we didn't read */
3143 r = sd_bus_message_skip(m, contents);
3144 return r;
3145 }
3146
3147 switch (contents[0]) {
3148
3149 case SD_BUS_TYPE_STRUCT_BEGIN:
3150
3151 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3152 uint32_t u;
3153
3154 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3155 if (r < 0)
3156 return bus_log_parse_error(r);
3157
3158 if (u > 0)
3159 printf("%s=%u\n", name, (unsigned) u);
3160 else if (arg_all)
3161 printf("%s=\n", name);
3162
3163 return 0;
3164
3165 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3166 const char *s;
3167
3168 r = sd_bus_message_read(m, "(so)", &s, NULL);
3169 if (r < 0)
3170 return bus_log_parse_error(r);
3171
3172 if (arg_all || !isempty(s))
3173 printf("%s=%s\n", name, s);
3174
3175 return 0;
3176
3177 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3178 const char *a = NULL, *b = NULL;
3179
3180 r = sd_bus_message_read(m, "(ss)", &a, &b);
3181 if (r < 0)
3182 return bus_log_parse_error(r);
3183
3184 if (arg_all || !isempty(a) || !isempty(b))
3185 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3186
3187 return 0;
3188 }
3189
3190 break;
3191
3192 case SD_BUS_TYPE_ARRAY:
3193
3194 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3195 const char *path;
3196 int ignore;
3197
3198 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3199 if (r < 0)
3200 return bus_log_parse_error(r);
3201
3202 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3203 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3204
3205 if (r < 0)
3206 return bus_log_parse_error(r);
3207
3208 r = sd_bus_message_exit_container(m);
3209 if (r < 0)
3210 return bus_log_parse_error(r);
3211
3212 return 0;
3213
3214 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3215 const char *type, *path;
3216
3217 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3218 if (r < 0)
3219 return bus_log_parse_error(r);
3220
3221 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3222 printf("%s=%s\n", type, path);
3223 if (r < 0)
3224 return bus_log_parse_error(r);
3225
3226 r = sd_bus_message_exit_container(m);
3227 if (r < 0)
3228 return bus_log_parse_error(r);
3229
3230 return 0;
3231
3232 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3233 const char *type, *path;
3234
3235 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3236 if (r < 0)
3237 return bus_log_parse_error(r);
3238
3239 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3240 printf("Listen%s=%s\n", type, path);
3241 if (r < 0)
3242 return bus_log_parse_error(r);
3243
3244 r = sd_bus_message_exit_container(m);
3245 if (r < 0)
3246 return bus_log_parse_error(r);
3247
3248 return 0;
3249
3250 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3251 const char *base;
3252 uint64_t value, next_elapse;
3253
3254 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3255 if (r < 0)
3256 return bus_log_parse_error(r);
3257
3258 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3259 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3260
3261 printf("%s={ value=%s ; next_elapse=%s }\n",
3262 base,
3263 format_timespan(timespan1, sizeof(timespan1), value, 0),
3264 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3265 }
3266 if (r < 0)
3267 return bus_log_parse_error(r);
3268
3269 r = sd_bus_message_exit_container(m);
3270 if (r < 0)
3271 return bus_log_parse_error(r);
3272
3273 return 0;
3274
3275 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3276 ExecStatusInfo info = {};
3277
3278 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3279 if (r < 0)
3280 return bus_log_parse_error(r);
3281
3282 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3283 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3284 _cleanup_free_ char *tt;
3285
3286 tt = strv_join(info.argv, " ");
3287
3288 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3289 name,
3290 strna(info.path),
3291 strna(tt),
3292 yes_no(info.ignore),
3293 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3294 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3295 (unsigned) info. pid,
3296 sigchld_code_to_string(info.code),
3297 info.status,
3298 info.code == CLD_EXITED ? "" : "/",
3299 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3300
3301 free(info.path);
3302 strv_free(info.argv);
3303 zero(info);
3304 }
3305
3306 r = sd_bus_message_exit_container(m);
3307 if (r < 0)
3308 return bus_log_parse_error(r);
3309
3310 return 0;
3311
3312 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
3313 const char *path, *rwm;
3314
3315 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3316 if (r < 0)
3317 return bus_log_parse_error(r);
3318
3319 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
3320 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3321 if (r < 0)
3322 return bus_log_parse_error(r);
3323
3324 r = sd_bus_message_exit_container(m);
3325 if (r < 0)
3326 return bus_log_parse_error(r);
3327
3328 return 0;
3329
3330 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
3331 const char *path;
3332 uint64_t weight;
3333
3334 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3335 if (r < 0)
3336 return bus_log_parse_error(r);
3337
3338 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
3339 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3340 if (r < 0)
3341 return bus_log_parse_error(r);
3342
3343 r = sd_bus_message_exit_container(m);
3344 if (r < 0)
3345 return bus_log_parse_error(r);
3346
3347 return 0;
3348
3349 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3350 const char *path;
3351 uint64_t bandwidth;
3352
3353 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3354 if (r < 0)
3355 return bus_log_parse_error(r);
3356
3357 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
3358 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3359 if (r < 0)
3360 return bus_log_parse_error(r);
3361
3362 r = sd_bus_message_exit_container(m);
3363 if (r < 0)
3364 return bus_log_parse_error(r);
3365
3366 return 0;
3367 }
3368
3369 break;
3370 }
3371
3372 r = bus_print_property(name, m, arg_all);
3373 if (r < 0)
3374 return bus_log_parse_error(r);
3375
3376 if (r == 0) {
3377 r = sd_bus_message_skip(m, contents);
3378 if (r < 0)
3379 return bus_log_parse_error(r);
3380
3381 if (arg_all)
3382 printf("%s=[unprintable]\n", name);
3383 }
3384
3385 return 0;
3386 }
3387
3388 static int show_one(
3389 const char *verb,
3390 sd_bus *bus,
3391 const char *path,
3392 bool show_properties,
3393 bool *new_line,
3394 bool *ellipsized) {
3395
3396 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3397 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3398 UnitStatusInfo info = {};
3399 ExecStatusInfo *p;
3400 int r;
3401
3402 assert(path);
3403 assert(new_line);
3404
3405 r = sd_bus_call_method(
3406 bus,
3407 "org.freedesktop.systemd1",
3408 path,
3409 "org.freedesktop.DBus.Properties",
3410 "GetAll",
3411 &error,
3412 &reply,
3413 "s", "");
3414 if (r < 0) {
3415 log_error("Failed to get properties: %s", bus_error_message(&error, r));
3416 return r;
3417 }
3418
3419 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
3420 if (r < 0)
3421 return bus_log_parse_error(r);
3422
3423 if (*new_line)
3424 printf("\n");
3425
3426 *new_line = true;
3427
3428 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
3429 const char *name, *contents;
3430
3431 r = sd_bus_message_read(reply, "s", &name);
3432 if (r < 0)
3433 return bus_log_parse_error(r);
3434
3435 r = sd_bus_message_peek_type(reply, NULL, &contents);
3436 if (r < 0)
3437 return bus_log_parse_error(r);
3438
3439 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
3440 if (r < 0)
3441 return bus_log_parse_error(r);
3442
3443 if (show_properties)
3444 r = print_property(name, reply, contents);
3445 else
3446 r = status_property(name, reply, &info, contents);
3447 if (r < 0)
3448 return r;
3449
3450 r = sd_bus_message_exit_container(reply);
3451 if (r < 0)
3452 return bus_log_parse_error(r);
3453
3454 r = sd_bus_message_exit_container(reply);
3455 if (r < 0)
3456 return bus_log_parse_error(r);
3457 }
3458 if (r < 0)
3459 return bus_log_parse_error(r);
3460
3461 r = sd_bus_message_exit_container(reply);
3462 if (r < 0)
3463 return bus_log_parse_error(r);
3464
3465 r = 0;
3466
3467 if (!show_properties) {
3468 if (streq(verb, "help"))
3469 show_unit_help(&info);
3470 else
3471 print_status_info(&info, ellipsized);
3472 }
3473
3474 strv_free(info.documentation);
3475 strv_free(info.dropin_paths);
3476 strv_free(info.listen);
3477
3478 if (!streq_ptr(info.active_state, "active") &&
3479 !streq_ptr(info.active_state, "reloading") &&
3480 streq(verb, "status")) {
3481 /* According to LSB: "program not running" */
3482 /* 0: program is running or service is OK
3483 * 1: program is dead and /var/run pid file exists
3484 * 2: program is dead and /var/lock lock file exists
3485 * 3: program is not running
3486 * 4: program or service status is unknown
3487 */
3488 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3489 r = 1;
3490 else
3491 r = 3;
3492 }
3493
3494 while ((p = info.exec)) {
3495 LIST_REMOVE(exec, info.exec, p);
3496 exec_status_info_free(p);
3497 }
3498
3499 return r;
3500 }
3501
3502 static int show_one_by_pid(
3503 const char *verb,
3504 sd_bus *bus,
3505 uint32_t pid,
3506 bool *new_line,
3507 bool *ellipsized) {
3508
3509 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3510 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3511 const char *path = NULL;
3512 int r;
3513
3514 r = sd_bus_call_method(
3515 bus,
3516 "org.freedesktop.systemd1",
3517 "/org/freedesktop/systemd1",
3518 "org.freedesktop.systemd1.Manager",
3519 "GetUnitByPID",
3520 &error,
3521 &reply,
3522 "u", pid);
3523 if (r < 0) {
3524 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
3525 return r;
3526 }
3527
3528 r = sd_bus_message_read(reply, "o", &path);
3529 if (r < 0)
3530 return bus_log_parse_error(r);
3531
3532 return show_one(verb, bus, path, false, new_line, ellipsized);
3533 }
3534
3535 static int show_all(
3536 const char* verb,
3537 sd_bus *bus,
3538 bool show_properties,
3539 bool *new_line,
3540 bool *ellipsized) {
3541
3542 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3543 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3544 _cleanup_free_ UnitInfo *unit_infos = NULL;
3545 const UnitInfo *u;
3546 unsigned c;
3547 int r;
3548
3549 r = get_unit_list(bus, &reply, &unit_infos);
3550 if (r < 0)
3551 return r;
3552
3553 c = (unsigned) r;
3554
3555 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
3556
3557 for (u = unit_infos; u < unit_infos + c; u++) {
3558 _cleanup_free_ char *p = NULL;
3559
3560 if (!output_show_unit(u))
3561 continue;
3562
3563 p = unit_dbus_path_from_name(u->id);
3564 if (!p)
3565 return log_oom();
3566
3567 printf("%s -> '%s'\n", u->id, p);
3568
3569 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3570 if (r != 0)
3571 return r;
3572 }
3573
3574 return 0;
3575 }
3576
3577 static int show(sd_bus *bus, char **args) {
3578 int r, ret = 0;
3579 bool show_properties, show_status, new_line = false;
3580 char **name;
3581 bool ellipsized = false;
3582
3583 assert(bus);
3584 assert(args);
3585
3586 show_properties = streq(args[0], "show");
3587 show_status = streq(args[0], "status");
3588
3589 if (show_properties)
3590 pager_open_if_enabled();
3591
3592 /* If no argument is specified inspect the manager itself */
3593
3594 if (show_properties && strv_length(args) <= 1)
3595 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3596
3597 if (show_status && strv_length(args) <= 1)
3598 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3599 else
3600 STRV_FOREACH(name, args+1) {
3601 uint32_t id;
3602
3603 if (safe_atou32(*name, &id) < 0) {
3604 _cleanup_free_ char *p = NULL, *n = NULL;
3605 /* Interpret as unit name */
3606
3607 n = unit_name_mangle(*name);
3608 if (!n)
3609 return log_oom();
3610
3611 p = unit_dbus_path_from_name(n);
3612 if (!p)
3613 return log_oom();
3614
3615 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3616 if (r != 0)
3617 ret = r;
3618
3619 } else if (show_properties) {
3620 _cleanup_free_ char *p = NULL;
3621
3622 /* Interpret as job id */
3623 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3624 return log_oom();
3625
3626 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3627 if (r != 0)
3628 ret = r;
3629
3630 } else {
3631 /* Interpret as PID */
3632 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3633 if (r != 0)
3634 ret = r;
3635 }
3636 }
3637
3638 if (ellipsized && !arg_quiet)
3639 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3640
3641 return ret;
3642 }
3643
3644 static int append_assignment(sd_bus_message *m, const char *assignment) {
3645 const char *eq;
3646 char *field;
3647 int r;
3648
3649 assert(m);
3650 assert(assignment);
3651
3652 eq = strchr(assignment, '=');
3653 if (!eq) {
3654 log_error("Not an assignment: %s", assignment);
3655 return -EINVAL;
3656 }
3657
3658 field = strndupa(assignment, eq - assignment);
3659 eq ++;
3660
3661 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
3662 if (r < 0)
3663 return bus_log_create_error(r);
3664
3665 if (streq(field, "CPUAccounting") ||
3666 streq(field, "MemoryAccounting") ||
3667 streq(field, "BlockIOAccounting")) {
3668
3669 r = parse_boolean(eq);
3670 if (r < 0) {
3671 log_error("Failed to parse boolean assignment %s.", assignment);
3672 return -EINVAL;
3673 }
3674
3675 r = sd_bus_message_append(m, "v", "b", r);
3676
3677 } else if (streq(field, "MemoryLimit")) {
3678 off_t bytes;
3679
3680 r = parse_bytes(eq, &bytes);
3681 if (r < 0) {
3682 log_error("Failed to parse bytes specification %s", assignment);
3683 return -EINVAL;
3684 }
3685
3686 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
3687
3688 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3689 uint64_t u;
3690
3691 r = safe_atou64(eq, &u);
3692 if (r < 0) {
3693 log_error("Failed to parse %s value %s.", field, eq);
3694 return -EINVAL;
3695 }
3696
3697 r = sd_bus_message_append(m, "v", "t", u);
3698
3699 } else if (streq(field, "DevicePolicy"))
3700 r = sd_bus_message_append(m, "v", "s", eq);
3701
3702 else if (streq(field, "DeviceAllow")) {
3703
3704 if (isempty(eq))
3705 r = sd_bus_message_append(m, "v", "a(ss)", 0);
3706 else {
3707 const char *path, *rwm;
3708 char *e;
3709
3710 e = strchr(eq, ' ');
3711 if (e) {
3712 path = strndupa(eq, e - eq);
3713 rwm = e+1;
3714 } else {
3715 path = eq;
3716 rwm = "";
3717 }
3718
3719 if (!path_startswith(path, "/dev")) {
3720 log_error("%s is not a device file in /dev.", path);
3721 return -EINVAL;
3722 }
3723
3724 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
3725 }
3726
3727 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3728
3729 if (isempty(eq))
3730 r = sd_bus_message_append(m, "v", "a(st)", 0);
3731 else {
3732 const char *path, *bandwidth;
3733 off_t bytes;
3734 char *e;
3735
3736 e = strchr(eq, ' ');
3737 if (e) {
3738 path = strndupa(eq, e - eq);
3739 bandwidth = e+1;
3740 } else {
3741 log_error("Failed to parse %s value %s.", field, eq);
3742 return -EINVAL;
3743 }
3744
3745 if (!path_startswith(path, "/dev")) {
3746 log_error("%s is not a device file in /dev.", path);
3747 return -EINVAL;
3748 }
3749
3750 r = parse_bytes(bandwidth, &bytes);
3751 if (r < 0) {
3752 log_error("Failed to parse byte value %s.", bandwidth);
3753 return -EINVAL;
3754 }
3755
3756 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
3757 }
3758
3759 } else if (streq(field, "BlockIODeviceWeight")) {
3760
3761 if (isempty(eq))
3762 r = sd_bus_message_append(m, "v", "a(st)", 0);
3763 else {
3764 const char *path, *weight;
3765 uint64_t u;
3766 char *e;
3767
3768 e = strchr(eq, ' ');
3769 if (e) {
3770 path = strndupa(eq, e - eq);
3771 weight = e+1;
3772 } else {
3773 log_error("Failed to parse %s value %s.", field, eq);
3774 return -EINVAL;
3775 }
3776
3777 if (!path_startswith(path, "/dev")) {
3778 log_error("%s is not a device file in /dev.", path);
3779 return -EINVAL;
3780 }
3781
3782 r = safe_atou64(weight, &u);
3783 if (r < 0) {
3784 log_error("Failed to parse %s value %s.", field, weight);
3785 return -EINVAL;
3786 }
3787 r = sd_bus_message_append(m, "v", "a(st)", path, u);
3788 }
3789
3790 } else {
3791 log_error("Unknown assignment %s.", assignment);
3792 return -EINVAL;
3793 }
3794
3795 if (r < 0)
3796 return bus_log_create_error(r);
3797
3798 return 0;
3799 }
3800
3801 static int set_property(sd_bus *bus, char **args) {
3802 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3803 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3804 _cleanup_free_ char *n = NULL;
3805 char **i;
3806 int r;
3807
3808 r = sd_bus_message_new_method_call(
3809 bus,
3810 "org.freedesktop.systemd1",
3811 "/org/freedesktop/systemd1",
3812 "org.freedesktop.systemd1.Manager",
3813 "SetUnitProperties",
3814 &m);
3815 if (r < 0)
3816 return bus_log_create_error(r);
3817
3818 n = unit_name_mangle(args[1]);
3819 if (!n)
3820 return log_oom();
3821
3822 r = sd_bus_message_append(m, "sb", n, arg_runtime);
3823 if (r < 0)
3824 return bus_log_create_error(r);
3825
3826 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
3827 if (r < 0)
3828 return bus_log_create_error(r);
3829
3830 STRV_FOREACH(i, args + 2) {
3831 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
3832 if (r < 0)
3833 return bus_log_create_error(r);
3834
3835 r = append_assignment(m, *i);
3836 if (r < 0)
3837 return r;
3838
3839 r = sd_bus_message_close_container(m);
3840 if (r < 0)
3841 return bus_log_create_error(r);
3842 }
3843
3844 r = sd_bus_message_close_container(m);
3845 if (r < 0)
3846 return bus_log_create_error(r);
3847
3848 r = sd_bus_send_with_reply_and_block(bus, m, -1, &error, NULL);
3849 if (r < 0) {
3850 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
3851 return r;
3852 }
3853
3854 return 0;
3855 }
3856
3857 static int snapshot(sd_bus *bus, char **args) {
3858 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3859 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3860 _cleanup_free_ char *n = NULL, *id = NULL;
3861 const char *path;
3862 int r;
3863
3864 if (strv_length(args) > 1)
3865 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3866 else
3867 n = strdup("");
3868 if (!n)
3869 return log_oom();
3870
3871 r = sd_bus_call_method(
3872 bus,
3873 "org.freedesktop.systemd1",
3874 "/org/freedesktop/systemd1",
3875 "org.freedesktop.systemd1.Manager",
3876 "CreateSnapshot",
3877 &error,
3878 &reply,
3879 "sb", n, false);
3880 if (r < 0) {
3881 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
3882 return r;
3883 }
3884
3885 r = sd_bus_message_read(reply, "o", &path);
3886 if (r < 0)
3887 return bus_log_parse_error(r);
3888
3889 r = sd_bus_get_property_string(
3890 bus,
3891 "org.freedesktop.systemd1",
3892 path,
3893 "org.freedesktop.systemd1.Unit",
3894 "Id",
3895 &error,
3896 &id);
3897 if (r < 0) {
3898 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
3899 return r;
3900 }
3901
3902 if (!arg_quiet)
3903 puts(id);
3904
3905 return 0;
3906 }
3907
3908 static int delete_snapshot(sd_bus *bus, char **args) {
3909 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3910 char **name;
3911 int r;
3912
3913 assert(args);
3914
3915 STRV_FOREACH(name, args+1) {
3916 _cleanup_free_ char *n = NULL;
3917
3918 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3919 if (!n)
3920 return log_oom();
3921
3922 r = sd_bus_call_method(
3923 bus,
3924 "org.freedesktop.systemd1",
3925 "/org/freedesktop/systemd1",
3926 "org.freedesktop.systemd1.Manager",
3927 "RemoveSnapshot",
3928 &error,
3929 NULL,
3930 "s", n);
3931 if (r < 0) {
3932 log_error("Failed to remove snapshot %s: %s", n, bus_error_message(&error, r));
3933 return r;
3934 }
3935 }
3936
3937 return 0;
3938 }
3939
3940 static int daemon_reload(sd_bus *bus, char **args) {
3941 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3942 const char *method;
3943 int r;
3944
3945 if (arg_action == ACTION_RELOAD)
3946 method = "Reload";
3947 else if (arg_action == ACTION_REEXEC)
3948 method = "Reexecute";
3949 else {
3950 assert(arg_action == ACTION_SYSTEMCTL);
3951
3952 method =
3953 streq(args[0], "clear-jobs") ||
3954 streq(args[0], "cancel") ? "ClearJobs" :
3955 streq(args[0], "daemon-reexec") ? "Reexecute" :
3956 streq(args[0], "reset-failed") ? "ResetFailed" :
3957 streq(args[0], "halt") ? "Halt" :
3958 streq(args[0], "poweroff") ? "PowerOff" :
3959 streq(args[0], "reboot") ? "Reboot" :
3960 streq(args[0], "kexec") ? "KExec" :
3961 streq(args[0], "exit") ? "Exit" :
3962 /* "daemon-reload" */ "Reload";
3963 }
3964
3965 r = sd_bus_call_method(
3966 bus,
3967 "org.freedesktop.systemd1",
3968 "/org/freedesktop/systemd1",
3969 "org.freedesktop.systemd1.Manager",
3970 method,
3971 &error,
3972 NULL,
3973 NULL);
3974
3975 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3976 /* There's always a fallback possible for
3977 * legacy actions. */
3978 r = -EADDRNOTAVAIL;
3979 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3980 /* On reexecution, we expect a disconnect, not a
3981 * reply */
3982 r = 0;
3983 else if (r < 0)
3984 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
3985
3986 return r < 0 ? r : 0;
3987 }
3988
3989 static int reset_failed(sd_bus *bus, char **args) {
3990 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3991 char **name;
3992 int r;
3993
3994 if (strv_length(args) <= 1)
3995 return daemon_reload(bus, args);
3996
3997 STRV_FOREACH(name, args+1) {
3998 _cleanup_free_ char *n;
3999
4000 n = unit_name_mangle(*name);
4001 if (!n)
4002 return log_oom();
4003
4004 r = sd_bus_call_method(
4005 bus,
4006 "org.freedesktop.systemd1",
4007 "/org/freedesktop/systemd1",
4008 "org.freedesktop.systemd1.Manager",
4009 "ResetFailedUnit",
4010 &error,
4011 NULL,
4012 "s", n);
4013 if (r < 0) {
4014 log_error("Failed to reset failed state of unit %s: %s", n, bus_error_message(&error, r));
4015 return r;
4016 }
4017 }
4018
4019 return 0;
4020 }
4021
4022 static int show_environment(sd_bus *bus, char **args) {
4023 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4024 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4025 const char *text;
4026 int r;
4027
4028 pager_open_if_enabled();
4029
4030 r = sd_bus_get_property(
4031 bus,
4032 "org.freedesktop.systemd1",
4033 "/org/freedesktop/systemd1",
4034 "org.freedesktop.systemd1.Manager",
4035 "Environment",
4036 &error,
4037 &reply,
4038 "as");
4039 if (r < 0) {
4040 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4041 return r;
4042 }
4043
4044 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4045 if (r < 0)
4046 return bus_log_parse_error(r);
4047
4048 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4049 puts(text);
4050 if (r < 0)
4051 return bus_log_parse_error(r);
4052
4053 r = sd_bus_message_exit_container(reply);
4054 if (r < 0)
4055 return bus_log_parse_error(r);
4056
4057 return 0;
4058 }
4059
4060 static int switch_root(sd_bus *bus, char **args) {
4061 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4062 _cleanup_free_ char *init = NULL;
4063 const char *root;
4064 unsigned l;
4065 int r;
4066
4067 l = strv_length(args);
4068 if (l < 2 || l > 3) {
4069 log_error("Wrong number of arguments.");
4070 return -EINVAL;
4071 }
4072
4073 root = args[1];
4074
4075 if (l >= 3)
4076 init = strdup(args[2]);
4077 else {
4078 parse_env_file("/proc/cmdline", WHITESPACE,
4079 "init", &init,
4080 NULL);
4081
4082 if (!init)
4083 init = strdup("");
4084 }
4085
4086 if (!init)
4087 return log_oom();
4088
4089 log_debug("switching root - root: %s; init: %s", root, init);
4090
4091 r = sd_bus_call_method(
4092 bus,
4093 "org.freedesktop.systemd1",
4094 "/org/freedesktop/systemd1",
4095 "org.freedesktop.systemd1.Manager",
4096 "SwitchRoot",
4097 &error,
4098 NULL,
4099 "ss", root, init);
4100 if (r < 0) {
4101 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4102 return r;
4103 }
4104
4105 return 0;
4106 }
4107
4108 static int set_environment(sd_bus *bus, char **args) {
4109 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4110 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4111 const char *method;
4112 int r;
4113
4114 assert(bus);
4115 assert(args);
4116
4117 method = streq(args[0], "set-environment")
4118 ? "SetEnvironment"
4119 : "UnsetEnvironment";
4120
4121 r = sd_bus_message_new_method_call(
4122 bus,
4123 "org.freedesktop.systemd1",
4124 "/org/freedesktop/systemd1",
4125 "org.freedesktop.systemd1.Manager",
4126 method,
4127 &m);
4128 if (r < 0)
4129 return bus_log_create_error(r);
4130
4131 r = sd_bus_message_append_strv(m, args + 1);
4132 if (r < 0)
4133 return bus_log_create_error(r);
4134
4135 r = sd_bus_send_with_reply_and_block(bus, m, -1, &error, NULL);
4136 if (r < 0) {
4137 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4138 return r;
4139 }
4140
4141 return 0;
4142 }
4143
4144 static int enable_sysv_units(const char *verb, char **args) {
4145 int r = 0;
4146
4147 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4148 unsigned f = 1, t = 1;
4149 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4150
4151 if (arg_scope != UNIT_FILE_SYSTEM)
4152 return 0;
4153
4154 if (!streq(verb, "enable") &&
4155 !streq(verb, "disable") &&
4156 !streq(verb, "is-enabled"))
4157 return 0;
4158
4159 /* Processes all SysV units, and reshuffles the array so that
4160 * afterwards only the native units remain */
4161
4162 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4163 if (r < 0)
4164 return r;
4165
4166 r = 0;
4167 for (f = 0; args[f]; f++) {
4168 const char *name;
4169 _cleanup_free_ char *p = NULL, *q = NULL;
4170 bool found_native = false, found_sysv;
4171 unsigned c = 1;
4172 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4173 char **k, *l;
4174 int j;
4175 pid_t pid;
4176 siginfo_t status;
4177
4178 name = args[f];
4179
4180 if (!endswith(name, ".service"))
4181 continue;
4182
4183 if (path_is_absolute(name))
4184 continue;
4185
4186 STRV_FOREACH(k, paths.unit_path) {
4187 if (!isempty(arg_root))
4188 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4189 else
4190 asprintf(&p, "%s/%s", *k, name);
4191
4192 if (!p) {
4193 r = log_oom();
4194 goto finish;
4195 }
4196
4197 found_native = access(p, F_OK) >= 0;
4198 free(p);
4199 p = NULL;
4200
4201 if (found_native)
4202 break;
4203 }
4204
4205 if (found_native)
4206 continue;
4207
4208 if (!isempty(arg_root))
4209 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4210 else
4211 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4212 if (!p) {
4213 r = log_oom();
4214 goto finish;
4215 }
4216
4217 p[strlen(p) - sizeof(".service") + 1] = 0;
4218 found_sysv = access(p, F_OK) >= 0;
4219
4220 if (!found_sysv)
4221 continue;
4222
4223 /* Mark this entry, so that we don't try enabling it as native unit */
4224 args[f] = (char*) "";
4225
4226 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4227
4228 if (!isempty(arg_root))
4229 argv[c++] = q = strappend("--root=", arg_root);
4230
4231 argv[c++] = path_get_file_name(p);
4232 argv[c++] =
4233 streq(verb, "enable") ? "on" :
4234 streq(verb, "disable") ? "off" : "--level=5";
4235 argv[c] = NULL;
4236
4237 l = strv_join((char**)argv, " ");
4238 if (!l) {
4239 r = log_oom();
4240 goto finish;
4241 }
4242
4243 log_info("Executing %s", l);
4244 free(l);
4245
4246 pid = fork();
4247 if (pid < 0) {
4248 log_error("Failed to fork: %m");
4249 r = -errno;
4250 goto finish;
4251 } else if (pid == 0) {
4252 /* Child */
4253
4254 execv(argv[0], (char**) argv);
4255 _exit(EXIT_FAILURE);
4256 }
4257
4258 j = wait_for_terminate(pid, &status);
4259 if (j < 0) {
4260 log_error("Failed to wait for child: %s", strerror(-r));
4261 r = j;
4262 goto finish;
4263 }
4264
4265 if (status.si_code == CLD_EXITED) {
4266 if (streq(verb, "is-enabled")) {
4267 if (status.si_status == 0) {
4268 if (!arg_quiet)
4269 puts("enabled");
4270 r = 1;
4271 } else {
4272 if (!arg_quiet)
4273 puts("disabled");
4274 }
4275
4276 } else if (status.si_status != 0) {
4277 r = -EINVAL;
4278 goto finish;
4279 }
4280 } else {
4281 r = -EPROTO;
4282 goto finish;
4283 }
4284 }
4285
4286 finish:
4287 /* Drop all SysV units */
4288 for (f = 0, t = 0; args[f]; f++) {
4289
4290 if (isempty(args[f]))
4291 continue;
4292
4293 args[t++] = args[f];
4294 }
4295
4296 args[t] = NULL;
4297
4298 #endif
4299 return r;
4300 }
4301
4302 static int mangle_names(char **original_names, char ***mangled_names) {
4303 char **i, **l, **name;
4304
4305 l = new(char*, strv_length(original_names) + 1);
4306 if (!l)
4307 return log_oom();
4308
4309 i = l;
4310 STRV_FOREACH(name, original_names) {
4311
4312 /* When enabling units qualified path names are OK,
4313 * too, hence allow them explicitly. */
4314
4315 if (is_path(*name))
4316 *i = strdup(*name);
4317 else
4318 *i = unit_name_mangle(*name);
4319
4320 if (!*i) {
4321 strv_free(l);
4322 return log_oom();
4323 }
4324
4325 i++;
4326 }
4327
4328 *i = NULL;
4329 *mangled_names = l;
4330
4331 return 0;
4332 }
4333
4334 static int enable_unit(sd_bus *bus, char **args) {
4335 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
4336 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4337 _cleanup_strv_free_ char **mangled_names = NULL;
4338 const char *verb = args[0];
4339 UnitFileChange *changes = NULL;
4340 unsigned n_changes = 0, i;
4341 int carries_install_info = -1;
4342 int r;
4343
4344 if (!args[1])
4345 return 0;
4346
4347 r = mangle_names(args+1, &mangled_names);
4348 if (r < 0)
4349 return r;
4350
4351 r = enable_sysv_units(verb, mangled_names);
4352 if (r < 0)
4353 return r;
4354
4355 if (!bus || avoid_bus()) {
4356 if (streq(verb, "enable")) {
4357 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4358 carries_install_info = r;
4359 } else if (streq(verb, "disable"))
4360 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4361 else if (streq(verb, "reenable")) {
4362 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4363 carries_install_info = r;
4364 } else if (streq(verb, "link"))
4365 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4366 else if (streq(verb, "preset")) {
4367 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4368 carries_install_info = r;
4369 } else if (streq(verb, "mask"))
4370 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4371 else if (streq(verb, "unmask"))
4372 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4373 else if (streq(verb, "set-default"))
4374 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4375 else
4376 assert_not_reached("Unknown verb");
4377
4378 if (r < 0) {
4379 log_error("Operation failed: %s", strerror(-r));
4380 goto finish;
4381 }
4382
4383 if (!arg_quiet) {
4384 for (i = 0; i < n_changes; i++) {
4385 if (changes[i].type == UNIT_FILE_SYMLINK)
4386 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4387 else
4388 log_info("rm '%s'", changes[i].path);
4389 }
4390 }
4391
4392 r = 0;
4393 } else {
4394 const char *method, *type, *path, *source;
4395 int expect_carries_install_info = false;
4396 bool send_force = true;
4397
4398 if (streq(verb, "enable")) {
4399 method = "EnableUnitFiles";
4400 expect_carries_install_info = true;
4401 } else if (streq(verb, "disable")) {
4402 method = "DisableUnitFiles";
4403 send_force = false;
4404 } else if (streq(verb, "reenable")) {
4405 method = "ReenableUnitFiles";
4406 expect_carries_install_info = true;
4407 } else if (streq(verb, "link"))
4408 method = "LinkUnitFiles";
4409 else if (streq(verb, "preset")) {
4410 method = "PresetUnitFiles";
4411 expect_carries_install_info = true;
4412 } else if (streq(verb, "mask"))
4413 method = "MaskUnitFiles";
4414 else if (streq(verb, "unmask")) {
4415 method = "UnmaskUnitFiles";
4416 send_force = false;
4417 } else if (streq(verb, "set-default")) {
4418 method = "SetDefaultTarget";
4419 } else
4420 assert_not_reached("Unknown verb");
4421
4422 r = sd_bus_message_new_method_call(
4423 bus,
4424 "org.freedesktop.systemd1",
4425 "/org/freedesktop/systemd1",
4426 "org.freedesktop.systemd1.Manager",
4427 method,
4428 &m);
4429 if (r < 0)
4430 return bus_log_create_error(r);
4431
4432 r = sd_bus_message_append_strv(m, mangled_names);
4433 if (r < 0)
4434 return bus_log_create_error(r);
4435
4436 r = sd_bus_message_append(m, "b", arg_runtime);
4437 if (r < 0)
4438 return bus_log_create_error(r);
4439
4440 if (send_force) {
4441 r = sd_bus_message_append(m, "b", arg_force);
4442 if (r < 0)
4443 return bus_log_create_error(r);
4444 }
4445
4446 r = sd_bus_send_with_reply_and_block(bus, m, -0, &error, &reply);
4447 if (r < 0) {
4448 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4449 return r;
4450 }
4451
4452 if (expect_carries_install_info) {
4453 r = sd_bus_message_read(reply, "b", &carries_install_info);
4454 if (r < 0)
4455 return bus_log_parse_error(r);
4456 }
4457
4458 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(sss)");
4459 if (r < 0)
4460 return bus_log_parse_error(r);
4461
4462 while ((r = sd_bus_message_read(reply, "(sss)", &type, &path, &source)) > 0) {
4463 if (!arg_quiet) {
4464 if (streq(type, "symlink"))
4465 log_info("ln -s '%s' '%s'", source, path);
4466 else
4467 log_info("rm '%s'", path);
4468 }
4469 }
4470 if (r < 0)
4471 return bus_log_parse_error(r);
4472
4473 r = sd_bus_message_exit_container(reply);
4474 if (r < 0)
4475 return bus_log_parse_error(r);
4476
4477 /* Try to reload if enabeld */
4478 if (!arg_no_reload)
4479 r = daemon_reload(bus, args);
4480 else
4481 r = 0;
4482 }
4483
4484 if (carries_install_info == 0)
4485 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4486 "using systemctl.\n"
4487 "Possible reasons for having this kind of units are:\n"
4488 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4489 " .wants/ or .requires/ directory.\n"
4490 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4491 " a requirement dependency on it.\n"
4492 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4493 " D-Bus, udev, scripted systemctl call, ...).\n");
4494
4495 finish:
4496 unit_file_changes_free(changes, n_changes);
4497
4498 return r;
4499 }
4500
4501 static int unit_is_enabled(sd_bus *bus, char **args) {
4502
4503 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4504 _cleanup_strv_free_ char **mangled_names = NULL;
4505 bool enabled;
4506 char **name;
4507 int r;
4508
4509 r = mangle_names(args+1, &mangled_names);
4510 if (r < 0)
4511 return r;
4512
4513 r = enable_sysv_units(args[0], mangled_names);
4514 if (r < 0)
4515 return r;
4516
4517 enabled = r > 0;
4518
4519 if (!bus || avoid_bus()) {
4520
4521 STRV_FOREACH(name, mangled_names) {
4522 UnitFileState state;
4523
4524 state = unit_file_get_state(arg_scope, arg_root, *name);
4525 if (state < 0) {
4526 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
4527 return state;
4528 }
4529
4530 if (state == UNIT_FILE_ENABLED ||
4531 state == UNIT_FILE_ENABLED_RUNTIME ||
4532 state == UNIT_FILE_STATIC)
4533 enabled = true;
4534
4535 if (!arg_quiet)
4536 puts(unit_file_state_to_string(state));
4537 }
4538
4539 } else {
4540 STRV_FOREACH(name, mangled_names) {
4541 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4542 const char *s;
4543
4544 r = sd_bus_call_method(
4545 bus,
4546 "org.freedesktop.systemd1",
4547 "/org/freedesktop/systemd1",
4548 "org.freedesktop.systemd1.Manager",
4549 "GetUnitFileState",
4550 &error,
4551 &reply,
4552 "s", name);
4553 if (r < 0) {
4554 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
4555 return r;
4556 }
4557
4558 r = sd_bus_message_read(reply, "s", &s);
4559 if (r < 0)
4560 return bus_log_parse_error(r);
4561
4562 if (streq(s, "enabled") ||
4563 streq(s, "enabled-runtime") ||
4564 streq(s, "static"))
4565 enabled = true;
4566
4567 if (!arg_quiet)
4568 puts(s);
4569 }
4570 }
4571
4572 return !enabled;
4573 }
4574
4575 static int systemctl_help(void) {
4576
4577 pager_open_if_enabled();
4578
4579 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4580 "Query or send control commands to the systemd manager.\n\n"
4581 " -h --help Show this help\n"
4582 " --version Show package version\n"
4583 " --system Connect to system manager\n"
4584 " --user Connect to user service manager\n"
4585 " -H --host=[USER@]HOST\n"
4586 " Operate on remote host\n"
4587 " -M --machine=CONTAINER\n"
4588 " Operate on local container\n"
4589 " -t --type=TYPE List only units of a particular type\n"
4590 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4591 " -p --property=NAME Show only properties by this name\n"
4592 " -a --all Show all loaded units/properties, including dead/empty\n"
4593 " ones. To list all units installed on the system, use\n"
4594 " the 'list-unit-files' command instead.\n"
4595 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4596 " -l --full Don't ellipsize unit names on output\n"
4597 " --fail When queueing a new job, fail if conflicting jobs are\n"
4598 " pending\n"
4599 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4600 " cancelled\n"
4601 " --ignore-dependencies\n"
4602 " When queueing a new job, ignore all its dependencies\n"
4603 " --show-types When showing sockets, explicitly show their type\n"
4604 " -i --ignore-inhibitors\n"
4605 " When shutting down or sleeping, ignore inhibitors\n"
4606 " --kill-who=WHO Who to send signal to\n"
4607 " -s --signal=SIGNAL Which signal to send\n"
4608 " -q --quiet Suppress output\n"
4609 " --no-block Do not wait until operation finished\n"
4610 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4611 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4612 " configuration\n"
4613 " --no-legend Do not print a legend (column headers and hints)\n"
4614 " --no-pager Do not pipe output into a pager\n"
4615 " --no-ask-password\n"
4616 " Do not ask for system passwords\n"
4617 " --global Enable/disable unit files globally\n"
4618 " --runtime Enable unit files only temporarily until next reboot\n"
4619 " -f --force When enabling unit files, override existing symlinks\n"
4620 " When shutting down, execute action immediately\n"
4621 " --root=PATH Enable unit files in the specified root directory\n"
4622 " -n --lines=INTEGER Number of journal entries to show\n"
4623 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4624 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4625 "Unit Commands:\n"
4626 " list-units List loaded units\n"
4627 " list-sockets List loaded sockets ordered by address\n"
4628 " list-timers List loaded timers ordered by next elapse\n"
4629 " start [NAME...] Start (activate) one or more units\n"
4630 " stop [NAME...] Stop (deactivate) one or more units\n"
4631 " reload [NAME...] Reload one or more units\n"
4632 " restart [NAME...] Start or restart one or more units\n"
4633 " try-restart [NAME...] Restart one or more units if active\n"
4634 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4635 " otherwise start or restart\n"
4636 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4637 " otherwise restart if active\n"
4638 " isolate [NAME] Start one unit and stop all others\n"
4639 " kill [NAME...] Send signal to processes of a unit\n"
4640 " is-active [NAME...] Check whether units are active\n"
4641 " is-failed [NAME...] Check whether units are failed\n"
4642 " status [NAME...|PID...] Show runtime status of one or more units\n"
4643 " show [NAME...|JOB...] Show properties of one or more\n"
4644 " units/jobs or the manager\n"
4645 " set-property [NAME] [ASSIGNMENT...]\n"
4646 " Sets one or more properties of a unit\n"
4647 " help [NAME...|PID...] Show manual for one or more units\n"
4648 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4649 " units\n"
4650 " list-dependencies [NAME] Recursively show units which are required\n"
4651 " or wanted by this unit or by which this\n"
4652 " unit is required or wanted\n\n"
4653 "Unit File Commands:\n"
4654 " list-unit-files List installed unit files\n"
4655 " enable [NAME...] Enable one or more unit files\n"
4656 " disable [NAME...] Disable one or more unit files\n"
4657 " reenable [NAME...] Reenable one or more unit files\n"
4658 " preset [NAME...] Enable/disable one or more unit files\n"
4659 " based on preset configuration\n"
4660 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4661 " mask [NAME...] Mask one or more units\n"
4662 " unmask [NAME...] Unmask one or more units\n"
4663 " link [PATH...] Link one or more units files into\n"
4664 " the search path\n"
4665 " get-default Get the name of the default target\n"
4666 " set-default NAME Set the default target\n\n"
4667 "Job Commands:\n"
4668 " list-jobs List jobs\n"
4669 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4670 "Snapshot Commands:\n"
4671 " snapshot [NAME] Create a snapshot\n"
4672 " delete [NAME...] Remove one or more snapshots\n\n"
4673 "Environment Commands:\n"
4674 " show-environment Dump environment\n"
4675 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4676 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4677 "Manager Lifecycle Commands:\n"
4678 " daemon-reload Reload systemd manager configuration\n"
4679 " daemon-reexec Reexecute systemd manager\n\n"
4680 "System Commands:\n"
4681 " default Enter system default mode\n"
4682 " rescue Enter system rescue mode\n"
4683 " emergency Enter system emergency mode\n"
4684 " halt Shut down and halt the system\n"
4685 " poweroff Shut down and power-off the system\n"
4686 " reboot [ARG] Shut down and reboot the system\n"
4687 " kexec Shut down and reboot the system with kexec\n"
4688 " exit Request user instance exit\n"
4689 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4690 " suspend Suspend the system\n"
4691 " hibernate Hibernate the system\n"
4692 " hybrid-sleep Hibernate and suspend the system\n",
4693 program_invocation_short_name);
4694
4695 return 0;
4696 }
4697
4698 static int halt_help(void) {
4699
4700 printf("%s [OPTIONS...]%s\n\n"
4701 "%s the system.\n\n"
4702 " --help Show this help\n"
4703 " --halt Halt the machine\n"
4704 " -p --poweroff Switch off the machine\n"
4705 " --reboot Reboot the machine\n"
4706 " -f --force Force immediate halt/power-off/reboot\n"
4707 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4708 " -d --no-wtmp Don't write wtmp record\n"
4709 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4710 program_invocation_short_name,
4711 arg_action == ACTION_REBOOT ? " [ARG]" : "",
4712 arg_action == ACTION_REBOOT ? "Reboot" :
4713 arg_action == ACTION_POWEROFF ? "Power off" :
4714 "Halt");
4715
4716 return 0;
4717 }
4718
4719 static int shutdown_help(void) {
4720
4721 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4722 "Shut down the system.\n\n"
4723 " --help Show this help\n"
4724 " -H --halt Halt the machine\n"
4725 " -P --poweroff Power-off the machine\n"
4726 " -r --reboot Reboot the machine\n"
4727 " -h Equivalent to --poweroff, overridden by --halt\n"
4728 " -k Don't halt/power-off/reboot, just send warnings\n"
4729 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4730 " -c Cancel a pending shutdown\n",
4731 program_invocation_short_name);
4732
4733 return 0;
4734 }
4735
4736 static int telinit_help(void) {
4737
4738 printf("%s [OPTIONS...] {COMMAND}\n\n"
4739 "Send control commands to the init daemon.\n\n"
4740 " --help Show this help\n"
4741 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4742 "Commands:\n"
4743 " 0 Power-off the machine\n"
4744 " 6 Reboot the machine\n"
4745 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4746 " 1, s, S Enter rescue mode\n"
4747 " q, Q Reload init daemon configuration\n"
4748 " u, U Reexecute init daemon\n",
4749 program_invocation_short_name);
4750
4751 return 0;
4752 }
4753
4754 static int runlevel_help(void) {
4755
4756 printf("%s [OPTIONS...]\n\n"
4757 "Prints the previous and current runlevel of the init system.\n\n"
4758 " --help Show this help\n",
4759 program_invocation_short_name);
4760
4761 return 0;
4762 }
4763
4764 static int help_types(void) {
4765 int i;
4766 const char *t;
4767
4768 puts("Available unit types:");
4769 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4770 t = unit_type_to_string(i);
4771 if (t)
4772 puts(t);
4773 }
4774
4775 return 0;
4776 }
4777
4778 static int systemctl_parse_argv(int argc, char *argv[]) {
4779
4780 enum {
4781 ARG_FAIL = 0x100,
4782 ARG_REVERSE,
4783 ARG_AFTER,
4784 ARG_BEFORE,
4785 ARG_SHOW_TYPES,
4786 ARG_IRREVERSIBLE,
4787 ARG_IGNORE_DEPENDENCIES,
4788 ARG_VERSION,
4789 ARG_USER,
4790 ARG_SYSTEM,
4791 ARG_GLOBAL,
4792 ARG_NO_BLOCK,
4793 ARG_NO_LEGEND,
4794 ARG_NO_PAGER,
4795 ARG_NO_WALL,
4796 ARG_ROOT,
4797 ARG_NO_RELOAD,
4798 ARG_KILL_WHO,
4799 ARG_NO_ASK_PASSWORD,
4800 ARG_FAILED,
4801 ARG_RUNTIME,
4802 ARG_FORCE,
4803 ARG_PLAIN,
4804 ARG_STATE
4805 };
4806
4807 static const struct option options[] = {
4808 { "help", no_argument, NULL, 'h' },
4809 { "version", no_argument, NULL, ARG_VERSION },
4810 { "type", required_argument, NULL, 't' },
4811 { "property", required_argument, NULL, 'p' },
4812 { "all", no_argument, NULL, 'a' },
4813 { "reverse", no_argument, NULL, ARG_REVERSE },
4814 { "after", no_argument, NULL, ARG_AFTER },
4815 { "before", no_argument, NULL, ARG_BEFORE },
4816 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4817 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4818 { "full", no_argument, NULL, 'l' },
4819 { "fail", no_argument, NULL, ARG_FAIL },
4820 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4821 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4822 { "ignore-inhibitors", no_argument, NULL, 'i' },
4823 { "user", no_argument, NULL, ARG_USER },
4824 { "system", no_argument, NULL, ARG_SYSTEM },
4825 { "global", no_argument, NULL, ARG_GLOBAL },
4826 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4827 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4828 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4829 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4830 { "quiet", no_argument, NULL, 'q' },
4831 { "root", required_argument, NULL, ARG_ROOT },
4832 { "force", no_argument, NULL, ARG_FORCE },
4833 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4834 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4835 { "signal", required_argument, NULL, 's' },
4836 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4837 { "host", required_argument, NULL, 'H' },
4838 { "machine", required_argument, NULL, 'M' },
4839 { "runtime", no_argument, NULL, ARG_RUNTIME },
4840 { "lines", required_argument, NULL, 'n' },
4841 { "output", required_argument, NULL, 'o' },
4842 { "plain", no_argument, NULL, ARG_PLAIN },
4843 { "state", required_argument, NULL, ARG_STATE },
4844 {}
4845 };
4846
4847 int c;
4848
4849 assert(argc >= 0);
4850 assert(argv);
4851
4852 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:i", options, NULL)) >= 0) {
4853
4854 switch (c) {
4855
4856 case 'h':
4857 return systemctl_help();
4858
4859 case ARG_VERSION:
4860 puts(PACKAGE_STRING);
4861 puts(SYSTEMD_FEATURES);
4862 return 0;
4863
4864 case 't': {
4865 char *word, *state;
4866 size_t size;
4867
4868 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4869 _cleanup_free_ char *type;
4870
4871 type = strndup(word, size);
4872 if (!type)
4873 return -ENOMEM;
4874
4875 if (streq(type, "help")) {
4876 help_types();
4877 return 0;
4878 }
4879
4880 if (unit_type_from_string(type) >= 0) {
4881 if (strv_push(&arg_types, type))
4882 return log_oom();
4883 type = NULL;
4884 continue;
4885 }
4886
4887 /* It's much nicer to use --state= for
4888 * load states, but let's support this
4889 * in --types= too for compatibility
4890 * with old versions */
4891 if (unit_load_state_from_string(optarg) >= 0) {
4892 if (strv_push(&arg_states, type) < 0)
4893 return log_oom();
4894 type = NULL;
4895 continue;
4896 }
4897
4898 log_error("Unknown unit type or load state '%s'.", type);
4899 log_info("Use -t help to see a list of allowed values.");
4900 return -EINVAL;
4901 }
4902
4903 break;
4904 }
4905
4906 case 'p': {
4907 /* Make sure that if the empty property list
4908 was specified, we won't show any properties. */
4909 if (isempty(optarg) && !arg_properties) {
4910 arg_properties = new0(char*, 1);
4911 if (!arg_properties)
4912 return log_oom();
4913 } else {
4914 char *word, *state;
4915 size_t size;
4916
4917 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4918 char *prop;
4919
4920 prop = strndup(word, size);
4921 if (!prop)
4922 return log_oom();
4923
4924 if (strv_push(&arg_properties, prop) < 0) {
4925 free(prop);
4926 return log_oom();
4927 }
4928 }
4929 }
4930
4931 /* If the user asked for a particular
4932 * property, show it to him, even if it is
4933 * empty. */
4934 arg_all = true;
4935
4936 break;
4937 }
4938
4939 case 'a':
4940 arg_all = true;
4941 break;
4942
4943 case ARG_REVERSE:
4944 arg_dependency = DEPENDENCY_REVERSE;
4945 break;
4946
4947 case ARG_AFTER:
4948 arg_dependency = DEPENDENCY_AFTER;
4949 break;
4950
4951 case ARG_BEFORE:
4952 arg_dependency = DEPENDENCY_BEFORE;
4953 break;
4954
4955 case ARG_SHOW_TYPES:
4956 arg_show_types = true;
4957 break;
4958
4959 case ARG_FAIL:
4960 arg_job_mode = "fail";
4961 break;
4962
4963 case ARG_IRREVERSIBLE:
4964 arg_job_mode = "replace-irreversibly";
4965 break;
4966
4967 case ARG_IGNORE_DEPENDENCIES:
4968 arg_job_mode = "ignore-dependencies";
4969 break;
4970
4971 case ARG_USER:
4972 arg_scope = UNIT_FILE_USER;
4973 break;
4974
4975 case ARG_SYSTEM:
4976 arg_scope = UNIT_FILE_SYSTEM;
4977 break;
4978
4979 case ARG_GLOBAL:
4980 arg_scope = UNIT_FILE_GLOBAL;
4981 break;
4982
4983 case ARG_NO_BLOCK:
4984 arg_no_block = true;
4985 break;
4986
4987 case ARG_NO_LEGEND:
4988 arg_no_legend = true;
4989 break;
4990
4991 case ARG_NO_PAGER:
4992 arg_no_pager = true;
4993 break;
4994
4995 case ARG_NO_WALL:
4996 arg_no_wall = true;
4997 break;
4998
4999 case ARG_ROOT:
5000 arg_root = optarg;
5001 break;
5002
5003 case 'l':
5004 arg_full = true;
5005 break;
5006
5007 case ARG_FAILED:
5008 if (strv_extend(&arg_states, "failed") < 0)
5009 return log_oom();
5010
5011 break;
5012
5013 case 'q':
5014 arg_quiet = true;
5015 break;
5016
5017 case ARG_FORCE:
5018 arg_force ++;
5019 break;
5020
5021 case 'f':
5022 arg_force ++;
5023 break;
5024
5025 case ARG_NO_RELOAD:
5026 arg_no_reload = true;
5027 break;
5028
5029 case ARG_KILL_WHO:
5030 arg_kill_who = optarg;
5031 break;
5032
5033 case 's':
5034 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5035 log_error("Failed to parse signal string %s.", optarg);
5036 return -EINVAL;
5037 }
5038 break;
5039
5040 case ARG_NO_ASK_PASSWORD:
5041 arg_ask_password = false;
5042 break;
5043
5044 case 'H':
5045 arg_transport = BUS_TRANSPORT_REMOTE;
5046 arg_host = optarg;
5047 break;
5048
5049 case 'M':
5050 arg_transport = BUS_TRANSPORT_CONTAINER;
5051 arg_host = optarg;
5052 break;
5053
5054 case ARG_RUNTIME:
5055 arg_runtime = true;
5056 break;
5057
5058 case 'n':
5059 if (safe_atou(optarg, &arg_lines) < 0) {
5060 log_error("Failed to parse lines '%s'", optarg);
5061 return -EINVAL;
5062 }
5063 break;
5064
5065 case 'o':
5066 arg_output = output_mode_from_string(optarg);
5067 if (arg_output < 0) {
5068 log_error("Unknown output '%s'.", optarg);
5069 return -EINVAL;
5070 }
5071 break;
5072
5073 case 'i':
5074 arg_ignore_inhibitors = true;
5075 break;
5076
5077 case ARG_PLAIN:
5078 arg_plain = true;
5079 break;
5080
5081 case ARG_STATE: {
5082 char *word, *state;
5083 size_t size;
5084
5085 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5086 char *s;
5087
5088 s = strndup(word, size);
5089 if (!s)
5090 return log_oom();
5091
5092 if (strv_push(&arg_states, s) < 0) {
5093 free(s);
5094 return log_oom();
5095 }
5096 }
5097 break;
5098 }
5099
5100 case '?':
5101 return -EINVAL;
5102
5103 default:
5104 assert_not_reached("Unhandled option");
5105 }
5106 }
5107
5108 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5109 log_error("Cannot access user instance remotely.");
5110 return -EINVAL;
5111 }
5112
5113 return 1;
5114 }
5115
5116 static int halt_parse_argv(int argc, char *argv[]) {
5117
5118 enum {
5119 ARG_HELP = 0x100,
5120 ARG_HALT,
5121 ARG_REBOOT,
5122 ARG_NO_WALL
5123 };
5124
5125 static const struct option options[] = {
5126 { "help", no_argument, NULL, ARG_HELP },
5127 { "halt", no_argument, NULL, ARG_HALT },
5128 { "poweroff", no_argument, NULL, 'p' },
5129 { "reboot", no_argument, NULL, ARG_REBOOT },
5130 { "force", no_argument, NULL, 'f' },
5131 { "wtmp-only", no_argument, NULL, 'w' },
5132 { "no-wtmp", no_argument, NULL, 'd' },
5133 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5134 {}
5135 };
5136
5137 int c, r, runlevel;
5138
5139 assert(argc >= 0);
5140 assert(argv);
5141
5142 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5143 if (runlevel == '0' || runlevel == '6')
5144 arg_force = 2;
5145
5146 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5147 switch (c) {
5148
5149 case ARG_HELP:
5150 return halt_help();
5151
5152 case ARG_HALT:
5153 arg_action = ACTION_HALT;
5154 break;
5155
5156 case 'p':
5157 if (arg_action != ACTION_REBOOT)
5158 arg_action = ACTION_POWEROFF;
5159 break;
5160
5161 case ARG_REBOOT:
5162 arg_action = ACTION_REBOOT;
5163 break;
5164
5165 case 'f':
5166 arg_force = 2;
5167 break;
5168
5169 case 'w':
5170 arg_dry = true;
5171 break;
5172
5173 case 'd':
5174 arg_no_wtmp = true;
5175 break;
5176
5177 case ARG_NO_WALL:
5178 arg_no_wall = true;
5179 break;
5180
5181 case 'i':
5182 case 'h':
5183 case 'n':
5184 /* Compatibility nops */
5185 break;
5186
5187 case '?':
5188 return -EINVAL;
5189
5190 default:
5191 assert_not_reached("Unhandled option");
5192 }
5193 }
5194
5195 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5196 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5197 if (r < 0) {
5198 log_error("Failed to write reboot param to "
5199 REBOOT_PARAM_FILE": %s", strerror(-r));
5200 return r;
5201 }
5202 } else if (optind < argc) {
5203 log_error("Too many arguments.");
5204 return -EINVAL;
5205 }
5206
5207 return 1;
5208 }
5209
5210 static int parse_time_spec(const char *t, usec_t *_u) {
5211 assert(t);
5212 assert(_u);
5213
5214 if (streq(t, "now"))
5215 *_u = 0;
5216 else if (!strchr(t, ':')) {
5217 uint64_t u;
5218
5219 if (safe_atou64(t, &u) < 0)
5220 return -EINVAL;
5221
5222 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5223 } else {
5224 char *e = NULL;
5225 long hour, minute;
5226 struct tm tm = {};
5227 time_t s;
5228 usec_t n;
5229
5230 errno = 0;
5231 hour = strtol(t, &e, 10);
5232 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5233 return -EINVAL;
5234
5235 minute = strtol(e+1, &e, 10);
5236 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5237 return -EINVAL;
5238
5239 n = now(CLOCK_REALTIME);
5240 s = (time_t) (n / USEC_PER_SEC);
5241
5242 assert_se(localtime_r(&s, &tm));
5243
5244 tm.tm_hour = (int) hour;
5245 tm.tm_min = (int) minute;
5246 tm.tm_sec = 0;
5247
5248 assert_se(s = mktime(&tm));
5249
5250 *_u = (usec_t) s * USEC_PER_SEC;
5251
5252 while (*_u <= n)
5253 *_u += USEC_PER_DAY;
5254 }
5255
5256 return 0;
5257 }
5258
5259 static int shutdown_parse_argv(int argc, char *argv[]) {
5260
5261 enum {
5262 ARG_HELP = 0x100,
5263 ARG_NO_WALL
5264 };
5265
5266 static const struct option options[] = {
5267 { "help", no_argument, NULL, ARG_HELP },
5268 { "halt", no_argument, NULL, 'H' },
5269 { "poweroff", no_argument, NULL, 'P' },
5270 { "reboot", no_argument, NULL, 'r' },
5271 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5272 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5273 {}
5274 };
5275
5276 int c, r;
5277
5278 assert(argc >= 0);
5279 assert(argv);
5280
5281 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5282 switch (c) {
5283
5284 case ARG_HELP:
5285 return shutdown_help();
5286
5287 case 'H':
5288 arg_action = ACTION_HALT;
5289 break;
5290
5291 case 'P':
5292 arg_action = ACTION_POWEROFF;
5293 break;
5294
5295 case 'r':
5296 if (kexec_loaded())
5297 arg_action = ACTION_KEXEC;
5298 else
5299 arg_action = ACTION_REBOOT;
5300 break;
5301
5302 case 'K':
5303 arg_action = ACTION_KEXEC;
5304 break;
5305
5306 case 'h':
5307 if (arg_action != ACTION_HALT)
5308 arg_action = ACTION_POWEROFF;
5309 break;
5310
5311 case 'k':
5312 arg_dry = true;
5313 break;
5314
5315 case ARG_NO_WALL:
5316 arg_no_wall = true;
5317 break;
5318
5319 case 't':
5320 case 'a':
5321 /* Compatibility nops */
5322 break;
5323
5324 case 'c':
5325 arg_action = ACTION_CANCEL_SHUTDOWN;
5326 break;
5327
5328 case '?':
5329 return -EINVAL;
5330
5331 default:
5332 assert_not_reached("Unhandled option");
5333 }
5334 }
5335
5336 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5337 r = parse_time_spec(argv[optind], &arg_when);
5338 if (r < 0) {
5339 log_error("Failed to parse time specification: %s", argv[optind]);
5340 return r;
5341 }
5342 } else
5343 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5344
5345 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5346 /* No time argument for shutdown cancel */
5347 arg_wall = argv + optind;
5348 else if (argc > optind + 1)
5349 /* We skip the time argument */
5350 arg_wall = argv + optind + 1;
5351
5352 optind = argc;
5353
5354 return 1;
5355 }
5356
5357 static int telinit_parse_argv(int argc, char *argv[]) {
5358
5359 enum {
5360 ARG_HELP = 0x100,
5361 ARG_NO_WALL
5362 };
5363
5364 static const struct option options[] = {
5365 { "help", no_argument, NULL, ARG_HELP },
5366 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5367 {}
5368 };
5369
5370 static const struct {
5371 char from;
5372 enum action to;
5373 } table[] = {
5374 { '0', ACTION_POWEROFF },
5375 { '6', ACTION_REBOOT },
5376 { '1', ACTION_RESCUE },
5377 { '2', ACTION_RUNLEVEL2 },
5378 { '3', ACTION_RUNLEVEL3 },
5379 { '4', ACTION_RUNLEVEL4 },
5380 { '5', ACTION_RUNLEVEL5 },
5381 { 's', ACTION_RESCUE },
5382 { 'S', ACTION_RESCUE },
5383 { 'q', ACTION_RELOAD },
5384 { 'Q', ACTION_RELOAD },
5385 { 'u', ACTION_REEXEC },
5386 { 'U', ACTION_REEXEC }
5387 };
5388
5389 unsigned i;
5390 int c;
5391
5392 assert(argc >= 0);
5393 assert(argv);
5394
5395 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5396 switch (c) {
5397
5398 case ARG_HELP:
5399 return telinit_help();
5400
5401 case ARG_NO_WALL:
5402 arg_no_wall = true;
5403 break;
5404
5405 case '?':
5406 return -EINVAL;
5407
5408 default:
5409 assert_not_reached("Unhandled option");
5410 }
5411 }
5412
5413 if (optind >= argc) {
5414 telinit_help();
5415 return -EINVAL;
5416 }
5417
5418 if (optind + 1 < argc) {
5419 log_error("Too many arguments.");
5420 return -EINVAL;
5421 }
5422
5423 if (strlen(argv[optind]) != 1) {
5424 log_error("Expected single character argument.");
5425 return -EINVAL;
5426 }
5427
5428 for (i = 0; i < ELEMENTSOF(table); i++)
5429 if (table[i].from == argv[optind][0])
5430 break;
5431
5432 if (i >= ELEMENTSOF(table)) {
5433 log_error("Unknown command '%s'.", argv[optind]);
5434 return -EINVAL;
5435 }
5436
5437 arg_action = table[i].to;
5438
5439 optind ++;
5440
5441 return 1;
5442 }
5443
5444 static int runlevel_parse_argv(int argc, char *argv[]) {
5445
5446 enum {
5447 ARG_HELP = 0x100,
5448 };
5449
5450 static const struct option options[] = {
5451 { "help", no_argument, NULL, ARG_HELP },
5452 {}
5453 };
5454
5455 int c;
5456
5457 assert(argc >= 0);
5458 assert(argv);
5459
5460 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5461 switch (c) {
5462
5463 case ARG_HELP:
5464 return runlevel_help();
5465 return 0;
5466
5467 case '?':
5468 return -EINVAL;
5469
5470 default:
5471 assert_not_reached("Unhandled option");
5472 }
5473 }
5474
5475 if (optind < argc) {
5476 log_error("Too many arguments.");
5477 return -EINVAL;
5478 }
5479
5480 return 1;
5481 }
5482
5483 static int parse_argv(int argc, char *argv[]) {
5484 assert(argc >= 0);
5485 assert(argv);
5486
5487 if (program_invocation_short_name) {
5488
5489 if (strstr(program_invocation_short_name, "halt")) {
5490 arg_action = ACTION_HALT;
5491 return halt_parse_argv(argc, argv);
5492 } else if (strstr(program_invocation_short_name, "poweroff")) {
5493 arg_action = ACTION_POWEROFF;
5494 return halt_parse_argv(argc, argv);
5495 } else if (strstr(program_invocation_short_name, "reboot")) {
5496 if (kexec_loaded())
5497 arg_action = ACTION_KEXEC;
5498 else
5499 arg_action = ACTION_REBOOT;
5500 return halt_parse_argv(argc, argv);
5501 } else if (strstr(program_invocation_short_name, "shutdown")) {
5502 arg_action = ACTION_POWEROFF;
5503 return shutdown_parse_argv(argc, argv);
5504 } else if (strstr(program_invocation_short_name, "init")) {
5505
5506 if (sd_booted() > 0) {
5507 arg_action = _ACTION_INVALID;
5508 return telinit_parse_argv(argc, argv);
5509 } else {
5510 /* Hmm, so some other init system is
5511 * running, we need to forward this
5512 * request to it. For now we simply
5513 * guess that it is Upstart. */
5514
5515 execv(TELINIT, argv);
5516
5517 log_error("Couldn't find an alternative telinit implementation to spawn.");
5518 return -EIO;
5519 }
5520
5521 } else if (strstr(program_invocation_short_name, "runlevel")) {
5522 arg_action = ACTION_RUNLEVEL;
5523 return runlevel_parse_argv(argc, argv);
5524 }
5525 }
5526
5527 arg_action = ACTION_SYSTEMCTL;
5528 return systemctl_parse_argv(argc, argv);
5529 }
5530
5531 _pure_ static int action_to_runlevel(void) {
5532
5533 static const char table[_ACTION_MAX] = {
5534 [ACTION_HALT] = '0',
5535 [ACTION_POWEROFF] = '0',
5536 [ACTION_REBOOT] = '6',
5537 [ACTION_RUNLEVEL2] = '2',
5538 [ACTION_RUNLEVEL3] = '3',
5539 [ACTION_RUNLEVEL4] = '4',
5540 [ACTION_RUNLEVEL5] = '5',
5541 [ACTION_RESCUE] = '1'
5542 };
5543
5544 assert(arg_action < _ACTION_MAX);
5545
5546 return table[arg_action];
5547 }
5548
5549 static int talk_initctl(void) {
5550
5551 struct init_request request = {
5552 .magic = INIT_MAGIC,
5553 .sleeptime = 0,
5554 .cmd = INIT_CMD_RUNLVL
5555 };
5556
5557 _cleanup_close_ int fd = -1;
5558 char rl;
5559 int r;
5560
5561 rl = action_to_runlevel();
5562 if (!rl)
5563 return 0;
5564
5565 request.runlevel = rl;
5566
5567 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5568 if (fd < 0) {
5569 if (errno == ENOENT)
5570 return 0;
5571
5572 log_error("Failed to open "INIT_FIFO": %m");
5573 return -errno;
5574 }
5575
5576 errno = 0;
5577 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5578 if (r) {
5579 log_error("Failed to write to "INIT_FIFO": %m");
5580 return errno > 0 ? -errno : -EIO;
5581 }
5582
5583 return 1;
5584 }
5585
5586 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
5587
5588 static const struct {
5589 const char* verb;
5590 const enum {
5591 MORE,
5592 LESS,
5593 EQUAL
5594 } argc_cmp;
5595 const int argc;
5596 int (* const dispatch)(sd_bus *bus, char **args);
5597 } verbs[] = {
5598 { "list-units", LESS, 1, list_units },
5599 { "list-unit-files", EQUAL, 1, list_unit_files },
5600 { "list-sockets", LESS, 1, list_sockets },
5601 { "list-timers", LESS, 1, list_timers },
5602 { "list-jobs", EQUAL, 1, list_jobs },
5603 { "clear-jobs", EQUAL, 1, daemon_reload },
5604 { "cancel", MORE, 2, cancel_job },
5605 { "start", MORE, 2, start_unit },
5606 { "stop", MORE, 2, start_unit },
5607 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5608 { "reload", MORE, 2, start_unit },
5609 { "restart", MORE, 2, start_unit },
5610 { "try-restart", MORE, 2, start_unit },
5611 { "reload-or-restart", MORE, 2, start_unit },
5612 { "reload-or-try-restart", MORE, 2, start_unit },
5613 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5614 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5615 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5616 { "isolate", EQUAL, 2, start_unit },
5617 { "kill", MORE, 2, kill_unit },
5618 { "is-active", MORE, 2, check_unit_active },
5619 { "check", MORE, 2, check_unit_active },
5620 { "is-failed", MORE, 2, check_unit_failed },
5621 { "show", MORE, 1, show },
5622 { "status", MORE, 1, show },
5623 { "help", MORE, 2, show },
5624 { "snapshot", LESS, 2, snapshot },
5625 { "delete", MORE, 2, delete_snapshot },
5626 { "daemon-reload", EQUAL, 1, daemon_reload },
5627 { "daemon-reexec", EQUAL, 1, daemon_reload },
5628 { "show-environment", EQUAL, 1, show_environment },
5629 { "set-environment", MORE, 2, set_environment },
5630 { "unset-environment", MORE, 2, set_environment },
5631 { "halt", EQUAL, 1, start_special },
5632 { "poweroff", EQUAL, 1, start_special },
5633 { "reboot", EQUAL, 1, start_special },
5634 { "kexec", EQUAL, 1, start_special },
5635 { "suspend", EQUAL, 1, start_special },
5636 { "hibernate", EQUAL, 1, start_special },
5637 { "hybrid-sleep", EQUAL, 1, start_special },
5638 { "default", EQUAL, 1, start_special },
5639 { "rescue", EQUAL, 1, start_special },
5640 { "emergency", EQUAL, 1, start_special },
5641 { "exit", EQUAL, 1, start_special },
5642 { "reset-failed", MORE, 1, reset_failed },
5643 { "enable", MORE, 2, enable_unit },
5644 { "disable", MORE, 2, enable_unit },
5645 { "is-enabled", MORE, 2, unit_is_enabled },
5646 { "reenable", MORE, 2, enable_unit },
5647 { "preset", MORE, 2, enable_unit },
5648 { "mask", MORE, 2, enable_unit },
5649 { "unmask", MORE, 2, enable_unit },
5650 { "link", MORE, 2, enable_unit },
5651 { "switch-root", MORE, 2, switch_root },
5652 { "list-dependencies", LESS, 2, list_dependencies },
5653 { "set-default", EQUAL, 2, enable_unit },
5654 { "get-default", LESS, 1, get_default },
5655 { "set-property", MORE, 3, set_property },
5656 };
5657
5658 int left;
5659 unsigned i;
5660
5661 assert(argc >= 0);
5662 assert(argv);
5663
5664 left = argc - optind;
5665
5666 if (left <= 0)
5667 /* Special rule: no arguments means "list-units" */
5668 i = 0;
5669 else {
5670 if (streq(argv[optind], "help") && !argv[optind+1]) {
5671 log_error("This command expects one or more "
5672 "unit names. Did you mean --help?");
5673 return -EINVAL;
5674 }
5675
5676 for (i = 0; i < ELEMENTSOF(verbs); i++)
5677 if (streq(argv[optind], verbs[i].verb))
5678 break;
5679
5680 if (i >= ELEMENTSOF(verbs)) {
5681 log_error("Unknown operation '%s'.", argv[optind]);
5682 return -EINVAL;
5683 }
5684 }
5685
5686 switch (verbs[i].argc_cmp) {
5687
5688 case EQUAL:
5689 if (left != verbs[i].argc) {
5690 log_error("Invalid number of arguments.");
5691 return -EINVAL;
5692 }
5693
5694 break;
5695
5696 case MORE:
5697 if (left < verbs[i].argc) {
5698 log_error("Too few arguments.");
5699 return -EINVAL;
5700 }
5701
5702 break;
5703
5704 case LESS:
5705 if (left > verbs[i].argc) {
5706 log_error("Too many arguments.");
5707 return -EINVAL;
5708 }
5709
5710 break;
5711
5712 default:
5713 assert_not_reached("Unknown comparison operator.");
5714 }
5715
5716 /* Require a bus connection for all operations but
5717 * enable/disable */
5718 if (!streq(verbs[i].verb, "enable") &&
5719 !streq(verbs[i].verb, "disable") &&
5720 !streq(verbs[i].verb, "is-enabled") &&
5721 !streq(verbs[i].verb, "list-unit-files") &&
5722 !streq(verbs[i].verb, "reenable") &&
5723 !streq(verbs[i].verb, "preset") &&
5724 !streq(verbs[i].verb, "mask") &&
5725 !streq(verbs[i].verb, "unmask") &&
5726 !streq(verbs[i].verb, "link") &&
5727 !streq(verbs[i].verb, "set-default") &&
5728 !streq(verbs[i].verb, "get-default")) {
5729
5730 if (running_in_chroot() > 0) {
5731 log_info("Running in chroot, ignoring request.");
5732 return 0;
5733 }
5734
5735 if (((!streq(verbs[i].verb, "reboot") &&
5736 !streq(verbs[i].verb, "halt") &&
5737 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5738 log_error("Failed to get D-Bus connection: %s", strerror (-bus_error));
5739 return -EIO;
5740 }
5741
5742 } else {
5743
5744 if (!bus && !avoid_bus()) {
5745 log_error("Failed to get D-Bus connection: %s", strerror (-bus_error));
5746 return -EIO;
5747 }
5748 }
5749
5750 return verbs[i].dispatch(bus, argv + optind);
5751 }
5752
5753 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5754
5755 struct sd_shutdown_command c = {
5756 .usec = t,
5757 .mode = mode,
5758 .dry_run = dry_run,
5759 .warn_wall = warn,
5760 };
5761
5762 union sockaddr_union sockaddr = {
5763 .un.sun_family = AF_UNIX,
5764 .un.sun_path = "/run/systemd/shutdownd",
5765 };
5766
5767 struct iovec iovec[2] = {{
5768 .iov_base = (char*) &c,
5769 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5770 }};
5771
5772 struct msghdr msghdr = {
5773 .msg_name = &sockaddr,
5774 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5775 + sizeof("/run/systemd/shutdownd") - 1,
5776 .msg_iov = iovec,
5777 .msg_iovlen = 1,
5778 };
5779
5780 _cleanup_close_ int fd;
5781
5782 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5783 if (fd < 0)
5784 return -errno;
5785
5786 if (!isempty(message)) {
5787 iovec[1].iov_base = (char*) message;
5788 iovec[1].iov_len = strlen(message);
5789 msghdr.msg_iovlen++;
5790 }
5791
5792 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5793 return -errno;
5794
5795 return 0;
5796 }
5797
5798 static int reload_with_fallback(sd_bus *bus) {
5799
5800 if (bus) {
5801 /* First, try systemd via D-Bus. */
5802 if (daemon_reload(bus, NULL) >= 0)
5803 return 0;
5804 }
5805
5806 /* Nothing else worked, so let's try signals */
5807 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5808
5809 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5810 log_error("kill() failed: %m");
5811 return -errno;
5812 }
5813
5814 return 0;
5815 }
5816
5817 static int start_with_fallback(sd_bus *bus) {
5818
5819 if (bus) {
5820 /* First, try systemd via D-Bus. */
5821 if (start_unit(bus, NULL) >= 0)
5822 goto done;
5823 }
5824
5825 /* Nothing else worked, so let's try
5826 * /dev/initctl */
5827 if (talk_initctl() > 0)
5828 goto done;
5829
5830 log_error("Failed to talk to init daemon.");
5831 return -EIO;
5832
5833 done:
5834 warn_wall(arg_action);
5835 return 0;
5836 }
5837
5838 static int halt_now(enum action a) {
5839
5840 /* Make sure C-A-D is handled by the kernel from this
5841 * point on... */
5842 reboot(RB_ENABLE_CAD);
5843
5844 switch (a) {
5845
5846 case ACTION_HALT:
5847 log_info("Halting.");
5848 reboot(RB_HALT_SYSTEM);
5849 return -errno;
5850
5851 case ACTION_POWEROFF:
5852 log_info("Powering off.");
5853 reboot(RB_POWER_OFF);
5854 return -errno;
5855
5856 case ACTION_REBOOT: {
5857 _cleanup_free_ char *param = NULL;
5858
5859 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
5860 log_info("Rebooting with argument '%s'.", param);
5861 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
5862 LINUX_REBOOT_CMD_RESTART2, param);
5863 }
5864
5865 log_info("Rebooting.");
5866 reboot(RB_AUTOBOOT);
5867 return -errno;
5868 }
5869
5870 default:
5871 assert_not_reached("Unknown action.");
5872 }
5873 }
5874
5875 static int halt_main(sd_bus *bus) {
5876 int r;
5877
5878 r = check_inhibitors(bus, arg_action);
5879 if (r < 0)
5880 return r;
5881
5882 if (geteuid() != 0) {
5883 /* Try logind if we are a normal user and no special
5884 * mode applies. Maybe PolicyKit allows us to shutdown
5885 * the machine. */
5886
5887 if (arg_when <= 0 &&
5888 !arg_dry &&
5889 arg_force <= 0 &&
5890 (arg_action == ACTION_POWEROFF ||
5891 arg_action == ACTION_REBOOT)) {
5892 r = reboot_with_logind(bus, arg_action);
5893 if (r >= 0)
5894 return r;
5895 }
5896
5897 log_error("Must be root.");
5898 return -EPERM;
5899 }
5900
5901 if (arg_when > 0) {
5902 _cleanup_free_ char *m;
5903
5904 m = strv_join(arg_wall, " ");
5905 if (!m)
5906 return log_oom();
5907
5908 r = send_shutdownd(arg_when,
5909 arg_action == ACTION_HALT ? 'H' :
5910 arg_action == ACTION_POWEROFF ? 'P' :
5911 arg_action == ACTION_KEXEC ? 'K' :
5912 'r',
5913 arg_dry,
5914 !arg_no_wall,
5915 m);
5916
5917 if (r < 0)
5918 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5919 else {
5920 char date[FORMAT_TIMESTAMP_MAX];
5921
5922 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5923 format_timestamp(date, sizeof(date), arg_when));
5924 return 0;
5925 }
5926 }
5927
5928 if (!arg_dry && !arg_force)
5929 return start_with_fallback(bus);
5930
5931 if (!arg_no_wtmp) {
5932 if (sd_booted() > 0)
5933 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5934 else {
5935 r = utmp_put_shutdown();
5936 if (r < 0)
5937 log_warning("Failed to write utmp record: %s", strerror(-r));
5938 }
5939 }
5940
5941 if (arg_dry)
5942 return 0;
5943
5944 r = halt_now(arg_action);
5945 log_error("Failed to reboot: %s", strerror(-r));
5946
5947 return r;
5948 }
5949
5950 static int runlevel_main(void) {
5951 int r, runlevel, previous;
5952
5953 r = utmp_get_runlevel(&runlevel, &previous);
5954 if (r < 0) {
5955 puts("unknown");
5956 return r;
5957 }
5958
5959 printf("%c %c\n",
5960 previous <= 0 ? 'N' : previous,
5961 runlevel <= 0 ? 'N' : runlevel);
5962
5963 return 0;
5964 }
5965
5966 int main(int argc, char*argv[]) {
5967 _cleanup_bus_unref_ sd_bus *bus = NULL;
5968 int r;
5969
5970 setlocale(LC_ALL, "");
5971 log_parse_environment();
5972 log_open();
5973
5974 /* Explicitly not on_tty() to avoid setting cached value.
5975 * This becomes relevant for piping output which might be
5976 * ellipsized. */
5977 original_stdout_is_tty = isatty(STDOUT_FILENO);
5978
5979 r = parse_argv(argc, argv);
5980 if (r <= 0)
5981 goto finish;
5982
5983 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5984 * let's shortcut this */
5985 if (arg_action == ACTION_RUNLEVEL) {
5986 r = runlevel_main();
5987 goto finish;
5988 }
5989
5990 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5991 log_info("Running in chroot, ignoring request.");
5992 r = 0;
5993 goto finish;
5994 }
5995
5996 if (!avoid_bus())
5997 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
5998
5999 /* systemctl_main() will print an error message for the bus
6000 * connection, but only if it needs to */
6001
6002 switch (arg_action) {
6003
6004 case ACTION_SYSTEMCTL:
6005 r = systemctl_main(bus, argc, argv, r);
6006 break;
6007
6008 case ACTION_HALT:
6009 case ACTION_POWEROFF:
6010 case ACTION_REBOOT:
6011 case ACTION_KEXEC:
6012 r = halt_main(bus);
6013 break;
6014
6015 case ACTION_RUNLEVEL2:
6016 case ACTION_RUNLEVEL3:
6017 case ACTION_RUNLEVEL4:
6018 case ACTION_RUNLEVEL5:
6019 case ACTION_RESCUE:
6020 case ACTION_EMERGENCY:
6021 case ACTION_DEFAULT:
6022 r = start_with_fallback(bus);
6023 break;
6024
6025 case ACTION_RELOAD:
6026 case ACTION_REEXEC:
6027 r = reload_with_fallback(bus);
6028 break;
6029
6030 case ACTION_CANCEL_SHUTDOWN: {
6031 _cleanup_free_ char *m = NULL;
6032
6033 if (arg_wall) {
6034 m = strv_join(arg_wall, " ");
6035 if (!m) {
6036 r = log_oom();
6037 goto finish;
6038 }
6039 }
6040
6041 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6042 if (r < 0)
6043 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6044 break;
6045 }
6046
6047 case ACTION_RUNLEVEL:
6048 case _ACTION_INVALID:
6049 default:
6050 assert_not_reached("Unknown action");
6051 }
6052
6053 finish:
6054 pager_close();
6055 ask_password_agent_close();
6056 polkit_agent_close();
6057
6058 strv_free(arg_types);
6059 strv_free(arg_states);
6060 strv_free(arg_properties);
6061
6062 return r < 0 ? EXIT_FAILURE : r;
6063 }