Skip to content

Commit 76e68b3

Browse files
committed
activate: simplify/rework implementation of --setenv
Previous implementation is simplified by using the new helper. The new code does more looping, but considering that it's unlikely that people set more than a handful of variables through commandline options, this should be OK. If a variable is specified on the command line, it overrides any automatically set variable. Effective behaviour was already were like this, because we would specify two variables, both would be set, and since glibc will return the first matching entry. ('systemd-socket-activate -E TERM=FOO -l 2000 --inetd -a env' would give 'TERM=FOO TERM=xterm-256color PATH=...', and getenv("TERM") returns "FOO".) But it's nicer to filter out any duplicate entries and only pass the intended variable to the child process.
1 parent 2f40067 commit 76e68b3

File tree

1 file changed

+27
-59
lines changed

1 file changed

+27
-59
lines changed

src/activate/activate.c

Lines changed: 27 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "sd-daemon.h"
1010

1111
#include "alloc-util.h"
12+
#include "env-util.h"
1213
#include "errno-util.h"
1314
#include "escape.h"
1415
#include "fd-util.h"
@@ -123,65 +124,24 @@ static int open_sockets(int *epoll_fd, bool accept) {
123124

124125
static int exec_process(const char *name, char **argv, int start_fd, size_t n_fds) {
125126
_cleanup_strv_free_ char **envp = NULL;
126-
_cleanup_free_ char *joined = NULL;
127-
size_t n_env = 0, length;
128-
const char *tocopy;
127+
const char *var;
129128
char **s;
130129
int r;
131130

132131
if (arg_inetd && n_fds != 1)
133132
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
134133
"--inetd only supported for single file descriptors.");
135134

136-
length = strv_length(arg_setenv);
137-
138-
/* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID, LISTEN_FDNAMES, NULL */
139-
envp = new0(char *, length + 8);
140-
if (!envp)
141-
return log_oom();
142-
143-
STRV_FOREACH(s, arg_setenv) {
144-
145-
if (strchr(*s, '=')) {
146-
char *k;
147-
148-
k = strdup(*s);
149-
if (!k)
150-
return log_oom();
151-
152-
envp[n_env++] = k;
153-
} else {
154-
_cleanup_free_ char *p = NULL;
155-
const char *n;
156-
157-
p = strjoin(*s, "=");
158-
if (!p)
159-
return log_oom();
160-
161-
n = strv_find_prefix(environ, p);
162-
if (!n)
163-
continue;
164-
165-
envp[n_env] = strdup(n);
166-
if (!envp[n_env])
167-
return log_oom();
168-
169-
n_env++;
170-
}
171-
}
172-
173-
FOREACH_STRING(tocopy, "TERM=", "PATH=", "USER=", "HOME=") {
135+
FOREACH_STRING(var, "TERM", "PATH", "USER", "HOME") {
174136
const char *n;
175137

176-
n = strv_find_prefix(environ, tocopy);
138+
n = strv_find_prefix(environ, var);
177139
if (!n)
178140
continue;
179141

180-
envp[n_env] = strdup(n);
181-
if (!envp[n_env])
182-
return log_oom();
183-
184-
n_env++;
142+
r = strv_extend(&envp, n);
143+
if (r < 0)
144+
return r;
185145
}
186146

187147
if (arg_inetd) {
@@ -201,16 +161,17 @@ static int exec_process(const char *name, char **argv, int start_fd, size_t n_fd
201161
safe_close(start_fd);
202162
}
203163

204-
if (asprintf((char **) (envp + n_env++), "LISTEN_FDS=%zu", n_fds) < 0)
205-
return log_oom();
164+
r = strv_extendf(&envp, "LISTEN_FDS=%zu", n_fds);
165+
if (r < 0)
166+
return r;
206167

207-
if (asprintf((char **) (envp + n_env++), "LISTEN_PID=" PID_FMT, getpid_cached()) < 0)
208-
return log_oom();
168+
r = strv_extendf(&envp, "LISTEN_PID=" PID_FMT, getpid_cached());
169+
if (r < 0)
170+
return r;
209171

210172
if (arg_fdnames) {
211173
_cleanup_free_ char *names = NULL;
212174
size_t len;
213-
char *e;
214175

215176
len = strv_length(arg_fdnames);
216177
if (len == 1)
@@ -226,15 +187,23 @@ static int exec_process(const char *name, char **argv, int start_fd, size_t n_fd
226187
if (!names)
227188
return log_oom();
228189

229-
e = strjoin("LISTEN_FDNAMES=", names);
230-
if (!e)
190+
char *t = strjoin("LISTEN_FDNAMES=", names);
191+
if (!t)
231192
return log_oom();
232193

233-
envp[n_env++] = e;
194+
r = strv_consume(&envp, t);
195+
if (r < 0)
196+
return r;
234197
}
235198
}
236199

237-
joined = strv_join(argv, " ");
200+
STRV_FOREACH(s, arg_setenv) {
201+
r = strv_env_replace_strdup(&envp, *s);
202+
if (r < 0)
203+
return r;
204+
}
205+
206+
_cleanup_free_ char *joined = strv_join(argv, " ");
238207
if (!joined)
239208
return log_oom();
240209

@@ -414,10 +383,9 @@ static int parse_argv(int argc, char *argv[]) {
414383
break;
415384

416385
case 'E':
417-
r = strv_extend(&arg_setenv, optarg);
386+
r = strv_env_replace_strdup_passthrough(&arg_setenv, optarg);
418387
if (r < 0)
419-
return log_oom();
420-
388+
return log_error_errno(r, "Cannot assign environment variable %s: %m", optarg);
421389
break;
422390

423391
case ARG_FDNAME: {

0 commit comments

Comments
 (0)