X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Factivate%2Factivate.c;h=d345e285679f397c6814e89a30a70d3e49f69b19;hp=537626d390c3e47d22c56a56f7ab02df281561a6;hb=b6e676ce41508e2aeea22202fc8f234126177f52;hpb=df49ccafc0d57c731a3da3014ad55d5bb9ed3e1b diff --git a/src/activate/activate.c b/src/activate/activate.c index 537626d39..d345e2856 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -20,14 +20,13 @@ ***/ #include -#include #include #include #include #include #include -#include +#include "systemd/sd-daemon.h" #include "socket-util.h" #include "build.h" @@ -38,7 +37,7 @@ static char** arg_listen = NULL; static bool arg_accept = false; static char** arg_args = NULL; -static char** arg_environ = NULL; +static char** arg_setenv = NULL; static int add_epoll(int epoll_fd, int fd) { struct epoll_event ev = { @@ -52,29 +51,9 @@ static int add_epoll(int epoll_fd, int fd) { ev.data.fd = fd; 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: %m", - epoll_fd, fd); - return -errno; -} - -static int make_socket_fd(const char* address, int flags) { - _cleanup_free_ char *p = NULL; - SocketAddress a; - int fd, r; - - r = socket_address_parse(&a, address); - if (r < 0) { - log_error("Failed to parse socket: %s", strerror(-r)); - return r; - } + return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd); - fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT, NULL, false, false, 0755, 0644, NULL); - if (fd < 0) { - log_error("Failed to listen: %s", strerror(-r)); - return fd; - } - - return fd; + return 0; } static int open_sockets(int *epoll_fd, bool accept) { @@ -83,11 +62,8 @@ static int open_sockets(int *epoll_fd, bool accept) { int count = 0; n = sd_listen_fds(true); - if (n < 0) { - log_error("Failed to read listening file descriptors from environment: %s", - strerror(-n)); - return n; - } + if (n < 0) + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); if (n > 0) { log_info("Received %i descriptors via the environment.", n); @@ -100,6 +76,17 @@ static int open_sockets(int *epoll_fd, bool accept) { } } + /* Close logging and all other descriptors */ + if (arg_listen) { + int except[3 + n]; + + for (fd = 0; fd < SD_LISTEN_FDS_START + n; fd++) + except[fd] = fd; + + log_close(); + close_all_fds(except, 3 + n); + } + /** Note: we leak some fd's on error here. I doesn't matter * much, since the program will exit immediately anyway, but * would be a pain to fix. @@ -107,21 +94,22 @@ static int open_sockets(int *epoll_fd, bool accept) { STRV_FOREACH(address, arg_listen) { - fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); + fd = make_socket_fd(LOG_DEBUG, *address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { - log_error("Failed to open '%s': %s", *address, strerror(-fd)); - return fd; + log_open(); + return log_error_errno(fd, "Failed to open '%s': %m", *address); } assert(fd == SD_LISTEN_FDS_START + count); count ++; } + if (arg_listen) + log_open(); + *epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (*epoll_fd < 0) { - log_error("Failed to create epoll object: %m"); - return -errno; - } + if (*epoll_fd < 0) + return log_error_errno(errno, "Failed to create epoll object: %m"); for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) { _cleanup_free_ char *name = NULL; @@ -146,14 +134,14 @@ static int launch(char* name, char **argv, char **env, int fds) { char **s; unsigned i; - length = strv_length(arg_environ); + length = strv_length(arg_setenv); /* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID, NULL */ envp = new0(char *, length + 7); if (!envp) return log_oom(); - STRV_FOREACH(s, arg_environ) { + STRV_FOREACH(s, arg_setenv) { if (strchr(*s, '=')) envp[n_env++] = *s; else { @@ -182,7 +170,7 @@ static int launch(char* name, char **argv, char **env, int fds) { log_info("Execing %s (%s)", name, tmp); execvpe(name, argv, envp); - log_error("Failed to execp %s (%s): %m", name, tmp); + log_error_errno(errno, "Failed to execp %s (%s): %m", name, tmp); return -errno; } @@ -199,28 +187,26 @@ static int launch1(const char* child, char** argv, char **env, int fd) { parent_pid = getpid(); child_pid = fork(); - if (child_pid < 0) { - log_error("Failed to fork: %m"); - return -errno; - } + if (child_pid < 0) + return log_error_errno(errno, "Failed to fork: %m"); /* In the child */ if (child_pid == 0) { r = dup2(fd, STDIN_FILENO); if (r < 0) { - log_error("Failed to dup connection to stdin: %m"); + log_error_errno(errno, "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"); + log_error_errno(errno, "Failed to dup connection to stdout: %m"); _exit(EXIT_FAILURE); } r = close(fd); if (r < 0) { - log_error("Failed to close dupped connection: %m"); + log_error_errno(errno, "Failed to close dupped connection: %m"); _exit(EXIT_FAILURE); } @@ -234,7 +220,7 @@ static int launch1(const char* child, char** argv, char **env, int fd) { _exit(EXIT_SUCCESS); execvp(child, argv); - log_error("Failed to exec child %s: %m", child); + log_error_errno(errno, "Failed to exec child %s: %m", child); _exit(EXIT_FAILURE); } @@ -245,11 +231,11 @@ static int launch1(const char* child, char** argv, char **env, int fd) { static int do_accept(const char* name, char **argv, char **envp, int fd) { _cleanup_free_ char *local = NULL, *peer = NULL; - int fd2; + _cleanup_close_ int fd2 = -1; fd2 = accept(fd, NULL, NULL); if (fd2 < 0) { - log_error("Failed to accept connection on fd:%d: %m", fd); + log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd); return fd2; } @@ -271,33 +257,29 @@ static void sigchld_hdl(int sig, siginfo_t *t, void *data) { static int install_chld_handler(void) { int r; - struct sigaction act; - zero(act); - act.sa_flags = SA_SIGINFO; - act.sa_sigaction = sigchld_hdl; + struct sigaction act = { + .sa_flags = SA_SIGINFO, + .sa_sigaction = sigchld_hdl, + }; r = sigaction(SIGCHLD, &act, 0); if (r < 0) - log_error("Failed to install SIGCHLD handler: %m"); + log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); return r; } -static int help(void) { +static void 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" - " -E --environment=NAME[=VALUE]\n" - " Pass an environment variable to children\n" - " --version Print version string and exit\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" + " -E --setenv=NAME[=VALUE] Pass an environment variable to children\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; + , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { @@ -306,11 +288,12 @@ static int parse_argv(int argc, char *argv[]) { }; 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' }, - { "environment", required_argument, NULL, 'E' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "listen", required_argument, NULL, 'l' }, + { "accept", no_argument, NULL, 'a' }, + { "setenv", required_argument, NULL, 'E' }, + { "environment", required_argument, NULL, 'E' }, /* alias */ {} }; @@ -319,10 +302,11 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hl:saE:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hl:aE:", options, NULL)) >= 0) switch(c) { case 'h': - return help(); + help(); + return 0; case ARG_VERSION: puts(PACKAGE_STRING); @@ -342,7 +326,7 @@ static int parse_argv(int argc, char *argv[]) { break; case 'E': { - int r = strv_extend(&arg_environ, optarg); + int r = strv_extend(&arg_setenv, optarg); if (r < 0) return r; @@ -357,7 +341,7 @@ static int parse_argv(int argc, char *argv[]) { } if (optind == argc) { - log_error("Usage: %s [OPTION...] PROGRAM [OPTION...]", + log_error("%s: command to execute is missing.", program_invocation_short_name); return -EINVAL; } @@ -398,7 +382,7 @@ int main(int argc, char **argv, char **envp) { if (errno == EINTR) continue; - log_error("epoll_wait() failed: %m"); + log_error_errno(errno, "epoll_wait() failed: %m"); return EXIT_FAILURE; }