]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl.c
Remove duplicate includes
[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 "socket-util.h"
69 #include "fileio.h"
70 #include "bus-util.h"
71 #include "bus-message.h"
72 #include "bus-error.h"
73
74 static char **arg_types = NULL;
75 static char **arg_states = NULL;
76 static char **arg_properties = NULL;
77 static bool arg_all = false;
78 static bool original_stdout_is_tty;
79 static enum dependency {
80 DEPENDENCY_FORWARD,
81 DEPENDENCY_REVERSE,
82 DEPENDENCY_AFTER,
83 DEPENDENCY_BEFORE,
84 } arg_dependency = DEPENDENCY_FORWARD;
85 static const char *arg_job_mode = "replace";
86 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
87 static bool arg_no_block = false;
88 static bool arg_no_legend = false;
89 static bool arg_no_pager = false;
90 static bool arg_no_wtmp = false;
91 static bool arg_no_wall = false;
92 static bool arg_no_reload = false;
93 static bool arg_show_types = false;
94 static bool arg_ignore_inhibitors = false;
95 static bool arg_dry = false;
96 static bool arg_quiet = false;
97 static bool arg_full = false;
98 static int arg_force = 0;
99 static bool arg_ask_password = true;
100 static bool arg_runtime = false;
101 static char **arg_wall = NULL;
102 static const char *arg_kill_who = NULL;
103 static int arg_signal = SIGTERM;
104 static const char *arg_root = NULL;
105 static usec_t arg_when = 0;
106 static enum action {
107 _ACTION_INVALID,
108 ACTION_SYSTEMCTL,
109 ACTION_HALT,
110 ACTION_POWEROFF,
111 ACTION_REBOOT,
112 ACTION_KEXEC,
113 ACTION_EXIT,
114 ACTION_SUSPEND,
115 ACTION_HIBERNATE,
116 ACTION_HYBRID_SLEEP,
117 ACTION_RUNLEVEL2,
118 ACTION_RUNLEVEL3,
119 ACTION_RUNLEVEL4,
120 ACTION_RUNLEVEL5,
121 ACTION_RESCUE,
122 ACTION_EMERGENCY,
123 ACTION_DEFAULT,
124 ACTION_RELOAD,
125 ACTION_REEXEC,
126 ACTION_RUNLEVEL,
127 ACTION_CANCEL_SHUTDOWN,
128 _ACTION_MAX
129 } arg_action = ACTION_SYSTEMCTL;
130 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
131 static char *arg_host = NULL;
132 static unsigned arg_lines = 10;
133 static OutputMode arg_output = OUTPUT_SHORT;
134 static bool arg_plain = false;
135
136 static int daemon_reload(sd_bus *bus, char **args);
137 static int halt_now(enum action a);
138
139 static void pager_open_if_enabled(void) {
140
141 if (arg_no_pager)
142 return;
143
144 pager_open(false);
145 }
146
147 static void ask_password_agent_open_if_enabled(void) {
148
149 /* Open the password agent as a child process if necessary */
150
151 if (!arg_ask_password)
152 return;
153
154 if (arg_scope != UNIT_FILE_SYSTEM)
155 return;
156
157 if (arg_transport != BUS_TRANSPORT_LOCAL)
158 return;
159
160 ask_password_agent_open();
161 }
162
163 #ifdef HAVE_LOGIND
164 static void polkit_agent_open_if_enabled(void) {
165
166 /* Open the polkit agent as a child process if necessary */
167
168 if (!arg_ask_password)
169 return;
170
171 if (arg_scope != UNIT_FILE_SYSTEM)
172 return;
173
174 if (arg_transport != BUS_TRANSPORT_LOCAL)
175 return;
176
177 polkit_agent_open();
178 }
179 #endif
180
181 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
182 assert(error);
183
184 if (!sd_bus_error_is_set(error))
185 return r;
186
187 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
188 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
189 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
190 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
191 return EXIT_NOPERMISSION;
192
193 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
194 return EXIT_NOTINSTALLED;
195
196 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
197 sd_bus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
198 return EXIT_NOTIMPLEMENTED;
199
200 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
201 return EXIT_NOTCONFIGURED;
202
203 if (r != 0)
204 return r;
205
206 return EXIT_FAILURE;
207 }
208
209 static void warn_wall(enum action a) {
210 static const char *table[_ACTION_MAX] = {
211 [ACTION_HALT] = "The system is going down for system halt NOW!",
212 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
213 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
214 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
215 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
216 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
217 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
218 };
219
220 if (arg_no_wall)
221 return;
222
223 if (arg_wall) {
224 _cleanup_free_ char *p;
225
226 p = strv_join(arg_wall, " ");
227 if (!p) {
228 log_oom();
229 return;
230 }
231
232 if (*p) {
233 utmp_wall(p, NULL);
234 return;
235 }
236 }
237
238 if (!table[a])
239 return;
240
241 utmp_wall(table[a], NULL);
242 }
243
244 static bool avoid_bus(void) {
245
246 if (running_in_chroot() > 0)
247 return true;
248
249 if (sd_booted() <= 0)
250 return true;
251
252 if (!isempty(arg_root))
253 return true;
254
255 if (arg_scope == UNIT_FILE_GLOBAL)
256 return true;
257
258 return false;
259 }
260
261 static int compare_unit_info(const void *a, const void *b) {
262 const UnitInfo *u = a, *v = b;
263 const char *d1, *d2;
264
265 d1 = strrchr(u->id, '.');
266 d2 = strrchr(v->id, '.');
267
268 if (d1 && d2) {
269 int r;
270
271 r = strcasecmp(d1, d2);
272 if (r != 0)
273 return r;
274 }
275
276 return strcasecmp(u->id, v->id);
277 }
278
279 static bool output_show_unit(const UnitInfo *u) {
280 const char *dot;
281
282 if (!strv_isempty(arg_states))
283 return
284 strv_contains(arg_states, u->load_state) ||
285 strv_contains(arg_states, u->sub_state) ||
286 strv_contains(arg_states, u->active_state);
287
288 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
289 strv_find(arg_types, dot+1))) &&
290 (arg_all || !(streq(u->active_state, "inactive")
291 || u->following[0]) || u->job_id > 0);
292 }
293
294 static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
295 unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
296 const UnitInfo *u;
297 unsigned n_shown = 0;
298 int job_count = 0;
299
300 max_id_len = sizeof("UNIT")-1;
301 load_len = sizeof("LOAD")-1;
302 active_len = sizeof("ACTIVE")-1;
303 sub_len = sizeof("SUB")-1;
304 job_len = sizeof("JOB")-1;
305 desc_len = 0;
306
307 for (u = unit_infos; u < unit_infos + c; u++) {
308 if (!output_show_unit(u))
309 continue;
310
311 max_id_len = MAX(max_id_len, strlen(u->id));
312 load_len = MAX(load_len, strlen(u->load_state));
313 active_len = MAX(active_len, strlen(u->active_state));
314 sub_len = MAX(sub_len, strlen(u->sub_state));
315
316 if (u->job_id != 0) {
317 job_len = MAX(job_len, strlen(u->job_type));
318 job_count++;
319 }
320 }
321
322 if (!arg_full && original_stdout_is_tty) {
323 unsigned basic_len;
324
325 id_len = MIN(max_id_len, 25u);
326 basic_len = 5 + id_len + 5 + active_len + sub_len;
327
328 if (job_count)
329 basic_len += job_len + 1;
330
331 if (basic_len < (unsigned) columns()) {
332 unsigned extra_len, incr;
333 extra_len = columns() - basic_len;
334
335 /* Either UNIT already got 25, or is fully satisfied.
336 * Grant up to 25 to DESC now. */
337 incr = MIN(extra_len, 25u);
338 desc_len += incr;
339 extra_len -= incr;
340
341 /* split the remaining space between UNIT and DESC,
342 * but do not give UNIT more than it needs. */
343 if (extra_len > 0) {
344 incr = MIN(extra_len / 2, max_id_len - id_len);
345 id_len += incr;
346 desc_len += extra_len - incr;
347 }
348 }
349 } else
350 id_len = max_id_len;
351
352 for (u = unit_infos; u < unit_infos + c; u++) {
353 _cleanup_free_ char *e = NULL;
354 const char *on_loaded, *off_loaded, *on = "";
355 const char *on_active, *off_active, *off = "";
356
357 if (!output_show_unit(u))
358 continue;
359
360 if (!n_shown && !arg_no_legend) {
361 printf("%-*s %-*s %-*s %-*s ",
362 id_len, "UNIT",
363 load_len, "LOAD",
364 active_len, "ACTIVE",
365 sub_len, "SUB");
366
367 if (job_count)
368 printf("%-*s ", job_len, "JOB");
369
370 if (!arg_full && arg_no_pager)
371 printf("%.*s\n", desc_len, "DESCRIPTION");
372 else
373 printf("%s\n", "DESCRIPTION");
374 }
375
376 n_shown++;
377
378 if (streq(u->load_state, "error") ||
379 streq(u->load_state, "not-found")) {
380 on_loaded = on = ansi_highlight_red();
381 off_loaded = off = ansi_highlight_off();
382 } else
383 on_loaded = off_loaded = "";
384
385 if (streq(u->active_state, "failed")) {
386 on_active = on = ansi_highlight_red();
387 off_active = off = ansi_highlight_off();
388 } else
389 on_active = off_active = "";
390
391 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
392
393 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
394 on, id_len, e ? e : u->id, off,
395 on_loaded, load_len, u->load_state, off_loaded,
396 on_active, active_len, u->active_state,
397 sub_len, u->sub_state, off_active,
398 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
399
400 if (desc_len > 0)
401 printf("%.*s\n", desc_len, u->description);
402 else
403 printf("%s\n", u->description);
404 }
405
406 if (!arg_no_legend) {
407 const char *on, *off;
408
409 if (n_shown) {
410 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
411 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
412 "SUB = The low-level unit activation state, values depend on unit type.\n");
413 if (job_count)
414 printf("JOB = Pending job for the unit.\n");
415 puts("");
416 on = ansi_highlight();
417 off = ansi_highlight_off();
418 } else {
419 on = ansi_highlight_red();
420 off = ansi_highlight_off();
421 }
422
423 if (arg_all)
424 printf("%s%u loaded units listed.%s\n"
425 "To show all installed unit files use 'systemctl list-unit-files'.\n",
426 on, n_shown, off);
427 else
428 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
429 "To show all installed unit files use 'systemctl list-unit-files'.\n",
430 on, n_shown, off);
431 }
432 }
433
434 static int get_unit_list(
435 sd_bus *bus,
436 sd_bus_message **_reply,
437 UnitInfo **_unit_infos) {
438
439 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
440 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
441 _cleanup_free_ UnitInfo *unit_infos = NULL;
442 size_t size = 0;
443 int r, c = 0;
444 UnitInfo u;
445
446 assert(bus);
447 assert(_reply);
448 assert(_unit_infos);
449
450 r = sd_bus_call_method(
451 bus,
452 "org.freedesktop.systemd1",
453 "/org/freedesktop/systemd1",
454 "org.freedesktop.systemd1.Manager",
455 "ListUnits",
456 &error,
457 &reply,
458 NULL);
459 if (r < 0) {
460 log_error("Failed to list units: %s", bus_error_message(&error, r));
461 return r;
462 }
463
464 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
465 if (r < 0)
466 return bus_log_parse_error(r);
467
468 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
469
470 if (!GREEDY_REALLOC(unit_infos, size, c+1))
471 return log_oom();
472
473 unit_infos[c++] = u;
474 }
475 if (r < 0)
476 return bus_log_parse_error(r);
477
478 r = sd_bus_message_exit_container(reply);
479 if (r < 0)
480 return bus_log_parse_error(r);
481
482 *_reply = reply;
483 reply = NULL;
484
485 *_unit_infos = unit_infos;
486 unit_infos = NULL;
487
488 return c;
489 }
490
491 static int list_units(sd_bus *bus, char **args) {
492 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
493 _cleanup_free_ UnitInfo *unit_infos = NULL;
494 int r;
495
496 pager_open_if_enabled();
497
498 r = get_unit_list(bus, &reply, &unit_infos);
499 if (r < 0)
500 return r;
501
502 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
503 output_units_list(unit_infos, r);
504
505 return 0;
506 }
507
508 static int get_triggered_units(
509 sd_bus *bus,
510 const char* path,
511 char*** ret) {
512
513 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
514 int r;
515
516 r = sd_bus_get_property_strv(
517 bus,
518 "org.freedesktop.systemd1",
519 path,
520 "org.freedesktop.systemd1.Unit",
521 "Triggers",
522 &error,
523 ret);
524
525 if (r < 0)
526 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
527
528 return 0;
529 }
530
531 static int get_listening(
532 sd_bus *bus,
533 const char* unit_path,
534 char*** listening) {
535
536 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
537 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
538 const char *type, *path;
539 int r, n = 0;
540
541 r = sd_bus_get_property(
542 bus,
543 "org.freedesktop.systemd1",
544 unit_path,
545 "org.freedesktop.systemd1.Socket",
546 "Listen",
547 &error,
548 &reply,
549 "a(ss)");
550 if (r < 0) {
551 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
552 return r;
553 }
554
555 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
556 if (r < 0)
557 return bus_log_parse_error(r);
558
559 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
560
561 r = strv_extend(listening, type);
562 if (r < 0)
563 return log_oom();
564
565 r = strv_extend(listening, path);
566 if (r < 0)
567 return log_oom();
568
569 n++;
570 }
571 if (r < 0)
572 return bus_log_parse_error(r);
573
574 r = sd_bus_message_exit_container(reply);
575 if (r < 0)
576 return bus_log_parse_error(r);
577
578 return n;
579 }
580
581 struct socket_info {
582 const char* id;
583
584 char* type;
585 char* path;
586
587 /* Note: triggered is a list here, although it almost certainly
588 * will always be one unit. Nevertheless, dbus API allows for multiple
589 * values, so let's follow that.*/
590 char** triggered;
591
592 /* The strv above is shared. free is set only in the first one. */
593 bool own_triggered;
594 };
595
596 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
597 int o;
598
599 assert(a);
600 assert(b);
601
602 o = strcmp(a->path, b->path);
603 if (o == 0)
604 o = strcmp(a->type, b->type);
605
606 return o;
607 }
608
609 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
610 struct socket_info *s;
611 unsigned pathlen = sizeof("LISTEN") - 1,
612 typelen = (sizeof("TYPE") - 1) * arg_show_types,
613 socklen = sizeof("UNIT") - 1,
614 servlen = sizeof("ACTIVATES") - 1;
615 const char *on, *off;
616
617 for (s = socket_infos; s < socket_infos + cs; s++) {
618 unsigned tmp = 0;
619 char **a;
620
621 socklen = MAX(socklen, strlen(s->id));
622 if (arg_show_types)
623 typelen = MAX(typelen, strlen(s->type));
624 pathlen = MAX(pathlen, strlen(s->path));
625
626 STRV_FOREACH(a, s->triggered)
627 tmp += strlen(*a) + 2*(a != s->triggered);
628 servlen = MAX(servlen, tmp);
629 }
630
631 if (cs) {
632 if (!arg_no_legend)
633 printf("%-*s %-*.*s%-*s %s\n",
634 pathlen, "LISTEN",
635 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
636 socklen, "UNIT",
637 "ACTIVATES");
638
639 for (s = socket_infos; s < socket_infos + cs; s++) {
640 char **a;
641
642 if (arg_show_types)
643 printf("%-*s %-*s %-*s",
644 pathlen, s->path, typelen, s->type, socklen, s->id);
645 else
646 printf("%-*s %-*s",
647 pathlen, s->path, socklen, s->id);
648 STRV_FOREACH(a, s->triggered)
649 printf("%s %s",
650 a == s->triggered ? "" : ",", *a);
651 printf("\n");
652 }
653
654 on = ansi_highlight();
655 off = ansi_highlight_off();
656 if (!arg_no_legend)
657 printf("\n");
658 } else {
659 on = ansi_highlight_red();
660 off = ansi_highlight_off();
661 }
662
663 if (!arg_no_legend) {
664 printf("%s%u sockets listed.%s\n", on, cs, off);
665 if (!arg_all)
666 printf("Pass --all to see loaded but inactive sockets, too.\n");
667 }
668
669 return 0;
670 }
671
672 static int list_sockets(sd_bus *bus, char **args) {
673 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
674 _cleanup_free_ UnitInfo *unit_infos = NULL;
675 struct socket_info *socket_infos = NULL;
676 const UnitInfo *u;
677 struct socket_info *s;
678 unsigned cs = 0;
679 size_t size = 0;
680 int r = 0, n;
681
682 pager_open_if_enabled();
683
684 n = get_unit_list(bus, &reply, &unit_infos);
685 if (n < 0)
686 return n;
687
688 for (u = unit_infos; u < unit_infos + n; u++) {
689 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
690 int i, c;
691
692 if (!output_show_unit(u))
693 continue;
694
695 if (!endswith(u->id, ".socket"))
696 continue;
697
698 r = get_triggered_units(bus, u->unit_path, &triggered);
699 if (r < 0)
700 goto cleanup;
701
702 c = get_listening(bus, u->unit_path, &listening);
703 if (c < 0) {
704 r = c;
705 goto cleanup;
706 }
707
708 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
709 r = log_oom();
710 goto cleanup;
711 }
712
713 for (i = 0; i < c; i++)
714 socket_infos[cs + i] = (struct socket_info) {
715 .id = u->id,
716 .type = listening[i*2],
717 .path = listening[i*2 + 1],
718 .triggered = triggered,
719 .own_triggered = i==0,
720 };
721
722 /* from this point on we will cleanup those socket_infos */
723 cs += c;
724 free(listening);
725 listening = triggered = NULL; /* avoid cleanup */
726 }
727
728 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
729 (__compar_fn_t) socket_info_compare);
730
731 output_sockets_list(socket_infos, cs);
732
733 cleanup:
734 assert(cs == 0 || socket_infos);
735 for (s = socket_infos; s < socket_infos + cs; s++) {
736 free(s->type);
737 free(s->path);
738 if (s->own_triggered)
739 strv_free(s->triggered);
740 }
741 free(socket_infos);
742
743 return r;
744 }
745
746 static int get_next_elapse(
747 sd_bus *bus,
748 const char *path,
749 dual_timestamp *next) {
750
751 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
752 dual_timestamp t;
753 int r;
754
755 assert(bus);
756 assert(path);
757 assert(next);
758
759 r = sd_bus_get_property_trivial(
760 bus,
761 "org.freedesktop.systemd1",
762 path,
763 "org.freedesktop.systemd1.Timer",
764 "NextElapseUSecMonotonic",
765 &error,
766 't',
767 &t.monotonic);
768 if (r < 0) {
769 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
770 return r;
771 }
772
773 r = sd_bus_get_property_trivial(
774 bus,
775 "org.freedesktop.systemd1",
776 path,
777 "org.freedesktop.systemd1.Timer",
778 "NextElapseUSecRealtime",
779 &error,
780 't',
781 &t.realtime);
782 if (r < 0) {
783 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
784 return r;
785 }
786
787 *next = t;
788 return 0;
789 }
790
791 struct timer_info {
792 const char* id;
793 usec_t next_elapse;
794 char** triggered;
795 };
796
797 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
798 assert(a);
799 assert(b);
800
801 if (a->next_elapse < b->next_elapse)
802 return -1;
803 if (a->next_elapse > b->next_elapse)
804 return 1;
805
806 return strcmp(a->id, b->id);
807 }
808
809 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
810 struct timer_info *t;
811 unsigned
812 nextlen = sizeof("NEXT") - 1,
813 leftlen = sizeof("LEFT") - 1,
814 unitlen = sizeof("UNIT") - 1,
815 activatelen = sizeof("ACTIVATES") - 1;
816
817 const char *on, *off;
818
819 assert(timer_infos || n == 0);
820
821 for (t = timer_infos; t < timer_infos + n; t++) {
822 unsigned ul = 0;
823 char **a;
824
825 if (t->next_elapse > 0) {
826 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
827
828 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
829 nextlen = MAX(nextlen, strlen(tstamp) + 1);
830
831 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
832 leftlen = MAX(leftlen, strlen(trel));
833 }
834
835 unitlen = MAX(unitlen, strlen(t->id));
836
837 STRV_FOREACH(a, t->triggered)
838 ul += strlen(*a) + 2*(a != t->triggered);
839 activatelen = MAX(activatelen, ul);
840 }
841
842 if (n > 0) {
843 if (!arg_no_legend)
844 printf("%-*s %-*s %-*s %s\n",
845 nextlen, "NEXT",
846 leftlen, "LEFT",
847 unitlen, "UNIT",
848 "ACTIVATES");
849
850 for (t = timer_infos; t < timer_infos + n; t++) {
851 char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
852 char **a;
853
854 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
855 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
856
857 printf("%-*s %-*s %-*s",
858 nextlen, tstamp, leftlen, trel, unitlen, t->id);
859
860 STRV_FOREACH(a, t->triggered)
861 printf("%s %s",
862 a == t->triggered ? "" : ",", *a);
863 printf("\n");
864 }
865
866 on = ansi_highlight();
867 off = ansi_highlight_off();
868 if (!arg_no_legend)
869 printf("\n");
870 } else {
871 on = ansi_highlight_red();
872 off = ansi_highlight_off();
873 }
874
875 if (!arg_no_legend) {
876 printf("%s%u timers listed.%s\n", on, n, off);
877 if (!arg_all)
878 printf("Pass --all to see loaded but inactive timers, too.\n");
879 }
880
881 return 0;
882 }
883
884 static int list_timers(sd_bus *bus, char **args) {
885
886 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
887 _cleanup_free_ struct timer_info *timer_infos = NULL;
888 _cleanup_free_ UnitInfo *unit_infos = NULL;
889 struct timer_info *t;
890 const UnitInfo *u;
891 size_t size = 0;
892 int n, c = 0;
893 dual_timestamp nw;
894 int r = 0;
895
896 pager_open_if_enabled();
897
898 n = get_unit_list(bus, &reply, &unit_infos);
899 if (n < 0)
900 return n;
901
902 dual_timestamp_get(&nw);
903
904 for (u = unit_infos; u < unit_infos + n; u++) {
905 _cleanup_strv_free_ char **triggered = NULL;
906 dual_timestamp next;
907 usec_t m;
908
909 if (!output_show_unit(u))
910 continue;
911
912 if (!endswith(u->id, ".timer"))
913 continue;
914
915 r = get_triggered_units(bus, u->unit_path, &triggered);
916 if (r < 0)
917 goto cleanup;
918
919 r = get_next_elapse(bus, u->unit_path, &next);
920 if (r < 0)
921 goto cleanup;
922
923 if (next.monotonic != (usec_t) -1 && next.monotonic > 0) {
924 usec_t converted;
925
926 if (next.monotonic > nw.monotonic)
927 converted = nw.realtime + (next.monotonic - nw.monotonic);
928 else
929 converted = nw.realtime - (nw.monotonic - next.monotonic);
930
931 if (next.realtime != (usec_t) -1 && next.realtime > 0)
932 m = MIN(converted, next.realtime);
933 else
934 m = converted;
935 } else
936 m = next.realtime;
937
938 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
939 r = log_oom();
940 goto cleanup;
941 }
942
943 timer_infos[c++] = (struct timer_info) {
944 .id = u->id,
945 .next_elapse = m,
946 .triggered = triggered,
947 };
948
949 triggered = NULL; /* avoid cleanup */
950 }
951
952 qsort_safe(timer_infos, c, sizeof(struct timer_info),
953 (__compar_fn_t) timer_info_compare);
954
955 output_timers_list(timer_infos, c);
956
957 cleanup:
958 for (t = timer_infos; t < timer_infos + c; t++)
959 strv_free(t->triggered);
960
961 return r;
962 }
963
964 static int compare_unit_file_list(const void *a, const void *b) {
965 const char *d1, *d2;
966 const UnitFileList *u = a, *v = b;
967
968 d1 = strrchr(u->path, '.');
969 d2 = strrchr(v->path, '.');
970
971 if (d1 && d2) {
972 int r;
973
974 r = strcasecmp(d1, d2);
975 if (r != 0)
976 return r;
977 }
978
979 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
980 }
981
982 static bool output_show_unit_file(const UnitFileList *u) {
983 const char *dot;
984
985 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
986 }
987
988 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
989 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
990 const UnitFileList *u;
991
992 max_id_len = sizeof("UNIT FILE")-1;
993 state_cols = sizeof("STATE")-1;
994
995 for (u = units; u < units + c; u++) {
996 if (!output_show_unit_file(u))
997 continue;
998
999 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
1000 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1001 }
1002
1003 if (!arg_full) {
1004 unsigned basic_cols;
1005
1006 id_cols = MIN(max_id_len, 25u);
1007 basic_cols = 1 + id_cols + state_cols;
1008 if (basic_cols < (unsigned) columns())
1009 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1010 } else
1011 id_cols = max_id_len;
1012
1013 if (!arg_no_legend)
1014 printf("%-*s %-*s\n",
1015 id_cols, "UNIT FILE",
1016 state_cols, "STATE");
1017
1018 for (u = units; u < units + c; u++) {
1019 _cleanup_free_ char *e = NULL;
1020 const char *on, *off;
1021 const char *id;
1022
1023 if (!output_show_unit_file(u))
1024 continue;
1025
1026 n_shown++;
1027
1028 if (u->state == UNIT_FILE_MASKED ||
1029 u->state == UNIT_FILE_MASKED_RUNTIME ||
1030 u->state == UNIT_FILE_DISABLED ||
1031 u->state == UNIT_FILE_INVALID) {
1032 on = ansi_highlight_red();
1033 off = ansi_highlight_off();
1034 } else if (u->state == UNIT_FILE_ENABLED) {
1035 on = ansi_highlight_green();
1036 off = ansi_highlight_off();
1037 } else
1038 on = off = "";
1039
1040 id = path_get_file_name(u->path);
1041
1042 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1043
1044 printf("%-*s %s%-*s%s\n",
1045 id_cols, e ? e : id,
1046 on, state_cols, unit_file_state_to_string(u->state), off);
1047 }
1048
1049 if (!arg_no_legend)
1050 printf("\n%u unit files listed.\n", n_shown);
1051 }
1052
1053 static int list_unit_files(sd_bus *bus, char **args) {
1054 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1055 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1056 _cleanup_free_ UnitFileList *units = NULL;
1057 unsigned c = 0;
1058 const char *state;
1059 char *path;
1060 int r;
1061
1062 pager_open_if_enabled();
1063
1064 if (avoid_bus()) {
1065 Hashmap *h;
1066 UnitFileList *u;
1067 Iterator i;
1068 unsigned n_units;
1069
1070 h = hashmap_new(string_hash_func, string_compare_func);
1071 if (!h)
1072 return log_oom();
1073
1074 r = unit_file_get_list(arg_scope, arg_root, h);
1075 if (r < 0) {
1076 unit_file_list_free(h);
1077 log_error("Failed to get unit file list: %s", strerror(-r));
1078 return r;
1079 }
1080
1081 n_units = hashmap_size(h);
1082 units = new(UnitFileList, n_units);
1083 if (!units) {
1084 unit_file_list_free(h);
1085 return log_oom();
1086 }
1087
1088 HASHMAP_FOREACH(u, h, i) {
1089 memcpy(units + c++, u, sizeof(UnitFileList));
1090 free(u);
1091 }
1092
1093 assert(c == n_units);
1094 hashmap_free(h);
1095 } else {
1096 size_t size = 0;
1097
1098 r = sd_bus_call_method(
1099 bus,
1100 "org.freedesktop.systemd1",
1101 "/org/freedesktop/systemd1",
1102 "org.freedesktop.systemd1.Manager",
1103 "ListUnitFiles",
1104 &error,
1105 &reply,
1106 NULL);
1107 if (r < 0) {
1108 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1109 return r;
1110 }
1111
1112 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1113 if (r < 0)
1114 return bus_log_parse_error(r);
1115
1116 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1117
1118 if (!GREEDY_REALLOC(units, size, c + 1))
1119 return log_oom();
1120
1121 units[c++] = (struct UnitFileList) {
1122 path,
1123 unit_file_state_from_string(state)
1124 };
1125 }
1126 if (r < 0)
1127 return bus_log_parse_error(r);
1128
1129 r = sd_bus_message_exit_container(reply);
1130 if (r < 0)
1131 return bus_log_parse_error(r);
1132 }
1133
1134 if (c > 0) {
1135 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1136 output_unit_file_list(units, c);
1137 }
1138
1139 return 0;
1140 }
1141
1142 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1143 _cleanup_free_ char *n = NULL;
1144 size_t max_len = MAX(columns(),20u);
1145 size_t len = 0;
1146 int i;
1147
1148 if (!arg_plain) {
1149
1150 for (i = level - 1; i >= 0; i--) {
1151 len += 2;
1152 if(len > max_len - 3 && !arg_full) {
1153 printf("%s...\n",max_len % 2 ? "" : " ");
1154 return 0;
1155 }
1156 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1157 }
1158 len += 2;
1159
1160 if(len > max_len - 3 && !arg_full) {
1161 printf("%s...\n",max_len % 2 ? "" : " ");
1162 return 0;
1163 }
1164
1165 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1166 }
1167
1168 if (arg_full){
1169 printf("%s\n", name);
1170 return 0;
1171 }
1172
1173 n = ellipsize(name, max_len-len, 100);
1174 if(!n)
1175 return log_oom();
1176
1177 printf("%s\n", n);
1178 return 0;
1179 }
1180
1181 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1182
1183 static const char *dependencies[] = {
1184 [DEPENDENCY_FORWARD] = "Requires\0"
1185 "RequiresOverridable\0"
1186 "Requisite\0"
1187 "RequisiteOverridable\0"
1188 "Wants\0",
1189 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1190 "RequiredByOverridable\0"
1191 "WantedBy\0"
1192 "PartOf\0",
1193 [DEPENDENCY_AFTER] = "After\0",
1194 [DEPENDENCY_BEFORE] = "Before\0",
1195 };
1196
1197 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1198 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1199 _cleanup_strv_free_ char **ret = NULL;
1200 _cleanup_free_ char *path = NULL;
1201 int r;
1202
1203 assert(bus);
1204 assert(name);
1205 assert(deps);
1206 assert(arg_dependency < ELEMENTSOF(dependencies));
1207
1208 path = unit_dbus_path_from_name(name);
1209 if (!path)
1210 return log_oom();
1211
1212 r = sd_bus_call_method(
1213 bus,
1214 "org.freedesktop.systemd1",
1215 path,
1216 "org.freedesktop.DBus.Properties",
1217 "GetAll",
1218 &error,
1219 &reply,
1220 "s", "org.freedesktop.systemd1.Unit");
1221 if (r < 0) {
1222 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1223 return r;
1224 }
1225
1226 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1227 if (r < 0)
1228 return bus_log_parse_error(r);
1229
1230 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1231 const char *prop;
1232
1233 r = sd_bus_message_read(reply, "s", &prop);
1234 if (r < 0)
1235 return bus_log_parse_error(r);
1236
1237 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1238 r = sd_bus_message_skip(reply, "v");
1239 if (r < 0)
1240 return bus_log_parse_error(r);
1241 } else {
1242
1243 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1244 if (r < 0)
1245 return bus_log_parse_error(r);
1246
1247 r = bus_message_read_strv_extend(reply, &ret);
1248 if (r < 0)
1249 return bus_log_parse_error(r);
1250
1251 r = sd_bus_message_exit_container(reply);
1252 if (r < 0)
1253 return bus_log_parse_error(r);
1254 }
1255
1256 r = sd_bus_message_exit_container(reply);
1257 if (r < 0)
1258 return bus_log_parse_error(r);
1259
1260 }
1261 if (r < 0)
1262 return bus_log_parse_error(r);
1263
1264 r = sd_bus_message_exit_container(reply);
1265 if (r < 0)
1266 return bus_log_parse_error(r);
1267
1268 *deps = ret;
1269 ret = NULL;
1270
1271 return 0;
1272 }
1273
1274 static int list_dependencies_compare(const void *_a, const void *_b) {
1275 const char **a = (const char**) _a, **b = (const char**) _b;
1276
1277 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1278 return 1;
1279 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1280 return -1;
1281
1282 return strcasecmp(*a, *b);
1283 }
1284
1285 static int list_dependencies_one(
1286 sd_bus *bus,
1287 const char *name,
1288 int level,
1289 char ***units,
1290 unsigned int branches) {
1291
1292 _cleanup_strv_free_ char **deps = NULL, **u;
1293 char **c;
1294 int r = 0;
1295
1296 assert(bus);
1297 assert(name);
1298 assert(units);
1299
1300 u = strv_append(*units, name);
1301 if (!u)
1302 return log_oom();
1303
1304 r = list_dependencies_get_dependencies(bus, name, &deps);
1305 if (r < 0)
1306 return r;
1307
1308 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1309
1310 STRV_FOREACH(c, deps) {
1311 if (strv_contains(u, *c)) {
1312 if (!arg_plain) {
1313 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1314 if (r < 0)
1315 return r;
1316 }
1317 continue;
1318 }
1319
1320 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1321 if (r < 0)
1322 return r;
1323
1324 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1325 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1326 if(r < 0)
1327 return r;
1328 }
1329 }
1330
1331 if (arg_plain) {
1332 strv_free(*units);
1333 *units = u;
1334 u = NULL;
1335 }
1336
1337 return 0;
1338 }
1339
1340 static int list_dependencies(sd_bus *bus, char **args) {
1341 _cleanup_strv_free_ char **units = NULL;
1342 _cleanup_free_ char *unit = NULL;
1343 const char *u;
1344
1345 assert(bus);
1346
1347 if (args[1]) {
1348 unit = unit_name_mangle(args[1]);
1349 if (!unit)
1350 return log_oom();
1351 u = unit;
1352 } else
1353 u = SPECIAL_DEFAULT_TARGET;
1354
1355 pager_open_if_enabled();
1356
1357 puts(u);
1358
1359 return list_dependencies_one(bus, u, 0, &units, 0);
1360 }
1361
1362 static int get_default(sd_bus *bus, char **args) {
1363 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1364 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1365 _cleanup_free_ char *_path = NULL;
1366 const char *path;
1367 int r;
1368
1369 if (!bus || avoid_bus()) {
1370 r = unit_file_get_default(arg_scope, arg_root, &_path);
1371 if (r < 0) {
1372 log_error("Failed to get default target: %s", strerror(-r));
1373 return r;
1374 }
1375 path = _path;
1376
1377 } else {
1378 r = sd_bus_call_method(
1379 bus,
1380 "org.freedesktop.systemd1",
1381 "/org/freedesktop/systemd1",
1382 "org.freedesktop.systemd1.Manager",
1383 "GetDefaultTarget",
1384 &error,
1385 &reply,
1386 NULL);
1387 if (r < 0) {
1388 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1389 return r;
1390 }
1391
1392 r = sd_bus_message_read(reply, "s", &path);
1393 if (r < 0)
1394 return bus_log_parse_error(r);
1395 }
1396
1397 if (path)
1398 printf("%s\n", path);
1399
1400 return 0;
1401 }
1402
1403 struct job_info {
1404 uint32_t id;
1405 const char *name, *type, *state;
1406 };
1407
1408 static void output_jobs_list(const struct job_info* jobs, unsigned n) {
1409 unsigned id_len, unit_len, type_len, state_len;
1410 const struct job_info *j;
1411 const char *on, *off;
1412 bool shorten = false;
1413
1414 assert(n == 0 || jobs);
1415
1416 if (n == 0) {
1417 on = ansi_highlight_green();
1418 off = ansi_highlight_off();
1419
1420 printf("%sNo jobs running.%s\n", on, off);
1421 return;
1422 }
1423
1424 pager_open_if_enabled();
1425
1426 id_len = sizeof("JOB")-1;
1427 unit_len = sizeof("UNIT")-1;
1428 type_len = sizeof("TYPE")-1;
1429 state_len = sizeof("STATE")-1;
1430
1431 for (j = jobs; j < jobs + n; j++) {
1432 uint32_t id = j->id;
1433 assert(j->name && j->type && j->state);
1434
1435 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1436 unit_len = MAX(unit_len, strlen(j->name));
1437 type_len = MAX(type_len, strlen(j->type));
1438 state_len = MAX(state_len, strlen(j->state));
1439 }
1440
1441 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1442 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1443 shorten = true;
1444 }
1445
1446 if (!arg_no_legend)
1447 printf("%*s %-*s %-*s %-*s\n",
1448 id_len, "JOB",
1449 unit_len, "UNIT",
1450 type_len, "TYPE",
1451 state_len, "STATE");
1452
1453 for (j = jobs; j < jobs + n; j++) {
1454 _cleanup_free_ char *e = NULL;
1455
1456 if (streq(j->state, "running")) {
1457 on = ansi_highlight();
1458 off = ansi_highlight_off();
1459 } else
1460 on = off = "";
1461
1462 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1463 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1464 id_len, j->id,
1465 on, unit_len, e ? e : j->name, off,
1466 type_len, j->type,
1467 on, state_len, j->state, off);
1468 }
1469
1470 if (!arg_no_legend) {
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
1478 static int list_jobs(sd_bus *bus, char **args) {
1479 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1480 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1481 const char *name, *type, *state, *job_path, *unit_path;
1482 _cleanup_free_ struct job_info *jobs = NULL;
1483 size_t size = 0;
1484 unsigned c = 0;
1485 uint32_t id;
1486 int r;
1487
1488 r = sd_bus_call_method(
1489 bus,
1490 "org.freedesktop.systemd1",
1491 "/org/freedesktop/systemd1",
1492 "org.freedesktop.systemd1.Manager",
1493 "ListJobs",
1494 &error,
1495 &reply,
1496 NULL);
1497 if (r < 0) {
1498 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
1499 return r;
1500 }
1501
1502 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
1503 if (r < 0)
1504 return bus_log_parse_error(r);
1505
1506 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
1507
1508 if (!GREEDY_REALLOC(jobs, size, c + 1))
1509 return log_oom();
1510
1511 jobs[c++] = (struct job_info) {
1512 id,
1513 name,
1514 type,
1515 state
1516 };
1517 }
1518 if (r < 0)
1519 return bus_log_parse_error(r);
1520
1521 r = sd_bus_message_exit_container(reply);
1522 if (r < 0)
1523 return bus_log_parse_error(r);
1524
1525 output_jobs_list(jobs, c);
1526 return r;
1527 }
1528
1529 static int cancel_job(sd_bus *bus, char **args) {
1530 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1531 char **name;
1532
1533 assert(args);
1534
1535 if (strv_length(args) <= 1)
1536 return daemon_reload(bus, args);
1537
1538 STRV_FOREACH(name, args+1) {
1539 uint32_t id;
1540 int r;
1541
1542 r = safe_atou32(*name, &id);
1543 if (r < 0) {
1544 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
1545 return r;
1546 }
1547
1548 r = sd_bus_call_method(
1549 bus,
1550 "org.freedesktop.systemd1",
1551 "/org/freedesktop/systemd1",
1552 "org.freedesktop.systemd1.Manager",
1553 "CancelJob",
1554 &error,
1555 NULL,
1556 "u", id);
1557 if (r < 0) {
1558 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
1559 return r;
1560 }
1561 }
1562
1563 return 0;
1564 }
1565
1566 static int need_daemon_reload(sd_bus *bus, const char *unit) {
1567 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1568 _cleanup_free_ char *n = NULL;
1569 const char *path;
1570 int b, r;
1571
1572 /* We ignore all errors here, since this is used to show a
1573 * warning only */
1574
1575 n = unit_name_mangle(unit);
1576 if (!n)
1577 return -ENOMEM;
1578
1579 /* We don't use unit_dbus_path_from_name() directly since we
1580 * don't want to load the unit if it isn't loaded. */
1581
1582 r = sd_bus_call_method(
1583 bus,
1584 "org.freedesktop.systemd1",
1585 "/org/freedesktop/systemd1",
1586 "org.freedesktop.systemd1.Manager",
1587 "GetUnit",
1588 NULL,
1589 &reply,
1590 "s", n);
1591 if (r < 0)
1592 return r;
1593
1594 r = sd_bus_message_read(reply, "o", &path);
1595 if (r < 0)
1596 return r;
1597
1598 r = sd_bus_get_property_trivial(
1599 bus,
1600 "org.freedesktop.systemd1",
1601 path,
1602 "org.freedesktop.systemd1.Unit",
1603 "NeedDaemonReload",
1604 NULL,
1605 'b', &b);
1606 if (r < 0)
1607 return r;
1608
1609 return b;
1610 }
1611
1612 typedef struct WaitData {
1613 Set *set;
1614
1615 char *name;
1616 char *result;
1617 } WaitData;
1618
1619 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data) {
1620 WaitData *d = data;
1621
1622 assert(bus);
1623 assert(m);
1624 assert(d);
1625
1626 log_debug("Got D-Bus request: %s.%s() on %s",
1627 sd_bus_message_get_interface(m),
1628 sd_bus_message_get_member(m),
1629 sd_bus_message_get_path(m));
1630
1631 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1632 log_error("Warning! D-Bus connection terminated.");
1633 sd_bus_close(bus);
1634 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1635 uint32_t id;
1636 const char *path, *result, *unit;
1637 char *ret;
1638 int r;
1639
1640 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1641 if (r >= 0) {
1642 ret = set_remove(d->set, (char*) path);
1643 if (!ret)
1644 return 0;
1645
1646 free(ret);
1647
1648 if (!isempty(result))
1649 d->result = strdup(result);
1650
1651 if (!isempty(unit))
1652 d->name = strdup(unit);
1653
1654 return 0;
1655 }
1656 #ifndef NOLEGACY
1657 r = sd_bus_message_read(m, "uos", &id, &path, &result);
1658 if (r >= 0) {
1659 ret = set_remove(d->set, (char*) path);
1660 if (!ret)
1661 return 0;
1662
1663 free(ret);
1664
1665 if (*result)
1666 d->result = strdup(result);
1667
1668 return 0;
1669 }
1670 #endif
1671
1672 log_error("Failed to parse message.");
1673 }
1674
1675 return 0;
1676 }
1677
1678 static int enable_wait_for_jobs(sd_bus *bus) {
1679 int r;
1680
1681 assert(bus);
1682
1683 r = sd_bus_add_match(
1684 bus,
1685 "type='signal',"
1686 "sender='org.freedesktop.systemd1',"
1687 "interface='org.freedesktop.systemd1.Manager',"
1688 "member='JobRemoved',"
1689 "path='/org/freedesktop/systemd1'",
1690 NULL, NULL);
1691 if (r < 0) {
1692 log_error("Failed to add match");
1693 return -EIO;
1694 }
1695
1696 /* This is slightly dirty, since we don't undo the match registrations. */
1697 return 0;
1698 }
1699
1700 static int wait_for_jobs(sd_bus *bus, Set *s) {
1701 WaitData d = { .set = s };
1702 int r;
1703
1704 assert(bus);
1705 assert(s);
1706
1707 r = sd_bus_add_filter(bus, wait_filter, &d);
1708 if (r < 0)
1709 return log_oom();
1710
1711 while (!set_isempty(s)) {
1712 for(;;) {
1713 r = sd_bus_process(bus, NULL);
1714 if (r < 0)
1715 return r;
1716 if (r > 0)
1717 break;
1718 r = sd_bus_wait(bus, (uint64_t) -1);
1719 if (r < 0)
1720 return r;
1721 }
1722
1723 if (!d.result)
1724 goto free_name;
1725
1726 if (!arg_quiet) {
1727 if (streq(d.result, "timeout"))
1728 log_error("Job for %s timed out.", strna(d.name));
1729 else if (streq(d.result, "canceled"))
1730 log_error("Job for %s canceled.", strna(d.name));
1731 else if (streq(d.result, "dependency"))
1732 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1733 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1734 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1735 }
1736
1737 if (streq_ptr(d.result, "timeout"))
1738 r = -ETIME;
1739 else if (streq_ptr(d.result, "canceled"))
1740 r = -ECANCELED;
1741 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1742 r = -EIO;
1743
1744 free(d.result);
1745 d.result = NULL;
1746
1747 free_name:
1748 free(d.name);
1749 d.name = NULL;
1750 }
1751
1752 return sd_bus_remove_filter(bus, wait_filter, &d);
1753 }
1754
1755 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
1756 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1757 _cleanup_free_ char *n = NULL, *state = NULL;
1758 const char *path;
1759 int r;
1760
1761 assert(name);
1762
1763 n = unit_name_mangle(name);
1764 if (!n)
1765 return log_oom();
1766
1767 /* We don't use unit_dbus_path_from_name() directly since we
1768 * don't want to load the unit if it isn't loaded. */
1769
1770 r = sd_bus_call_method(
1771 bus,
1772 "org.freedesktop.systemd1",
1773 "/org/freedesktop/systemd1",
1774 "org.freedesktop.systemd1.Manager",
1775 "GetUnit",
1776 NULL,
1777 &reply,
1778 "s", n);
1779 if (r < 0) {
1780 if (!quiet)
1781 puts("unknown");
1782 return 0;
1783 }
1784
1785 r = sd_bus_message_read(reply, "o", &path);
1786 if (r < 0)
1787 return bus_log_parse_error(r);
1788
1789 r = sd_bus_get_property_string(
1790 bus,
1791 "org.freedesktop.systemd1",
1792 path,
1793 "org.freedesktop.systemd1.Unit",
1794 "ActiveState",
1795 NULL,
1796 &state);
1797 if (r < 0) {
1798 if (!quiet)
1799 puts("unknown");
1800 return 0;
1801 }
1802
1803 if (!quiet)
1804 puts(state);
1805
1806 return nulstr_contains(good_states, state);
1807 }
1808
1809 static int check_triggering_units(
1810 sd_bus *bus,
1811 const char *name) {
1812
1813 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1814 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
1815 _cleanup_strv_free_ char **triggered_by = NULL;
1816 bool print_warning_label = true;
1817 char **i;
1818 int r;
1819
1820 n = unit_name_mangle(name);
1821 if (!n)
1822 return log_oom();
1823
1824 path = unit_dbus_path_from_name(n);
1825 if (!path)
1826 return log_oom();
1827
1828 r = sd_bus_get_property_string(
1829 bus,
1830 "org.freedesktop.systemd1",
1831 path,
1832 "org.freedesktop.systemd1.Unit",
1833 "LoadState",
1834 &error,
1835 &state);
1836 if (r < 0) {
1837 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
1838 return r;
1839 }
1840
1841 if (streq(state, "masked"))
1842 return 0;
1843
1844 r = sd_bus_get_property_strv(
1845 bus,
1846 "org.freedesktop.systemd1",
1847 path,
1848 "org.freedesktop.systemd1.Unit",
1849 "TriggeredBy",
1850 &error,
1851 &triggered_by);
1852 if (r < 0) {
1853 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
1854 return r;
1855 }
1856
1857 STRV_FOREACH(i, triggered_by) {
1858 r = check_one_unit(bus, *i, "active\0reloading\0", true);
1859 if (r < 0) {
1860 log_error("Failed to check unit: %s", strerror(-r));
1861 return r;
1862 }
1863
1864 if (r == 0)
1865 continue;
1866
1867 if (print_warning_label) {
1868 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
1869 print_warning_label = false;
1870 }
1871
1872 log_warning(" %s", *i);
1873 }
1874
1875 return 0;
1876 }
1877
1878 static int start_unit_one(
1879 sd_bus *bus,
1880 const char *method,
1881 const char *name,
1882 const char *mode,
1883 sd_bus_error *error,
1884 Set *s) {
1885
1886 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1887 _cleanup_free_ char *n;
1888 const char *path;
1889 int r;
1890
1891 assert(method);
1892 assert(name);
1893 assert(mode);
1894 assert(error);
1895
1896 n = unit_name_mangle(name);
1897 if (!n)
1898 return log_oom();
1899
1900 r = sd_bus_call_method(
1901 bus,
1902 "org.freedesktop.systemd1",
1903 "/org/freedesktop/systemd1",
1904 "org.freedesktop.systemd1.Manager",
1905 method,
1906 error,
1907 &reply,
1908 "ss", n, mode);
1909 if (r < 0) {
1910 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1911 /* There's always a fallback possible for
1912 * legacy actions. */
1913 return -EADDRNOTAVAIL;
1914
1915 log_error("Failed to start %s: %s", name, bus_error_message(error, r));
1916 return r;
1917 }
1918
1919 r = sd_bus_message_read(reply, "o", &path);
1920 if (r < 0)
1921 return bus_log_parse_error(r);
1922
1923 if (need_daemon_reload(bus, n) > 0)
1924 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
1925 n, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
1926
1927 if (s) {
1928 char *p;
1929
1930 p = strdup(path);
1931 if (!p)
1932 return log_oom();
1933
1934 r = set_consume(s, p);
1935 if (r < 0)
1936 return log_oom();
1937 }
1938
1939 return 0;
1940 }
1941
1942 static const struct {
1943 const char *target;
1944 const char *verb;
1945 const char *mode;
1946 } action_table[_ACTION_MAX] = {
1947 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1948 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1949 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1950 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1951 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1952 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1953 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1954 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1955 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1956 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1957 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1958 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1959 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1960 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1961 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1962 };
1963
1964 static enum action verb_to_action(const char *verb) {
1965 enum action i;
1966
1967 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
1968 if (streq_ptr(action_table[i].verb, verb))
1969 return i;
1970
1971 return _ACTION_INVALID;
1972 }
1973
1974 static int start_unit(sd_bus *bus, char **args) {
1975 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1976 _cleanup_set_free_free_ Set *s = NULL;
1977 const char *method, *mode, *one_name;
1978 char **name;
1979 int r;
1980
1981 assert(bus);
1982
1983 ask_password_agent_open_if_enabled();
1984
1985 if (arg_action == ACTION_SYSTEMCTL) {
1986 enum action action;
1987 method =
1988 streq(args[0], "stop") ||
1989 streq(args[0], "condstop") ? "StopUnit" :
1990 streq(args[0], "reload") ? "ReloadUnit" :
1991 streq(args[0], "restart") ? "RestartUnit" :
1992
1993 streq(args[0], "try-restart") ||
1994 streq(args[0], "condrestart") ? "TryRestartUnit" :
1995
1996 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1997
1998 streq(args[0], "reload-or-try-restart") ||
1999 streq(args[0], "condreload") ||
2000 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
2001 "StartUnit";
2002 action = verb_to_action(args[0]);
2003
2004 mode = streq(args[0], "isolate") ? "isolate" :
2005 action_table[action].mode ?: arg_job_mode;
2006
2007 one_name = action_table[action].target;
2008 } else {
2009 assert(arg_action < ELEMENTSOF(action_table));
2010 assert(action_table[arg_action].target);
2011
2012 method = "StartUnit";
2013
2014 mode = action_table[arg_action].mode;
2015 one_name = action_table[arg_action].target;
2016 }
2017
2018 if (!arg_no_block) {
2019 r = enable_wait_for_jobs(bus);
2020 if (r < 0) {
2021 log_error("Could not watch jobs: %s", strerror(-r));
2022 return r;
2023 }
2024
2025 s = set_new(string_hash_func, string_compare_func);
2026 if (!s)
2027 return log_oom();
2028 }
2029
2030 if (one_name) {
2031 r = start_unit_one(bus, method, one_name, mode, &error, s);
2032 if (r < 0)
2033 r = translate_bus_error_to_exit_status(r, &error);
2034 } else {
2035 r = 0;
2036
2037 STRV_FOREACH(name, args+1) {
2038 int q;
2039
2040 q = start_unit_one(bus, method, *name, mode, &error, s);
2041 if (q < 0) {
2042 r = translate_bus_error_to_exit_status(r, &error);
2043 sd_bus_error_free(&error);
2044 }
2045 }
2046 }
2047
2048 if (!arg_no_block) {
2049 int q;
2050
2051 q = wait_for_jobs(bus, s);
2052 if (q < 0)
2053 return q;
2054
2055 /* When stopping units, warn if they can still be triggered by
2056 * another active unit (socket, path, timer) */
2057 if (!arg_quiet && streq(method, "StopUnit")) {
2058 if (one_name)
2059 check_triggering_units(bus, one_name);
2060 else
2061 STRV_FOREACH(name, args+1)
2062 check_triggering_units(bus, *name);
2063 }
2064 }
2065
2066 return r;
2067 }
2068
2069 /* Ask systemd-logind, which might grant access to unprivileged users
2070 * through PolicyKit */
2071 static int reboot_with_logind(sd_bus *bus, enum action a) {
2072 #ifdef HAVE_LOGIND
2073 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2074 const char *method;
2075 int r;
2076
2077 if (!bus)
2078 return -EIO;
2079
2080 polkit_agent_open_if_enabled();
2081
2082 switch (a) {
2083
2084 case ACTION_REBOOT:
2085 method = "Reboot";
2086 break;
2087
2088 case ACTION_POWEROFF:
2089 method = "PowerOff";
2090 break;
2091
2092 case ACTION_SUSPEND:
2093 method = "Suspend";
2094 break;
2095
2096 case ACTION_HIBERNATE:
2097 method = "Hibernate";
2098 break;
2099
2100 case ACTION_HYBRID_SLEEP:
2101 method = "HybridSleep";
2102 break;
2103
2104 default:
2105 return -EINVAL;
2106 }
2107
2108 r = sd_bus_call_method(
2109 bus,
2110 "org.freedesktop.login1",
2111 "/org/freedesktop/login1",
2112 "org.freedesktop.login1.Manager",
2113 method,
2114 &error,
2115 NULL,
2116 "b", true);
2117 if (r < 0)
2118 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2119
2120 return r;
2121 #else
2122 return -ENOSYS;
2123 #endif
2124 }
2125
2126 static int check_inhibitors(sd_bus *bus, enum action a) {
2127 #ifdef HAVE_LOGIND
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_message_unref_ sd_bus_message *reply = NULL;
3543 _cleanup_free_ UnitInfo *unit_infos = NULL;
3544 const UnitInfo *u;
3545 unsigned c;
3546 int r;
3547
3548 r = get_unit_list(bus, &reply, &unit_infos);
3549 if (r < 0)
3550 return r;
3551
3552 c = (unsigned) r;
3553
3554 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
3555
3556 for (u = unit_infos; u < unit_infos + c; u++) {
3557 _cleanup_free_ char *p = NULL;
3558
3559 if (!output_show_unit(u))
3560 continue;
3561
3562 p = unit_dbus_path_from_name(u->id);
3563 if (!p)
3564 return log_oom();
3565
3566 printf("%s -> '%s'\n", u->id, p);
3567
3568 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3569 if (r != 0)
3570 return r;
3571 }
3572
3573 return 0;
3574 }
3575
3576 static int show(sd_bus *bus, char **args) {
3577 int r, ret = 0;
3578 bool show_properties, show_status, new_line = false;
3579 char **name;
3580 bool ellipsized = false;
3581
3582 assert(bus);
3583 assert(args);
3584
3585 show_properties = streq(args[0], "show");
3586 show_status = streq(args[0], "status");
3587
3588 if (show_properties)
3589 pager_open_if_enabled();
3590
3591 /* If no argument is specified inspect the manager itself */
3592
3593 if (show_properties && strv_length(args) <= 1)
3594 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3595
3596 if (show_status && strv_length(args) <= 1)
3597 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3598 else
3599 STRV_FOREACH(name, args+1) {
3600 uint32_t id;
3601
3602 if (safe_atou32(*name, &id) < 0) {
3603 _cleanup_free_ char *p = NULL, *n = NULL;
3604 /* Interpret as unit name */
3605
3606 n = unit_name_mangle(*name);
3607 if (!n)
3608 return log_oom();
3609
3610 p = unit_dbus_path_from_name(n);
3611 if (!p)
3612 return log_oom();
3613
3614 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3615 if (r != 0)
3616 ret = r;
3617
3618 } else if (show_properties) {
3619 _cleanup_free_ char *p = NULL;
3620
3621 /* Interpret as job id */
3622 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3623 return log_oom();
3624
3625 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3626 if (r != 0)
3627 ret = r;
3628
3629 } else {
3630 /* Interpret as PID */
3631 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3632 if (r != 0)
3633 ret = r;
3634 }
3635 }
3636
3637 if (ellipsized && !arg_quiet)
3638 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3639
3640 return ret;
3641 }
3642
3643 static int append_assignment(sd_bus_message *m, const char *assignment) {
3644 const char *eq;
3645 char *field;
3646 int r;
3647
3648 assert(m);
3649 assert(assignment);
3650
3651 eq = strchr(assignment, '=');
3652 if (!eq) {
3653 log_error("Not an assignment: %s", assignment);
3654 return -EINVAL;
3655 }
3656
3657 field = strndupa(assignment, eq - assignment);
3658 eq ++;
3659
3660 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
3661 if (r < 0)
3662 return bus_log_create_error(r);
3663
3664 if (streq(field, "CPUAccounting") ||
3665 streq(field, "MemoryAccounting") ||
3666 streq(field, "BlockIOAccounting")) {
3667
3668 r = parse_boolean(eq);
3669 if (r < 0) {
3670 log_error("Failed to parse boolean assignment %s.", assignment);
3671 return -EINVAL;
3672 }
3673
3674 r = sd_bus_message_append(m, "v", "b", r);
3675
3676 } else if (streq(field, "MemoryLimit")) {
3677 off_t bytes;
3678
3679 r = parse_bytes(eq, &bytes);
3680 if (r < 0) {
3681 log_error("Failed to parse bytes specification %s", assignment);
3682 return -EINVAL;
3683 }
3684
3685 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
3686
3687 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3688 uint64_t u;
3689
3690 r = safe_atou64(eq, &u);
3691 if (r < 0) {
3692 log_error("Failed to parse %s value %s.", field, eq);
3693 return -EINVAL;
3694 }
3695
3696 r = sd_bus_message_append(m, "v", "t", u);
3697
3698 } else if (streq(field, "DevicePolicy"))
3699 r = sd_bus_message_append(m, "v", "s", eq);
3700
3701 else if (streq(field, "DeviceAllow")) {
3702
3703 if (isempty(eq))
3704 r = sd_bus_message_append(m, "v", "a(ss)", 0);
3705 else {
3706 const char *path, *rwm;
3707 char *e;
3708
3709 e = strchr(eq, ' ');
3710 if (e) {
3711 path = strndupa(eq, e - eq);
3712 rwm = e+1;
3713 } else {
3714 path = eq;
3715 rwm = "";
3716 }
3717
3718 if (!path_startswith(path, "/dev")) {
3719 log_error("%s is not a device file in /dev.", path);
3720 return -EINVAL;
3721 }
3722
3723 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
3724 }
3725
3726 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3727
3728 if (isempty(eq))
3729 r = sd_bus_message_append(m, "v", "a(st)", 0);
3730 else {
3731 const char *path, *bandwidth;
3732 off_t bytes;
3733 char *e;
3734
3735 e = strchr(eq, ' ');
3736 if (e) {
3737 path = strndupa(eq, e - eq);
3738 bandwidth = e+1;
3739 } else {
3740 log_error("Failed to parse %s value %s.", field, eq);
3741 return -EINVAL;
3742 }
3743
3744 if (!path_startswith(path, "/dev")) {
3745 log_error("%s is not a device file in /dev.", path);
3746 return -EINVAL;
3747 }
3748
3749 r = parse_bytes(bandwidth, &bytes);
3750 if (r < 0) {
3751 log_error("Failed to parse byte value %s.", bandwidth);
3752 return -EINVAL;
3753 }
3754
3755 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
3756 }
3757
3758 } else if (streq(field, "BlockIODeviceWeight")) {
3759
3760 if (isempty(eq))
3761 r = sd_bus_message_append(m, "v", "a(st)", 0);
3762 else {
3763 const char *path, *weight;
3764 uint64_t u;
3765 char *e;
3766
3767 e = strchr(eq, ' ');
3768 if (e) {
3769 path = strndupa(eq, e - eq);
3770 weight = e+1;
3771 } else {
3772 log_error("Failed to parse %s value %s.", field, eq);
3773 return -EINVAL;
3774 }
3775
3776 if (!path_startswith(path, "/dev")) {
3777 log_error("%s is not a device file in /dev.", path);
3778 return -EINVAL;
3779 }
3780
3781 r = safe_atou64(weight, &u);
3782 if (r < 0) {
3783 log_error("Failed to parse %s value %s.", field, weight);
3784 return -EINVAL;
3785 }
3786 r = sd_bus_message_append(m, "v", "a(st)", path, u);
3787 }
3788
3789 } else {
3790 log_error("Unknown assignment %s.", assignment);
3791 return -EINVAL;
3792 }
3793
3794 if (r < 0)
3795 return bus_log_create_error(r);
3796
3797 return 0;
3798 }
3799
3800 static int set_property(sd_bus *bus, char **args) {
3801 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3802 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3803 _cleanup_free_ char *n = NULL;
3804 char **i;
3805 int r;
3806
3807 r = sd_bus_message_new_method_call(
3808 bus,
3809 "org.freedesktop.systemd1",
3810 "/org/freedesktop/systemd1",
3811 "org.freedesktop.systemd1.Manager",
3812 "SetUnitProperties",
3813 &m);
3814 if (r < 0)
3815 return bus_log_create_error(r);
3816
3817 n = unit_name_mangle(args[1]);
3818 if (!n)
3819 return log_oom();
3820
3821 r = sd_bus_message_append(m, "sb", n, arg_runtime);
3822 if (r < 0)
3823 return bus_log_create_error(r);
3824
3825 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
3826 if (r < 0)
3827 return bus_log_create_error(r);
3828
3829 STRV_FOREACH(i, args + 2) {
3830 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
3831 if (r < 0)
3832 return bus_log_create_error(r);
3833
3834 r = append_assignment(m, *i);
3835 if (r < 0)
3836 return r;
3837
3838 r = sd_bus_message_close_container(m);
3839 if (r < 0)
3840 return bus_log_create_error(r);
3841 }
3842
3843 r = sd_bus_message_close_container(m);
3844 if (r < 0)
3845 return bus_log_create_error(r);
3846
3847 r = sd_bus_call(bus, m, 0, &error, NULL);
3848 if (r < 0) {
3849 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
3850 return r;
3851 }
3852
3853 return 0;
3854 }
3855
3856 static int snapshot(sd_bus *bus, char **args) {
3857 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3858 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3859 _cleanup_free_ char *n = NULL, *id = NULL;
3860 const char *path;
3861 int r;
3862
3863 if (strv_length(args) > 1)
3864 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3865 else
3866 n = strdup("");
3867 if (!n)
3868 return log_oom();
3869
3870 r = sd_bus_call_method(
3871 bus,
3872 "org.freedesktop.systemd1",
3873 "/org/freedesktop/systemd1",
3874 "org.freedesktop.systemd1.Manager",
3875 "CreateSnapshot",
3876 &error,
3877 &reply,
3878 "sb", n, false);
3879 if (r < 0) {
3880 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
3881 return r;
3882 }
3883
3884 r = sd_bus_message_read(reply, "o", &path);
3885 if (r < 0)
3886 return bus_log_parse_error(r);
3887
3888 r = sd_bus_get_property_string(
3889 bus,
3890 "org.freedesktop.systemd1",
3891 path,
3892 "org.freedesktop.systemd1.Unit",
3893 "Id",
3894 &error,
3895 &id);
3896 if (r < 0) {
3897 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
3898 return r;
3899 }
3900
3901 if (!arg_quiet)
3902 puts(id);
3903
3904 return 0;
3905 }
3906
3907 static int delete_snapshot(sd_bus *bus, char **args) {
3908 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3909 char **name;
3910 int r;
3911
3912 assert(args);
3913
3914 STRV_FOREACH(name, args+1) {
3915 _cleanup_free_ char *n = NULL;
3916
3917 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3918 if (!n)
3919 return log_oom();
3920
3921 r = sd_bus_call_method(
3922 bus,
3923 "org.freedesktop.systemd1",
3924 "/org/freedesktop/systemd1",
3925 "org.freedesktop.systemd1.Manager",
3926 "RemoveSnapshot",
3927 &error,
3928 NULL,
3929 "s", n);
3930 if (r < 0) {
3931 log_error("Failed to remove snapshot %s: %s", n, bus_error_message(&error, r));
3932 return r;
3933 }
3934 }
3935
3936 return 0;
3937 }
3938
3939 static int daemon_reload(sd_bus *bus, char **args) {
3940 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3941 const char *method;
3942 int r;
3943
3944 if (arg_action == ACTION_RELOAD)
3945 method = "Reload";
3946 else if (arg_action == ACTION_REEXEC)
3947 method = "Reexecute";
3948 else {
3949 assert(arg_action == ACTION_SYSTEMCTL);
3950
3951 method =
3952 streq(args[0], "clear-jobs") ||
3953 streq(args[0], "cancel") ? "ClearJobs" :
3954 streq(args[0], "daemon-reexec") ? "Reexecute" :
3955 streq(args[0], "reset-failed") ? "ResetFailed" :
3956 streq(args[0], "halt") ? "Halt" :
3957 streq(args[0], "poweroff") ? "PowerOff" :
3958 streq(args[0], "reboot") ? "Reboot" :
3959 streq(args[0], "kexec") ? "KExec" :
3960 streq(args[0], "exit") ? "Exit" :
3961 /* "daemon-reload" */ "Reload";
3962 }
3963
3964 r = sd_bus_call_method(
3965 bus,
3966 "org.freedesktop.systemd1",
3967 "/org/freedesktop/systemd1",
3968 "org.freedesktop.systemd1.Manager",
3969 method,
3970 &error,
3971 NULL,
3972 NULL);
3973
3974 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3975 /* There's always a fallback possible for
3976 * legacy actions. */
3977 r = -EADDRNOTAVAIL;
3978 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3979 /* On reexecution, we expect a disconnect, not a
3980 * reply */
3981 r = 0;
3982 else if (r < 0)
3983 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
3984
3985 return r < 0 ? r : 0;
3986 }
3987
3988 static int reset_failed(sd_bus *bus, char **args) {
3989 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3990 char **name;
3991 int r;
3992
3993 if (strv_length(args) <= 1)
3994 return daemon_reload(bus, args);
3995
3996 STRV_FOREACH(name, args+1) {
3997 _cleanup_free_ char *n;
3998
3999 n = unit_name_mangle(*name);
4000 if (!n)
4001 return log_oom();
4002
4003 r = sd_bus_call_method(
4004 bus,
4005 "org.freedesktop.systemd1",
4006 "/org/freedesktop/systemd1",
4007 "org.freedesktop.systemd1.Manager",
4008 "ResetFailedUnit",
4009 &error,
4010 NULL,
4011 "s", n);
4012 if (r < 0) {
4013 log_error("Failed to reset failed state of unit %s: %s", n, bus_error_message(&error, r));
4014 return r;
4015 }
4016 }
4017
4018 return 0;
4019 }
4020
4021 static int show_environment(sd_bus *bus, char **args) {
4022 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4023 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4024 const char *text;
4025 int r;
4026
4027 pager_open_if_enabled();
4028
4029 r = sd_bus_get_property(
4030 bus,
4031 "org.freedesktop.systemd1",
4032 "/org/freedesktop/systemd1",
4033 "org.freedesktop.systemd1.Manager",
4034 "Environment",
4035 &error,
4036 &reply,
4037 "as");
4038 if (r < 0) {
4039 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4040 return r;
4041 }
4042
4043 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4044 if (r < 0)
4045 return bus_log_parse_error(r);
4046
4047 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4048 puts(text);
4049 if (r < 0)
4050 return bus_log_parse_error(r);
4051
4052 r = sd_bus_message_exit_container(reply);
4053 if (r < 0)
4054 return bus_log_parse_error(r);
4055
4056 return 0;
4057 }
4058
4059 static int switch_root(sd_bus *bus, char **args) {
4060 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4061 _cleanup_free_ char *init = NULL;
4062 const char *root;
4063 unsigned l;
4064 int r;
4065
4066 l = strv_length(args);
4067 if (l < 2 || l > 3) {
4068 log_error("Wrong number of arguments.");
4069 return -EINVAL;
4070 }
4071
4072 root = args[1];
4073
4074 if (l >= 3)
4075 init = strdup(args[2]);
4076 else {
4077 parse_env_file("/proc/cmdline", WHITESPACE,
4078 "init", &init,
4079 NULL);
4080
4081 if (!init)
4082 init = strdup("");
4083 }
4084
4085 if (!init)
4086 return log_oom();
4087
4088 log_debug("switching root - root: %s; init: %s", root, init);
4089
4090 r = sd_bus_call_method(
4091 bus,
4092 "org.freedesktop.systemd1",
4093 "/org/freedesktop/systemd1",
4094 "org.freedesktop.systemd1.Manager",
4095 "SwitchRoot",
4096 &error,
4097 NULL,
4098 "ss", root, init);
4099 if (r < 0) {
4100 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4101 return r;
4102 }
4103
4104 return 0;
4105 }
4106
4107 static int set_environment(sd_bus *bus, char **args) {
4108 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4109 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4110 const char *method;
4111 int r;
4112
4113 assert(bus);
4114 assert(args);
4115
4116 method = streq(args[0], "set-environment")
4117 ? "SetEnvironment"
4118 : "UnsetEnvironment";
4119
4120 r = sd_bus_message_new_method_call(
4121 bus,
4122 "org.freedesktop.systemd1",
4123 "/org/freedesktop/systemd1",
4124 "org.freedesktop.systemd1.Manager",
4125 method,
4126 &m);
4127 if (r < 0)
4128 return bus_log_create_error(r);
4129
4130 r = sd_bus_message_append_strv(m, args + 1);
4131 if (r < 0)
4132 return bus_log_create_error(r);
4133
4134 r = sd_bus_call(bus, m, 0, &error, NULL);
4135 if (r < 0) {
4136 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4137 return r;
4138 }
4139
4140 return 0;
4141 }
4142
4143 static int enable_sysv_units(const char *verb, char **args) {
4144 int r = 0;
4145
4146 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4147 unsigned f = 1, t = 1;
4148 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4149
4150 if (arg_scope != UNIT_FILE_SYSTEM)
4151 return 0;
4152
4153 if (!streq(verb, "enable") &&
4154 !streq(verb, "disable") &&
4155 !streq(verb, "is-enabled"))
4156 return 0;
4157
4158 /* Processes all SysV units, and reshuffles the array so that
4159 * afterwards only the native units remain */
4160
4161 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4162 if (r < 0)
4163 return r;
4164
4165 r = 0;
4166 for (f = 0; args[f]; f++) {
4167 const char *name;
4168 _cleanup_free_ char *p = NULL, *q = NULL;
4169 bool found_native = false, found_sysv;
4170 unsigned c = 1;
4171 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4172 char **k, *l;
4173 int j;
4174 pid_t pid;
4175 siginfo_t status;
4176
4177 name = args[f];
4178
4179 if (!endswith(name, ".service"))
4180 continue;
4181
4182 if (path_is_absolute(name))
4183 continue;
4184
4185 STRV_FOREACH(k, paths.unit_path) {
4186 if (!isempty(arg_root))
4187 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4188 else
4189 asprintf(&p, "%s/%s", *k, name);
4190
4191 if (!p) {
4192 r = log_oom();
4193 goto finish;
4194 }
4195
4196 found_native = access(p, F_OK) >= 0;
4197 free(p);
4198 p = NULL;
4199
4200 if (found_native)
4201 break;
4202 }
4203
4204 if (found_native)
4205 continue;
4206
4207 if (!isempty(arg_root))
4208 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4209 else
4210 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4211 if (!p) {
4212 r = log_oom();
4213 goto finish;
4214 }
4215
4216 p[strlen(p) - sizeof(".service") + 1] = 0;
4217 found_sysv = access(p, F_OK) >= 0;
4218
4219 if (!found_sysv)
4220 continue;
4221
4222 /* Mark this entry, so that we don't try enabling it as native unit */
4223 args[f] = (char*) "";
4224
4225 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4226
4227 if (!isempty(arg_root))
4228 argv[c++] = q = strappend("--root=", arg_root);
4229
4230 argv[c++] = path_get_file_name(p);
4231 argv[c++] =
4232 streq(verb, "enable") ? "on" :
4233 streq(verb, "disable") ? "off" : "--level=5";
4234 argv[c] = NULL;
4235
4236 l = strv_join((char**)argv, " ");
4237 if (!l) {
4238 r = log_oom();
4239 goto finish;
4240 }
4241
4242 log_info("Executing %s", l);
4243 free(l);
4244
4245 pid = fork();
4246 if (pid < 0) {
4247 log_error("Failed to fork: %m");
4248 r = -errno;
4249 goto finish;
4250 } else if (pid == 0) {
4251 /* Child */
4252
4253 execv(argv[0], (char**) argv);
4254 _exit(EXIT_FAILURE);
4255 }
4256
4257 j = wait_for_terminate(pid, &status);
4258 if (j < 0) {
4259 log_error("Failed to wait for child: %s", strerror(-r));
4260 r = j;
4261 goto finish;
4262 }
4263
4264 if (status.si_code == CLD_EXITED) {
4265 if (streq(verb, "is-enabled")) {
4266 if (status.si_status == 0) {
4267 if (!arg_quiet)
4268 puts("enabled");
4269 r = 1;
4270 } else {
4271 if (!arg_quiet)
4272 puts("disabled");
4273 }
4274
4275 } else if (status.si_status != 0) {
4276 r = -EINVAL;
4277 goto finish;
4278 }
4279 } else {
4280 r = -EPROTO;
4281 goto finish;
4282 }
4283 }
4284
4285 finish:
4286 /* Drop all SysV units */
4287 for (f = 0, t = 0; args[f]; f++) {
4288
4289 if (isempty(args[f]))
4290 continue;
4291
4292 args[t++] = args[f];
4293 }
4294
4295 args[t] = NULL;
4296
4297 #endif
4298 return r;
4299 }
4300
4301 static int mangle_names(char **original_names, char ***mangled_names) {
4302 char **i, **l, **name;
4303
4304 l = new(char*, strv_length(original_names) + 1);
4305 if (!l)
4306 return log_oom();
4307
4308 i = l;
4309 STRV_FOREACH(name, original_names) {
4310
4311 /* When enabling units qualified path names are OK,
4312 * too, hence allow them explicitly. */
4313
4314 if (is_path(*name))
4315 *i = strdup(*name);
4316 else
4317 *i = unit_name_mangle(*name);
4318
4319 if (!*i) {
4320 strv_free(l);
4321 return log_oom();
4322 }
4323
4324 i++;
4325 }
4326
4327 *i = NULL;
4328 *mangled_names = l;
4329
4330 return 0;
4331 }
4332
4333 static int enable_unit(sd_bus *bus, char **args) {
4334 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
4335 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4336 _cleanup_strv_free_ char **mangled_names = NULL;
4337 const char *verb = args[0];
4338 UnitFileChange *changes = NULL;
4339 unsigned n_changes = 0, i;
4340 int carries_install_info = -1;
4341 int r;
4342
4343 if (!args[1])
4344 return 0;
4345
4346 r = mangle_names(args+1, &mangled_names);
4347 if (r < 0)
4348 return r;
4349
4350 r = enable_sysv_units(verb, mangled_names);
4351 if (r < 0)
4352 return r;
4353
4354 if (!bus || avoid_bus()) {
4355 if (streq(verb, "enable")) {
4356 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4357 carries_install_info = r;
4358 } else if (streq(verb, "disable"))
4359 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4360 else if (streq(verb, "reenable")) {
4361 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4362 carries_install_info = r;
4363 } else if (streq(verb, "link"))
4364 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4365 else if (streq(verb, "preset")) {
4366 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4367 carries_install_info = r;
4368 } else if (streq(verb, "mask"))
4369 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4370 else if (streq(verb, "unmask"))
4371 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4372 else if (streq(verb, "set-default"))
4373 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4374 else
4375 assert_not_reached("Unknown verb");
4376
4377 if (r < 0) {
4378 log_error("Operation failed: %s", strerror(-r));
4379 goto finish;
4380 }
4381
4382 if (!arg_quiet) {
4383 for (i = 0; i < n_changes; i++) {
4384 if (changes[i].type == UNIT_FILE_SYMLINK)
4385 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4386 else
4387 log_info("rm '%s'", changes[i].path);
4388 }
4389 }
4390
4391 r = 0;
4392 } else {
4393 const char *method, *type, *path, *source;
4394 int expect_carries_install_info = false;
4395 bool send_force = true;
4396
4397 if (streq(verb, "enable")) {
4398 method = "EnableUnitFiles";
4399 expect_carries_install_info = true;
4400 } else if (streq(verb, "disable")) {
4401 method = "DisableUnitFiles";
4402 send_force = false;
4403 } else if (streq(verb, "reenable")) {
4404 method = "ReenableUnitFiles";
4405 expect_carries_install_info = true;
4406 } else if (streq(verb, "link"))
4407 method = "LinkUnitFiles";
4408 else if (streq(verb, "preset")) {
4409 method = "PresetUnitFiles";
4410 expect_carries_install_info = true;
4411 } else if (streq(verb, "mask"))
4412 method = "MaskUnitFiles";
4413 else if (streq(verb, "unmask")) {
4414 method = "UnmaskUnitFiles";
4415 send_force = false;
4416 } else if (streq(verb, "set-default")) {
4417 method = "SetDefaultTarget";
4418 } else
4419 assert_not_reached("Unknown verb");
4420
4421 r = sd_bus_message_new_method_call(
4422 bus,
4423 "org.freedesktop.systemd1",
4424 "/org/freedesktop/systemd1",
4425 "org.freedesktop.systemd1.Manager",
4426 method,
4427 &m);
4428 if (r < 0)
4429 return bus_log_create_error(r);
4430
4431 r = sd_bus_message_append_strv(m, mangled_names);
4432 if (r < 0)
4433 return bus_log_create_error(r);
4434
4435 r = sd_bus_message_append(m, "b", arg_runtime);
4436 if (r < 0)
4437 return bus_log_create_error(r);
4438
4439 if (send_force) {
4440 r = sd_bus_message_append(m, "b", arg_force);
4441 if (r < 0)
4442 return bus_log_create_error(r);
4443 }
4444
4445 r = sd_bus_call(bus, m, 0, &error, &reply);
4446 if (r < 0) {
4447 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4448 return r;
4449 }
4450
4451 if (expect_carries_install_info) {
4452 r = sd_bus_message_read(reply, "b", &carries_install_info);
4453 if (r < 0)
4454 return bus_log_parse_error(r);
4455 }
4456
4457 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(sss)");
4458 if (r < 0)
4459 return bus_log_parse_error(r);
4460
4461 while ((r = sd_bus_message_read(reply, "(sss)", &type, &path, &source)) > 0) {
4462 if (!arg_quiet) {
4463 if (streq(type, "symlink"))
4464 log_info("ln -s '%s' '%s'", source, path);
4465 else
4466 log_info("rm '%s'", path);
4467 }
4468 }
4469 if (r < 0)
4470 return bus_log_parse_error(r);
4471
4472 r = sd_bus_message_exit_container(reply);
4473 if (r < 0)
4474 return bus_log_parse_error(r);
4475
4476 /* Try to reload if enabeld */
4477 if (!arg_no_reload)
4478 r = daemon_reload(bus, args);
4479 else
4480 r = 0;
4481 }
4482
4483 if (carries_install_info == 0)
4484 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4485 "using systemctl.\n"
4486 "Possible reasons for having this kind of units are:\n"
4487 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4488 " .wants/ or .requires/ directory.\n"
4489 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4490 " a requirement dependency on it.\n"
4491 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4492 " D-Bus, udev, scripted systemctl call, ...).\n");
4493
4494 finish:
4495 unit_file_changes_free(changes, n_changes);
4496
4497 return r;
4498 }
4499
4500 static int unit_is_enabled(sd_bus *bus, char **args) {
4501
4502 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4503 _cleanup_strv_free_ char **mangled_names = NULL;
4504 bool enabled;
4505 char **name;
4506 int r;
4507
4508 r = mangle_names(args+1, &mangled_names);
4509 if (r < 0)
4510 return r;
4511
4512 r = enable_sysv_units(args[0], mangled_names);
4513 if (r < 0)
4514 return r;
4515
4516 enabled = r > 0;
4517
4518 if (!bus || avoid_bus()) {
4519
4520 STRV_FOREACH(name, mangled_names) {
4521 UnitFileState state;
4522
4523 state = unit_file_get_state(arg_scope, arg_root, *name);
4524 if (state < 0) {
4525 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
4526 return state;
4527 }
4528
4529 if (state == UNIT_FILE_ENABLED ||
4530 state == UNIT_FILE_ENABLED_RUNTIME ||
4531 state == UNIT_FILE_STATIC)
4532 enabled = true;
4533
4534 if (!arg_quiet)
4535 puts(unit_file_state_to_string(state));
4536 }
4537
4538 } else {
4539 STRV_FOREACH(name, mangled_names) {
4540 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4541 const char *s;
4542
4543 r = sd_bus_call_method(
4544 bus,
4545 "org.freedesktop.systemd1",
4546 "/org/freedesktop/systemd1",
4547 "org.freedesktop.systemd1.Manager",
4548 "GetUnitFileState",
4549 &error,
4550 &reply,
4551 "s", name);
4552 if (r < 0) {
4553 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
4554 return r;
4555 }
4556
4557 r = sd_bus_message_read(reply, "s", &s);
4558 if (r < 0)
4559 return bus_log_parse_error(r);
4560
4561 if (streq(s, "enabled") ||
4562 streq(s, "enabled-runtime") ||
4563 streq(s, "static"))
4564 enabled = true;
4565
4566 if (!arg_quiet)
4567 puts(s);
4568 }
4569 }
4570
4571 return !enabled;
4572 }
4573
4574 static int systemctl_help(void) {
4575
4576 pager_open_if_enabled();
4577
4578 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4579 "Query or send control commands to the systemd manager.\n\n"
4580 " -h --help Show this help\n"
4581 " --version Show package version\n"
4582 " --system Connect to system manager\n"
4583 " --user Connect to user service manager\n"
4584 " -H --host=[USER@]HOST\n"
4585 " Operate on remote host\n"
4586 " -M --machine=CONTAINER\n"
4587 " Operate on local container\n"
4588 " -t --type=TYPE List only units of a particular type\n"
4589 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4590 " -p --property=NAME Show only properties by this name\n"
4591 " -a --all Show all loaded units/properties, including dead/empty\n"
4592 " ones. To list all units installed on the system, use\n"
4593 " the 'list-unit-files' command instead.\n"
4594 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4595 " -l --full Don't ellipsize unit names on output\n"
4596 " --fail When queueing a new job, fail if conflicting jobs are\n"
4597 " pending\n"
4598 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4599 " cancelled\n"
4600 " --ignore-dependencies\n"
4601 " When queueing a new job, ignore all its dependencies\n"
4602 " --show-types When showing sockets, explicitly show their type\n"
4603 " -i --ignore-inhibitors\n"
4604 " When shutting down or sleeping, ignore inhibitors\n"
4605 " --kill-who=WHO Who to send signal to\n"
4606 " -s --signal=SIGNAL Which signal to send\n"
4607 " -q --quiet Suppress output\n"
4608 " --no-block Do not wait until operation finished\n"
4609 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4610 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4611 " configuration\n"
4612 " --no-legend Do not print a legend (column headers and hints)\n"
4613 " --no-pager Do not pipe output into a pager\n"
4614 " --no-ask-password\n"
4615 " Do not ask for system passwords\n"
4616 " --global Enable/disable unit files globally\n"
4617 " --runtime Enable unit files only temporarily until next reboot\n"
4618 " -f --force When enabling unit files, override existing symlinks\n"
4619 " When shutting down, execute action immediately\n"
4620 " --root=PATH Enable unit files in the specified root directory\n"
4621 " -n --lines=INTEGER Number of journal entries to show\n"
4622 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4623 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4624 "Unit Commands:\n"
4625 " list-units List loaded units\n"
4626 " list-sockets List loaded sockets ordered by address\n"
4627 " list-timers List loaded timers ordered by next elapse\n"
4628 " start [NAME...] Start (activate) one or more units\n"
4629 " stop [NAME...] Stop (deactivate) one or more units\n"
4630 " reload [NAME...] Reload one or more units\n"
4631 " restart [NAME...] Start or restart one or more units\n"
4632 " try-restart [NAME...] Restart one or more units if active\n"
4633 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4634 " otherwise start or restart\n"
4635 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4636 " otherwise restart if active\n"
4637 " isolate [NAME] Start one unit and stop all others\n"
4638 " kill [NAME...] Send signal to processes of a unit\n"
4639 " is-active [NAME...] Check whether units are active\n"
4640 " is-failed [NAME...] Check whether units are failed\n"
4641 " status [NAME...|PID...] Show runtime status of one or more units\n"
4642 " show [NAME...|JOB...] Show properties of one or more\n"
4643 " units/jobs or the manager\n"
4644 " set-property [NAME] [ASSIGNMENT...]\n"
4645 " Sets one or more properties of a unit\n"
4646 " help [NAME...|PID...] Show manual for one or more units\n"
4647 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4648 " units\n"
4649 " list-dependencies [NAME] Recursively show units which are required\n"
4650 " or wanted by this unit or by which this\n"
4651 " unit is required or wanted\n\n"
4652 "Unit File Commands:\n"
4653 " list-unit-files List installed unit files\n"
4654 " enable [NAME...] Enable one or more unit files\n"
4655 " disable [NAME...] Disable one or more unit files\n"
4656 " reenable [NAME...] Reenable one or more unit files\n"
4657 " preset [NAME...] Enable/disable one or more unit files\n"
4658 " based on preset configuration\n"
4659 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4660 " mask [NAME...] Mask one or more units\n"
4661 " unmask [NAME...] Unmask one or more units\n"
4662 " link [PATH...] Link one or more units files into\n"
4663 " the search path\n"
4664 " get-default Get the name of the default target\n"
4665 " set-default NAME Set the default target\n\n"
4666 "Job Commands:\n"
4667 " list-jobs List jobs\n"
4668 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4669 "Snapshot Commands:\n"
4670 " snapshot [NAME] Create a snapshot\n"
4671 " delete [NAME...] Remove one or more snapshots\n\n"
4672 "Environment Commands:\n"
4673 " show-environment Dump environment\n"
4674 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4675 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4676 "Manager Lifecycle Commands:\n"
4677 " daemon-reload Reload systemd manager configuration\n"
4678 " daemon-reexec Reexecute systemd manager\n\n"
4679 "System Commands:\n"
4680 " default Enter system default mode\n"
4681 " rescue Enter system rescue mode\n"
4682 " emergency Enter system emergency mode\n"
4683 " halt Shut down and halt the system\n"
4684 " poweroff Shut down and power-off the system\n"
4685 " reboot [ARG] Shut down and reboot the system\n"
4686 " kexec Shut down and reboot the system with kexec\n"
4687 " exit Request user instance exit\n"
4688 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4689 " suspend Suspend the system\n"
4690 " hibernate Hibernate the system\n"
4691 " hybrid-sleep Hibernate and suspend the system\n",
4692 program_invocation_short_name);
4693
4694 return 0;
4695 }
4696
4697 static int halt_help(void) {
4698
4699 printf("%s [OPTIONS...]%s\n\n"
4700 "%s the system.\n\n"
4701 " --help Show this help\n"
4702 " --halt Halt the machine\n"
4703 " -p --poweroff Switch off the machine\n"
4704 " --reboot Reboot the machine\n"
4705 " -f --force Force immediate halt/power-off/reboot\n"
4706 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4707 " -d --no-wtmp Don't write wtmp record\n"
4708 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4709 program_invocation_short_name,
4710 arg_action == ACTION_REBOOT ? " [ARG]" : "",
4711 arg_action == ACTION_REBOOT ? "Reboot" :
4712 arg_action == ACTION_POWEROFF ? "Power off" :
4713 "Halt");
4714
4715 return 0;
4716 }
4717
4718 static int shutdown_help(void) {
4719
4720 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4721 "Shut down the system.\n\n"
4722 " --help Show this help\n"
4723 " -H --halt Halt the machine\n"
4724 " -P --poweroff Power-off the machine\n"
4725 " -r --reboot Reboot the machine\n"
4726 " -h Equivalent to --poweroff, overridden by --halt\n"
4727 " -k Don't halt/power-off/reboot, just send warnings\n"
4728 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4729 " -c Cancel a pending shutdown\n",
4730 program_invocation_short_name);
4731
4732 return 0;
4733 }
4734
4735 static int telinit_help(void) {
4736
4737 printf("%s [OPTIONS...] {COMMAND}\n\n"
4738 "Send control commands to the init daemon.\n\n"
4739 " --help Show this help\n"
4740 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4741 "Commands:\n"
4742 " 0 Power-off the machine\n"
4743 " 6 Reboot the machine\n"
4744 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4745 " 1, s, S Enter rescue mode\n"
4746 " q, Q Reload init daemon configuration\n"
4747 " u, U Reexecute init daemon\n",
4748 program_invocation_short_name);
4749
4750 return 0;
4751 }
4752
4753 static int runlevel_help(void) {
4754
4755 printf("%s [OPTIONS...]\n\n"
4756 "Prints the previous and current runlevel of the init system.\n\n"
4757 " --help Show this help\n",
4758 program_invocation_short_name);
4759
4760 return 0;
4761 }
4762
4763 static int help_types(void) {
4764 int i;
4765 const char *t;
4766
4767 puts("Available unit types:");
4768 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4769 t = unit_type_to_string(i);
4770 if (t)
4771 puts(t);
4772 }
4773
4774 return 0;
4775 }
4776
4777 static int systemctl_parse_argv(int argc, char *argv[]) {
4778
4779 enum {
4780 ARG_FAIL = 0x100,
4781 ARG_REVERSE,
4782 ARG_AFTER,
4783 ARG_BEFORE,
4784 ARG_SHOW_TYPES,
4785 ARG_IRREVERSIBLE,
4786 ARG_IGNORE_DEPENDENCIES,
4787 ARG_VERSION,
4788 ARG_USER,
4789 ARG_SYSTEM,
4790 ARG_GLOBAL,
4791 ARG_NO_BLOCK,
4792 ARG_NO_LEGEND,
4793 ARG_NO_PAGER,
4794 ARG_NO_WALL,
4795 ARG_ROOT,
4796 ARG_NO_RELOAD,
4797 ARG_KILL_WHO,
4798 ARG_NO_ASK_PASSWORD,
4799 ARG_FAILED,
4800 ARG_RUNTIME,
4801 ARG_FORCE,
4802 ARG_PLAIN,
4803 ARG_STATE
4804 };
4805
4806 static const struct option options[] = {
4807 { "help", no_argument, NULL, 'h' },
4808 { "version", no_argument, NULL, ARG_VERSION },
4809 { "type", required_argument, NULL, 't' },
4810 { "property", required_argument, NULL, 'p' },
4811 { "all", no_argument, NULL, 'a' },
4812 { "reverse", no_argument, NULL, ARG_REVERSE },
4813 { "after", no_argument, NULL, ARG_AFTER },
4814 { "before", no_argument, NULL, ARG_BEFORE },
4815 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4816 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4817 { "full", no_argument, NULL, 'l' },
4818 { "fail", no_argument, NULL, ARG_FAIL },
4819 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4820 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4821 { "ignore-inhibitors", no_argument, NULL, 'i' },
4822 { "user", no_argument, NULL, ARG_USER },
4823 { "system", no_argument, NULL, ARG_SYSTEM },
4824 { "global", no_argument, NULL, ARG_GLOBAL },
4825 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4826 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4827 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4828 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4829 { "quiet", no_argument, NULL, 'q' },
4830 { "root", required_argument, NULL, ARG_ROOT },
4831 { "force", no_argument, NULL, ARG_FORCE },
4832 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4833 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4834 { "signal", required_argument, NULL, 's' },
4835 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4836 { "host", required_argument, NULL, 'H' },
4837 { "machine", required_argument, NULL, 'M' },
4838 { "runtime", no_argument, NULL, ARG_RUNTIME },
4839 { "lines", required_argument, NULL, 'n' },
4840 { "output", required_argument, NULL, 'o' },
4841 { "plain", no_argument, NULL, ARG_PLAIN },
4842 { "state", required_argument, NULL, ARG_STATE },
4843 {}
4844 };
4845
4846 int c;
4847
4848 assert(argc >= 0);
4849 assert(argv);
4850
4851 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:i", options, NULL)) >= 0) {
4852
4853 switch (c) {
4854
4855 case 'h':
4856 return systemctl_help();
4857
4858 case ARG_VERSION:
4859 puts(PACKAGE_STRING);
4860 puts(SYSTEMD_FEATURES);
4861 return 0;
4862
4863 case 't': {
4864 char *word, *state;
4865 size_t size;
4866
4867 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4868 _cleanup_free_ char *type;
4869
4870 type = strndup(word, size);
4871 if (!type)
4872 return -ENOMEM;
4873
4874 if (streq(type, "help")) {
4875 help_types();
4876 return 0;
4877 }
4878
4879 if (unit_type_from_string(type) >= 0) {
4880 if (strv_push(&arg_types, type))
4881 return log_oom();
4882 type = NULL;
4883 continue;
4884 }
4885
4886 /* It's much nicer to use --state= for
4887 * load states, but let's support this
4888 * in --types= too for compatibility
4889 * with old versions */
4890 if (unit_load_state_from_string(optarg) >= 0) {
4891 if (strv_push(&arg_states, type) < 0)
4892 return log_oom();
4893 type = NULL;
4894 continue;
4895 }
4896
4897 log_error("Unknown unit type or load state '%s'.", type);
4898 log_info("Use -t help to see a list of allowed values.");
4899 return -EINVAL;
4900 }
4901
4902 break;
4903 }
4904
4905 case 'p': {
4906 /* Make sure that if the empty property list
4907 was specified, we won't show any properties. */
4908 if (isempty(optarg) && !arg_properties) {
4909 arg_properties = new0(char*, 1);
4910 if (!arg_properties)
4911 return log_oom();
4912 } else {
4913 char *word, *state;
4914 size_t size;
4915
4916 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4917 char *prop;
4918
4919 prop = strndup(word, size);
4920 if (!prop)
4921 return log_oom();
4922
4923 if (strv_push(&arg_properties, prop) < 0) {
4924 free(prop);
4925 return log_oom();
4926 }
4927 }
4928 }
4929
4930 /* If the user asked for a particular
4931 * property, show it to him, even if it is
4932 * empty. */
4933 arg_all = true;
4934
4935 break;
4936 }
4937
4938 case 'a':
4939 arg_all = true;
4940 break;
4941
4942 case ARG_REVERSE:
4943 arg_dependency = DEPENDENCY_REVERSE;
4944 break;
4945
4946 case ARG_AFTER:
4947 arg_dependency = DEPENDENCY_AFTER;
4948 break;
4949
4950 case ARG_BEFORE:
4951 arg_dependency = DEPENDENCY_BEFORE;
4952 break;
4953
4954 case ARG_SHOW_TYPES:
4955 arg_show_types = true;
4956 break;
4957
4958 case ARG_FAIL:
4959 arg_job_mode = "fail";
4960 break;
4961
4962 case ARG_IRREVERSIBLE:
4963 arg_job_mode = "replace-irreversibly";
4964 break;
4965
4966 case ARG_IGNORE_DEPENDENCIES:
4967 arg_job_mode = "ignore-dependencies";
4968 break;
4969
4970 case ARG_USER:
4971 arg_scope = UNIT_FILE_USER;
4972 break;
4973
4974 case ARG_SYSTEM:
4975 arg_scope = UNIT_FILE_SYSTEM;
4976 break;
4977
4978 case ARG_GLOBAL:
4979 arg_scope = UNIT_FILE_GLOBAL;
4980 break;
4981
4982 case ARG_NO_BLOCK:
4983 arg_no_block = true;
4984 break;
4985
4986 case ARG_NO_LEGEND:
4987 arg_no_legend = true;
4988 break;
4989
4990 case ARG_NO_PAGER:
4991 arg_no_pager = true;
4992 break;
4993
4994 case ARG_NO_WALL:
4995 arg_no_wall = true;
4996 break;
4997
4998 case ARG_ROOT:
4999 arg_root = optarg;
5000 break;
5001
5002 case 'l':
5003 arg_full = true;
5004 break;
5005
5006 case ARG_FAILED:
5007 if (strv_extend(&arg_states, "failed") < 0)
5008 return log_oom();
5009
5010 break;
5011
5012 case 'q':
5013 arg_quiet = true;
5014 break;
5015
5016 case ARG_FORCE:
5017 arg_force ++;
5018 break;
5019
5020 case 'f':
5021 arg_force ++;
5022 break;
5023
5024 case ARG_NO_RELOAD:
5025 arg_no_reload = true;
5026 break;
5027
5028 case ARG_KILL_WHO:
5029 arg_kill_who = optarg;
5030 break;
5031
5032 case 's':
5033 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5034 log_error("Failed to parse signal string %s.", optarg);
5035 return -EINVAL;
5036 }
5037 break;
5038
5039 case ARG_NO_ASK_PASSWORD:
5040 arg_ask_password = false;
5041 break;
5042
5043 case 'H':
5044 arg_transport = BUS_TRANSPORT_REMOTE;
5045 arg_host = optarg;
5046 break;
5047
5048 case 'M':
5049 arg_transport = BUS_TRANSPORT_CONTAINER;
5050 arg_host = optarg;
5051 break;
5052
5053 case ARG_RUNTIME:
5054 arg_runtime = true;
5055 break;
5056
5057 case 'n':
5058 if (safe_atou(optarg, &arg_lines) < 0) {
5059 log_error("Failed to parse lines '%s'", optarg);
5060 return -EINVAL;
5061 }
5062 break;
5063
5064 case 'o':
5065 arg_output = output_mode_from_string(optarg);
5066 if (arg_output < 0) {
5067 log_error("Unknown output '%s'.", optarg);
5068 return -EINVAL;
5069 }
5070 break;
5071
5072 case 'i':
5073 arg_ignore_inhibitors = true;
5074 break;
5075
5076 case ARG_PLAIN:
5077 arg_plain = true;
5078 break;
5079
5080 case ARG_STATE: {
5081 char *word, *state;
5082 size_t size;
5083
5084 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5085 char *s;
5086
5087 s = strndup(word, size);
5088 if (!s)
5089 return log_oom();
5090
5091 if (strv_push(&arg_states, s) < 0) {
5092 free(s);
5093 return log_oom();
5094 }
5095 }
5096 break;
5097 }
5098
5099 case '?':
5100 return -EINVAL;
5101
5102 default:
5103 assert_not_reached("Unhandled option");
5104 }
5105 }
5106
5107 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5108 log_error("Cannot access user instance remotely.");
5109 return -EINVAL;
5110 }
5111
5112 return 1;
5113 }
5114
5115 static int halt_parse_argv(int argc, char *argv[]) {
5116
5117 enum {
5118 ARG_HELP = 0x100,
5119 ARG_HALT,
5120 ARG_REBOOT,
5121 ARG_NO_WALL
5122 };
5123
5124 static const struct option options[] = {
5125 { "help", no_argument, NULL, ARG_HELP },
5126 { "halt", no_argument, NULL, ARG_HALT },
5127 { "poweroff", no_argument, NULL, 'p' },
5128 { "reboot", no_argument, NULL, ARG_REBOOT },
5129 { "force", no_argument, NULL, 'f' },
5130 { "wtmp-only", no_argument, NULL, 'w' },
5131 { "no-wtmp", no_argument, NULL, 'd' },
5132 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5133 {}
5134 };
5135
5136 int c, r, runlevel;
5137
5138 assert(argc >= 0);
5139 assert(argv);
5140
5141 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5142 if (runlevel == '0' || runlevel == '6')
5143 arg_force = 2;
5144
5145 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5146 switch (c) {
5147
5148 case ARG_HELP:
5149 return halt_help();
5150
5151 case ARG_HALT:
5152 arg_action = ACTION_HALT;
5153 break;
5154
5155 case 'p':
5156 if (arg_action != ACTION_REBOOT)
5157 arg_action = ACTION_POWEROFF;
5158 break;
5159
5160 case ARG_REBOOT:
5161 arg_action = ACTION_REBOOT;
5162 break;
5163
5164 case 'f':
5165 arg_force = 2;
5166 break;
5167
5168 case 'w':
5169 arg_dry = true;
5170 break;
5171
5172 case 'd':
5173 arg_no_wtmp = true;
5174 break;
5175
5176 case ARG_NO_WALL:
5177 arg_no_wall = true;
5178 break;
5179
5180 case 'i':
5181 case 'h':
5182 case 'n':
5183 /* Compatibility nops */
5184 break;
5185
5186 case '?':
5187 return -EINVAL;
5188
5189 default:
5190 assert_not_reached("Unhandled option");
5191 }
5192 }
5193
5194 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5195 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5196 if (r < 0) {
5197 log_error("Failed to write reboot param to "
5198 REBOOT_PARAM_FILE": %s", strerror(-r));
5199 return r;
5200 }
5201 } else if (optind < argc) {
5202 log_error("Too many arguments.");
5203 return -EINVAL;
5204 }
5205
5206 return 1;
5207 }
5208
5209 static int parse_time_spec(const char *t, usec_t *_u) {
5210 assert(t);
5211 assert(_u);
5212
5213 if (streq(t, "now"))
5214 *_u = 0;
5215 else if (!strchr(t, ':')) {
5216 uint64_t u;
5217
5218 if (safe_atou64(t, &u) < 0)
5219 return -EINVAL;
5220
5221 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5222 } else {
5223 char *e = NULL;
5224 long hour, minute;
5225 struct tm tm = {};
5226 time_t s;
5227 usec_t n;
5228
5229 errno = 0;
5230 hour = strtol(t, &e, 10);
5231 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5232 return -EINVAL;
5233
5234 minute = strtol(e+1, &e, 10);
5235 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5236 return -EINVAL;
5237
5238 n = now(CLOCK_REALTIME);
5239 s = (time_t) (n / USEC_PER_SEC);
5240
5241 assert_se(localtime_r(&s, &tm));
5242
5243 tm.tm_hour = (int) hour;
5244 tm.tm_min = (int) minute;
5245 tm.tm_sec = 0;
5246
5247 assert_se(s = mktime(&tm));
5248
5249 *_u = (usec_t) s * USEC_PER_SEC;
5250
5251 while (*_u <= n)
5252 *_u += USEC_PER_DAY;
5253 }
5254
5255 return 0;
5256 }
5257
5258 static int shutdown_parse_argv(int argc, char *argv[]) {
5259
5260 enum {
5261 ARG_HELP = 0x100,
5262 ARG_NO_WALL
5263 };
5264
5265 static const struct option options[] = {
5266 { "help", no_argument, NULL, ARG_HELP },
5267 { "halt", no_argument, NULL, 'H' },
5268 { "poweroff", no_argument, NULL, 'P' },
5269 { "reboot", no_argument, NULL, 'r' },
5270 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5271 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5272 {}
5273 };
5274
5275 int c, r;
5276
5277 assert(argc >= 0);
5278 assert(argv);
5279
5280 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5281 switch (c) {
5282
5283 case ARG_HELP:
5284 return shutdown_help();
5285
5286 case 'H':
5287 arg_action = ACTION_HALT;
5288 break;
5289
5290 case 'P':
5291 arg_action = ACTION_POWEROFF;
5292 break;
5293
5294 case 'r':
5295 if (kexec_loaded())
5296 arg_action = ACTION_KEXEC;
5297 else
5298 arg_action = ACTION_REBOOT;
5299 break;
5300
5301 case 'K':
5302 arg_action = ACTION_KEXEC;
5303 break;
5304
5305 case 'h':
5306 if (arg_action != ACTION_HALT)
5307 arg_action = ACTION_POWEROFF;
5308 break;
5309
5310 case 'k':
5311 arg_dry = true;
5312 break;
5313
5314 case ARG_NO_WALL:
5315 arg_no_wall = true;
5316 break;
5317
5318 case 't':
5319 case 'a':
5320 /* Compatibility nops */
5321 break;
5322
5323 case 'c':
5324 arg_action = ACTION_CANCEL_SHUTDOWN;
5325 break;
5326
5327 case '?':
5328 return -EINVAL;
5329
5330 default:
5331 assert_not_reached("Unhandled option");
5332 }
5333 }
5334
5335 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5336 r = parse_time_spec(argv[optind], &arg_when);
5337 if (r < 0) {
5338 log_error("Failed to parse time specification: %s", argv[optind]);
5339 return r;
5340 }
5341 } else
5342 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5343
5344 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5345 /* No time argument for shutdown cancel */
5346 arg_wall = argv + optind;
5347 else if (argc > optind + 1)
5348 /* We skip the time argument */
5349 arg_wall = argv + optind + 1;
5350
5351 optind = argc;
5352
5353 return 1;
5354 }
5355
5356 static int telinit_parse_argv(int argc, char *argv[]) {
5357
5358 enum {
5359 ARG_HELP = 0x100,
5360 ARG_NO_WALL
5361 };
5362
5363 static const struct option options[] = {
5364 { "help", no_argument, NULL, ARG_HELP },
5365 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5366 {}
5367 };
5368
5369 static const struct {
5370 char from;
5371 enum action to;
5372 } table[] = {
5373 { '0', ACTION_POWEROFF },
5374 { '6', ACTION_REBOOT },
5375 { '1', ACTION_RESCUE },
5376 { '2', ACTION_RUNLEVEL2 },
5377 { '3', ACTION_RUNLEVEL3 },
5378 { '4', ACTION_RUNLEVEL4 },
5379 { '5', ACTION_RUNLEVEL5 },
5380 { 's', ACTION_RESCUE },
5381 { 'S', ACTION_RESCUE },
5382 { 'q', ACTION_RELOAD },
5383 { 'Q', ACTION_RELOAD },
5384 { 'u', ACTION_REEXEC },
5385 { 'U', ACTION_REEXEC }
5386 };
5387
5388 unsigned i;
5389 int c;
5390
5391 assert(argc >= 0);
5392 assert(argv);
5393
5394 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5395 switch (c) {
5396
5397 case ARG_HELP:
5398 return telinit_help();
5399
5400 case ARG_NO_WALL:
5401 arg_no_wall = true;
5402 break;
5403
5404 case '?':
5405 return -EINVAL;
5406
5407 default:
5408 assert_not_reached("Unhandled option");
5409 }
5410 }
5411
5412 if (optind >= argc) {
5413 telinit_help();
5414 return -EINVAL;
5415 }
5416
5417 if (optind + 1 < argc) {
5418 log_error("Too many arguments.");
5419 return -EINVAL;
5420 }
5421
5422 if (strlen(argv[optind]) != 1) {
5423 log_error("Expected single character argument.");
5424 return -EINVAL;
5425 }
5426
5427 for (i = 0; i < ELEMENTSOF(table); i++)
5428 if (table[i].from == argv[optind][0])
5429 break;
5430
5431 if (i >= ELEMENTSOF(table)) {
5432 log_error("Unknown command '%s'.", argv[optind]);
5433 return -EINVAL;
5434 }
5435
5436 arg_action = table[i].to;
5437
5438 optind ++;
5439
5440 return 1;
5441 }
5442
5443 static int runlevel_parse_argv(int argc, char *argv[]) {
5444
5445 enum {
5446 ARG_HELP = 0x100,
5447 };
5448
5449 static const struct option options[] = {
5450 { "help", no_argument, NULL, ARG_HELP },
5451 {}
5452 };
5453
5454 int c;
5455
5456 assert(argc >= 0);
5457 assert(argv);
5458
5459 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5460 switch (c) {
5461
5462 case ARG_HELP:
5463 return runlevel_help();
5464 return 0;
5465
5466 case '?':
5467 return -EINVAL;
5468
5469 default:
5470 assert_not_reached("Unhandled option");
5471 }
5472 }
5473
5474 if (optind < argc) {
5475 log_error("Too many arguments.");
5476 return -EINVAL;
5477 }
5478
5479 return 1;
5480 }
5481
5482 static int parse_argv(int argc, char *argv[]) {
5483 assert(argc >= 0);
5484 assert(argv);
5485
5486 if (program_invocation_short_name) {
5487
5488 if (strstr(program_invocation_short_name, "halt")) {
5489 arg_action = ACTION_HALT;
5490 return halt_parse_argv(argc, argv);
5491 } else if (strstr(program_invocation_short_name, "poweroff")) {
5492 arg_action = ACTION_POWEROFF;
5493 return halt_parse_argv(argc, argv);
5494 } else if (strstr(program_invocation_short_name, "reboot")) {
5495 if (kexec_loaded())
5496 arg_action = ACTION_KEXEC;
5497 else
5498 arg_action = ACTION_REBOOT;
5499 return halt_parse_argv(argc, argv);
5500 } else if (strstr(program_invocation_short_name, "shutdown")) {
5501 arg_action = ACTION_POWEROFF;
5502 return shutdown_parse_argv(argc, argv);
5503 } else if (strstr(program_invocation_short_name, "init")) {
5504
5505 if (sd_booted() > 0) {
5506 arg_action = _ACTION_INVALID;
5507 return telinit_parse_argv(argc, argv);
5508 } else {
5509 /* Hmm, so some other init system is
5510 * running, we need to forward this
5511 * request to it. For now we simply
5512 * guess that it is Upstart. */
5513
5514 execv(TELINIT, argv);
5515
5516 log_error("Couldn't find an alternative telinit implementation to spawn.");
5517 return -EIO;
5518 }
5519
5520 } else if (strstr(program_invocation_short_name, "runlevel")) {
5521 arg_action = ACTION_RUNLEVEL;
5522 return runlevel_parse_argv(argc, argv);
5523 }
5524 }
5525
5526 arg_action = ACTION_SYSTEMCTL;
5527 return systemctl_parse_argv(argc, argv);
5528 }
5529
5530 _pure_ static int action_to_runlevel(void) {
5531
5532 static const char table[_ACTION_MAX] = {
5533 [ACTION_HALT] = '0',
5534 [ACTION_POWEROFF] = '0',
5535 [ACTION_REBOOT] = '6',
5536 [ACTION_RUNLEVEL2] = '2',
5537 [ACTION_RUNLEVEL3] = '3',
5538 [ACTION_RUNLEVEL4] = '4',
5539 [ACTION_RUNLEVEL5] = '5',
5540 [ACTION_RESCUE] = '1'
5541 };
5542
5543 assert(arg_action < _ACTION_MAX);
5544
5545 return table[arg_action];
5546 }
5547
5548 static int talk_initctl(void) {
5549
5550 struct init_request request = {
5551 .magic = INIT_MAGIC,
5552 .sleeptime = 0,
5553 .cmd = INIT_CMD_RUNLVL
5554 };
5555
5556 _cleanup_close_ int fd = -1;
5557 char rl;
5558 int r;
5559
5560 rl = action_to_runlevel();
5561 if (!rl)
5562 return 0;
5563
5564 request.runlevel = rl;
5565
5566 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5567 if (fd < 0) {
5568 if (errno == ENOENT)
5569 return 0;
5570
5571 log_error("Failed to open "INIT_FIFO": %m");
5572 return -errno;
5573 }
5574
5575 errno = 0;
5576 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5577 if (r) {
5578 log_error("Failed to write to "INIT_FIFO": %m");
5579 return errno > 0 ? -errno : -EIO;
5580 }
5581
5582 return 1;
5583 }
5584
5585 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
5586
5587 static const struct {
5588 const char* verb;
5589 const enum {
5590 MORE,
5591 LESS,
5592 EQUAL
5593 } argc_cmp;
5594 const int argc;
5595 int (* const dispatch)(sd_bus *bus, char **args);
5596 } verbs[] = {
5597 { "list-units", LESS, 1, list_units },
5598 { "list-unit-files", EQUAL, 1, list_unit_files },
5599 { "list-sockets", LESS, 1, list_sockets },
5600 { "list-timers", LESS, 1, list_timers },
5601 { "list-jobs", EQUAL, 1, list_jobs },
5602 { "clear-jobs", EQUAL, 1, daemon_reload },
5603 { "cancel", MORE, 2, cancel_job },
5604 { "start", MORE, 2, start_unit },
5605 { "stop", MORE, 2, start_unit },
5606 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5607 { "reload", MORE, 2, start_unit },
5608 { "restart", MORE, 2, start_unit },
5609 { "try-restart", MORE, 2, start_unit },
5610 { "reload-or-restart", MORE, 2, start_unit },
5611 { "reload-or-try-restart", MORE, 2, start_unit },
5612 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5613 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5614 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5615 { "isolate", EQUAL, 2, start_unit },
5616 { "kill", MORE, 2, kill_unit },
5617 { "is-active", MORE, 2, check_unit_active },
5618 { "check", MORE, 2, check_unit_active },
5619 { "is-failed", MORE, 2, check_unit_failed },
5620 { "show", MORE, 1, show },
5621 { "status", MORE, 1, show },
5622 { "help", MORE, 2, show },
5623 { "snapshot", LESS, 2, snapshot },
5624 { "delete", MORE, 2, delete_snapshot },
5625 { "daemon-reload", EQUAL, 1, daemon_reload },
5626 { "daemon-reexec", EQUAL, 1, daemon_reload },
5627 { "show-environment", EQUAL, 1, show_environment },
5628 { "set-environment", MORE, 2, set_environment },
5629 { "unset-environment", MORE, 2, set_environment },
5630 { "halt", EQUAL, 1, start_special },
5631 { "poweroff", EQUAL, 1, start_special },
5632 { "reboot", EQUAL, 1, start_special },
5633 { "kexec", EQUAL, 1, start_special },
5634 { "suspend", EQUAL, 1, start_special },
5635 { "hibernate", EQUAL, 1, start_special },
5636 { "hybrid-sleep", EQUAL, 1, start_special },
5637 { "default", EQUAL, 1, start_special },
5638 { "rescue", EQUAL, 1, start_special },
5639 { "emergency", EQUAL, 1, start_special },
5640 { "exit", EQUAL, 1, start_special },
5641 { "reset-failed", MORE, 1, reset_failed },
5642 { "enable", MORE, 2, enable_unit },
5643 { "disable", MORE, 2, enable_unit },
5644 { "is-enabled", MORE, 2, unit_is_enabled },
5645 { "reenable", MORE, 2, enable_unit },
5646 { "preset", MORE, 2, enable_unit },
5647 { "mask", MORE, 2, enable_unit },
5648 { "unmask", MORE, 2, enable_unit },
5649 { "link", MORE, 2, enable_unit },
5650 { "switch-root", MORE, 2, switch_root },
5651 { "list-dependencies", LESS, 2, list_dependencies },
5652 { "set-default", EQUAL, 2, enable_unit },
5653 { "get-default", LESS, 1, get_default },
5654 { "set-property", MORE, 3, set_property },
5655 };
5656
5657 int left;
5658 unsigned i;
5659
5660 assert(argc >= 0);
5661 assert(argv);
5662
5663 left = argc - optind;
5664
5665 if (left <= 0)
5666 /* Special rule: no arguments means "list-units" */
5667 i = 0;
5668 else {
5669 if (streq(argv[optind], "help") && !argv[optind+1]) {
5670 log_error("This command expects one or more "
5671 "unit names. Did you mean --help?");
5672 return -EINVAL;
5673 }
5674
5675 for (i = 0; i < ELEMENTSOF(verbs); i++)
5676 if (streq(argv[optind], verbs[i].verb))
5677 break;
5678
5679 if (i >= ELEMENTSOF(verbs)) {
5680 log_error("Unknown operation '%s'.", argv[optind]);
5681 return -EINVAL;
5682 }
5683 }
5684
5685 switch (verbs[i].argc_cmp) {
5686
5687 case EQUAL:
5688 if (left != verbs[i].argc) {
5689 log_error("Invalid number of arguments.");
5690 return -EINVAL;
5691 }
5692
5693 break;
5694
5695 case MORE:
5696 if (left < verbs[i].argc) {
5697 log_error("Too few arguments.");
5698 return -EINVAL;
5699 }
5700
5701 break;
5702
5703 case LESS:
5704 if (left > verbs[i].argc) {
5705 log_error("Too many arguments.");
5706 return -EINVAL;
5707 }
5708
5709 break;
5710
5711 default:
5712 assert_not_reached("Unknown comparison operator.");
5713 }
5714
5715 /* Require a bus connection for all operations but
5716 * enable/disable */
5717 if (!streq(verbs[i].verb, "enable") &&
5718 !streq(verbs[i].verb, "disable") &&
5719 !streq(verbs[i].verb, "is-enabled") &&
5720 !streq(verbs[i].verb, "list-unit-files") &&
5721 !streq(verbs[i].verb, "reenable") &&
5722 !streq(verbs[i].verb, "preset") &&
5723 !streq(verbs[i].verb, "mask") &&
5724 !streq(verbs[i].verb, "unmask") &&
5725 !streq(verbs[i].verb, "link") &&
5726 !streq(verbs[i].verb, "set-default") &&
5727 !streq(verbs[i].verb, "get-default")) {
5728
5729 if (running_in_chroot() > 0) {
5730 log_info("Running in chroot, ignoring request.");
5731 return 0;
5732 }
5733
5734 if (((!streq(verbs[i].verb, "reboot") &&
5735 !streq(verbs[i].verb, "halt") &&
5736 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5737 log_error("Failed to get D-Bus connection: %s", strerror (-bus_error));
5738 return -EIO;
5739 }
5740
5741 } else {
5742
5743 if (!bus && !avoid_bus()) {
5744 log_error("Failed to get D-Bus connection: %s", strerror (-bus_error));
5745 return -EIO;
5746 }
5747 }
5748
5749 return verbs[i].dispatch(bus, argv + optind);
5750 }
5751
5752 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5753
5754 struct sd_shutdown_command c = {
5755 .usec = t,
5756 .mode = mode,
5757 .dry_run = dry_run,
5758 .warn_wall = warn,
5759 };
5760
5761 union sockaddr_union sockaddr = {
5762 .un.sun_family = AF_UNIX,
5763 .un.sun_path = "/run/systemd/shutdownd",
5764 };
5765
5766 struct iovec iovec[2] = {{
5767 .iov_base = (char*) &c,
5768 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5769 }};
5770
5771 struct msghdr msghdr = {
5772 .msg_name = &sockaddr,
5773 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5774 + sizeof("/run/systemd/shutdownd") - 1,
5775 .msg_iov = iovec,
5776 .msg_iovlen = 1,
5777 };
5778
5779 _cleanup_close_ int fd;
5780
5781 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5782 if (fd < 0)
5783 return -errno;
5784
5785 if (!isempty(message)) {
5786 iovec[1].iov_base = (char*) message;
5787 iovec[1].iov_len = strlen(message);
5788 msghdr.msg_iovlen++;
5789 }
5790
5791 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5792 return -errno;
5793
5794 return 0;
5795 }
5796
5797 static int reload_with_fallback(sd_bus *bus) {
5798
5799 if (bus) {
5800 /* First, try systemd via D-Bus. */
5801 if (daemon_reload(bus, NULL) >= 0)
5802 return 0;
5803 }
5804
5805 /* Nothing else worked, so let's try signals */
5806 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5807
5808 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5809 log_error("kill() failed: %m");
5810 return -errno;
5811 }
5812
5813 return 0;
5814 }
5815
5816 static int start_with_fallback(sd_bus *bus) {
5817
5818 if (bus) {
5819 /* First, try systemd via D-Bus. */
5820 if (start_unit(bus, NULL) >= 0)
5821 goto done;
5822 }
5823
5824 /* Nothing else worked, so let's try
5825 * /dev/initctl */
5826 if (talk_initctl() > 0)
5827 goto done;
5828
5829 log_error("Failed to talk to init daemon.");
5830 return -EIO;
5831
5832 done:
5833 warn_wall(arg_action);
5834 return 0;
5835 }
5836
5837 static int halt_now(enum action a) {
5838
5839 /* Make sure C-A-D is handled by the kernel from this
5840 * point on... */
5841 reboot(RB_ENABLE_CAD);
5842
5843 switch (a) {
5844
5845 case ACTION_HALT:
5846 log_info("Halting.");
5847 reboot(RB_HALT_SYSTEM);
5848 return -errno;
5849
5850 case ACTION_POWEROFF:
5851 log_info("Powering off.");
5852 reboot(RB_POWER_OFF);
5853 return -errno;
5854
5855 case ACTION_REBOOT: {
5856 _cleanup_free_ char *param = NULL;
5857
5858 if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
5859 log_info("Rebooting with argument '%s'.", param);
5860 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
5861 LINUX_REBOOT_CMD_RESTART2, param);
5862 }
5863
5864 log_info("Rebooting.");
5865 reboot(RB_AUTOBOOT);
5866 return -errno;
5867 }
5868
5869 default:
5870 assert_not_reached("Unknown action.");
5871 }
5872 }
5873
5874 static int halt_main(sd_bus *bus) {
5875 int r;
5876
5877 r = check_inhibitors(bus, arg_action);
5878 if (r < 0)
5879 return r;
5880
5881 if (geteuid() != 0) {
5882 /* Try logind if we are a normal user and no special
5883 * mode applies. Maybe PolicyKit allows us to shutdown
5884 * the machine. */
5885
5886 if (arg_when <= 0 &&
5887 !arg_dry &&
5888 arg_force <= 0 &&
5889 (arg_action == ACTION_POWEROFF ||
5890 arg_action == ACTION_REBOOT)) {
5891 r = reboot_with_logind(bus, arg_action);
5892 if (r >= 0)
5893 return r;
5894 }
5895
5896 log_error("Must be root.");
5897 return -EPERM;
5898 }
5899
5900 if (arg_when > 0) {
5901 _cleanup_free_ char *m;
5902
5903 m = strv_join(arg_wall, " ");
5904 if (!m)
5905 return log_oom();
5906
5907 r = send_shutdownd(arg_when,
5908 arg_action == ACTION_HALT ? 'H' :
5909 arg_action == ACTION_POWEROFF ? 'P' :
5910 arg_action == ACTION_KEXEC ? 'K' :
5911 'r',
5912 arg_dry,
5913 !arg_no_wall,
5914 m);
5915
5916 if (r < 0)
5917 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5918 else {
5919 char date[FORMAT_TIMESTAMP_MAX];
5920
5921 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5922 format_timestamp(date, sizeof(date), arg_when));
5923 return 0;
5924 }
5925 }
5926
5927 if (!arg_dry && !arg_force)
5928 return start_with_fallback(bus);
5929
5930 if (!arg_no_wtmp) {
5931 if (sd_booted() > 0)
5932 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5933 else {
5934 r = utmp_put_shutdown();
5935 if (r < 0)
5936 log_warning("Failed to write utmp record: %s", strerror(-r));
5937 }
5938 }
5939
5940 if (arg_dry)
5941 return 0;
5942
5943 r = halt_now(arg_action);
5944 log_error("Failed to reboot: %s", strerror(-r));
5945
5946 return r;
5947 }
5948
5949 static int runlevel_main(void) {
5950 int r, runlevel, previous;
5951
5952 r = utmp_get_runlevel(&runlevel, &previous);
5953 if (r < 0) {
5954 puts("unknown");
5955 return r;
5956 }
5957
5958 printf("%c %c\n",
5959 previous <= 0 ? 'N' : previous,
5960 runlevel <= 0 ? 'N' : runlevel);
5961
5962 return 0;
5963 }
5964
5965 int main(int argc, char*argv[]) {
5966 _cleanup_bus_unref_ sd_bus *bus = NULL;
5967 int r;
5968
5969 setlocale(LC_ALL, "");
5970 log_parse_environment();
5971 log_open();
5972
5973 /* Explicitly not on_tty() to avoid setting cached value.
5974 * This becomes relevant for piping output which might be
5975 * ellipsized. */
5976 original_stdout_is_tty = isatty(STDOUT_FILENO);
5977
5978 r = parse_argv(argc, argv);
5979 if (r <= 0)
5980 goto finish;
5981
5982 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5983 * let's shortcut this */
5984 if (arg_action == ACTION_RUNLEVEL) {
5985 r = runlevel_main();
5986 goto finish;
5987 }
5988
5989 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5990 log_info("Running in chroot, ignoring request.");
5991 r = 0;
5992 goto finish;
5993 }
5994
5995 if (!avoid_bus())
5996 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
5997
5998 /* systemctl_main() will print an error message for the bus
5999 * connection, but only if it needs to */
6000
6001 switch (arg_action) {
6002
6003 case ACTION_SYSTEMCTL:
6004 r = systemctl_main(bus, argc, argv, r);
6005 break;
6006
6007 case ACTION_HALT:
6008 case ACTION_POWEROFF:
6009 case ACTION_REBOOT:
6010 case ACTION_KEXEC:
6011 r = halt_main(bus);
6012 break;
6013
6014 case ACTION_RUNLEVEL2:
6015 case ACTION_RUNLEVEL3:
6016 case ACTION_RUNLEVEL4:
6017 case ACTION_RUNLEVEL5:
6018 case ACTION_RESCUE:
6019 case ACTION_EMERGENCY:
6020 case ACTION_DEFAULT:
6021 r = start_with_fallback(bus);
6022 break;
6023
6024 case ACTION_RELOAD:
6025 case ACTION_REEXEC:
6026 r = reload_with_fallback(bus);
6027 break;
6028
6029 case ACTION_CANCEL_SHUTDOWN: {
6030 _cleanup_free_ char *m = NULL;
6031
6032 if (arg_wall) {
6033 m = strv_join(arg_wall, " ");
6034 if (!m) {
6035 r = log_oom();
6036 goto finish;
6037 }
6038 }
6039
6040 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6041 if (r < 0)
6042 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6043 break;
6044 }
6045
6046 case ACTION_RUNLEVEL:
6047 case _ACTION_INVALID:
6048 default:
6049 assert_not_reached("Unknown action");
6050 }
6051
6052 finish:
6053 pager_close();
6054 ask_password_agent_close();
6055 polkit_agent_close();
6056
6057 strv_free(arg_types);
6058 strv_free(arg_states);
6059 strv_free(arg_properties);
6060
6061 return r < 0 ? EXIT_FAILURE : r;
6062 }