X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Factivate%2Factivate.c;h=23c484ca968e96ed42a6af481815f22a68322e43;hb=819c7e4fa4422af1298a0bf074b1f5644e46fa13;hp=f0944aac5c846e9339f887b639a4a14109869581;hpb=30374ebe5e9f0b37e99dcbdc965c00fcf542f89d;p=elogind.git diff --git a/src/activate/activate.c b/src/activate/activate.c index f0944aac5..23c484ca9 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -38,7 +38,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 = { @@ -51,14 +51,15 @@ 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; + if (r < 0) { + log_error("Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd); + return -errno; + } + + return 0; } static int make_socket_fd(const char* address, int flags) { - _cleanup_free_ char *p = NULL; SocketAddress a; int fd, r; @@ -100,6 +101,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. @@ -109,6 +121,7 @@ static int open_sockets(int *epoll_fd, bool accept) { fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { + log_open(); log_error("Failed to open '%s': %s", *address, strerror(-fd)); return fd; } @@ -117,6 +130,9 @@ static int open_sockets(int *epoll_fd, bool accept) { count ++; } + if (arg_listen) + log_open(); + *epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (*epoll_fd < 0) { log_error("Failed to create epoll object: %m"); @@ -127,7 +143,7 @@ static int open_sockets(int *epoll_fd, bool accept) { _cleanup_free_ char *name = NULL; getsockname_pretty(fd, &name); - log_info("Listening on %s.", strna(name)); + log_info("Listening on %s as %i.", strna(name), fd); r = add_epoll(*epoll_fd, fd); if (r < 0) @@ -146,14 +162,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 { @@ -262,6 +278,8 @@ 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) { + PROTECT_ERRNO; + 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); @@ -269,10 +287,10 @@ 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) @@ -284,10 +302,11 @@ 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" + " -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 @@ -302,11 +321,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 */ {} }; @@ -315,7 +335,7 @@ 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(); @@ -338,7 +358,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; @@ -381,6 +401,10 @@ int main(int argc, char **argv, char **envp) { n = open_sockets(&epoll_fd, arg_accept); if (n < 0) return EXIT_FAILURE; + if (n == 0) { + log_error("No sockets to listen on specified or passed in."); + return EXIT_FAILURE; + } for (;;) { struct epoll_event event; @@ -394,7 +418,7 @@ int main(int argc, char **argv, char **envp) { return EXIT_FAILURE; } - log_info("Communication attempt on fd:%d", event.data.fd); + log_info("Communication attempt on fd %i.", event.data.fd); if (arg_accept) { r = do_accept(argv[optind], argv + optind, envp, event.data.fd);