[systemd-commits] 6 commits - make-directive-index.py Makefile.am Makefile-man.am make-man-rules.py man/systemd-activate.xml man/systemd-nspawn.xml src/activate src/nspawn src/shared TODO

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Wed Feb 27 19:28:07 PST 2013


 Makefile-man.am          |    3 
 Makefile.am              |   19 ++
 TODO                     |    2 
 make-directive-index.py  |    5 
 make-man-rules.py        |    6 
 man/systemd-activate.xml |  171 +++++++++++++++++++
 man/systemd-nspawn.xml   |   28 ++-
 src/activate/activate.c  |  410 +++++++++++++++++++++++++++++++++++++++++++++++
 src/nspawn/nspawn.c      |    7 
 src/shared/socket-util.c |   39 ++++
 src/shared/socket-util.h |    2 
 11 files changed, 676 insertions(+), 16 deletions(-)

New commits:
commit 870c4365cf3d407270788abe14d216a636ecf6c3
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Feb 27 22:25:40 2013 -0500

    man: document systemd-nspawn behaviour with -b
    
    Cf. cb96a2c69 and 1ddf879a.

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 41477b4..8adcd94 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -51,7 +51,14 @@
                 <cmdsynopsis>
                         <command>systemd-nspawn</command>
                         <arg choice="opt" rep="repeat">OPTIONS</arg>
-                        <arg choice="opt">COMMAND</arg>
+                        <arg choice="opt"><replaceable>COMMAND</replaceable>
+                        <arg choice="opt" rep="repeat">ARGS</arg>
+                        </arg>
+                </cmdsynopsis>
+                <cmdsynopsis>
+                        <command>systemd-nspawn</command>
+                        <arg choice="plain">-b</arg>
+                        <arg choice="opt" rep="repeat">OPTIONS</arg>
                         <arg choice="opt" rep="repeat">ARGS</arg>
                 </cmdsynopsis>
         </refsynopsisdiv>
@@ -131,10 +138,16 @@
         <refsect1>
                 <title>Options</title>
 
-                <para>If no arguments are passed the container is set
-                up and a shell started in it, otherwise the passed
-                command and arguments are executed in it. The
-                following options are understood:</para>
+                <para>If option <option>-b</option> is specified, the
+                arguments are used as arguments for the init
+                binary. Otherwise, <replaceable>COMMAND</replaceable>
+                specifies the program to launch in the container, and
+                the remaining arguments are used as arguments for this
+                program. If <option>-b</option> is not used and no
+                arguments are specifed, a shell is launched in the
+                container.</para>
+
+                <para>The following options are understood:</para>
 
                 <variablelist>
                         <varlistentry>
@@ -170,7 +183,10 @@
                                 <listitem><para>Automatically search
                                 for an init binary and invoke it
                                 instead of a shell or a user supplied
-                                program.</para></listitem>
+                                program. If this option is used, arguments
+                                specified on the command line are used
+                                as arguments for the init binary.
+                                </para></listitem>
                         </varlistentry>
 
                         <varlistentry>

commit 2ca0435be9359bde3020eeb528c2a6d72ac1e0b0
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sat Feb 23 17:52:04 2013 +0100

    systemd-activate: add a socket-activation test tool

diff --git a/Makefile-man.am b/Makefile-man.am
index 9a2f2f5..d02fff0 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -44,6 +44,7 @@ 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 \
diff --git a/Makefile.am b/Makefile.am
index cc0d4da..d00ca11 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2314,6 +2314,18 @@ EXTRA_DIST += \
 	src/libsystemd-id128/libsystemd-id128.sym
 
 # ------------------------------------------------------------------------------
+
+rootlibexec_PROGRAMS += \
+	systemd-activate
+
+systemd_activate_SOURCES = \
+	src/activate/activate.c
+
+systemd_activate_LDADD = \
+	libsystemd-shared.la \
+	libsystemd-daemon.la
+
+# ------------------------------------------------------------------------------
 systemd_journald_SOURCES = \
 	src/journal/journald.c \
 	src/journal/journald-server.h
