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