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