@@ -2559,6 +2571,8 @@ libsystemd-journal-uninstall-hook:
 INSTALL_EXEC_HOOKS += libsystemd-journal-install-hook
 UNINSTALL_EXEC_HOOKS += libsystemd-journal-uninstall-hook
 
+# ------------------------------------------------------------------------------
+
 # Update catalog on installation. Do not bother if installing
 # in DESTDIR, since this is likely for packaging purposes.
 catalog-update-hook:
diff --git a/TODO b/TODO
index 5427d1b..f99f894 100644
--- a/TODO
+++ b/TODO
@@ -350,8 +350,6 @@ Features:
 
 * explore multiple service instances per listening socket idea
 
-* testing tool for socket activation: some binary that listens on a socket and passes it on using the usual socket activation protocol to some server.
-
 * shutdown: don't read-only mount anything when running in container
 
 * MountFlags=shared acts as MountFlags=slave right now.
diff --git a/man/systemd-activate.xml b/man/systemd-activate.xml
new file mode 100644
index 0000000..b2987d9
--- /dev/null
+++ b/man/systemd-activate.xml
@@ -0,0 +1,171 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!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-journal-gatewayd.service">
+
+  <refentryinfo>
+    <title>systemd-activate</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Zbigniew</firstname>
+        <surname>Jędrzejewski-Szmek</surname>
+        <email>zbyszek at 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> can be used to
+    launch a socket activated daemon from the command-line for
+    testing purposes. It can also be used to launch single instances
+    of the daemon per connection (inetd-style).
+    </para>
+
+    <para>The daemon to launch and its options should be specifed
+    after options intended for <command>systemd-activate</command>.
+    </para>
+
+    <para>If the <option>-a</option> option is given, file descriptor
+    of the connection 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 dameon, in the original positions. Other sockets specified
+    with <option>--listen</option> will use consecutive descriptors.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Options</title>
+    <variablelist>
+      <varlistentry>
+        <term><option>--help</option></term>
+        <term><option>-h</option></term>
+
+        <listitem><para>Prints a short help
+        text and exits.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--version</option></term>
+
+        <listitem><para>Prints a short version
+        string and exits.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-l</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 a separate instance of daemon per
+        connection and pass the connection socket as standard input
+        and standard output.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Environment variables</title>
+    <variablelist class='environment-variables'>
+      <varlistentry>
+        <term><varname>$LISTEN_FDS</varname></term>
+        <term><varname>$LISTEN_PID</varname></term>
+
+        <para>See
+        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+      </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>
+
+        <para>Same as in
+        <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Example 1</title>
+
+    <programlisting>$ /usr/lib/systemd/systemd-activate -l 2000 -a cat</programlisting>
+
+    <para>This runs an echo server on port 2000.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Example 2</title>
+
+    <programlisting>$ /usr/lib/systemd/systemd-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd</programlisting>
+
+    <para>This runs a socket activated instance of
+    <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+  </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>cat</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+</refentry>
diff --git a/src/activate/activate.c b/src/activate/activate.c
new file mode 100644
index 0000000..7fcb0a9
--- /dev/null
+++ b/src/activate/activate.c
@@ -0,0 +1,410 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  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/>.
+***/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <getopt.h>
+
+#include <systemd/sd-daemon.h>
+
+#include "socket-util.h"
+#include "build.h"
+#include "log.h"
+#include "strv.h"
+#include "macro.h"
+
+static char** arg_listen = NULL;
+static bool arg_accept = false;
+static char** arg_args = NULL;
+
+static int add_epoll(int epoll_fd, int fd) {
+        int r;
+        struct epoll_event ev = {EPOLLIN};
+        ev.data.fd = fd;
+
+        assert(epoll_fd >= 0);
+        assert(fd >= 0);
+
+        r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
+        if (r < 0)
+                log_error("Failed to add event on epoll fd:%d for fd:%d: %s",
+                          epoll_fd, fd, strerror(-r));
+        return r;
+}
+
+static int set_nocloexec(int fd) {
+        int flags;
+
+        flags = fcntl(fd, F_GETFD);
+        if (flags < 0) {
+                log_error("Querying flags for fd:%d: %m", fd);
+                return -errno;
+        }
+
+        if (!(flags & FD_CLOEXEC))
+                return 0;
+
+        if (fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) < 0) {
+                log_error("Settings flags for fd:%d: %m", fd);
+                return -errno;
+        }
+
+        return 0;
+}
+
+static int print_socket(const char* desc, int fd) {
+        int r;
+        SocketAddress addr = {
+                .size = sizeof(union sockaddr_union),
+                .type = SOCK_STREAM,
+        };
+        int family;
+
+        r = getsockname(fd, &addr.sockaddr.sa, &addr.size);
+        if (r < 0) {
+                log_warning("Failed to query socket on fd:%d: %m", fd);
+                return 0;
+        }
+
+        family = socket_address_family(&addr);
+        switch(family) {
+        case AF_INET:
+        case AF_INET6: {
+                char* _cleanup_free_ a = NULL;
+                r = socket_address_print(&addr, &a);
+                if (r < 0)
+                        log_warning("socket_address_print(): %s", strerror(-r));
+                else
+                        log_info("%s %s address %s",
+                                 desc,
+                                 family == AF_INET ? "IP" : "IPv6",
+                                 a);
+                break;
+        }
+        default:
+                log_warning("Connection with unknown family %d", family);
+        }
+
+        return 0;
+}
+
+static int open_sockets(int *epoll_fd, bool accept) {
+        int n, fd;
+        int count = 0;
+        char **address;
+
+        n = sd_listen_fds(true);
+        if (n < 0) {
+                log_error("Failed to read listening file descriptors from environment: %s",
+                          strerror(-n));
+                return n;
+        }
+        log_info("Received %d descriptors", n);
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
+                log_debug("Received descriptor fd:%d", fd);
+                print_socket("Listening on", fd);
+
+                if (!arg_accept) {
+                        int r = set_nocloexec(fd);
+                        if (r < 0)
+                                return r;
+                }
+
+                count ++;
+        }
+
+        STRV_FOREACH(address, arg_listen) {
+                log_info("Opening address %s", *address);
+
+                fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC));
+                if (fd < 0) {
+                        log_error("Failed to open '%s': %s", *address, strerror(-fd));
+                        return fd;
+                }
+
+                count ++;
+        }
+
+        *epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+        if (*epoll_fd < 0) {
+                log_error("Failed to create epoll object: %m");
+                return -errno;
+        }
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) {
+                int r = add_epoll(*epoll_fd, fd);
+                if (r < 0)
+                        return r;
+        }
+
+        return count;
+}
+
+static int launch(char* name, char **argv, char **environ, int fds) {
+        unsigned n_env = 0;
+        char* envp[7] = {NULL}; /* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID */
+        static const char* tocopy[] = {"TERM=", "PATH=", "USER=", "HOME="};
+        char _cleanup_free_ *tmp = NULL;
+        unsigned i;
+
+        for (i = 0; i < ELEMENTSOF(tocopy); i++) {
+                envp[n_env] = strv_find_prefix(environ, tocopy[i]);
+                if (envp[n_env])
+                        n_env ++;
+        }
+
+        if ((asprintf((char**)(envp + n_env++), "LISTEN_FDS=%d", fds) < 0) ||
+            (asprintf((char**)(envp + n_env++), "LISTEN_PID=%d", getpid()) < 0))
+                return log_oom();
+
+        tmp = strv_join(argv, " ");
+        if (!tmp)
+                return log_oom();
+
+        log_info("Execing %s (%s)", name, tmp);
+        execvpe(name, argv, envp);
+        log_error("Failed to execp %s (%s): %m", name, tmp);
+        return -errno;
+}
+
+static int launch1(const char* child, char** argv, char **environ, int fd) {
+        pid_t parent_pid, child_pid;
+        int r;
+
+        char _cleanup_free_ *tmp = NULL;
+        tmp = strv_join(argv, " ");
+        if (!tmp)
+                return log_oom();
+
+        parent_pid = getpid();
+
+        child_pid = fork();
+        if (child_pid < 0) {
+                log_error("Failed to fork: %m");
+                return -errno;
+        }
+
+        /* In the child */
+        if (child_pid == 0) {
+                r = dup2(fd, STDIN_FILENO);
+                if (r < 0) {
+                        log_error("Failed to dup connection to stdin: %m");
+                        _exit(EXIT_FAILURE);
+                }
+
+                r = dup2(fd, STDOUT_FILENO);
+                if (r < 0) {
+                        log_error("Failed to dup connection to stdout: %m");
+                        _exit(EXIT_FAILURE);
+                }
+
+                r = close(fd);
+                if (r < 0) {
+                        log_error("Failed to close dupped connection: %m");
+                        _exit(EXIT_FAILURE);
+                }
+
+                /* Make sure the child goes away when the parent dies */
+                if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                        _exit(EXIT_FAILURE);
+
+                /* Check whether our parent died before we were able
+                 * to set the death signal */
+                if (getppid() != parent_pid)
+                        _exit(EXIT_SUCCESS);
+
+                execvp(child, argv);
+                log_error("Failed to exec child %s: %m", child);
+                _exit(EXIT_FAILURE);
+        }
+
+        log_info("Spawned %s (%s) as PID %d", child, tmp, child_pid);
+
+        return 0;
+}
+
+static int do_accept(const char* name, char **argv, char **envp, int fd) {
+        SocketAddress addr = {
+                .size = sizeof(union sockaddr_union),
+                .type = SOCK_STREAM,
+        };
+        int fd2, r;
+
+        fd2 = accept(fd, &addr.sockaddr.sa, &addr.size);
+        if (fd2 < 0) {
+                log_error("Failed to accept connection on fd:%d: %m", fd);
+                return fd2;
+        }
+
+        print_socket("Connection from", fd2);
+
+        r = launch1(name, argv, envp, fd2);
+        return r;
+}
+
+/* SIGCHLD handler. */
+static void sigchld_hdl(int sig, siginfo_t *t, void *data)
+{
+        log_info("Child %d died with code %d", t->si_pid, t->si_status);
+	/* Wait for a dead child. */
+	waitpid(t->si_pid, NULL, 0);
+}
+
+static int install_chld_handler(void) {
+        int r;
+	struct sigaction act;
+        zero(act);
+        act.sa_flags = SA_SIGINFO;
+        act.sa_sigaction = sigchld_hdl;
+
+        r = sigaction(SIGCHLD, &act, 0);
+        if (r < 0)
+                log_error("Failed to install SIGCHLD handler: %m");
+        return r;
+}
+
+static int help(void) {
+        printf("%s [OPTIONS...]\n\n"
+               "Listen on sockets and launch child on connection.\n\n"
+               "Options:\n"
+               "  -l --listen=ADDR     Listen for raw connections at ADDR\n"
+               "  -a --accept          Spawn separate child for each connection\n"
+               "  -h --help            Show this help and exit\n"
+               "  --version            Print version string and exit\n"
+               "\n"
+               "Note: file descriptors from sd_listen_fds() will be passed through.\n"
+               , program_invocation_short_name
+               );
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+        enum {
+                ARG_VERSION = 0x100,
+        };
+
+        static const struct option options[] = {
+                { "help",         no_argument,       NULL, 'h'           },
+                { "version",      no_argument,       NULL, ARG_VERSION   },
+                { "listen",       required_argument, NULL, 'l'           },
+                { "accept",       no_argument,       NULL, 'a'           },
+                { NULL,           0,                 NULL, 0             }
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "+hl:sa", options, NULL)) >= 0)
+                switch(c) {
+                case 'h':
+                        help();
+                        return 0 /* done */;
+
+                case ARG_VERSION:
+                        puts(PACKAGE_STRING);
+                        puts(SYSTEMD_FEATURES);
+                        return 0 /* done */;
+
+                case 'l': {
+                        int r = strv_extend(&arg_listen, optarg);
+                        if (r < 0)
+                                return r;
+
+                        break;
+                }
+
+                case 'a':
+                        arg_accept = true;
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        log_error("Unknown option code %c", c);
+                        return -EINVAL;
+                }
+
+        if (optind == argc) {
+                log_error("Usage: %s [OPTION...] PROGRAM [OPTION...]",
+                          program_invocation_short_name);
+                return -EINVAL;
+        }
+
+        arg_args = argv + optind;
+
+        return 1 /* work to do */;
+}
+
+int main(int argc, char **argv, char **envp) {
+        int r, n;
+        int epoll_fd = -1;
+
+        log_set_max_level(LOG_DEBUG);
+        log_show_color(true);
+        log_parse_environment();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+
+        r = install_chld_handler();
+        if (r < 0)
+                return EXIT_FAILURE;
+
+        n = open_sockets(&epoll_fd, arg_accept);
+        if (n < 0)
+                return EXIT_FAILURE;
+
+        while (true) {
+                struct epoll_event event;
+
+                r = epoll_wait(epoll_fd, &event, 1, -1);
+                if (r < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        log_error("epoll_wait() failed: %m");
+                        return EXIT_FAILURE;
+                }
+
+                log_info("Communication attempt on fd:%d", event.data.fd);
+                if (arg_accept) {
+                        r = do_accept(argv[optind], argv + optind, envp,
+                                      event.data.fd);
+                        if (r < 0)
+                                return EXIT_FAILURE;
+                } else
+                        break;
+        }
+
+        launch(argv[optind], argv + optind, envp, n);
+
+        return EXIT_SUCCESS;
+}
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index 6c94d69..f6ddea3 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -565,6 +565,45 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
         return false;
 }
 
+int make_socket_fd(const char* address, int flags) {
+        SocketAddress a;
+        int fd, r;
+        char _cleanup_free_ *p = NULL;
+
+        r = socket_address_parse(&a, address);
+        if (r < 0) {
+                log_error("failed to parse socket: %s", strerror(-r));
+                return r;
+        }
+
+        fd = socket(socket_address_family(&a), flags, 0);
+        if (fd < 0) {
+                log_error("socket(): %m");
+                return -errno;
+        }
+
+        r = socket_address_print(&a, &p);
+        if (r < 0) {
+                log_error("socket_address_print(): %s", strerror(-r));
+                return r;
+        }
+        log_info("Listening on %s", p);
+
+        r = bind(fd, &a.sockaddr.sa, a.size);
+        if (r < 0) {
+                log_error("bind to %s: %m", address);
+                return -errno;
+        }
+
+        r = listen(fd, SOMAXCONN);
+        if (r < 0) {
+                log_error("listen on %s: %m", address);
+                return -errno;
+        }
+
+        return fd;
+}
+
 static const char* const netlink_family_table[] = {
         [NETLINK_ROUTE] = "route",
         [NETLINK_FIREWALL] = "firewall",
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 771765d..3383834 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -88,6 +88,8 @@ bool socket_address_is_netlink(const SocketAddress *a, const char *s);
 
 bool socket_address_matches_fd(const SocketAddress *a, int fd);
 
+int make_socket_fd(const char* address, int flags);
+
 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b);
 
 bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);

