summaryrefslogtreecommitdiff
path: root/src/systemd-activate
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd-activate')
-rw-r--r--src/systemd-activate/Makefile8
-rw-r--r--src/systemd-activate/activate.c118
-rw-r--r--src/systemd-activate/systemd-activate.xml204
3 files changed, 80 insertions, 250 deletions
diff --git a/src/systemd-activate/Makefile b/src/systemd-activate/Makefile
index 058e10809e..5e2299f00e 100644
--- a/src/systemd-activate/Makefile
+++ b/src/systemd-activate/Makefile
@@ -24,13 +24,13 @@ include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk
include $(topsrcdir)/build-aux/Makefile.head.mk
-libexec_PROGRAMS += \
- systemd-activate
+bin_PROGRAMS += \
+ systemd-socket-activate
-systemd_activate_SOURCES = \
+systemd_socket_activate_SOURCES = \
src/activate/activate.c
-systemd_activate_LDADD = \
+systemd_socket_activate_LDADD = \
libshared.la
include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/systemd-activate/activate.c b/src/systemd-activate/activate.c
index 94f99028e5..89cc1ee813 100644
--- a/src/systemd-activate/activate.c
+++ b/src/systemd-activate/activate.c
@@ -27,6 +27,7 @@
#include <systemd/sd-daemon.h>
#include "alloc-util.h"
+#include "escape.h"
#include "fd-util.h"
#include "log.h"
#include "macro.h"
@@ -40,7 +41,7 @@ static bool arg_accept = false;
static int arg_socket_type = SOCK_STREAM;
static char** arg_args = NULL;
static char** arg_setenv = NULL;
-static const char *arg_fdname = NULL;
+static char **arg_fdnames = NULL;
static bool arg_inetd = false;
static int add_epoll(int epoll_fd, int fd) {
@@ -76,7 +77,7 @@ static int open_sockets(int *epoll_fd, bool accept) {
if (r < 0)
return r;
- count ++;
+ count++;
}
}
@@ -104,7 +105,7 @@ static int open_sockets(int *epoll_fd, bool accept) {
}
assert(fd == SD_LISTEN_FDS_START + count);
- count ++;
+ count++;
}
if (arg_listen)
@@ -134,7 +135,6 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
_cleanup_free_ char *joined = NULL;
unsigned n_env = 0, length;
const char *tocopy;
- unsigned i;
char **s;
int r;
@@ -176,7 +176,7 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (!envp[n_env])
return log_oom();
- n_env ++;
+ n_env++;
}
}
@@ -191,7 +191,7 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (!envp[n_env])
return log_oom();
- n_env ++;
+ n_env++;
}
if (arg_inetd) {
@@ -224,25 +224,30 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT, getpid()) < 0)
return log_oom();
- if (arg_fdname) {
+ if (arg_fdnames) {
+ _cleanup_free_ char *names = NULL;
+ size_t len;
char *e;
+ int i;
+
+ len = strv_length(arg_fdnames);
+ if (len == 1)
+ for (i = 1; i < n_fds; i++) {
+ r = strv_extend(&arg_fdnames, arg_fdnames[0]);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extend strv: %m");
+ }
+ else if (len != (unsigned) n_fds)
+ log_warning("The number of fd names is different than number of fds: %zu vs %d",
+ len, n_fds);
- e = strappend("LISTEN_FDNAMES=", arg_fdname);
- if (!e)
+ names = strv_join(arg_fdnames, ":");
+ if (!names)
return log_oom();
- for (i = 1; i < (unsigned) n_fds; i++) {
- char *c;
-
- c = strjoin(e, ":", arg_fdname, NULL);
- if (!c) {
- free(e);
- return log_oom();
- }
-
- free(e);
- e = c;
- }
+ e = strappend("LISTEN_FDNAMES=", names);
+ if (!e)
+ return log_oom();
envp[n_env++] = e;
}
@@ -311,19 +316,31 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) {
}
/* SIGCHLD handler. */
-static void sigchld_hdl(int sig, siginfo_t *t, void *data) {
+static void sigchld_hdl(int sig) {
PROTECT_ERRNO;
- log_info("Child %d died with code %d", t->si_pid, t->si_status);
+ for (;;) {
+ siginfo_t si;
+ int r;
+
+ si.si_pid = 0;
+ r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG);
+ if (r < 0) {
+ if (errno != ECHILD)
+ log_error_errno(errno, "Failed to reap children: %m");
+ return;
+ }
+ if (si.si_pid == 0)
+ return;
- /* Wait for a dead child. */
- (void) waitpid(t->si_pid, NULL, 0);
+ log_info("Child %d died with code %d", si.si_pid, si.si_status);
+ }
}
static int install_chld_handler(void) {
static const struct sigaction act = {
- .sa_flags = SA_SIGINFO,
- .sa_sigaction = sigchld_hdl,
+ .sa_flags = SA_NOCLDSTOP,
+ .sa_handler = sigchld_hdl,
};
int r;
@@ -339,14 +356,15 @@ static void help(void) {
printf("%s [OPTIONS...]\n\n"
"Listen on sockets and launch child on connection.\n\n"
"Options:\n"
- " -h --help Show this help and exit\n"
- " --version Print version string and exit\n"
- " -l --listen=ADDR Listen for raw connections at ADDR\n"
- " -d --datagram Listen on datagram instead of stream socket\n"
- " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n"
- " -a --accept Spawn separate child for each connection\n"
- " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n"
- " --inetd Enable inetd file descriptor passing protocol\n"
+ " -h --help Show this help and exit\n"
+ " --version Print version string and exit\n"
+ " -l --listen=ADDR Listen for raw connections at ADDR\n"
+ " -d --datagram Listen on datagram instead of stream socket\n"
+ " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n"
+ " -a --accept Spawn separate child for each connection\n"
+ " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n"
+ " --fdname=NAME[:NAME...] Specify names for file descriptors\n"
+ " --inetd Enable inetd file descriptor passing protocol\n"
"\n"
"Note: file descriptors from sd_listen_fds() will be passed through.\n"
, program_invocation_short_name);
@@ -379,7 +397,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hl:aEd", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hl:aE:d", options, NULL)) >= 0)
switch(c) {
case 'h':
help();
@@ -424,14 +442,30 @@ static int parse_argv(int argc, char *argv[]) {
break;
- case ARG_FDNAME:
- if (!fdname_is_valid(optarg)) {
- log_error("File descriptor name %s is not valid, refusing.", optarg);
- return -EINVAL;
- }
+ case ARG_FDNAME: {
+ _cleanup_strv_free_ char **names;
+ char **s;
+
+ names = strv_split(optarg, ":");
+ if (!names)
+ return log_oom();
- arg_fdname = optarg;
+ STRV_FOREACH(s, names)
+ if (!fdname_is_valid(*s)) {
+ _cleanup_free_ char *esc;
+
+ esc = cescape(*s);
+ log_warning("File descriptor name \"%s\" is not valid.", esc);
+ }
+
+ /* Empty optargs means one empty name */
+ r = strv_extend_strv(&arg_fdnames,
+ strv_isempty(names) ? STRV_MAKE("") : names,
+ false);
+ if (r < 0)
+ return log_error_errno(r, "strv_extend_strv: %m");
break;
+ }
case ARG_INETD:
arg_inetd = true;
diff --git a/src/systemd-activate/systemd-activate.xml b/src/systemd-activate/systemd-activate.xml
deleted file mode 100644
index 995e6eecce..0000000000
--- a/src/systemd-activate/systemd-activate.xml
+++ /dev/null
@@ -1,204 +0,0 @@
-<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
--->
-
-<refentry id="systemd-activate"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
- <refentryinfo>
- <title>systemd-activate</title>
- <productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>systemd-activate</refentrytitle>
- <manvolnum>8</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>systemd-activate</refname>
- <refpurpose>Test socket activation of daemons</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>/usr/lib/systemd/systemd-activate</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <arg choice="plain"><replaceable>daemon</replaceable></arg>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para><command>systemd-activate</command> may be used to launch a socket-activated service binary from the command
- line for testing purposes. It may also be used to launch individual instances of the service binary per connection.
- </para>
-
- <para>The daemon to launch and its options should be specified
- after options intended for <command>systemd-activate</command>.
- </para>
-
- <para>If the <option>--inetd</option> option is given, the socket file descriptor will be used as the standard
- input and output of the launched process. Otherwise, standard input and output will be inherited, and sockets will
- be passed through file descriptors 3 and higher. Sockets passed through <varname>$LISTEN_FDS</varname> to
- <command>systemd-activate</command> will be passed through to the daemon, in the original positions. Other sockets
- specified with <option>--listen=</option> will use consecutive descriptors. By default,
- <command>systemd-activate</command> listens on a stream socket, use <option>--datagram</option> and
- <option>--seqpacket</option> to listen on datagram or sequential packet sockets instead (see below).
- </para>
- </refsect1>
-
- <refsect1>
- <title>Options</title>
- <variablelist>
- <varlistentry>
- <term><option>-l <replaceable>address</replaceable></option></term>
- <term><option>--listen=<replaceable>address</replaceable></option></term>
-
- <listitem><para>Listen on this <replaceable>address</replaceable>.
- Takes a string like <literal>2000</literal> or
- <literal>127.0.0.1:2001</literal>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-a</option></term>
- <term><option>--accept</option></term>
-
- <listitem><para>Launch an instance of the service binary for each connection and pass the connection
- socket.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
- <term><option>--datagram</option></term>
-
- <listitem><para>Listen on a datagram socket (<constant>SOCK_DGRAM</constant>), instead of a stream socket
- (<constant>SOCK_STREAM</constant>). May not be combined with <option>--seqpacket</option>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--seqpacket</option></term>
-
- <listitem><para>Listen on a sequential packet socket (<constant>SOCK_SEQPACKET</constant>), instead of a stream
- socket (<constant>SOCK_STREAM</constant>). May not be combined with
- <option>--datagram</option>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--inetd</option></term>
-
- <listitem><para>Use the inetd protocol for passing file descriptors, i.e. as standard input and standard
- output, instead of the new-style protocol for passing file descriptors using <varname>$LISTEN_FDS</varname>
- (see above).</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-E <replaceable>VAR</replaceable><optional>=<replaceable>VALUE</replaceable></optional></option></term>
- <term><option>--setenv=<replaceable>VAR</replaceable><optional>=<replaceable>VALUE</replaceable></optional></option></term>
-
- <listitem><para>Add this variable to the environment of the
- launched process. If <replaceable>VAR</replaceable> is
- followed by <literal>=</literal>, assume that it is a
- variable–value pair. Otherwise, obtain the value from the
- environment of <command>systemd-activate</command> itself.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--fdname=</option><replaceable>NAME</replaceable></term>
-
- <listitem><para>Specify a name for the activation file
- descriptors. This is equivalent to setting
- <varname>FileDescriptorName=</varname> in socket unit files, and
- enables use of
- <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
- </varlistentry>
-
- <xi:include href="standard-options.xml" xpointer="help" />
- <xi:include href="standard-options.xml" xpointer="version" />
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Environment variables</title>
- <variablelist class='environment-variables'>
- <varlistentry>
- <term><varname>$LISTEN_FDS</varname></term>
- <term><varname>$LISTEN_PID</varname></term>
- <term><varname>$LISTEN_FDNAMES</varname></term>
-
- <listitem><para>See
- <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>$SYSTEMD_LOG_TARGET</varname></term>
- <term><varname>$SYSTEMD_LOG_LEVEL</varname></term>
- <term><varname>$SYSTEMD_LOG_COLOR</varname></term>
- <term><varname>$SYSTEMD_LOG_LOCATION</varname></term>
-
- <listitem><para>Same as in
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <example>
- <title>Run an echo server on port 2000</title>
-
- <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 --inetd -a cat</programlisting>
- </example>
-
- <example>
- <title>Run a socket-activated instance of <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry></title>
-
- <programlisting>$ /usr/lib/systemd/systemd-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd</programlisting>
- </example>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>cat</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- </para>
- </refsect1>
-</refentry>