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