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