File: | build-scan/../src/activate/activate.c |
Warning: | line 194, column 25 Value stored to 'start_fd' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | |
3 | #include <getopt.h> |
4 | #include <sys/epoll.h> |
5 | #include <sys/prctl.h> |
6 | #include <sys/socket.h> |
7 | #include <sys/wait.h> |
8 | #include <unistd.h> |
9 | |
10 | #include "sd-daemon.h" |
11 | |
12 | #include "alloc-util.h" |
13 | #include "escape.h" |
14 | #include "fd-util.h" |
15 | #include "log.h" |
16 | #include "macro.h" |
17 | #include "process-util.h" |
18 | #include "signal-util.h" |
19 | #include "socket-util.h" |
20 | #include "string-util.h" |
21 | #include "strv.h" |
22 | |
23 | static char** arg_listen = NULL((void*)0); |
24 | static bool_Bool arg_accept = false0; |
25 | static int arg_socket_type = SOCK_STREAMSOCK_STREAM; |
26 | static char** arg_args = NULL((void*)0); |
27 | static char** arg_setenv = NULL((void*)0); |
28 | static char **arg_fdnames = NULL((void*)0); |
29 | static bool_Bool arg_inetd = false0; |
30 | |
31 | static int add_epoll(int epoll_fd, int fd) { |
32 | struct epoll_event ev = { |
33 | .events = EPOLLINEPOLLIN, |
34 | .data.fd = fd, |
35 | }; |
36 | |
37 | assert(epoll_fd >= 0)do { if ((__builtin_expect(!!(!(epoll_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("epoll_fd >= 0"), "../src/activate/activate.c" , 37, __PRETTY_FUNCTION__); } while (0); |
38 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/activate/activate.c" , 38, __PRETTY_FUNCTION__); } while (0); |
39 | |
40 | if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD1, fd, &ev) < 0) |
41 | return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 41, __func__ , "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd , fd) : -abs(_e); }); |
42 | |
43 | return 0; |
44 | } |
45 | |
46 | static int open_sockets(int *epoll_fd, bool_Bool accept) { |
47 | char **address; |
48 | int n, fd, r; |
49 | int count = 0; |
50 | |
51 | n = sd_listen_fds(true1); |
52 | if (n < 0) |
53 | return log_error_errno(n, "Failed to read listening file descriptors from environment: %m")({ int _level = ((3)), _e = ((n)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 53, __func__, "Failed to read listening file descriptors from environment: %m" ) : -abs(_e); }); |
54 | if (n > 0) { |
55 | log_info("Received %i descriptors via the environment.", n)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 55, __func__, "Received %i descriptors via the environment." , n) : -abs(_e); }); |
56 | |
57 | for (fd = SD_LISTEN_FDS_START3; fd < SD_LISTEN_FDS_START3 + n; fd++) { |
58 | r = fd_cloexec(fd, arg_accept); |
59 | if (r < 0) |
60 | return r; |
61 | |
62 | count++; |
63 | } |
64 | } |
65 | |
66 | /* Close logging and all other descriptors */ |
67 | if (arg_listen) { |
68 | int except[3 + n]; |
69 | |
70 | for (fd = 0; fd < SD_LISTEN_FDS_START3 + n; fd++) |
71 | except[fd] = fd; |
72 | |
73 | log_close(); |
74 | close_all_fds(except, 3 + n); |
75 | } |
76 | |
77 | /** Note: we leak some fd's on error here. I doesn't matter |
78 | * much, since the program will exit immediately anyway, but |
79 | * would be a pain to fix. |
80 | */ |
81 | |
82 | STRV_FOREACH(address, arg_listen)for ((address) = (arg_listen); (address) && *(address ); (address)++) { |
83 | fd = make_socket_fd(LOG_DEBUG7, *address, arg_socket_type, (arg_accept*SOCK_CLOEXECSOCK_CLOEXEC)); |
84 | if (fd < 0) { |
85 | log_open(); |
86 | return log_error_errno(fd, "Failed to open '%s': %m", *address)({ int _level = ((3)), _e = ((fd)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 86, __func__, "Failed to open '%s': %m" , *address) : -abs(_e); }); |
87 | } |
88 | |
89 | assert(fd == SD_LISTEN_FDS_START + count)do { if ((__builtin_expect(!!(!(fd == 3 + count)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd == SD_LISTEN_FDS_START + count"), "../src/activate/activate.c" , 89, __PRETTY_FUNCTION__); } while (0); |
90 | count++; |
91 | } |
92 | |
93 | if (arg_listen) |
94 | log_open(); |
95 | |
96 | *epoll_fd = epoll_create1(EPOLL_CLOEXECEPOLL_CLOEXEC); |
97 | if (*epoll_fd < 0) |
98 | return log_error_errno(errno, "Failed to create epoll object: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 98, __func__ , "Failed to create epoll object: %m") : -abs(_e); }); |
99 | |
100 | for (fd = SD_LISTEN_FDS_START3; fd < SD_LISTEN_FDS_START3 + count; fd++) { |
101 | _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0); |
102 | |
103 | getsockname_pretty(fd, &name); |
104 | log_info("Listening on %s as %i.", strna(name), fd)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 104, __func__, "Listening on %s as %i." , strna(name), fd) : -abs(_e); }); |
105 | |
106 | r = add_epoll(*epoll_fd, fd); |
107 | if (r < 0) |
108 | return r; |
109 | } |
110 | |
111 | return count; |
112 | } |
113 | |
114 | static int exec_process(const char* name, char **argv, char **env, int start_fd, size_t n_fds) { |
115 | |
116 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **envp = NULL((void*)0); |
117 | _cleanup_free___attribute__((cleanup(freep))) char *joined = NULL((void*)0); |
118 | size_t n_env = 0, length; |
119 | const char *tocopy; |
120 | char **s; |
121 | int r; |
122 | |
123 | if (arg_inetd && n_fds != 1) { |
124 | log_error("--inetd only supported for single file descriptors.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 124, __func__, "--inetd only supported for single file descriptors." ) : -abs(_e); }); |
125 | return -EINVAL22; |
126 | } |
127 | |
128 | length = strv_length(arg_setenv); |
129 | |
130 | /* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID, LISTEN_FDNAMES, NULL */ |
131 | envp = new0(char *, length + 8)((char **) calloc((length + 8), sizeof(char *))); |
132 | if (!envp) |
133 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 133, __func__); |
134 | |
135 | STRV_FOREACH(s, arg_setenv)for ((s) = (arg_setenv); (s) && *(s); (s)++) { |
136 | |
137 | if (strchr(*s, '=')) { |
138 | char *k; |
139 | |
140 | k = strdup(*s); |
141 | if (!k) |
142 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 142, __func__); |
143 | |
144 | envp[n_env++] = k; |
145 | } else { |
146 | _cleanup_free___attribute__((cleanup(freep))) char *p; |
147 | const char *n; |
148 | |
149 | p = strappend(*s, "="); |
150 | if (!p) |
151 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 151, __func__); |
152 | |
153 | n = strv_find_prefix(env, p); |
154 | if (!n) |
155 | continue; |
156 | |
157 | envp[n_env] = strdup(n); |
158 | if (!envp[n_env]) |
159 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 159, __func__); |
160 | |
161 | n_env++; |
162 | } |
163 | } |
164 | |
165 | FOREACH_STRING(tocopy, "TERM=", "PATH=", "USER=", "HOME=")for (char **_l = ({ char **_ll = ((char**) ((const char*[]) { "TERM=", "PATH=", "USER=", "HOME=", ((void*)0) })); tocopy = _ll ? _ll[0] : ((void*)0); _ll; }); _l && *_l; tocopy = ({ _l ++; _l[0]; })) { |
166 | const char *n; |
167 | |
168 | n = strv_find_prefix(env, tocopy); |
169 | if (!n) |
170 | continue; |
171 | |
172 | envp[n_env] = strdup(n); |
173 | if (!envp[n_env]) |
174 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 174, __func__); |
175 | |
176 | n_env++; |
177 | } |
178 | |
179 | if (arg_inetd) { |
180 | assert(n_fds == 1)do { if ((__builtin_expect(!!(!(n_fds == 1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n_fds == 1"), "../src/activate/activate.c" , 180, __PRETTY_FUNCTION__); } while (0); |
181 | |
182 | r = rearrange_stdio(start_fd, start_fd, STDERR_FILENO2); /* invalidates start_fd on success + error */ |
183 | if (r < 0) |
184 | return log_error_errno(r, "Failed to move fd to stdin+stdout: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 184, __func__, "Failed to move fd to stdin+stdout: %m" ) : -abs(_e); }); |
185 | |
186 | } else { |
187 | if (start_fd != SD_LISTEN_FDS_START3) { |
188 | assert(n_fds == 1)do { if ((__builtin_expect(!!(!(n_fds == 1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n_fds == 1"), "../src/activate/activate.c" , 188, __PRETTY_FUNCTION__); } while (0); |
189 | |
190 | if (dup2(start_fd, SD_LISTEN_FDS_START3) < 0) |
191 | return log_error_errno(errno, "Failed to dup connection: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 191, __func__ , "Failed to dup connection: %m") : -abs(_e); }); |
192 | |
193 | safe_close(start_fd); |
194 | start_fd = SD_LISTEN_FDS_START3; |
Value stored to 'start_fd' is never read | |
195 | } |
196 | |
197 | if (asprintf((char**)(envp + n_env++), "LISTEN_FDS=%zu", n_fds) < 0) |
198 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 198, __func__); |
199 | |
200 | if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT"%" "i", getpid_cached()) < 0) |
201 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 201, __func__); |
202 | |
203 | if (arg_fdnames) { |
204 | _cleanup_free___attribute__((cleanup(freep))) char *names = NULL((void*)0); |
205 | size_t len; |
206 | char *e; |
207 | |
208 | len = strv_length(arg_fdnames); |
209 | if (len == 1) { |
210 | size_t i; |
211 | |
212 | for (i = 1; i < n_fds; i++) { |
213 | r = strv_extend(&arg_fdnames, arg_fdnames[0]); |
214 | if (r < 0) |
215 | return log_error_errno(r, "Failed to extend strv: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 215, __func__, "Failed to extend strv: %m" ) : -abs(_e); }); |
216 | } |
217 | } else if (len != n_fds) |
218 | log_warning("The number of fd names is different than number of fds: %zu vs %zu", len, n_fds)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 218, __func__, "The number of fd names is different than number of fds: %zu vs %zu" , len, n_fds) : -abs(_e); }); |
219 | |
220 | names = strv_join(arg_fdnames, ":"); |
221 | if (!names) |
222 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 222, __func__); |
223 | |
224 | e = strappend("LISTEN_FDNAMES=", names); |
225 | if (!e) |
226 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 226, __func__); |
227 | |
228 | envp[n_env++] = e; |
229 | } |
230 | } |
231 | |
232 | joined = strv_join(argv, " "); |
233 | if (!joined) |
234 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 234, __func__); |
235 | |
236 | log_info("Execing %s (%s)", name, joined)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 236, __func__, "Execing %s (%s)" , name, joined) : -abs(_e); }); |
237 | execvpe(name, argv, envp); |
238 | |
239 | return log_error_errno(errno, "Failed to execp %s (%s): %m", name, joined)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 239, __func__ , "Failed to execp %s (%s): %m", name, joined) : -abs(_e); }); |
240 | } |
241 | |
242 | static int fork_and_exec_process(const char* child, char** argv, char **env, int fd) { |
243 | _cleanup_free___attribute__((cleanup(freep))) char *joined = NULL((void*)0); |
244 | pid_t child_pid; |
245 | int r; |
246 | |
247 | joined = strv_join(argv, " "); |
248 | if (!joined) |
249 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 249, __func__); |
250 | |
251 | r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid); |
252 | if (r < 0) |
253 | return r; |
254 | if (r == 0) { |
255 | /* In the child */ |
256 | exec_process(child, argv, env, fd, 1); |
257 | _exit(EXIT_FAILURE1); |
258 | } |
259 | |
260 | log_info("Spawned %s (%s) as PID " PID_FMT ".", child, joined, child_pid)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 260, __func__, "Spawned %s (%s) as PID " "%" "i" ".", child, joined, child_pid) : -abs(_e); }); |
261 | return 0; |
262 | } |
263 | |
264 | static int do_accept(const char* name, char **argv, char **envp, int fd) { |
265 | _cleanup_free___attribute__((cleanup(freep))) char *local = NULL((void*)0), *peer = NULL((void*)0); |
266 | _cleanup_close___attribute__((cleanup(closep))) int fd_accepted = -1; |
267 | |
268 | fd_accepted = accept4(fd, NULL((void*)0), NULL((void*)0), 0); |
269 | if (fd_accepted < 0) |
270 | return log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 270, __func__ , "Failed to accept connection on fd:%d: %m", fd) : -abs(_e); }); |
271 | |
272 | getsockname_pretty(fd_accepted, &local); |
273 | getpeername_pretty(fd_accepted, true1, &peer); |
274 | log_info("Connection from %s to %s", strna(peer), strna(local))({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 274, __func__, "Connection from %s to %s" , strna(peer), strna(local)) : -abs(_e); }); |
275 | |
276 | return fork_and_exec_process(name, argv, envp, fd_accepted); |
277 | } |
278 | |
279 | /* SIGCHLD handler. */ |
280 | static void sigchld_hdl(int sig) { |
281 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); |
282 | |
283 | for (;;) { |
284 | siginfo_t si; |
285 | int r; |
286 | |
287 | si.si_pid_sifields._kill.si_pid = 0; |
288 | r = waitid(P_ALL, 0, &si, WEXITED4|WNOHANG1); |
289 | if (r < 0) { |
290 | if (errno(*__errno_location ()) != ECHILD10) |
291 | log_error_errno(errno, "Failed to reap children: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 291, __func__ , "Failed to reap children: %m") : -abs(_e); }); |
292 | return; |
293 | } |
294 | if (si.si_pid_sifields._kill.si_pid == 0) |
295 | return; |
296 | |
297 | log_info("Child %d died with code %d", si.si_pid, si.si_status)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 297, __func__, "Child %d died with code %d" , si._sifields._kill.si_pid, si._sifields._sigchld.si_status) : -abs(_e); }); |
298 | } |
299 | } |
300 | |
301 | static int install_chld_handler(void) { |
302 | static const struct sigaction act = { |
303 | .sa_flags = SA_NOCLDSTOP1|SA_RESTART0x10000000, |
304 | .sa_handler__sigaction_handler.sa_handler = sigchld_hdl, |
305 | }; |
306 | |
307 | if (sigaction(SIGCHLD17, &act, 0) < 0) |
308 | return log_error_errno(errno, "Failed to install SIGCHLD handler: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 308, __func__ , "Failed to install SIGCHLD handler: %m") : -abs(_e); }); |
309 | |
310 | return 0; |
311 | } |
312 | |
313 | static void help(void) { |
314 | printf("%s [OPTIONS...]\n\n" |
315 | "Listen on sockets and launch child on connection.\n\n" |
316 | "Options:\n" |
317 | " -h --help Show this help and exit\n" |
318 | " --version Print version string and exit\n" |
319 | " -l --listen=ADDR Listen for raw connections at ADDR\n" |
320 | " -d --datagram Listen on datagram instead of stream socket\n" |
321 | " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n" |
322 | " -a --accept Spawn separate child for each connection\n" |
323 | " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n" |
324 | " --fdname=NAME[:NAME...] Specify names for file descriptors\n" |
325 | " --inetd Enable inetd file descriptor passing protocol\n" |
326 | "\n" |
327 | "Note: file descriptors from sd_listen_fds() will be passed through.\n" |
328 | , program_invocation_short_name); |
329 | } |
330 | |
331 | static int parse_argv(int argc, char *argv[]) { |
332 | enum { |
333 | ARG_VERSION = 0x100, |
334 | ARG_FDNAME, |
335 | ARG_SEQPACKET, |
336 | ARG_INETD, |
337 | }; |
338 | |
339 | static const struct option options[] = { |
340 | { "help", no_argument0, NULL((void*)0), 'h' }, |
341 | { "version", no_argument0, NULL((void*)0), ARG_VERSION }, |
342 | { "datagram", no_argument0, NULL((void*)0), 'd' }, |
343 | { "seqpacket", no_argument0, NULL((void*)0), ARG_SEQPACKET }, |
344 | { "listen", required_argument1, NULL((void*)0), 'l' }, |
345 | { "accept", no_argument0, NULL((void*)0), 'a' }, |
346 | { "setenv", required_argument1, NULL((void*)0), 'E' }, |
347 | { "environment", required_argument1, NULL((void*)0), 'E' }, /* legacy alias */ |
348 | { "fdname", required_argument1, NULL((void*)0), ARG_FDNAME }, |
349 | { "inetd", no_argument0, NULL((void*)0), ARG_INETD }, |
350 | {} |
351 | }; |
352 | |
353 | int c, r; |
354 | |
355 | assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/activate/activate.c" , 355, __PRETTY_FUNCTION__); } while (0); |
356 | assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argv"), "../src/activate/activate.c", 356 , __PRETTY_FUNCTION__); } while (0); |
357 | |
358 | while ((c = getopt_long(argc, argv, "+hl:aE:d", options, NULL((void*)0))) >= 0) |
359 | switch(c) { |
360 | case 'h': |
361 | help(); |
362 | return 0; |
363 | |
364 | case ARG_VERSION: |
365 | return version(); |
366 | |
367 | case 'l': |
368 | r = strv_extend(&arg_listen, optarg); |
369 | if (r < 0) |
370 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 370, __func__); |
371 | |
372 | break; |
373 | |
374 | case 'd': |
375 | if (arg_socket_type == SOCK_SEQPACKETSOCK_SEQPACKET) { |
376 | log_error("--datagram may not be combined with --seqpacket.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 376, __func__, "--datagram may not be combined with --seqpacket." ) : -abs(_e); }); |
377 | return -EINVAL22; |
378 | } |
379 | |
380 | arg_socket_type = SOCK_DGRAMSOCK_DGRAM; |
381 | break; |
382 | |
383 | case ARG_SEQPACKET: |
384 | if (arg_socket_type == SOCK_DGRAMSOCK_DGRAM) { |
385 | log_error("--seqpacket may not be combined with --datagram.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 385, __func__, "--seqpacket may not be combined with --datagram." ) : -abs(_e); }); |
386 | return -EINVAL22; |
387 | } |
388 | |
389 | arg_socket_type = SOCK_SEQPACKETSOCK_SEQPACKET; |
390 | break; |
391 | |
392 | case 'a': |
393 | arg_accept = true1; |
394 | break; |
395 | |
396 | case 'E': |
397 | r = strv_extend(&arg_setenv, optarg); |
398 | if (r < 0) |
399 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 399, __func__); |
400 | |
401 | break; |
402 | |
403 | case ARG_FDNAME: { |
404 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **names; |
405 | char **s; |
406 | |
407 | names = strv_split(optarg, ":"); |
408 | if (!names) |
409 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/activate/activate.c" , 409, __func__); |
410 | |
411 | STRV_FOREACH(s, names)for ((s) = (names); (s) && *(s); (s)++) |
412 | if (!fdname_is_valid(*s)) { |
413 | _cleanup_free___attribute__((cleanup(freep))) char *esc; |
414 | |
415 | esc = cescape(*s); |
416 | log_warning("File descriptor name \"%s\" is not valid.", esc)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 416, __func__, "File descriptor name \"%s\" is not valid." , esc) : -abs(_e); }); |
417 | } |
418 | |
419 | /* Empty optargs means one empty name */ |
420 | r = strv_extend_strv(&arg_fdnames, |
421 | strv_isempty(names) ? STRV_MAKE("")((char**) ((const char*[]) { "", ((void*)0) })) : names, |
422 | false0); |
423 | if (r < 0) |
424 | return log_error_errno(r, "strv_extend_strv: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 424, __func__, "strv_extend_strv: %m" ) : -abs(_e); }); |
425 | break; |
426 | } |
427 | |
428 | case ARG_INETD: |
429 | arg_inetd = true1; |
430 | break; |
431 | |
432 | case '?': |
433 | return -EINVAL22; |
434 | |
435 | default: |
436 | assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unhandled option"), "../src/activate/activate.c", 436, __PRETTY_FUNCTION__ ); } while (0); |
437 | } |
438 | |
439 | if (optind == argc) { |
440 | log_error("%s: command to execute is missing.",({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 441, __func__, "%s: command to execute is missing." , program_invocation_short_name) : -abs(_e); }) |
441 | program_invocation_short_name)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 441, __func__, "%s: command to execute is missing." , program_invocation_short_name) : -abs(_e); }); |
442 | return -EINVAL22; |
443 | } |
444 | |
445 | if (arg_socket_type == SOCK_DGRAMSOCK_DGRAM && arg_accept) { |
446 | log_error("Datagram sockets do not accept connections. "({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 447, __func__, "Datagram sockets do not accept connections. " "The --datagram and --accept options may not be combined.") : -abs(_e); }) |
447 | "The --datagram and --accept options may not be combined.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 447, __func__, "Datagram sockets do not accept connections. " "The --datagram and --accept options may not be combined.") : -abs(_e); }); |
448 | return -EINVAL22; |
449 | } |
450 | |
451 | arg_args = argv + optind; |
452 | |
453 | return 1 /* work to do */; |
454 | } |
455 | |
456 | int main(int argc, char **argv, char **envp) { |
457 | int r, n; |
458 | int epoll_fd = -1; |
459 | |
460 | log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD); |
461 | log_open(); |
462 | |
463 | r = parse_argv(argc, argv); |
464 | if (r <= 0) |
465 | return r == 0 ? EXIT_SUCCESS0 : EXIT_FAILURE1; |
466 | |
467 | r = install_chld_handler(); |
468 | if (r < 0) |
469 | return EXIT_FAILURE1; |
470 | |
471 | n = open_sockets(&epoll_fd, arg_accept); |
472 | if (n < 0) |
473 | return EXIT_FAILURE1; |
474 | if (n == 0) { |
475 | log_error("No sockets to listen on specified or passed in.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 475, __func__, "No sockets to listen on specified or passed in." ) : -abs(_e); }); |
476 | return EXIT_FAILURE1; |
477 | } |
478 | |
479 | for (;;) { |
480 | struct epoll_event event; |
481 | |
482 | if (epoll_wait(epoll_fd, &event, 1, -1) < 0) { |
483 | if (errno(*__errno_location ()) == EINTR4) |
484 | continue; |
485 | |
486 | log_error_errno(errno, "epoll_wait() failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/activate/activate.c", 486, __func__ , "epoll_wait() failed: %m") : -abs(_e); }); |
487 | return EXIT_FAILURE1; |
488 | } |
489 | |
490 | log_info("Communication attempt on fd %i.", event.data.fd)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/activate/activate.c", 490, __func__, "Communication attempt on fd %i." , event.data.fd) : -abs(_e); }); |
491 | if (arg_accept) { |
492 | r = do_accept(argv[optind], argv + optind, envp, event.data.fd); |
493 | if (r < 0) |
494 | return EXIT_FAILURE1; |
495 | } else |
496 | break; |
497 | } |
498 | |
499 | exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START3, (size_t) n); |
500 | |
501 | return EXIT_SUCCESS0; |
502 | } |