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