chiark / gitweb /
build: Allow disabling maintainer mode
[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
537         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
538         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
539         const char *type, *path;
540         int r, n = 0;
541
542         r = sd_bus_get_property(
543                         bus,
544                         "org.freedesktop.systemd1",
545                         unit_path,
546                         "org.freedesktop.systemd1.Socket",
547                         "Listen",
548                         &error,
549                         &reply,
550                         "a(ss)");
551         if (r < 0) {
552                 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
553                 return r;
554         }
555
556         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
557         if (r < 0)
558                 return bus_log_parse_error(r);
559
560         while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
561
562                 r = strv_extend(listening, type);
563                 if (r < 0)
564                         return log_oom();
565
566                 r = strv_extend(listening, path);
567                 if (r < 0)
568                         return log_oom();
569
570                 n++;
571         }
572         if (r < 0)
573                 return bus_log_parse_error(r);
574
575         r = sd_bus_message_exit_container(reply);
576         if (r < 0)
577                 return bus_log_parse_error(r);
578
579         return n;
580 }
581
582 struct socket_info {
583         const char* id;
584
585         char* type;
586         char* path;
587
588         /* Note: triggered is a list here, although it almost certainly
589          * will always be one unit. Nevertheless, dbus API allows for multiple
590          * values, so let's follow that.*/
591         char** triggered;
592
593         /* The strv above is shared. free is set only in the first one. */
594         bool own_triggered;
595 };
596
597 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
598         int o;
599
600         assert(a);
601         assert(b);
602
603         o = strcmp(a->path, b->path);
604         if (o == 0)
605                 o = strcmp(a->type, b->type);
606
607         return o;
608 }
609
610 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
611         struct socket_info *s;
612         unsigned pathlen = sizeof("LISTEN") - 1,
613                 typelen = (sizeof("TYPE") - 1) * arg_show_types,
614                 socklen = sizeof("UNIT") - 1,
615                 servlen = sizeof("ACTIVATES") - 1;
616         const char *on, *off;
617
618         for (s = socket_infos; s < socket_infos + cs; s++) {
619                 unsigned tmp = 0;
620                 char **a;
621
622                 socklen = MAX(socklen, strlen(s->id));
623                 if (arg_show_types)
624                         typelen = MAX(typelen, strlen(s->type));
625                 pathlen = MAX(pathlen, strlen(s->path));
626
627                 STRV_FOREACH(a, s->triggered)
628                         tmp += strlen(*a) + 2*(a != s->triggered);
629                 servlen = MAX(servlen, tmp);
630         }
631
632         if (cs) {
633                 if (!arg_no_legend)
634                         printf("%-*s %-*.*s%-*s %s\n",
635                                pathlen, "LISTEN",
636                                typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
637                                socklen, "UNIT",
638                                "ACTIVATES");
639
640                 for (s = socket_infos; s < socket_infos + cs; s++) {
641                         char **a;
642
643                         if (arg_show_types)
644                                 printf("%-*s %-*s %-*s",
645                                        pathlen, s->path, typelen, s->type, socklen, s->id);
646                         else
647                                 printf("%-*s %-*s",
648                                        pathlen, s->path, socklen, s->id);
649                         STRV_FOREACH(a, s->triggered)
650                                 printf("%s %s",
651                                        a == s->triggered ? "" : ",", *a);
652                         printf("\n");
653                 }
654
655                 on = ansi_highlight();
656                 off = ansi_highlight_off();
657                 if (!arg_no_legend)
658                         printf("\n");
659         } else {
660                 on = ansi_highlight_red();
661                 off = ansi_highlight_off();
662         }
663
664         if (!arg_no_legend) {
665                 printf("%s%u sockets listed.%s\n", on, cs, off);
666                 if (!arg_all)
667                         printf("Pass --all to see loaded but inactive sockets, too.\n");
668         }
669
670         return 0;
671 }
672
673 static int list_sockets(sd_bus *bus, char **args) {
674         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
675         _cleanup_free_ UnitInfo *unit_infos = NULL;
676         struct socket_info *socket_infos = NULL;
677         const UnitInfo *u;
678         struct socket_info *s;
679         unsigned cs = 0;
680         size_t size = 0;
681         int r = 0, n;
682
683         pager_open_if_enabled();
684
685         n = get_unit_list(bus, &reply, &unit_infos);
686         if (n < 0)
687                 return n;
688
689         for (u = unit_infos; u < unit_infos + n; u++) {
690                 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
691                 int i, c;
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                 c = get_listening(bus, u->unit_path, &listening);
704                 if (c < 0) {
705                         r = c;
706                         goto cleanup;
707                 }
708
709                 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
710                         r = log_oom();
711                         goto cleanup;
712                 }
713
714                 for (i = 0; i < c; i++)
715                         socket_infos[cs + i] = (struct socket_info) {
716                                 .id = u->id,
717                                 .type = listening[i*2],
718                                 .path = listening[i*2 + 1],
719                                 .triggered = triggered,
720                                 .own_triggered = i==0,
721                         };
722
723                 /* from this point on we will cleanup those socket_infos */
724                 cs += c;
725                 free(listening);
726                 listening = triggered = NULL; /* avoid cleanup */
727         }
728
729         qsort_safe(socket_infos, cs, sizeof(struct socket_info),
730                    (__compar_fn_t) socket_info_compare);
731
732         output_sockets_list(socket_infos, cs);
733
734  cleanup:
735         assert(cs == 0 || socket_infos);
736         for (s = socket_infos; s < socket_infos + cs; s++) {
737                 free(s->type);
738                 free(s->path);
739                 if (s->own_triggered)
740                         strv_free(s->triggered);
741         }
742         free(socket_infos);
743
744         return r;
745 }
746
747 static int get_next_elapse(
748                 sd_bus *bus,
749                 const char *path,
750                 dual_timestamp *next) {
751
752         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
753         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
754         dual_timestamp t;
755         int r;
756
757         assert(bus);
758         assert(path);
759         assert(next);
760
761         r = sd_bus_get_property_trivial(
762                         bus,
763                         "org.freedesktop.systemd1",
764                         path,
765                         "org.freedesktop.systemd1.Timer",
766                         "NextElapseUSecMonotonic",
767                         &error,
768                         't',
769                         &t.monotonic);
770         if (r < 0) {
771                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
772                 return r;
773         }
774
775         r = sd_bus_get_property_trivial(
776                         bus,
777                         "org.freedesktop.systemd1",
778                         path,
779                         "org.freedesktop.systemd1.Timer",
780                         "NextElapseUSecRealtime",
781                         &error,
782                         't',
783                         &t.realtime);
784         if (r < 0) {
785                 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
786                 return r;
787         }
788
789         *next = t;
790         return 0;
791 }
792
793 struct timer_info {
794         const char* id;
795         usec_t next_elapse;
796         char** triggered;
797 };
798
799 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
800         assert(a);
801         assert(b);
802
803         if (a->next_elapse < b->next_elapse)
804                 return -1;
805         if (a->next_elapse > b->next_elapse)
806                 return 1;
807
808         return strcmp(a->id, b->id);
809 }
810
811 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
812         struct timer_info *t;
813         unsigned
814                 nextlen = sizeof("NEXT") - 1,
815                 leftlen = sizeof("LEFT") - 1,
816                 unitlen = sizeof("UNIT") - 1,
817                 activatelen = sizeof("ACTIVATES") - 1;
818
819         const char *on, *off;
820
821         assert(timer_infos || n == 0);
822
823         for (t = timer_infos; t < timer_infos + n; t++) {
824                 unsigned ul = 0;
825                 char **a;
826
827                 if (t->next_elapse > 0) {
828                         char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
829
830                         format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
831                         nextlen = MAX(nextlen, strlen(tstamp) + 1);
832
833                         format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
834                         leftlen = MAX(leftlen, strlen(trel));
835                 }
836
837                 unitlen = MAX(unitlen, strlen(t->id));
838
839                 STRV_FOREACH(a, t->triggered)
840                         ul += strlen(*a) + 2*(a != t->triggered);
841                 activatelen = MAX(activatelen, ul);
842         }
843
844         if (n > 0) {
845                 if (!arg_no_legend)
846                         printf("%-*s %-*s %-*s %s\n",
847                                nextlen, "NEXT",
848                                leftlen, "LEFT",
849                                unitlen, "UNIT",
850                                         "ACTIVATES");
851
852                 for (t = timer_infos; t < timer_infos + n; t++) {
853                         char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
854                         char **a;
855
856                         format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
857                         format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
858
859                         printf("%-*s %-*s %-*s",
860                                nextlen, tstamp, leftlen, trel, unitlen, t->id);
861
862                         STRV_FOREACH(a, t->triggered)
863                                 printf("%s %s",
864                                        a == t->triggered ? "" : ",", *a);
865                         printf("\n");
866                 }
867
868                 on = ansi_highlight();
869                 off = ansi_highlight_off();
870                 if (!arg_no_legend)
871                         printf("\n");
872         } else {
873                 on = ansi_highlight_red();
874                 off = ansi_highlight_off();
875         }
876
877         if (!arg_no_legend) {
878                 printf("%s%u timers listed.%s\n", on, n, off);
879                 if (!arg_all)
880                         printf("Pass --all to see loaded but inactive timers, too.\n");
881         }
882
883         return 0;
884 }
885
886 static int list_timers(sd_bus *bus, char **args) {
887
888         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
889         _cleanup_free_ struct timer_info *timer_infos = NULL;
890         _cleanup_free_ UnitInfo *unit_infos = NULL;
891         struct timer_info *t;
892         const UnitInfo *u;
893         size_t size = 0;
894         int n, c = 0;
895         dual_timestamp nw;
896         int r = 0;
897
898         pager_open_if_enabled();
899
900         n = get_unit_list(bus, &reply, &unit_infos);
901         if (n < 0)
902                 return n;
903
904         dual_timestamp_get(&nw);
905
906         for (u = unit_infos; u < unit_infos + n; u++) {
907                 _cleanup_strv_free_ char **triggered = NULL;
908                 dual_timestamp next;
909                 usec_t m;
910
911                 if (!output_show_unit(u))
912                         continue;
913
914                 if (!endswith(u->id, ".timer"))
915                         continue;
916
917                 r = get_triggered_units(bus, u->unit_path, &triggered);
918                 if (r < 0)
919                         goto cleanup;
920
921                 r = get_next_elapse(bus, u->unit_path, &next);
922                 if (r < 0)
923                         goto cleanup;
924
925                 if (next.monotonic != (usec_t) -1 && next.monotonic > 0) {
926                         usec_t converted;
927
928                         if (next.monotonic > nw.monotonic)
929                                 converted = nw.realtime + (next.monotonic - nw.monotonic);
930                         else
931                                 converted = nw.realtime - (nw.monotonic - next.monotonic);
932
933                         if (next.realtime != (usec_t) -1 && next.realtime > 0)
934                                 m = MIN(converted, next.realtime);
935                         else
936                                 m = converted;
937                 } else
938                         m = next.realtime;
939
940                 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
941                         r = log_oom();
942                         goto cleanup;
943                 }
944
945                 timer_infos[c++] = (struct timer_info) {
946                         .id = u->id,
947                         .next_elapse = m,
948                         .triggered = triggered,
949                 };
950
951                 triggered = NULL; /* avoid cleanup */
952         }
953
954         qsort_safe(timer_infos, c, sizeof(struct timer_info),
955                    (__compar_fn_t) timer_info_compare);
956
957         output_timers_list(timer_infos, c);
958
959  cleanup:
960         for (t = timer_infos; t < timer_infos + c; t++)
961                 strv_free(t->triggered);
962
963         return r;
964 }
965
966 static int compare_unit_file_list(const void *a, const void *b) {
967         const char *d1, *d2;
968         const UnitFileList *u = a, *v = b;
969
970         d1 = strrchr(u->path, '.');
971         d2 = strrchr(v->path, '.');
972
973         if (d1 && d2) {
974                 int r;
975
976                 r = strcasecmp(d1, d2);
977                 if (r != 0)
978                         return r;
979         }
980
981         return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
982 }
983
984 static bool output_show_unit_file(const UnitFileList *u) {
985         const char *dot;
986
987         return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
988 }
989
990 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
991         unsigned max_id_len, id_cols, state_cols, n_shown = 0;
992         const UnitFileList *u;
993
994         max_id_len = sizeof("UNIT FILE")-1;
995         state_cols = sizeof("STATE")-1;
996
997         for (u = units; u < units + c; u++) {
998                 if (!output_show_unit_file(u))
999                         continue;
1000
1001                 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
1002                 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1003         }
1004
1005         if (!arg_full) {
1006                 unsigned basic_cols;
1007
1008                 id_cols = MIN(max_id_len, 25u);
1009                 basic_cols = 1 + id_cols + state_cols;
1010                 if (basic_cols < (unsigned) columns())
1011                         id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1012         } else
1013                 id_cols = max_id_len;
1014
1015         if (!arg_no_legend)
1016                 printf("%-*s %-*s\n",
1017                        id_cols, "UNIT FILE",
1018                        state_cols, "STATE");
1019
1020         for (u = units; u < units + c; u++) {
1021                 _cleanup_free_ char *e = NULL;
1022                 const char *on, *off;
1023                 const char *id;
1024
1025                 if (!output_show_unit_file(u))
1026                         continue;
1027
1028                 n_shown++;
1029
1030                 if (u->state == UNIT_FILE_MASKED ||
1031                     u->state == UNIT_FILE_MASKED_RUNTIME ||
1032                     u->state == UNIT_FILE_DISABLED ||
1033                     u->state == UNIT_FILE_INVALID) {
1034                         on  = ansi_highlight_red();
1035                         off = ansi_highlight_off();
1036                 } else if (u->state == UNIT_FILE_ENABLED) {
1037                         on  = ansi_highlight_green();
1038                         off = ansi_highlight_off();
1039                 } else
1040                         on = off = "";
1041
1042                 id = path_get_file_name(u->path);
1043
1044                 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1045
1046                 printf("%-*s %s%-*s%s\n",
1047                        id_cols, e ? e : id,
1048                        on, state_cols, unit_file_state_to_string(u->state), off);
1049         }
1050
1051         if (!arg_no_legend)
1052                 printf("\n%u unit files listed.\n", n_shown);
1053 }
1054
1055 static int list_unit_files(sd_bus *bus, char **args) {
1056         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1057         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1058         _cleanup_free_ UnitFileList *units = NULL;
1059         unsigned c = 0;
1060         const char *state;
1061         char *path;
1062         int r;
1063
1064         pager_open_if_enabled();
1065
1066         if (avoid_bus()) {
1067                 Hashmap *h;
1068                 UnitFileList *u;
1069                 Iterator i;
1070                 unsigned n_units;
1071
1072                 h = hashmap_new(string_hash_func, string_compare_func);
1073                 if (!h)
1074                         return log_oom();
1075
1076                 r = unit_file_get_list(arg_scope, arg_root, h);
1077                 if (r < 0) {
1078                         unit_file_list_free(h);
1079                         log_error("Failed to get unit file list: %s", strerror(-r));
1080                         return r;
1081                 }
1082
1083                 n_units = hashmap_size(h);
1084                 units = new(UnitFileList, n_units);
1085                 if (!units) {
1086                         unit_file_list_free(h);
1087                         return log_oom();
1088                 }
1089
1090                 HASHMAP_FOREACH(u, h, i) {
1091                         memcpy(units + c++, u, sizeof(UnitFileList));
1092                         free(u);
1093                 }
1094
1095                 assert(c == n_units);
1096                 hashmap_free(h);
1097         } else {
1098                 size_t size = 0;
1099
1100                 r = sd_bus_call_method(
1101                                 bus,
1102                                 "org.freedesktop.systemd1",
1103                                 "/org/freedesktop/systemd1",
1104                                 "org.freedesktop.systemd1.Manager",
1105                                 "ListUnitFiles",
1106                                 &error,
1107                                 &reply,
1108                                 NULL);
1109                 if (r < 0) {
1110                         log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1111                         return r;
1112                 }
1113
1114                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1115                 if (r < 0)
1116                         return bus_log_parse_error(r);
1117
1118                 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1119
1120                         if (!GREEDY_REALLOC(units, size, c + 1))
1121                                 return log_oom();
1122
1123                         units[c++] = (struct UnitFileList) {
1124                                 path,
1125                                 unit_file_state_from_string(state)
1126                         };
1127                 }
1128                 if (r < 0)
1129                         return bus_log_parse_error(r);
1130
1131                 r = sd_bus_message_exit_container(reply);
1132                 if (r < 0)
1133                         return bus_log_parse_error(r);
1134         }
1135
1136         if (c > 0) {
1137                 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1138                 output_unit_file_list(units, c);
1139         }
1140
1141         return 0;
1142 }
1143
1144 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1145         _cleanup_free_ char *n = NULL;
1146         size_t max_len = MAX(columns(),20u);
1147         size_t len = 0;
1148         int i;
1149
1150         if (!arg_plain) {
1151
1152                 for (i = level - 1; i >= 0; i--) {
1153                         len += 2;
1154                         if(len > max_len - 3 && !arg_full) {
1155                                 printf("%s...\n",max_len % 2 ? "" : " ");
1156                                 return 0;
1157                         }
1158                         printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1159                 }
1160                 len += 2;
1161
1162                 if(len > max_len - 3 && !arg_full) {
1163                         printf("%s...\n",max_len % 2 ? "" : " ");
1164                         return 0;
1165                 }
1166
1167                 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1168         }
1169
1170         if (arg_full){
1171                 printf("%s\n", name);
1172                 return 0;
1173         }
1174
1175         n = ellipsize(name, max_len-len, 100);
1176         if(!n)
1177                 return log_oom();
1178
1179         printf("%s\n", n);
1180         return 0;
1181 }
1182
1183 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1184
1185         static const char *dependencies[] = {
1186                 [DEPENDENCY_FORWARD] = "Requires\0"
1187                                        "RequiresOverridable\0"
1188                                        "Requisite\0"
1189                                        "RequisiteOverridable\0"
1190                                        "Wants\0",
1191                 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1192                                        "RequiredByOverridable\0"
1193                                        "WantedBy\0"
1194                                        "PartOf\0",
1195                 [DEPENDENCY_AFTER]   = "After\0",
1196                 [DEPENDENCY_BEFORE]  = "Before\0",
1197         };
1198
1199         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1200         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1201         _cleanup_strv_free_ char **ret = NULL;
1202         _cleanup_free_ char *path = NULL;
1203         int r;
1204
1205         assert(bus);
1206         assert(name);
1207         assert(deps);
1208         assert(arg_dependency < ELEMENTSOF(dependencies));
1209
1210         path = unit_dbus_path_from_name(name);
1211         if (!path)
1212                 return log_oom();
1213
1214         r = sd_bus_call_method(
1215                         bus,
1216                         "org.freedesktop.systemd1",
1217                         path,
1218                         "org.freedesktop.DBus.Properties",
1219                         "GetAll",
1220                         &error,
1221                         &reply,
1222                         "s", "org.freedesktop.systemd1.Unit");
1223         if (r < 0) {
1224                 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1225                 return r;
1226         }
1227
1228         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1229         if (r < 0)
1230                 return bus_log_parse_error(r);
1231
1232         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1233                 const char *prop;
1234
1235                 r = sd_bus_message_read(reply, "s", &prop);
1236                 if (r < 0)
1237                         return bus_log_parse_error(r);
1238
1239                 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1240                         r = sd_bus_message_skip(reply, "v");
1241                         if (r < 0)
1242                                 return bus_log_parse_error(r);
1243                 } else {
1244
1245                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1246                         if (r < 0)
1247                                 return bus_log_parse_error(r);
1248
1249                         r = bus_message_read_strv_extend(reply, &ret);
1250                         if (r < 0)
1251                                 return bus_log_parse_error(r);
1252
1253                         r = sd_bus_message_exit_container(reply);
1254                         if (r < 0)
1255                                 return bus_log_parse_error(r);
1256                 }
1257
1258                 r = sd_bus_message_exit_container(reply);
1259                 if (r < 0)
1260                         return bus_log_parse_error(r);
1261
1262         }
1263         if (r < 0)
1264                 return bus_log_parse_error(r);
1265
1266         r = sd_bus_message_exit_container(reply);
1267         if (r < 0)
1268                 return bus_log_parse_error(r);
1269
1270         *deps = ret;
1271         ret = NULL;
1272
1273         return 0;
1274 }
1275
1276 static int list_dependencies_compare(const void *_a, const void *_b) {
1277         const char **a = (const char**) _a, **b = (const char**) _b;
1278
1279         if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1280                 return 1;
1281         if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1282                 return -1;
1283
1284         return strcasecmp(*a, *b);
1285 }
1286
1287 static int list_dependencies_one(
1288                 sd_bus *bus,
1289                 const char *name,
1290                 int level,
1291                 char ***units,
1292                 unsigned int branches) {
1293
1294         _cleanup_strv_free_ char **deps = NULL, **u;
1295         char **c;
1296         int r = 0;
1297
1298         assert(bus);
1299         assert(name);
1300         assert(units);
1301
1302         u = strv_append(*units, name);
1303         if (!u)
1304                 return log_oom();
1305
1306         r = list_dependencies_get_dependencies(bus, name, &deps);
1307         if (r < 0)
1308                 return r;
1309
1310         qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1311
1312         STRV_FOREACH(c, deps) {
1313                 if (strv_contains(u, *c)) {
1314                         if (!arg_plain) {
1315                                 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1316                                 if (r < 0)
1317                                         return r;
1318                         }
1319                         continue;
1320                 }
1321
1322                 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1323                 if (r < 0)
1324                         return r;
1325
1326                 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1327                        r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1328                        if(r < 0)
1329                                return r;
1330                 }
1331         }
1332
1333         if (arg_plain) {
1334                 strv_free(*units);
1335                 *units = u;
1336                 u = NULL;
1337         }
1338
1339         return 0;
1340 }
1341
1342 static int list_dependencies(sd_bus *bus, char **args) {
1343         _cleanup_strv_free_ char **units = NULL;
1344         _cleanup_free_ char *unit = NULL;
1345         const char *u;
1346
1347         assert(bus);
1348
1349         if (args[1]) {
1350                 unit = unit_name_mangle(args[1]);
1351                 if (!unit)
1352                         return log_oom();
1353                 u = unit;
1354         } else
1355                 u = SPECIAL_DEFAULT_TARGET;
1356
1357         pager_open_if_enabled();
1358
1359         puts(u);
1360
1361         return list_dependencies_one(bus, u, 0, &units, 0);
1362 }
1363
1364 static int get_default(sd_bus *bus, char **args) {
1365         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1366         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1367         _cleanup_free_ char *_path = NULL;
1368         const char *path;
1369         int r;
1370
1371         if (!bus || avoid_bus()) {
1372                 r = unit_file_get_default(arg_scope, arg_root, &_path);
1373                 if (r < 0) {
1374                         log_error("Failed to get default target: %s", strerror(-r));
1375                         return r;
1376                 }
1377                 path = _path;
1378
1379         } else {
1380                 r = sd_bus_call_method(
1381                                 bus,
1382                                 "org.freedesktop.systemd1",
1383                                 "/org/freedesktop/systemd1",
1384                                 "org.freedesktop.systemd1.Manager",
1385                                 "GetDefaultTarget",
1386                                 &error,
1387                                 &reply,
1388                                 NULL);
1389                 if (r < 0) {
1390                         log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1391                         return r;
1392                 }
1393
1394                 r = sd_bus_message_read(reply, "s", &path);
1395                 if (r < 0)
1396                         return bus_log_parse_error(r);
1397         }
1398
1399         if (path)
1400                 printf("%s\n", path);
1401
1402         return 0;
1403 }
1404
1405 struct job_info {
1406         uint32_t id;
1407         const char *name, *type, *state;
1408 };
1409
1410 static void output_jobs_list(const struct job_info* jobs, unsigned n) {
1411         unsigned id_len, unit_len, type_len, state_len;
1412         const struct job_info *j;
1413         const char *on, *off;
1414         bool shorten = false;
1415
1416         assert(n == 0 || jobs);
1417
1418         if (n == 0) {
1419                 on = ansi_highlight_green();
1420                 off = ansi_highlight_off();
1421
1422                 printf("%sNo jobs running.%s\n", on, off);
1423                 return;
1424         }
1425
1426         pager_open_if_enabled();
1427
1428         id_len = sizeof("JOB")-1;
1429         unit_len = sizeof("UNIT")-1;
1430         type_len = sizeof("TYPE")-1;
1431         state_len = sizeof("STATE")-1;
1432
1433         for (j = jobs; j < jobs + n; j++) {
1434                 uint32_t id = j->id;
1435                 assert(j->name && j->type && j->state);
1436
1437                 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1438                 unit_len = MAX(unit_len, strlen(j->name));
1439                 type_len = MAX(type_len, strlen(j->type));
1440                 state_len = MAX(state_len, strlen(j->state));
1441         }
1442
1443         if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1444                 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1445                 shorten = true;
1446         }
1447
1448         printf("%*s %-*s %-*s %-*s\n",
1449                id_len, "JOB",
1450                unit_len, "UNIT",
1451                type_len, "TYPE",
1452                state_len, "STATE");
1453
1454         for (j = jobs; j < jobs + n; j++) {
1455                 _cleanup_free_ char *e = NULL;
1456
1457                 if (streq(j->state, "running")) {
1458                         on = ansi_highlight();
1459                         off = ansi_highlight_off();
1460                 } else
1461                         on = off = "";
1462
1463                 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1464                 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1465                        id_len, j->id,
1466                        on, unit_len, e ? e : j->name, off,
1467                        type_len, j->type,
1468                        on, state_len, j->state, off);
1469         }
1470
1471         on = ansi_highlight();
1472         off = ansi_highlight_off();
1473
1474         printf("\n%s%u jobs listed%s.\n", on, n, off);
1475 }
1476
1477 static int list_jobs(sd_bus *bus, char **args) {
1478         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1479         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1480         const char *name, *type, *state, *job_path, *unit_path;
1481         _cleanup_free_ struct job_info *jobs = NULL;
1482         size_t size = 0;
1483         unsigned c = 0;
1484         uint32_t id;
1485         int r;
1486
1487         r = sd_bus_call_method(
1488                         bus,
1489                         "org.freedesktop.systemd1",
1490                         "/org/freedesktop/systemd1",
1491                         "org.freedesktop.systemd1.Manager",
1492                         "ListJobs",
1493                         &error,
1494                         &reply,
1495                         NULL);
1496         if (r < 0) {
1497                 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
1498                 return r;
1499         }
1500
1501         r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
1502         if (r < 0)
1503                 return bus_log_parse_error(r);
1504
1505         while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
1506
1507                 if (!GREEDY_REALLOC(jobs, size, c + 1))
1508                         return log_oom();
1509
1510                 jobs[c++] = (struct job_info) {
1511                         id,
1512                         name,
1513                         type,
1514                         state
1515                 };
1516         }
1517         if (r < 0)
1518                 return bus_log_parse_error(r);
1519
1520         r = sd_bus_message_exit_container(reply);
1521         if (r < 0)
1522                 return bus_log_parse_error(r);
1523
1524         output_jobs_list(jobs, c);
1525         return r;
1526 }
1527
1528 static int cancel_job(sd_bus *bus, char **args) {
1529         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1530         char **name;
1531
1532         assert(args);
1533
1534         if (strv_length(args) <= 1)
1535                 return daemon_reload(bus, args);
1536
1537         STRV_FOREACH(name, args+1) {
1538                 uint32_t id;
1539                 int r;
1540
1541                 r = safe_atou32(*name, &id);
1542                 if (r < 0) {
1543                         log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
1544                         return r;
1545                 }
1546
1547                 r = sd_bus_call_method(
1548                                 bus,
1549                                 "org.freedesktop.systemd1",
1550                                 "/org/freedesktop/systemd1",
1551                                 "org.freedesktop.systemd1.Manager",
1552                                 "CancelJob",
1553                                 &error,
1554                                 NULL,
1555                                 "u", id);
1556                 if (r < 0) {
1557                         log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
1558                         return r;
1559                 }
1560         }
1561
1562         return 0;
1563 }
1564
1565 static int need_daemon_reload(sd_bus *bus, const char *unit) {
1566         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1567         _cleanup_free_ char *n = NULL;
1568         const char *path;
1569         int b, r;
1570
1571         /* We ignore all errors here, since this is used to show a
1572          * warning only */
1573
1574         n = unit_name_mangle(unit);
1575         if (!n)
1576                 return -ENOMEM;
1577
1578         /* We don't use unit_dbus_path_from_name() directly since we
1579          * don't want to load the unit if it isn't loaded. */
1580
1581         r = sd_bus_call_method(
1582                         bus,
1583                         "org.freedesktop.systemd1",
1584                         "/org/freedesktop/systemd1",
1585                         "org.freedesktop.systemd1.Manager",
1586                         "GetUnit",
1587                         NULL,
1588                         &reply,
1589                         "s", n);
1590         if (r < 0)
1591                 return r;
1592
1593         r = sd_bus_message_read(reply, "o", &path);
1594         if (r < 0)
1595                 return r;
1596
1597         r = sd_bus_get_property_trivial(
1598                         bus,
1599                         "org.freedesktop.systemd1",
1600                         path,
1601                         "org.freedesktop.systemd1.Unit",
1602                         "NeedDaemonReload",
1603                         NULL,
1604                         'b', &b);
1605         if (r < 0)
1606                 return r;
1607
1608         return b;
1609 }
1610
1611 typedef struct WaitData {
1612         Set *set;
1613
1614         char *name;
1615         char *result;
1616 } WaitData;
1617
1618 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data) {
1619         WaitData *d = data;
1620
1621         assert(bus);
1622         assert(m);
1623         assert(d);
1624
1625         log_debug("Got D-Bus request: %s.%s() on %s",
1626                   sd_bus_message_get_interface(m),
1627                   sd_bus_message_get_member(m),
1628                   sd_bus_message_get_path(m));
1629
1630         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1631                 log_error("Warning! D-Bus connection terminated.");
1632                 sd_bus_close(bus);
1633         } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1634                 uint32_t id;
1635                 const char *path, *result, *unit;
1636                 char *ret;
1637                 int r;
1638
1639                 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1640                 if (r >= 0) {
1641                         ret = set_remove(d->set, (char*) path);
1642                         if (!ret)
1643                                 return 0;
1644
1645                         free(ret);
1646
1647                         if (!isempty(result))
1648                                 d->result = strdup(result);
1649
1650                         if (!isempty(unit))
1651                                 d->name = strdup(unit);
1652
1653                         return 0;
1654                 }
1655 #ifndef NOLEGACY
1656                 r = sd_bus_message_read(m, "uos", &id, &path, &result);
1657                 if (r >= 0) {
1658                         ret = set_remove(d->set, (char*) path);
1659                         if (!ret)
1660                                 return 0;
1661
1662                         free(ret);
1663
1664                         if (*result)
1665                                 d->result = strdup(result);
1666
1667                         return 0;
1668                 }
1669 #endif
1670
1671                 log_error("Failed to parse message.");
1672         }
1673
1674         return 0;
1675 }
1676
1677 static int enable_wait_for_jobs(sd_bus *bus) {
1678         int r;
1679
1680         assert(bus);
1681
1682         r = sd_bus_add_match(
1683                         bus,
1684                         "type='signal',"
1685                         "sender='org.freedesktop.systemd1',"
1686                         "interface='org.freedesktop.systemd1.Manager',"
1687                         "member='JobRemoved',"
1688                         "path='/org/freedesktop/systemd1'",
1689                         NULL, NULL);
1690         if (r < 0) {
1691                 log_error("Failed to add match");
1692                 return -EIO;
1693         }
1694
1695         /* This is slightly dirty, since we don't undo the match registrations. */
1696         return 0;
1697 }
1698
1699 static int wait_for_jobs(sd_bus *bus, Set *s) {
1700         WaitData d = { .set = s };
1701         int r;
1702
1703         assert(bus);
1704         assert(s);
1705
1706         r = sd_bus_add_filter(bus, wait_filter, &d);
1707         if (r < 0)
1708                 return log_oom();
1709
1710         while (!set_isempty(s)) {
1711                 for(;;) {
1712                         r = sd_bus_process(bus, NULL);
1713                         if (r < 0)
1714                                 return r;
1715                         if (r > 0)
1716                                 break;
1717                         r = sd_bus_wait(bus, (uint64_t) -1);
1718                         if (r < 0)
1719                                 return r;
1720                 }
1721
1722                 if (!d.result)
1723                         goto free_name;
1724
1725                 if (!arg_quiet) {
1726                         if (streq(d.result, "timeout"))
1727                                 log_error("Job for %s timed out.", strna(d.name));
1728                         else if (streq(d.result, "canceled"))
1729                                 log_error("Job for %s canceled.", strna(d.name));
1730                         else if (streq(d.result, "dependency"))
1731                                 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1732                         else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1733                                 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1734                 }
1735
1736                 if (streq_ptr(d.result, "timeout"))
1737                         r = -ETIME;
1738                 else if (streq_ptr(d.result, "canceled"))
1739                         r = -ECANCELED;
1740                 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1741                         r = -EIO;
1742
1743                 free(d.result);
1744                 d.result = NULL;
1745
1746         free_name:
1747                 free(d.name);
1748                 d.name = NULL;
1749         }
1750
1751         return sd_bus_remove_filter(bus, wait_filter, &d);
1752 }
1753
1754 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
1755         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1756         _cleanup_free_ char *n = NULL, *state = NULL;
1757         const char *path;
1758         int r;
1759
1760         assert(name);
1761
1762         n = unit_name_mangle(name);
1763         if (!n)
1764                 return log_oom();
1765
1766         /* We don't use unit_dbus_path_from_name() directly since we
1767          * don't want to load the unit if it isn't loaded. */
1768
1769         r = sd_bus_call_method(
1770                         bus,
1771                         "org.freedesktop.systemd1",
1772                         "/org/freedesktop/systemd1",
1773                         "org.freedesktop.systemd1.Manager",
1774                         "GetUnit",
1775                         NULL,
1776                         &reply,
1777                         "s", n);
1778         if (r < 0) {
1779                 if (!quiet)
1780                         puts("unknown");
1781                 return 0;
1782         }
1783
1784         r = sd_bus_message_read(reply, "o", &path);
1785         if (r < 0)
1786                 return bus_log_parse_error(r);
1787
1788         r = sd_bus_get_property_string(
1789                         bus,
1790                         "org.freedesktop.systemd1",
1791                         path,
1792                         "org.freedesktop.systemd1.Unit",
1793                         "ActiveState",
1794                         NULL,
1795                         &state);
1796         if (r < 0) {
1797                 if (!quiet)
1798                         puts("unknown");
1799                 return 0;
1800         }
1801
1802         if (!quiet)
1803                 puts(state);
1804
1805         return nulstr_contains(good_states, state);
1806 }
1807
1808 static int check_triggering_units(
1809                 sd_bus *bus,
1810                 const char *name) {
1811
1812         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1813         _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
1814         _cleanup_strv_free_ char **triggered_by = NULL;
1815         bool print_warning_label = true;
1816         char **i;
1817         int r;
1818
1819         n = unit_name_mangle(name);
1820         if (!n)
1821                 return log_oom();
1822
1823         path = unit_dbus_path_from_name(n);
1824         if (!path)
1825                 return log_oom();
1826
1827         r = sd_bus_get_property_string(
1828                         bus,
1829                         "org.freedesktop.systemd1",
1830                         path,
1831                         "org.freedesktop.systemd1.Unit",
1832                         "LoadState",
1833                         &error,
1834                         &state);
1835         if (r < 0) {
1836                 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
1837                 return r;
1838         }
1839
1840         if (streq(state, "masked"))
1841                 return 0;
1842
1843         r = sd_bus_get_property_strv(
1844                         bus,
1845                         "org.freedesktop.systemd1",
1846                         path,
1847                         "org.freedesktop.systemd1.Unit",
1848                         "TriggeredBy",
1849                         &error,
1850                         &triggered_by);
1851         if (r < 0) {
1852                 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
1853                 return r;
1854         }
1855
1856         STRV_FOREACH(i, triggered_by) {
1857                 r = check_one_unit(bus, *i, "active\0reloading\0", true);
1858                 if (r < 0) {
1859                         log_error("Failed to check unit: %s", strerror(-r));
1860                         return r;
1861                 }
1862
1863                 if (r == 0)
1864                         continue;
1865
1866                 if (print_warning_label) {
1867                         log_warning("Warning: Stopping %s, but it can still be activated by:", n);
1868                         print_warning_label = false;
1869                 }
1870
1871                 log_warning("  %s", *i);
1872         }
1873
1874         return 0;
1875 }
1876
1877 static int start_unit_one(
1878                 sd_bus *bus,
1879                 const char *method,
1880                 const char *name,
1881                 const char *mode,
1882                 sd_bus_error *error,
1883                 Set *s) {
1884
1885         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1886         _cleanup_free_ char *n;
1887         const char *path;
1888         int r;
1889
1890         assert(method);
1891         assert(name);
1892         assert(mode);
1893         assert(error);
1894
1895         n = unit_name_mangle(name);
1896         if (!n)
1897                 return log_oom();
1898
1899         r = sd_bus_call_method(
1900                         bus,
1901                         "org.freedesktop.systemd1",
1902                         "/org/freedesktop/systemd1",
1903                         "org.freedesktop.systemd1.Manager",
1904                         method,
1905                         error,
1906                         &reply,
1907                         "ss", n, mode);
1908         if (r < 0) {
1909                 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1910                         /* There's always a fallback possible for
1911                          * legacy actions. */
1912                         return -EADDRNOTAVAIL;
1913
1914                 log_error("Failed to start %s: %s", name, bus_error_message(error, r));
1915                 return r;
1916         }
1917
1918         r = sd_bus_message_read(reply, "o", &path);
1919         if (r < 0)
1920                 return bus_log_parse_error(r);
1921
1922         if (need_daemon_reload(bus, n) > 0)
1923                 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
1924                             n, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
1925
1926         if (s) {
1927                 char *p;
1928
1929                 p = strdup(path);
1930                 if (!p)
1931                         return log_oom();
1932
1933                 r = set_consume(s, p);
1934                 if (r < 0)
1935                         return log_oom();
1936         }
1937
1938         return 0;
1939 }
1940
1941 static const struct {
1942         const char *target;
1943         const char *verb;
1944         const char *mode;
1945 } action_table[_ACTION_MAX] = {
1946         [ACTION_HALT]         = { SPECIAL_HALT_TARGET,         "halt",         "replace-irreversibly" },
1947         [ACTION_POWEROFF]     = { SPECIAL_POWEROFF_TARGET,     "poweroff",     "replace-irreversibly" },
1948         [ACTION_REBOOT]       = { SPECIAL_REBOOT_TARGET,       "reboot",       "replace-irreversibly" },
1949         [ACTION_KEXEC]        = { SPECIAL_KEXEC_TARGET,        "kexec",        "replace-irreversibly" },
1950         [ACTION_RUNLEVEL2]    = { SPECIAL_RUNLEVEL2_TARGET,    NULL,           "isolate" },
1951         [ACTION_RUNLEVEL3]    = { SPECIAL_RUNLEVEL3_TARGET,    NULL,           "isolate" },
1952         [ACTION_RUNLEVEL4]    = { SPECIAL_RUNLEVEL4_TARGET,    NULL,           "isolate" },
1953         [ACTION_RUNLEVEL5]    = { SPECIAL_RUNLEVEL5_TARGET,    NULL,           "isolate" },
1954         [ACTION_RESCUE]       = { SPECIAL_RESCUE_TARGET,       "rescue",       "isolate" },
1955         [ACTION_EMERGENCY]    = { SPECIAL_EMERGENCY_TARGET,    "emergency",    "isolate" },
1956         [ACTION_DEFAULT]      = { SPECIAL_DEFAULT_TARGET,      "default",      "isolate" },
1957         [ACTION_EXIT]         = { SPECIAL_EXIT_TARGET,         "exit",         "replace-irreversibly" },
1958         [ACTION_SUSPEND]      = { SPECIAL_SUSPEND_TARGET,      "suspend",      "replace-irreversibly" },
1959         [ACTION_HIBERNATE]    = { SPECIAL_HIBERNATE_TARGET,    "hibernate",    "replace-irreversibly" },
1960         [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1961 };
1962
1963 static enum action verb_to_action(const char *verb) {
1964         enum action i;
1965
1966         for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
1967                 if (streq_ptr(action_table[i].verb, verb))
1968                         return i;
1969
1970         return _ACTION_INVALID;
1971 }
1972
1973 static int start_unit(sd_bus *bus, char **args) {
1974         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1975         _cleanup_set_free_free_ Set *s = NULL;
1976         const char *method, *mode, *one_name;
1977         char **name;
1978         int r;
1979
1980         assert(bus);
1981
1982         ask_password_agent_open_if_enabled();
1983
1984         if (arg_action == ACTION_SYSTEMCTL) {
1985                 enum action action;
1986                 method =
1987                         streq(args[0], "stop") ||
1988                         streq(args[0], "condstop")              ? "StopUnit" :
1989                         streq(args[0], "reload")                ? "ReloadUnit" :
1990                         streq(args[0], "restart")               ? "RestartUnit" :
1991
1992                         streq(args[0], "try-restart")           ||
1993                         streq(args[0], "condrestart")           ? "TryRestartUnit" :
1994
1995                         streq(args[0], "reload-or-restart")     ? "ReloadOrRestartUnit" :
1996
1997                         streq(args[0], "reload-or-try-restart") ||
1998                         streq(args[0], "condreload")            ||
1999                         streq(args[0], "force-reload")          ? "ReloadOrTryRestartUnit" :
2000                                                                   "StartUnit";
2001                 action = verb_to_action(args[0]);
2002
2003                 mode = streq(args[0], "isolate") ? "isolate" :
2004                        action_table[action].mode ?: arg_job_mode;
2005
2006                 one_name = action_table[action].target;
2007         } else {
2008                 assert(arg_action < ELEMENTSOF(action_table));
2009                 assert(action_table[arg_action].target);
2010
2011                 method = "StartUnit";
2012
2013                 mode = action_table[arg_action].mode;
2014                 one_name = action_table[arg_action].target;
2015         }
2016
2017         if (!arg_no_block) {
2018                 r = enable_wait_for_jobs(bus);
2019                 if (r < 0) {
2020                         log_error("Could not watch jobs: %s", strerror(-r));
2021                         return r;
2022                 }
2023
2024                 s = set_new(string_hash_func, string_compare_func);
2025                 if (!s)
2026                         return log_oom();
2027         }
2028
2029         if (one_name) {
2030                 r = start_unit_one(bus, method, one_name, mode, &error, s);
2031                 if (r < 0)
2032                         r = translate_bus_error_to_exit_status(r, &error);
2033         } else {
2034                 r = 0;
2035
2036                 STRV_FOREACH(name, args+1) {
2037                         int q;
2038
2039                         q = start_unit_one(bus, method, *name, mode, &error, s);
2040                         if (q < 0) {
2041                                 r = translate_bus_error_to_exit_status(r, &error);
2042                                 sd_bus_error_free(&error);
2043                         }
2044                 }
2045         }
2046
2047         if (!arg_no_block) {
2048                 int q;
2049
2050                 q = wait_for_jobs(bus, s);
2051                 if (q < 0)
2052                         return q;
2053
2054                 /* When stopping units, warn if they can still be triggered by
2055                  * another active unit (socket, path, timer) */
2056                 if (!arg_quiet && streq(method, "StopUnit")) {
2057                         if (one_name)
2058                                 check_triggering_units(bus, one_name);
2059                         else
2060                                 STRV_FOREACH(name, args+1)
2061                                         check_triggering_units(bus, *name);
2062                 }
2063         }
2064
2065         return r;
2066 }
2067
2068 /* Ask systemd-logind, which might grant access to unprivileged users
2069  * through PolicyKit */
2070 static int reboot_with_logind(sd_bus *bus, enum action a) {
2071 #ifdef HAVE_LOGIND
2072         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2073         const char *method;
2074         int r;
2075
2076         if (!bus)
2077                 return -EIO;
2078
2079         polkit_agent_open_if_enabled();
2080
2081         switch (a) {
2082
2083         case ACTION_REBOOT:
2084                 method = "Reboot";
2085                 break;
2086
2087         case ACTION_POWEROFF:
2088                 method = "PowerOff";
2089                 break;
2090
2091         case ACTION_SUSPEND:
2092                 method = "Suspend";
2093                 break;
2094
2095         case ACTION_HIBERNATE:
2096                 method = "Hibernate";
2097                 break;
2098
2099         case ACTION_HYBRID_SLEEP:
2100                 method = "HybridSleep";
2101                 break;
2102
2103         default:
2104                 return -EINVAL;
2105         }
2106
2107         r = sd_bus_call_method(
2108                         bus,
2109                         "org.freedesktop.login1",
2110                         "/org/freedesktop/login1",
2111                         "org.freedesktop.login1.Manager",
2112                         method,
2113                         &error,
2114                         NULL,
2115                         "b", true);
2116         if (r < 0)
2117                 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2118
2119         return r;
2120 #else
2121         return -ENOSYS;
2122 #endif
2123 }
2124
2125 static int check_inhibitors(sd_bus *bus, enum action a) {
2126 #ifdef HAVE_LOGIND
2127         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2128         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2129         _cleanup_strv_free_ char **sessions = NULL;
2130         const char *what, *who, *why, *mode;
2131         uint32_t uid, pid;
2132         unsigned c = 0;
2133         char **s;
2134         int r;
2135
2136         if (!bus)
2137                 return 0;
2138
2139         if (arg_ignore_inhibitors || arg_force > 0)
2140                 return 0;
2141
2142         if (arg_when > 0)
2143                 return 0;
2144
2145         if (geteuid() == 0)
2146                 return 0;
2147
2148         if (!on_tty())
2149                 return 0;
2150
2151         r = sd_bus_call_method(
2152                         bus,
2153                         "org.freedesktop.login1",
2154                         "/org/freedesktop/login1",
2155                         "org.freedesktop.login1.Manager",
2156                         "ListInhibitors",
2157                         NULL,
2158                         &reply,
2159                         NULL);
2160         if (r < 0)
2161                 /* If logind is not around, then there are no inhibitors... */
2162                 return 0;
2163
2164         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2165         if (r < 0)
2166                 return bus_log_parse_error(r);
2167
2168         while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2169                 _cleanup_free_ char *comm = NULL, *user = NULL;
2170                 _cleanup_strv_free_ char **sv = NULL;
2171
2172                 if (!streq(mode, "block"))
2173                         continue;
2174
2175                 sv = strv_split(what, ":");
2176                 if (!sv)
2177                         return log_oom();
2178
2179                 if (!strv_contains(sv,
2180                                   a == ACTION_HALT ||
2181                                   a == ACTION_POWEROFF ||
2182                                   a == ACTION_REBOOT ||
2183                                   a == ACTION_KEXEC ? "shutdown" : "sleep"))
2184                         continue;
2185
2186                 get_process_comm(pid, &comm);
2187                 user = uid_to_name(uid);
2188
2189                 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2190                             who, (unsigned long) pid, strna(comm), strna(user), why);
2191
2192                 c++;
2193         }
2194         if (r < 0)
2195                 return bus_log_parse_error(r);
2196
2197         r = sd_bus_message_exit_container(reply);
2198         if (r < 0)
2199                 return bus_log_parse_error(r);
2200
2201         /* Check for current sessions */
2202         sd_get_sessions(&sessions);
2203         STRV_FOREACH(s, sessions) {
2204                 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2205
2206                 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2207                         continue;
2208
2209                 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2210                         continue;
2211
2212                 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2213                         continue;
2214
2215                 sd_session_get_tty(*s, &tty);
2216                 sd_session_get_seat(*s, &seat);
2217                 sd_session_get_service(*s, &service);
2218                 user = uid_to_name(uid);
2219
2220                 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2221                 c++;
2222         }
2223
2224         if (c <= 0)
2225                 return 0;
2226
2227         log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2228                   action_table[a].verb);
2229
2230         return -EPERM;
2231 #else
2232         return 0;
2233 #endif
2234 }
2235
2236 static int start_special(sd_bus *bus, char **args) {
2237         enum action a;
2238         int r;
2239
2240         assert(args);
2241
2242         a = verb_to_action(args[0]);
2243
2244         r = check_inhibitors(bus, a);
2245         if (r < 0)
2246                 return r;
2247
2248         if (arg_force >= 2 && geteuid() != 0) {
2249                 log_error("Must be root.");
2250                 return -EPERM;
2251         }
2252
2253         if (arg_force >= 2 &&
2254             (a == ACTION_HALT ||
2255              a == ACTION_POWEROFF ||
2256              a == ACTION_REBOOT))
2257                 return halt_now(a);
2258
2259         if (arg_force >= 1 &&
2260             (a == ACTION_HALT ||
2261              a == ACTION_POWEROFF ||
2262              a == ACTION_REBOOT ||
2263              a == ACTION_KEXEC ||
2264              a == ACTION_EXIT))
2265                 return daemon_reload(bus, args);
2266
2267         /* first try logind, to allow authentication with polkit */
2268         if (geteuid() != 0 &&
2269             (a == ACTION_POWEROFF ||
2270              a == ACTION_REBOOT ||
2271              a == ACTION_SUSPEND ||
2272              a == ACTION_HIBERNATE ||
2273              a == ACTION_HYBRID_SLEEP)) {
2274                 r = reboot_with_logind(bus, a);
2275                 if (r >= 0)
2276                         return r;
2277         }
2278
2279         r = start_unit(bus, args);
2280         if (r == EXIT_SUCCESS)
2281                 warn_wall(a);
2282
2283         return r;
2284 }
2285
2286 static int check_unit_active(sd_bus *bus, char **args) {
2287         char **name;
2288         int r = 3; /* According to LSB: "program is not running" */
2289
2290         assert(bus);
2291         assert(args);
2292
2293         STRV_FOREACH(name, args+1) {
2294                 int state;
2295
2296                 state = check_one_unit(bus, *name, "active\0reloading\0", arg_quiet);
2297                 if (state < 0)
2298                         return state;
2299                 if (state > 0)
2300                         r = 0;
2301         }
2302
2303         return r;
2304 }
2305
2306 static int check_unit_failed(sd_bus *bus, char **args) {
2307         char **name;
2308         int r = 1;
2309
2310         assert(bus);
2311         assert(args);
2312
2313         STRV_FOREACH(name, args+1) {
2314                 int state;
2315
2316                 state = check_one_unit(bus, *name, "failed\0", arg_quiet);
2317                 if (state < 0)
2318                         return state;
2319                 if (state > 0)
2320                         r = 0;
2321         }
2322
2323         return r;
2324 }
2325
2326 static int kill_unit(sd_bus *bus, char **args) {
2327         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2328         char **name;
2329         int r = 0;
2330
2331         assert(bus);
2332         assert(args);
2333
2334         if (!arg_kill_who)
2335                 arg_kill_who = "all";
2336
2337         STRV_FOREACH(name, args+1) {
2338                 _cleanup_free_ char *n = NULL;
2339
2340                 n = unit_name_mangle(*name);
2341                 if (!n)
2342                         return log_oom();
2343
2344                 r = sd_bus_call_method(
2345                                 bus,
2346                                 "org.freedesktop.systemd1",
2347                                 "/org/freedesktop/systemd1",
2348                                 "org.freedesktop.systemd1.Manager",
2349                                 "KillUnit",
2350                                 &error,
2351                                 NULL,
2352                                 "ssi", n, arg_kill_who, arg_signal);
2353                 if (r < 0) {
2354                         log_error("Failed to kill unit %s: %s", n, bus_error_message(&error, r));
2355                         return r;
2356                 }
2357         }
2358
2359         return 0;
2360 }
2361
2362 typedef struct ExecStatusInfo {
2363         char *name;
2364
2365         char *path;
2366         char **argv;
2367
2368         bool ignore;
2369
2370         usec_t start_timestamp;
2371         usec_t exit_timestamp;
2372         pid_t pid;
2373         int code;
2374         int status;
2375
2376         LIST_FIELDS(struct ExecStatusInfo, exec);
2377 } ExecStatusInfo;
2378
2379 static void exec_status_info_free(ExecStatusInfo *i) {
2380         assert(i);
2381
2382         free(i->name);
2383         free(i->path);
2384         strv_free(i->argv);
2385         free(i);
2386 }
2387
2388 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2389         uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2390         const char *path;
2391         uint32_t pid;
2392         int32_t code, status;
2393         int ignore, r;
2394
2395         assert(m);
2396         assert(i);
2397
2398         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
2399         if (r < 0)
2400                 return bus_log_parse_error(r);
2401         else if (r == 0)
2402                 return 0;
2403
2404         r = sd_bus_message_read(m, "s", &path);
2405         if (r < 0)
2406                 return bus_log_parse_error(r);
2407
2408         i->path = strdup(path);
2409         if (!i->path)
2410                 return log_oom();
2411
2412         r = sd_bus_message_read_strv(m, &i->argv);
2413         if (r < 0)
2414                 return bus_log_parse_error(r);
2415
2416         r = sd_bus_message_read(m,
2417                                 "bttttuii",
2418                                 &ignore,
2419                                 &start_timestamp, &start_timestamp_monotonic,
2420                                 &exit_timestamp, &exit_timestamp_monotonic,
2421                                 &pid,
2422                                 &code, &status);
2423         if (r < 0)
2424                 return bus_log_parse_error(r);
2425
2426         i->ignore = ignore;
2427         i->start_timestamp = (usec_t) start_timestamp;
2428         i->exit_timestamp = (usec_t) exit_timestamp;
2429         i->pid = (pid_t) pid;
2430         i->code = code;
2431         i->status = status;
2432
2433         r = sd_bus_message_exit_container(m);
2434         if (r < 0)
2435                 return bus_log_parse_error(r);
2436
2437         return 1;
2438 }
2439
2440 typedef struct UnitStatusInfo {
2441         const char *id;
2442         const char *load_state;
2443         const char *active_state;
2444         const char *sub_state;
2445         const char *unit_file_state;
2446
2447         const char *description;
2448         const char *following;
2449
2450         char **documentation;
2451
2452         const char *fragment_path;
2453         const char *source_path;
2454         const char *control_group;
2455
2456         char **dropin_paths;
2457
2458         const char *load_error;
2459         const char *result;
2460
2461         usec_t inactive_exit_timestamp;
2462         usec_t inactive_exit_timestamp_monotonic;
2463         usec_t active_enter_timestamp;
2464         usec_t active_exit_timestamp;
2465         usec_t inactive_enter_timestamp;
2466
2467         bool need_daemon_reload;
2468
2469         /* Service */
2470         pid_t main_pid;
2471         pid_t control_pid;
2472         const char *status_text;
2473         const char *pid_file;
2474         bool running:1;
2475
2476         usec_t start_timestamp;
2477         usec_t exit_timestamp;
2478
2479         int exit_code, exit_status;
2480
2481         usec_t condition_timestamp;
2482         bool condition_result;
2483         bool failed_condition_trigger;
2484         bool failed_condition_negate;
2485         const char *failed_condition;
2486         const char *failed_condition_param;
2487
2488         /* Socket */
2489         unsigned n_accepted;
2490         unsigned n_connections;
2491         bool accept;
2492
2493         /* Pairs of type, path */
2494         char **listen;
2495
2496         /* Device */
2497         const char *sysfs_path;
2498
2499         /* Mount, Automount */
2500         const char *where;
2501
2502         /* Swap */
2503         const char *what;
2504
2505         LIST_HEAD(ExecStatusInfo, exec);
2506 } UnitStatusInfo;
2507
2508 static void print_status_info(
2509                 UnitStatusInfo *i,
2510                 bool *ellipsized) {
2511
2512         ExecStatusInfo *p;
2513         const char *on, *off, *ss;
2514         usec_t timestamp;
2515         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2516         char since2[FORMAT_TIMESTAMP_MAX], *s2;
2517         const char *path;
2518         int flags =
2519                 arg_all * OUTPUT_SHOW_ALL |
2520                 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2521                 on_tty() * OUTPUT_COLOR |
2522                 !arg_quiet * OUTPUT_WARN_CUTOFF |
2523                 arg_full * OUTPUT_FULL_WIDTH;
2524         char **t, **t2;
2525
2526         assert(i);
2527
2528         /* This shows pretty information about a unit. See
2529          * print_property() for a low-level property printer */
2530
2531         printf("%s", strna(i->id));
2532
2533         if (i->description && !streq_ptr(i->id, i->description))
2534                 printf(" - %s", i->description);
2535
2536         printf("\n");
2537
2538         if (i->following)
2539                 printf("   Follow: unit currently follows state of %s\n", i->following);
2540
2541         if (streq_ptr(i->load_state, "error")) {
2542                 on = ansi_highlight_red();
2543                 off = ansi_highlight_off();
2544         } else
2545                 on = off = "";
2546
2547         path = i->source_path ? i->source_path : i->fragment_path;
2548
2549         if (i->load_error)
2550                 printf("   Loaded: %s%s%s (Reason: %s)\n",
2551                        on, strna(i->load_state), off, i->load_error);
2552         else if (path && i->unit_file_state)
2553                 printf("   Loaded: %s%s%s (%s; %s)\n",
2554                        on, strna(i->load_state), off, path, i->unit_file_state);
2555         else if (path)
2556                 printf("   Loaded: %s%s%s (%s)\n",
2557                        on, strna(i->load_state), off, path);
2558         else
2559                 printf("   Loaded: %s%s%s\n",
2560                        on, strna(i->load_state), off);
2561
2562         if (!strv_isempty(i->dropin_paths)) {
2563                 _cleanup_free_ char *dir = NULL;
2564                 bool last = false;
2565                 char ** dropin;
2566
2567                 STRV_FOREACH(dropin, i->dropin_paths) {
2568                         if (! dir || last) {
2569                                 printf(dir ? "        " : "  Drop-In: ");
2570
2571                                 free(dir);
2572                                 dir = NULL;
2573
2574                                 if (path_get_parent(*dropin, &dir) < 0) {
2575                                         log_oom();
2576                                         return;
2577                                 }
2578
2579                                 printf("%s\n           %s", dir,
2580                                        draw_special_char(DRAW_TREE_RIGHT));
2581                         }
2582
2583                         last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2584
2585                         printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2586                 }
2587         }
2588
2589         ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2590
2591         if (streq_ptr(i->active_state, "failed")) {
2592                 on = ansi_highlight_red();
2593                 off = ansi_highlight_off();
2594         } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2595                 on = ansi_highlight_green();
2596                 off = ansi_highlight_off();
2597         } else
2598                 on = off = "";
2599
2600         if (ss)
2601                 printf("   Active: %s%s (%s)%s",
2602                        on, strna(i->active_state), ss, off);
2603         else
2604                 printf("   Active: %s%s%s",
2605                        on, strna(i->active_state), off);
2606
2607         if (!isempty(i->result) && !streq(i->result, "success"))
2608                 printf(" (Result: %s)", i->result);
2609
2610         timestamp = (streq_ptr(i->active_state, "active")      ||
2611                      streq_ptr(i->active_state, "reloading"))   ? i->active_enter_timestamp :
2612                     (streq_ptr(i->active_state, "inactive")    ||
2613                      streq_ptr(i->active_state, "failed"))      ? i->inactive_enter_timestamp :
2614                     streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
2615                                                                   i->active_exit_timestamp;
2616
2617         s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2618         s2 = format_timestamp(since2, sizeof(since2), timestamp);
2619
2620         if (s1)
2621                 printf(" since %s; %s\n", s2, s1);
2622         else if (s2)
2623                 printf(" since %s\n", s2);
2624         else
2625                 printf("\n");
2626
2627         if (!i->condition_result && i->condition_timestamp > 0) {
2628                 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2629                 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2630
2631                 printf("           start condition failed at %s%s%s\n",
2632                        s2, s1 ? "; " : "", s1 ? s1 : "");
2633                 if (i->failed_condition_trigger)
2634                         printf("           none of the trigger conditions were met\n");
2635                 else if (i->failed_condition)
2636                         printf("           %s=%s%s was not met\n",
2637                                i->failed_condition,
2638                                i->failed_condition_negate ? "!" : "",
2639                                i->failed_condition_param);
2640         }
2641
2642         if (i->sysfs_path)
2643                 printf("   Device: %s\n", i->sysfs_path);
2644         if (i->where)
2645                 printf("    Where: %s\n", i->where);
2646         if (i->what)
2647                 printf("     What: %s\n", i->what);
2648
2649         STRV_FOREACH(t, i->documentation)
2650                 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2651
2652         STRV_FOREACH_PAIR(t, t2, i->listen)
2653                 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2654
2655         if (i->accept)
2656                 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2657
2658         LIST_FOREACH(exec, p, i->exec) {
2659                 _cleanup_free_ char *argv = NULL;
2660                 bool good;
2661
2662                 /* Only show exited processes here */
2663                 if (p->code == 0)
2664                         continue;
2665
2666                 argv = strv_join(p->argv, " ");
2667                 printf("  Process: %u %s=%s ", p->pid, p->name, strna(argv));
2668
2669                 good = is_clean_exit_lsb(p->code, p->status, NULL);
2670                 if (!good) {
2671                         on = ansi_highlight_red();
2672                         off = ansi_highlight_off();
2673                 } else
2674                         on = off = "";
2675
2676                 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2677
2678                 if (p->code == CLD_EXITED) {
2679                         const char *c;
2680
2681                         printf("status=%i", p->status);
2682
2683                         c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2684                         if (c)
2685                                 printf("/%s", c);
2686
2687                 } else
2688                         printf("signal=%s", signal_to_string(p->status));
2689
2690                 printf(")%s\n", off);
2691
2692                 if (i->main_pid == p->pid &&
2693                     i->start_timestamp == p->start_timestamp &&
2694                     i->exit_timestamp == p->start_timestamp)
2695                         /* Let's not show this twice */
2696                         i->main_pid = 0;
2697
2698                 if (p->pid == i->control_pid)
2699                         i->control_pid = 0;
2700         }
2701
2702         if (i->main_pid > 0 || i->control_pid > 0) {
2703                 if (i->main_pid > 0) {
2704                         printf(" Main PID: %u", (unsigned) i->main_pid);
2705
2706                         if (i->running) {
2707                                 _cleanup_free_ char *comm = NULL;
2708                                 get_process_comm(i->main_pid, &comm);
2709                                 if (comm)
2710                                         printf(" (%s)", comm);
2711                         } else if (i->exit_code > 0) {
2712                                 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2713
2714                                 if (i->exit_code == CLD_EXITED) {
2715                                         const char *c;
2716
2717                                         printf("status=%i", i->exit_status);
2718
2719                                         c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2720                                         if (c)
2721                                                 printf("/%s", c);
2722
2723                                 } else
2724                                         printf("signal=%s", signal_to_string(i->exit_status));
2725                                 printf(")");
2726                         }
2727
2728                         if (i->control_pid > 0)
2729                                 printf(";");
2730                 }
2731
2732                 if (i->control_pid > 0) {
2733                         _cleanup_free_ char *c = NULL;
2734
2735                         printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2736
2737                         get_process_comm(i->control_pid, &c);
2738                         if (c)
2739                                 printf(" (%s)", c);
2740                 }
2741
2742                 printf("\n");
2743         }
2744
2745         if (i->status_text)
2746                 printf("   Status: \"%s\"\n", i->status_text);
2747
2748         if (i->control_group &&
2749             (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2750                 unsigned c;
2751
2752                 printf("   CGroup: %s\n", i->control_group);
2753
2754                 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
2755                         unsigned k = 0;
2756                         pid_t extra[2];
2757                         char prefix[] = "           ";
2758
2759                         c = columns();
2760                         if (c > sizeof(prefix) - 1)
2761                                 c -= sizeof(prefix) - 1;
2762                         else
2763                                 c = 0;
2764
2765                         if (i->main_pid > 0)
2766                                 extra[k++] = i->main_pid;
2767
2768                         if (i->control_pid > 0)
2769                                 extra[k++] = i->control_pid;
2770
2771                         show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2772                                                       c, false, extra, k, flags);
2773                 }
2774         }
2775
2776         if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
2777                 printf("\n");
2778                 show_journal_by_unit(stdout,
2779                                      i->id,
2780                                      arg_output,
2781                                      0,
2782                                      i->inactive_exit_timestamp_monotonic,
2783                                      arg_lines,
2784                                      getuid(),
2785                                      flags,
2786                                      arg_scope == UNIT_FILE_SYSTEM,
2787                                      ellipsized);
2788         }
2789
2790         if (i->need_daemon_reload)
2791                 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2792                        ansi_highlight_red(),
2793                        ansi_highlight_off(),
2794                        arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2795 }
2796
2797 static void show_unit_help(UnitStatusInfo *i) {
2798         char **p;
2799
2800         assert(i);
2801
2802         if (!i->documentation) {
2803                 log_info("Documentation for %s not known.", i->id);
2804                 return;
2805         }
2806
2807         STRV_FOREACH(p, i->documentation) {
2808
2809                 if (startswith(*p, "man:")) {
2810                         const char *args[4] = { "man", NULL, NULL, NULL };
2811                         _cleanup_free_ char *page = NULL, *section = NULL;
2812                         char *e = NULL;
2813                         pid_t pid;
2814                         size_t k;
2815
2816                         k = strlen(*p);
2817
2818                         if ((*p)[k-1] == ')')
2819                                 e = strrchr(*p, '(');
2820
2821                         if (e) {
2822                                 page = strndup((*p) + 4, e - *p - 4);
2823                                 section = strndup(e + 1, *p + k - e - 2);
2824                                 if (!page || !section) {
2825                                         log_oom();
2826                                         return;
2827                                 }
2828
2829                                 args[1] = section;
2830                                 args[2] = page;
2831                         } else
2832                                 args[1] = *p + 4;
2833
2834                         pid = fork();
2835                         if (pid < 0) {
2836                                 log_error("Failed to fork: %m");
2837                                 continue;
2838                         }
2839
2840                         if (pid == 0) {
2841                                 /* Child */
2842                                 execvp(args[0], (char**) args);
2843                                 log_error("Failed to execute man: %m");
2844                                 _exit(EXIT_FAILURE);
2845                         }
2846
2847                         wait_for_terminate(pid, NULL);
2848                 } else
2849                         log_info("Can't show: %s", *p);
2850         }
2851 }
2852
2853 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
2854         int r;
2855
2856         assert(name);
2857         assert(m);
2858         assert(i);
2859
2860         switch (contents[0]) {
2861
2862         case SD_BUS_TYPE_STRING: {
2863                 const char *s;
2864
2865                 r = sd_bus_message_read(m, "s", &s);
2866                 if (r < 0)
2867                         return bus_log_parse_error(r);
2868
2869                 if (!isempty(s)) {
2870                         if (streq(name, "Id"))
2871                                 i->id = s;
2872                         else if (streq(name, "LoadState"))
2873                                 i->load_state = s;
2874                         else if (streq(name, "ActiveState"))
2875                                 i->active_state = s;
2876                         else if (streq(name, "SubState"))
2877                                 i->sub_state = s;
2878                         else if (streq(name, "Description"))
2879                                 i->description = s;
2880                         else if (streq(name, "FragmentPath"))
2881                                 i->fragment_path = s;
2882                         else if (streq(name, "SourcePath"))
2883                                 i->source_path = s;
2884 #ifndef NOLEGACY
2885                         else if (streq(name, "DefaultControlGroup")) {
2886                                 const char *e;
2887                                 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2888                                 if (e)
2889                                         i->control_group = e;
2890                         }
2891 #endif
2892                         else if (streq(name, "ControlGroup"))
2893                                 i->control_group = s;
2894                         else if (streq(name, "StatusText"))
2895                                 i->status_text = s;
2896                         else if (streq(name, "PIDFile"))
2897                                 i->pid_file = s;
2898                         else if (streq(name, "SysFSPath"))
2899                                 i->sysfs_path = s;
2900                         else if (streq(name, "Where"))
2901                                 i->where = s;
2902                         else if (streq(name, "What"))
2903                                 i->what = s;
2904                         else if (streq(name, "Following"))
2905                                 i->following = s;
2906                         else if (streq(name, "UnitFileState"))
2907                                 i->unit_file_state = s;
2908                         else if (streq(name, "Result"))
2909                                 i->result = s;
2910                 }
2911
2912                 break;
2913         }
2914
2915         case SD_BUS_TYPE_BOOLEAN: {
2916                 int b;
2917
2918                 r = sd_bus_message_read(m, "b", &b);
2919                 if (r < 0)
2920                         return bus_log_parse_error(r);
2921
2922                 if (streq(name, "Accept"))
2923                         i->accept = b;
2924                 else if (streq(name, "NeedDaemonReload"))
2925                         i->need_daemon_reload = b;
2926                 else if (streq(name, "ConditionResult"))
2927                         i->condition_result = b;
2928
2929                 break;
2930         }
2931
2932         case SD_BUS_TYPE_UINT32: {
2933                 uint32_t u;
2934
2935                 r = sd_bus_message_read(m, "u", &u);
2936                 if (r < 0)
2937                         return bus_log_parse_error(r);
2938
2939                 if (streq(name, "MainPID")) {
2940                         if (u > 0) {
2941                                 i->main_pid = (pid_t) u;
2942                                 i->running = true;
2943                         }
2944                 } else if (streq(name, "ControlPID"))
2945                         i->control_pid = (pid_t) u;
2946                 else if (streq(name, "ExecMainPID")) {
2947                         if (u > 0)
2948                                 i->main_pid = (pid_t) u;
2949                 } else if (streq(name, "NAccepted"))
2950                         i->n_accepted = u;
2951                 else if (streq(name, "NConnections"))
2952                         i->n_connections = u;
2953
2954                 break;
2955         }
2956
2957         case SD_BUS_TYPE_INT32: {
2958                 int32_t j;
2959
2960                 r = sd_bus_message_read(m, "i", &j);
2961                 if (r < 0)
2962                         return bus_log_parse_error(r);
2963
2964                 if (streq(name, "ExecMainCode"))
2965                         i->exit_code = (int) j;
2966                 else if (streq(name, "ExecMainStatus"))
2967                         i->exit_status = (int) j;
2968
2969                 break;
2970         }
2971
2972         case SD_BUS_TYPE_UINT64: {
2973                 uint64_t u;
2974
2975                 r = sd_bus_message_read(m, "t", &u);
2976                 if (r < 0)
2977                         return bus_log_parse_error(r);
2978
2979                 if (streq(name, "ExecMainStartTimestamp"))
2980                         i->start_timestamp = (usec_t) u;
2981                 else if (streq(name, "ExecMainExitTimestamp"))
2982                         i->exit_timestamp = (usec_t) u;
2983                 else if (streq(name, "ActiveEnterTimestamp"))
2984                         i->active_enter_timestamp = (usec_t) u;
2985                 else if (streq(name, "InactiveEnterTimestamp"))
2986                         i->inactive_enter_timestamp = (usec_t) u;
2987                 else if (streq(name, "InactiveExitTimestamp"))
2988                         i->inactive_exit_timestamp = (usec_t) u;
2989                 else if (streq(name, "InactiveExitTimestampMonotonic"))
2990                         i->inactive_exit_timestamp_monotonic = (usec_t) u;
2991                 else if (streq(name, "ActiveExitTimestamp"))
2992                         i->active_exit_timestamp = (usec_t) u;
2993                 else if (streq(name, "ConditionTimestamp"))
2994                         i->condition_timestamp = (usec_t) u;
2995
2996                 break;
2997         }
2998
2999         case SD_BUS_TYPE_ARRAY:
3000
3001                 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3002                         _cleanup_free_ ExecStatusInfo *info = NULL;
3003
3004                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3005                         if (r < 0)
3006                                 return bus_log_parse_error(r);
3007
3008                         info = new0(ExecStatusInfo, 1);
3009                         if (!info)
3010                                 return log_oom();
3011
3012                         while ((r = exec_status_info_deserialize(m, info)) > 0) {
3013
3014                                 info->name = strdup(name);
3015                                 if (!info->name)
3016                                         log_oom();
3017
3018                                 LIST_PREPEND(exec, i->exec, info);
3019
3020                                 info = new0(ExecStatusInfo, 1);
3021                                 if (!info)
3022                                         log_oom();
3023                         }
3024
3025                         if (r < 0)
3026                                 return bus_log_parse_error(r);
3027
3028                         r = sd_bus_message_exit_container(m);
3029                         if (r < 0)
3030                                 return bus_log_parse_error(r);
3031
3032                         return 0;
3033
3034                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3035                         const char *type, *path;
3036
3037                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3038                         if (r < 0)
3039                                 return bus_log_parse_error(r);
3040
3041                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3042
3043                                 r = strv_extend(&i->listen, type);
3044                                 if (r < 0)
3045                                         return r;
3046
3047                                 r = strv_extend(&i->listen, path);
3048                                 if (r < 0)
3049                                         return r;
3050                         }
3051                         if (r < 0)
3052                                 return bus_log_parse_error(r);
3053
3054                         r = sd_bus_message_exit_container(m);
3055                         if (r < 0)
3056                                 return bus_log_parse_error(r);
3057
3058                         return 0;
3059
3060                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3061
3062                         r = sd_bus_message_read_strv(m, &i->dropin_paths);
3063                         if (r < 0)
3064                                 return bus_log_parse_error(r);
3065
3066                 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3067
3068                         r = sd_bus_message_read_strv(m, &i->documentation);
3069                         if (r < 0)
3070                                 return bus_log_parse_error(r);
3071
3072                 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3073                         const char *cond, *param;
3074                         int trigger, negate;
3075                         int32_t state;
3076
3077                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3078                         if (r < 0)
3079                                 return bus_log_parse_error(r);
3080
3081                         while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
3082                                 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3083                                 if (state < 0 && (!trigger || !i->failed_condition)) {
3084                                         i->failed_condition = cond;
3085                                         i->failed_condition_trigger = trigger;
3086                                         i->failed_condition_negate = negate;
3087                                         i->failed_condition_param = param;
3088                                 }
3089                         }
3090                         if (r < 0)
3091                                 return bus_log_parse_error(r);
3092
3093                         r = sd_bus_message_exit_container(m);
3094                         if (r < 0)
3095                                 return bus_log_parse_error(r);
3096
3097                 } else
3098                         goto skip;
3099
3100                 break;
3101
3102         case SD_BUS_TYPE_STRUCT_BEGIN:
3103
3104                 if (streq(name, "LoadError")) {
3105   &nbs