1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "bus-error.h"
4 #include "bus-locator.h"
5 #include "proc-cmdline.h"
6 #include "systemctl-daemon-reload.h"
7 #include "systemctl-set-default.h"
8 #include "systemctl-util.h"
9 #include "systemctl.h"
10 
parse_proc_cmdline_item(const char * key,const char * value,void * data)11 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
12         char **ret = data;
13 
14         if (streq(key, "systemd.unit")) {
15                 if (proc_cmdline_value_missing(key, value))
16                         return 0;
17                 if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
18                         log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
19                         return 0;
20                 }
21 
22                 return free_and_strdup_warn(ret, key);
23 
24         } else if (!value) {
25                 if (runlevel_to_target(key))
26                         return free_and_strdup_warn(ret, key);
27         }
28 
29         return 0;
30 }
31 
emit_cmdline_warning(void)32 static void emit_cmdline_warning(void) {
33         if (arg_quiet || arg_root)
34                 /* don't bother checking the commandline if we're operating on a container */
35                 return;
36 
37         _cleanup_free_ char *override = NULL;
38         int r;
39 
40         r = proc_cmdline_parse(parse_proc_cmdline_item, &override, 0);
41         if (r < 0)
42                 log_debug_errno(r, "Failed to parse kernel command line, ignoring: %m");
43         if (override)
44                 log_notice("Note: found \"%s\" on the kernel commandline, which overrides the default unit.",
45                            override);
46 }
47 
determine_default(char ** ret_name)48 static int determine_default(char **ret_name) {
49         int r;
50 
51         if (install_client_side()) {
52                 r = unit_file_get_default(arg_scope, arg_root, ret_name);
53                 if (r < 0)
54                         return log_error_errno(r, "Failed to get default target: %m");
55                 return 0;
56 
57         } else {
58                 sd_bus *bus;
59                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
60                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
61                 const char *name;
62 
63                 r = acquire_bus(BUS_MANAGER, &bus);
64                 if (r < 0)
65                         return r;
66 
67                 r = bus_call_method(bus, bus_systemd_mgr, "GetDefaultTarget", &error, &reply, NULL);
68                 if (r < 0)
69                         return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
70 
71                 r = sd_bus_message_read(reply, "s", &name);
72                 if (r < 0)
73                         return bus_log_parse_error(r);
74 
75                 return free_and_strdup_warn(ret_name, name);
76         }
77 }
78 
verb_get_default(int argc,char * argv[],void * userdata)79 int verb_get_default(int argc, char *argv[], void *userdata) {
80         _cleanup_free_ char *name = NULL;
81         int r;
82 
83         r = determine_default(&name);
84         if (r < 0)
85                 return r;
86 
87         printf("%s\n", name);
88 
89         emit_cmdline_warning();
90 
91         return 0;
92 }
93 
verb_set_default(int argc,char * argv[],void * userdata)94 int verb_set_default(int argc, char *argv[], void *userdata) {
95         _cleanup_free_ char *unit = NULL;
96         UnitFileChange *changes = NULL;
97         size_t n_changes = 0;
98         int r;
99 
100         assert(argc >= 2);
101         assert(argv);
102 
103         r = unit_name_mangle_with_suffix(argv[1], "set-default",
104                                          arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
105                                          ".target", &unit);
106         if (r < 0)
107                 return log_error_errno(r, "Failed to mangle unit name: %m");
108 
109         if (install_client_side()) {
110                 r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
111                 unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
112 
113                 if (r > 0)
114                         r = 0;
115         } else {
116                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
117                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
118                 sd_bus *bus;
119 
120                 polkit_agent_open_maybe();
121 
122                 r = acquire_bus(BUS_MANAGER, &bus);
123                 if (r < 0)
124                         return r;
125 
126                 r = bus_call_method(bus, bus_systemd_mgr, "SetDefaultTarget", &error, &reply, "sb", unit, 1);
127                 if (r < 0)
128                         return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
129 
130                 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
131                 if (r < 0)
132                         goto finish;
133 
134                 /* Try to reload if enabled */
135                 if (!arg_no_reload) {
136                         r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
137                         if (r > 0)
138                                 r = 0;
139                 } else
140                         r = 0;
141         }
142 
143         emit_cmdline_warning();
144 
145         if (!arg_quiet) {
146                 _cleanup_free_ char *final = NULL;
147 
148                 r = determine_default(&final);
149                 if (r < 0)
150                         return r;
151 
152                 if (!streq(final, unit))
153                         log_notice("Note: \"%s\" is the default unit (possibly a runtime override).", final);
154         }
155 
156 finish:
157         unit_file_changes_free(changes, n_changes);
158 
159         return r;
160 }
161