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