From afe773b01a704b98a350a36fa518bfcd6a54323b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 11 Feb 2016 23:24:14 -0500 Subject: [PATCH 1/3] basic/strv: fix strv_join for first empty argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empty strings were ignored in strv_join, but only if they were at the beginning of the string. Empty strings after at least one non-empty item were treated normally. Previously: {"x"} → "x" {"x", ""} → "x" {"x", "", ""} → "x::" {""} → "" {"", ""} → "" {"", "", ""} → "" {"", "x"} → "x" {"", "x", ""} → "x:" Now: {"x"} → "x" {"x", ""} → "x" {"x", "", ""} → "x::" {""} → "" {"", ""} → ":" {"", "", ""} → "::" {"", "x"} → ":x" {"", "x", ""} → ":x:" --- src/basic/strv.c | 4 ++-- src/test/test-strv.c | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/basic/strv.c b/src/basic/strv.c index b5d4d8191b1..8282298dcaf 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -371,7 +371,7 @@ char *strv_join(char **l, const char *separator) { n = 0; STRV_FOREACH(s, l) { - if (n != 0) + if (s != l) n += k; n += strlen(*s); } @@ -382,7 +382,7 @@ char *strv_join(char **l, const char *separator) { e = r; STRV_FOREACH(s, l) { - if (e != r) + if (s != l) e = stpcpy(e, separator); e = stpcpy(e, *s); diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 2b2f76cc7f9..ef451c6abfc 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -70,6 +70,18 @@ static const char* const input_table_none[] = { NULL, }; +static const char* const input_table_two_empties[] = { + "", + "", + NULL, +}; + +static const char* const input_table_one_empty[] = { + "", + NULL, +}; + + static const char* const input_table_quotes[] = { "\"", "'", @@ -130,7 +142,7 @@ static void test_strv_find_startswith(void) { } static void test_strv_join(void) { - _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL; + _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; p = strv_join((char **)input_table_multiple, ", "); assert_se(p); @@ -151,6 +163,14 @@ static void test_strv_join(void) { t = strv_join((char **)input_table_none, ", "); assert_se(t); assert_se(streq(t, "")); + + v = strv_join((char **)input_table_two_empties, ", "); + assert_se(v); + assert_se(streq(v, ", ")); + + w = strv_join((char **)input_table_one_empty, ", "); + assert_se(w); + assert_se(streq(w, "")); } static void test_strv_quote_unquote(const char* const *split, const char *quoted) { @@ -653,6 +673,8 @@ int main(int argc, char *argv[]) { test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\""); test_strv_quote_unquote(input_table_one, "\"one\""); test_strv_quote_unquote(input_table_none, ""); + test_strv_quote_unquote(input_table_one_empty, "\"\""); + test_strv_quote_unquote(input_table_two_empties, "\"\" \"\""); test_strv_quote_unquote(input_table_quotes, QUOTES_STRING); test_strv_quote_unquote(input_table_spaces, SPACES_STRING); From cf98937cc73201a71fabbd35fd9853cbe2790ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 11 Feb 2016 23:33:09 -0500 Subject: [PATCH 2/3] activate: allow multiple, possibly invalid, fd names Previous code only allowed a single name to be passed, and duplicated it over all descriptors. For the sake of testing, allow different names and in arbitrary number. If just one is given, duplicate it to match the number of sockets. This matches previuos behaviour. Since this is a testing tool, it seems useful to allow passing invalid names to test application behaviour with invalid names. Hence, only warn. When warning, escape the name. --- man/systemd-activate.xml | 14 ++++--- src/activate/activate.c | 84 +++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/man/systemd-activate.xml b/man/systemd-activate.xml index 995e6eecce6..a8e17f2a2a0 100644 --- a/man/systemd-activate.xml +++ b/man/systemd-activate.xml @@ -136,13 +136,15 @@ - NAME + NAME:NAME... - Specify a name for the activation file - descriptors. This is equivalent to setting - FileDescriptorName= in socket unit files, and - enables use of - sd_listen_fds_with_names3. + Specify names for the file descriptors passed. This is equivalent to setting + FileDescriptorName= in socket unit files, and enables use of + sd_listen_fds_with_names3. + Multiple entries may be specifies using separate options or by separating names with colons + (:) in one option. In case more names are given than descriptors, superflous ones willl be + ignored. In case less names are given than descriptors, the remaining file descriptors will be unnamed. + diff --git a/src/activate/activate.c b/src/activate/activate.c index 0db4967edba..23244fdc62a 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -27,6 +27,7 @@ #include "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) { @@ -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; @@ -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; - e = strappend("LISTEN_FDNAMES=", arg_fdname); - if (!e) + 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); + + 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; } @@ -339,14 +344,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); @@ -424,14 +430,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; - arg_fdname = optarg; + names = strv_split(optarg, ":"); + if (!names) + return log_oom(); + + 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; From 7f6e804332f50dbd52afe04f5c3ce9db1072c98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 11 Feb 2016 22:11:33 -0500 Subject: [PATCH 3/3] Promote systemd-activate to /usr/bin/systemd-socket-activate It has fairly wide functionality now and the interface has been stable for a while. It it a useful testing tool. The name is changed to better indicate what it does. --- .gitignore | 2 +- Makefile-man.am | 4 +-- Makefile.am | 8 +++--- NEWS | 6 +++++ ...tivate.xml => systemd-socket-activate.xml} | 26 +++++++++---------- 5 files changed, 26 insertions(+), 20 deletions(-) rename man/{systemd-activate.xml => systemd-socket-activate.xml} (88%) diff --git a/.gitignore b/.gitignore index cc24233ab88..4ac63a4e284 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,6 @@ /systemctl /systemd /systemd-ac-power -/systemd-activate /systemd-analyze /systemd-ask-password /systemd-backlight @@ -109,6 +108,7 @@ /systemd-run /systemd-shutdown /systemd-sleep +/systemd-socket-activate /systemd-socket-proxyd /systemd-stdio-bridge /systemd-sysctl diff --git a/Makefile-man.am b/Makefile-man.am index 28b5fb6adb9..f4c9edc42c7 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -94,7 +94,6 @@ MANPAGES += \ man/shutdown.8 \ man/sysctl.d.5 \ man/systemctl.1 \ - man/systemd-activate.8 \ man/systemd-analyze.1 \ man/systemd-ask-password-console.service.8 \ man/systemd-ask-password.1 \ @@ -126,6 +125,7 @@ MANPAGES += \ man/systemd-resolve.1 \ man/systemd-run.1 \ man/systemd-sleep.conf.5 \ + man/systemd-socket-activate.1 \ man/systemd-socket-proxyd.8 \ man/systemd-suspend.service.8 \ man/systemd-sysctl.service.8 \ @@ -2574,7 +2574,6 @@ EXTRA_DIST += \ man/standard-options.xml \ man/sysctl.d.xml \ man/systemctl.xml \ - man/systemd-activate.xml \ man/systemd-analyze.xml \ man/systemd-ask-password-console.service.xml \ man/systemd-ask-password.xml \ @@ -2628,6 +2627,7 @@ EXTRA_DIST += \ man/systemd-rfkill.service.xml \ man/systemd-run.xml \ man/systemd-sleep.conf.xml \ + man/systemd-socket-activate.xml \ man/systemd-socket-proxyd.xml \ man/systemd-suspend.service.xml \ man/systemd-sysctl.service.xml \ diff --git a/Makefile.am b/Makefile.am index 676d97c7d46..da94b502a37 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3875,13 +3875,13 @@ tests += \ # ------------------------------------------------------------------------------ -rootlibexec_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 # ------------------------------------------------------------------------------ diff --git a/NEWS b/NEWS index 265847c7bdb..80e59c53d39 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ systemd System and Service Manager +CHANGES WITH 230 in spe: + + * Testing tool /usr/lib/systemd/systemd-activate is renamed to + systemd-socket-activate and installed into /usr/bin. It is now fully + supported. + CHANGES WITH 229: * The systemd-resolved DNS resolver service has gained a substantial diff --git a/man/systemd-activate.xml b/man/systemd-socket-activate.xml similarity index 88% rename from man/systemd-activate.xml rename to man/systemd-socket-activate.xml index a8e17f2a2a0..5d7f157c72d 100644 --- a/man/systemd-activate.xml +++ b/man/systemd-socket-activate.xml @@ -21,11 +21,11 @@ along with systemd; If not, see . --> - - systemd-activate + systemd-socket-activate systemd @@ -39,18 +39,18 @@ - systemd-activate - 8 + systemd-socket-activate + 1 - systemd-activate + systemd-socket-activate Test socket activation of daemons - /usr/lib/systemd/systemd-activate + systemd-socket-activate OPTIONS daemon OPTIONS @@ -60,20 +60,20 @@ Description - systemd-activate may be used to launch a socket-activated service binary from the command + systemd-socket-activate 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. The daemon to launch and its options should be specified - after options intended for systemd-activate. + after options intended for systemd-socket-activate. If the 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 $LISTEN_FDS to - systemd-activate will be passed through to the daemon, in the original positions. Other sockets + systemd-socket-activate will be passed through to the daemon, in the original positions. Other sockets specified with will use consecutive descriptors. By default, - systemd-activate listens on a stream socket, use and + systemd-socket-activate listens on a stream socket, use and to listen on datagram or sequential packet sockets instead (see below). @@ -131,7 +131,7 @@ launched process. If VAR is followed by =, assume that it is a variable–value pair. Otherwise, obtain the value from the - environment of systemd-activate itself. + environment of systemd-socket-activate itself. @@ -182,13 +182,13 @@ Run an echo server on port 2000 - $ /usr/lib/systemd/systemd-activate -l 2000 --inetd -a cat + $ systemd-socket-activate -l 2000 --inetd -a cat Run a socket-activated instance of <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry> - $ /usr/lib/systemd/systemd-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd + $ systemd-socket-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd