]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/systemctl/systemctl-set-environment.c
strv: make iterator in STRV_FOREACH() declaread in the loop
[thirdparty/systemd.git] / src / systemctl / systemctl-set-environment.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
daf71ef6
LP
2
3#include "bus-error.h"
4#include "bus-locator.h"
5#include "env-util.h"
6#include "escape.h"
7#include "systemctl-set-environment.h"
8#include "systemctl-util.h"
9#include "systemctl.h"
10
5ef599b3
JH
11static int json_transform_message(sd_bus_message *m, JsonVariant **ret) {
12 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
92b29166 13 const char *text;
5ef599b3
JH
14 int r;
15
16 assert(m);
17 assert(ret);
18
19 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &text)) > 0) {
92b29166
LP
20 _cleanup_free_ char *n = NULL;
21 const char *sep;
5ef599b3 22
92b29166 23 sep = strchr(text, '=');
5ef599b3
JH
24 if (!sep)
25 return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
26 "Invalid environment block");
27
92b29166
LP
28 n = strndup(text, sep - text);
29 if (!n)
30 return log_oom();
5ef599b3 31
92b29166 32 sep++;
5ef599b3 33
92b29166 34 r = json_variant_set_field_string(&v, n, sep);
5ef599b3 35 if (r < 0)
92b29166 36 return log_error_errno(r, "Failed to set JSON field '%s' to '%s': %m", n, sep);
5ef599b3
JH
37 }
38 if (r < 0)
39 return bus_log_parse_error(r);
40
41 *ret = TAKE_PTR(v);
92b29166 42 return 0;
5ef599b3
JH
43}
44
daf71ef6
LP
45static int print_variable(const char *s) {
46 const char *sep;
47 _cleanup_free_ char *esc = NULL;
48
49 sep = strchr(s, '=');
50 if (!sep)
51 return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
52 "Invalid environment block");
53
9e53c10a 54 esc = shell_maybe_quote(sep + 1, SHELL_ESCAPE_POSIX);
daf71ef6
LP
55 if (!esc)
56 return log_oom();
57
58 printf("%.*s=%s\n", (int)(sep-s), s, esc);
59 return 0;
60}
61
32baf64d 62int verb_show_environment(int argc, char *argv[], void *userdata) {
daf71ef6
LP
63 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
64 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
65 const char *text;
66 sd_bus *bus;
67 int r;
68
69 r = acquire_bus(BUS_MANAGER, &bus);
70 if (r < 0)
71 return r;
72
384c2c32 73 pager_open(arg_pager_flags);
daf71ef6
LP
74
75 r = bus_get_property(bus, bus_systemd_mgr, "Environment", &error, &reply, "as");
76 if (r < 0)
77 return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
78
79 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
80 if (r < 0)
81 return bus_log_parse_error(r);
82
5ef599b3
JH
83 if (OUTPUT_MODE_IS_JSON(arg_output)) {
84 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
5ef599b3
JH
85
86 r = json_transform_message(reply, &v);
daf71ef6
LP
87 if (r < 0)
88 return r;
5ef599b3 89
92b29166 90 json_variant_dump(v, output_mode_to_json_format_flags(arg_output), stdout, NULL);
5ef599b3
JH
91 } else {
92 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
93 r = print_variable(text);
94 if (r < 0)
95 return r;
96 }
97 if (r < 0)
98 return bus_log_parse_error(r);
daf71ef6 99 }
daf71ef6
LP
100
101 r = sd_bus_message_exit_container(reply);
102 if (r < 0)
103 return bus_log_parse_error(r);
104
105 return 0;
106}
107
a4ccce22
ZJS
108static void invalid_callback(const char *p, void *userdata) {
109 _cleanup_free_ char *t = cescape(p);
edfa5517 110
a4ccce22
ZJS
111 log_debug("Ignoring invalid environment assignment \"%s\".", strnull(t));
112}
113
32baf64d 114int verb_set_environment(int argc, char *argv[], void *userdata) {
daf71ef6
LP
115 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
116 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
117 const char *method;
118 sd_bus *bus;
119 int r;
120
121 assert(argc > 1);
122 assert(argv);
123
124 r = acquire_bus(BUS_MANAGER, &bus);
125 if (r < 0)
126 return r;
127
128 polkit_agent_open_maybe();
129
130 method = streq(argv[0], "set-environment")
131 ? "SetEnvironment"
132 : "UnsetEnvironment";
133
134 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
135 if (r < 0)
136 return bus_log_create_error(r);
137
138 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
139 if (r < 0)
140 return bus_log_create_error(r);
141
142 r = sd_bus_call(bus, m, 0, &error, NULL);
143 if (r < 0)
144 return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
145
146 return 0;
147}
148
32baf64d 149int verb_import_environment(int argc, char *argv[], void *userdata) {
daf71ef6
LP
150 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
151 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
152 sd_bus *bus;
153 int r;
154
155 r = acquire_bus(BUS_MANAGER, &bus);
156 if (r < 0)
157 return r;
158
159 polkit_agent_open_maybe();
160
161 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetEnvironment");
162 if (r < 0)
163 return bus_log_create_error(r);
164
a4ccce22 165 if (argc < 2) {
32854f70 166 log_warning("Calling import-environment without a list of variable names is deprecated.");
edfa5517 167
32854f70 168 _cleanup_strv_free_ char **copy = strv_copy(environ);
a4ccce22
ZJS
169 if (!copy)
170 return log_oom();
edfa5517 171
a4ccce22 172 strv_env_clean_with_callback(copy, invalid_callback, NULL);
edfa5517 173
e9155cd0
ZJS
174 STRV_FOREACH(e, copy)
175 if (string_has_cc(*e, NULL))
176 log_notice("Environment variable $%.*s contains control characters, importing anyway.",
177 (int) strcspn(*e, "="), *e);
178
a4ccce22
ZJS
179 r = sd_bus_message_append_strv(m, copy);
180
181 } else {
daf71ef6
LP
182 r = sd_bus_message_open_container(m, 'a', "s");
183 if (r < 0)
184 return bus_log_create_error(r);
185
186 STRV_FOREACH(a, strv_skip(argv, 1)) {
187
188 if (!env_name_is_valid(*a))
c4899ea4
ZJS
189 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
190 "Not a valid environment variable name: %s", *a);
daf71ef6 191
c4899ea4 192 bool found = false;
daf71ef6
LP
193 STRV_FOREACH(b, environ) {
194 const char *eq;
195
196 eq = startswith(*b, *a);
197 if (eq && *eq == '=') {
e9155cd0
ZJS
198 if (string_has_cc(eq + 1, NULL))
199 log_notice("Environment variable $%.*s contains control characters, importing anyway.",
200 (int) (eq - *b), *b);
201
daf71ef6
LP
202 r = sd_bus_message_append(m, "s", *b);
203 if (r < 0)
204 return bus_log_create_error(r);
205
c4899ea4 206 found = true;
daf71ef6
LP
207 break;
208 }
209 }
c4899ea4
ZJS
210
211 if (!found)
212 log_notice("Environment variable $%s not set, ignoring.", *a);
daf71ef6
LP
213 }
214
215 r = sd_bus_message_close_container(m);
216 }
217 if (r < 0)
218 return bus_log_create_error(r);
219
220 r = sd_bus_call(bus, m, 0, &error, NULL);
221 if (r < 0)
222 return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
223
224 return 0;
225}