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