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