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