commit 5674767ec2cf7d168fe9c30f78074231fbe3408c
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Sat Feb 23 14:44:16 2013 +0100

    nspawn: environment would be truncated with TERM unset

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index d35a8b5..8b57421 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1296,7 +1296,7 @@ int main(int argc, char *argv[]) {
                         const char *home = NULL;
                         uid_t uid = (uid_t) -1;
                         gid_t gid = (gid_t) -1;
-                        unsigned n_env = 0;
+                        unsigned n_env = 2;
                         const char *envp[] = {
                                 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                                 "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
@@ -1310,8 +1310,9 @@ int main(int argc, char *argv[]) {
                                 NULL
                         };
 
-                        envp[2] = strv_find_prefix(environ, "TERM=");
-                        n_env = 3;
+                        envp[n_env] = strv_find_prefix(environ, "TERM=");
+                        if (envp[n_env])
+                                n_env ++;
 
                         close_nointr_nofail(pipefd[1]);
                         fd_wait_for_event(pipefd[0], POLLHUP, -1);

commit 699ad6c06c0e235f588c900934bdf4bed421503b
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Feb 27 21:31:02 2013 -0500

    man: drop rhs parts in snippets in directive index
    
    -       --exit-if-exists=file
    +       --exit-if-exists=
    etc.

diff --git a/make-directive-index.py b/make-directive-index.py
index 15bd9b9..c61383b 100755
--- a/make-directive-index.py
+++ b/make-directive-index.py
@@ -185,7 +185,10 @@ def _extract_directives(directive_groups, formatting, page):
                 stor[text].append((pagename, section))
                 if text not in formatting:
                     # use element as formatted display
-                    name.tail = ''
+                    if name.text[-1] in '= ':
+                        name.clear()
+                    else:
+                        name.tail = ''
                     name.text = text
                     formatting[text] = name
 

commit 185c3be03cec26023acc11b49553753aa7330a1d
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Feb 27 20:16:38 2013 -0500

    build-sys: fix update-man-rules for vpath builds

diff --git a/Makefile-man.am b/Makefile-man.am
index 526c05d..9a2f2f5 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -1,5 +1,5 @@
 # Do not edit. Generated by make-man-rules.py.
-# Regenerate with 'make update-man-list'.
+# Regenerate with 'make all update-man-list'.
 
 MANPAGES += \
 	man/bootup.7 \
diff --git a/Makefile.am b/Makefile.am
index e0c8529..cc0d4da 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -519,7 +519,7 @@ man/index.html:
 
 NON_INDEX_XML_FILES = $(filter-out man/systemd.index.xml,$(XML_FILES))
 
-XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml $(top_srcdir)/man/*.xml.in)
+XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml $(top_srcdir)/man/*.xml.in $(top_builddir)/man/*.xml)
 update-man-list: make-man-rules.py $(XML_GLOB)
 	$(AM_V_GEN)$(PYTHON) $^ > $(top_srcdir)/Makefile-man.tmp
 	$(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am
diff --git a/make-man-rules.py b/make-man-rules.py
index 9c50c8d..5415984 100644
--- a/make-man-rules.py
+++ b/make-man-rules.py
@@ -21,6 +21,7 @@ from __future__ import print_function
 import xml.etree.ElementTree as tree
 import collections
 import sys
+import os
 
 SECTION = '''\
 MANPAGES += \\
@@ -40,7 +41,7 @@ endif
 
 HEADER = '''\
 # Do not edit. Generated by make-man-rules.py.
-# Regenerate with 'make update-man-list'.
+# Regenerate with 'make all update-man-list'.
 
 '''
 
@@ -96,7 +97,8 @@ def make_makefile(rules, cleanfiles):
 
 if __name__ == '__main__':
     sources = set(sys.argv[1:])
+    basenames = [os.path.basename(source) for source in sources]
     spares = set([source for source in sources
-                  if source + '.in' in sources])
+                  if os.path.basename(source) + '.in' in basenames])
     rules = create_rules(*(sources - spares))
     print(make_makefile(rules, spares), end='')

commit fcc43d015815c23700854a8d3800850910282c8c
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Wed Feb 27 21:48:34 2013 -0500

    build-sys: tell Makefile.am to distribute kernel-install

diff --git a/Makefile.am b/Makefile.am
index 2108abe..e0c8529 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -281,6 +281,9 @@ bin_PROGRAMS = \
 bin_SCRIPTS = \
 	src/kernel-install/kernel-install
 
+EXTRA_DIST += \
+	src/kernel-install/kernel-install
+
 rootlibexec_PROGRAMS = \
 	systemd \
 	systemd-cgroups-agent \



More information about the systemd-commits mailing list