diff --git a/acinclude.m4 b/acinclude.m4 index 51cf130c9e7..f2d6fb888aa 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -618,19 +618,26 @@ AC_DEFUN([APACHE_CHECK_SYSTEMD], [ dnl Check for systemd support for listen.c's socket activation. case $host in *-linux-*) - if test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd; then - SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd` - elif test -n "$PKGCONFIG" && $PKGCONFIG --exists libsystemd-daemon; then - SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd-daemon` - else + for libsd in libsystemd libsystemd-daemon; do + if test -n "$PKGCONFIG" && $PKGCONFIG --exists $libsd; then + SYSTEMD_LIBS=`$PKGCONFIG --libs $libsd` + SYSTEMD_VERS=`$PKGCONFIG --modversion $libsd` + break + fi + done + if test -n "$SYSTEMD_LIBS"; then AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon") fi if test -n "$SYSTEMD_LIBS"; then AC_CHECK_HEADERS(systemd/sd-daemon.h) - if test "${ac_cv_header_systemd_sd_daemon_h}" = "no" || test -z "${SYSTEMD_LIBS}"; then + if test "${ac_cv_header_systemd_sd_daemon_h}" = "no"; then AC_MSG_WARN([Your system does not support systemd.]) else AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is supported]) + if test -n "$SYSTEMD_VERS" -a "$SYSTEMD_VERS" -gt 0; then + AC_DEFINE_UNQUOTED([AP_SYSTEMD_VERSION], [$SYSTEMD_VERS], + [Define to the systemd version if available]) + fi fi fi ;; diff --git a/modules/loggers/config.m4 b/modules/loggers/config.m4 index 762e773e945..0848d2e3771 100644 --- a/modules/loggers/config.m4 +++ b/modules/loggers/config.m4 @@ -5,6 +5,8 @@ dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) APACHE_MODPATH_INIT(loggers) APACHE_MODULE(log_config, logging configuration. You won't be able to log requests to the server without this module., , , yes) +APR_ADDTO(MOD_LOG_CONFIG_LDADD, [$SYSTEMD_LIBS]) + APACHE_MODULE(log_debug, configurable debug logging, , , most) APACHE_MODULE(log_forensic, forensic logging) diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 5c2d635df8c..28dcb638bfa 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -172,6 +172,10 @@ #include #endif +#ifdef HAVE_SYSTEMD +#include +#endif + #define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b" module AP_MODULE_DECLARE_DATA log_config_module; @@ -1630,6 +1634,26 @@ static apr_status_t ap_default_log_writer( request_rec *r, return rv; } + +static apr_status_t wrap_journal_stream(apr_pool_t *p, apr_file_t **outfd, + int priority) +{ +#if defined(HAVE_SYSTEMD) && defined(AP_SYSTEMD_VERSION) && AP_SYSTEMD_VERSION >= 187 + int fd; + + fd = sd_journal_stream_fd("httpd", priority, 0); + /* Returns a negative errno value on error, invert into apr_status_t. */ + if (fd < 0) return APR_FROM_OS_ERROR(-fd); + + /* This is an AF_UNIX socket fd so is more pipe-like than + * file-like (the fd is neither seekable or readable), and use of + * apr_os_pipe_put_ex() allows cleanup registration. */ + return apr_os_pipe_put_ex(outfd, &fd, 1, p); +#else + return APR_ENOTIMPL; +#endif +} + static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s, const char* name) { @@ -1642,6 +1666,32 @@ static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s, } return ap_piped_log_write_fd(pl); } + else if (strncasecmp(name, "journald:", 9) == 0) { + int priority; + const char *err = ap_parse_log_level(name + 9, &priority); + apr_status_t rv; + apr_file_t *fd; + + if (err == NULL && priority > APLOG_DEBUG) { + err = "TRACE level debugging not supported with journald"; + } + + if (err) { + ap_log_error(APLOG_MARK, APLOG_ERR, APR_EINVAL, s, APLOGNO(10544) + "invalid journald log priority name %s: %s", + name, err); + return NULL; + } + + rv = wrap_journal_stream(p, &fd, priority); + if (rv) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10545) + "could not open journald log stream"); + return NULL; + } + + return fd; + } else { const char *fname = ap_server_root_relative(p, name); apr_file_t *fd;