chiark / gitweb /
Remove src/journal-remote
authorAndy Wingo <wingo@pobox.com>
Sun, 19 Apr 2015 11:28:46 +0000 (13:28 +0200)
committerAndy Wingo <wingo@pobox.com>
Sun, 19 Apr 2015 11:28:46 +0000 (13:28 +0200)
18 files changed:
src/journal-remote/.gitignore [deleted file]
src/journal-remote/Makefile [deleted symlink]
src/journal-remote/browse.html [deleted file]
src/journal-remote/journal-gatewayd.c [deleted file]
src/journal-remote/journal-remote-parse.c [deleted file]
src/journal-remote/journal-remote-parse.h [deleted file]
src/journal-remote/journal-remote-write.c [deleted file]
src/journal-remote/journal-remote-write.h [deleted file]
src/journal-remote/journal-remote.c [deleted file]
src/journal-remote/journal-remote.conf.in [deleted file]
src/journal-remote/journal-remote.h [deleted file]
src/journal-remote/journal-upload-journal.c [deleted file]
src/journal-remote/journal-upload.c [deleted file]
src/journal-remote/journal-upload.conf.in [deleted file]
src/journal-remote/journal-upload.h [deleted file]
src/journal-remote/log-generator.py [deleted file]
src/journal-remote/microhttpd-util.c [deleted file]
src/journal-remote/microhttpd-util.h [deleted file]

diff --git a/src/journal-remote/.gitignore b/src/journal-remote/.gitignore
deleted file mode 100644 (file)
index 06847b6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/journal-remote.conf
-/journal-upload.conf
diff --git a/src/journal-remote/Makefile b/src/journal-remote/Makefile
deleted file mode 120000 (symlink)
index d0b0e8e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile
\ No newline at end of file
diff --git a/src/journal-remote/browse.html b/src/journal-remote/browse.html
deleted file mode 100644 (file)
index 3594f70..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-        <title>Journal</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <style type="text/css">
-                div#divlogs, div#diventry {
-                        font-family: monospace;
-                        font-size: 7pt;
-                        background-color: #ffffff;
-                        padding: 1em;
-                        margin: 2em 0em;
-                        border-radius: 10px 10px 10px 10px;
-                        border: 1px solid threedshadow;
-                        white-space: nowrap;
-                        overflow-x: scroll;
-                }
-                div#diventry {
-                        display: none;
-                }
-                div#divlogs {
-                        display: block;
-                }
-                body {
-                        background-color: #ededed;
-                        color: #313739;
-                        font: message-box;
-                        margin: 3em;
-                }
-                td.timestamp {
-                        text-align: right;
-                        border-right: 1px dotted lightgrey;
-                        padding-right: 5px;
-                }
-                td.process {
-                        border-right: 1px dotted lightgrey;
-                        padding-left: 5px;
-                        padding-right: 5px;
-                }
-                td.message {
-                        padding-left: 5px;
-                }
-                td.message > a:link, td.message > a:visited {
-                        text-decoration: none;
-                        color: #313739;
-                }
-                td.message-error {
-                        padding-left: 5px;
-                        color: red;
-                        font-weight: bold;
-                }
-                td.message-error > a:link, td.message-error > a:visited {
-                        text-decoration: none;
-                        color: red;
-                }
-                td.message-highlight {
-                        padding-left: 5px;
-                        font-weight: bold;
-                }
-                td.message-highlight > a:link, td.message-highlight > a:visited {
-                        text-decoration: none;
-                        color: #313739;
-                }
-                td > a:hover, td > a:active {
-                        text-decoration: underline;
-                        color: #c13739;
-                }
-                table#tablelogs, table#tableentry {
-                        border-collapse: collapse;
-                }
-                td.field {
-                        text-align: right;
-                        border-right: 1px dotted lightgrey;
-                        padding-right: 5px;
-                }
-                td.data {
-                        padding-left: 5px;
-                }
-                div#keynav {
-                        text-align: center;
-                        font-size: 7pt;
-                        color: #818789;
-                        padding-top: 2em;
-                }
-                span.key {
-                        font-weight: bold;
-                        color: #313739;
-                }
-                div#buttonnav {
-                        text-align: center;
-                }
-                button {
-                        font-size: 18pt;
-                        font-weight: bold;
-                        width: 2em;
-                        height: 2em;
-                }
-                div#filternav {
-                        text-align: center;
-                }
-                select {
-                        width: 50em;
-                }
-        </style>
-</head>
-
-<body>
-        <!-- TODO:
-                - live display
-                - show red lines for reboots -->
-
-        <h1 id="title"></h1>
-
-        <div id="os"></div>
-        <div id="virtualization"></div>
-        <div id="cutoff"></div>
-        <div id="machine"></div>
-        <div id="usage"></div>
-        <div id="showing"></div>
-
-        <div id="filternav">
-                <select id="filter" onchange="onFilterChange(this);" onfocus="onFilterFocus(this);">
-                        <option>No filter</option>
-                </select>
-                &nbsp;&nbsp;&nbsp;&nbsp;
-                <input id="boot" type="checkbox" onchange="onBootChange(this);">Only current boot</input>
-        </div>
-
-        <div id="divlogs"><table id="tablelogs"></table></div>
-        <a name="entry"></a>
-        <div id="diventry"><table id="tableentry"></table></div>
-
-        <div id="buttonnav">
-                <button id="head" onclick="entriesLoadHead();" title="First Page">&#8676;</button>
-                <button id="previous" type="button" onclick="entriesLoadPrevious();" title="Previous Page"/>&#8592;</button>
-                <button id="next" type="button" onclick="entriesLoadNext();" title="Next Page"/>&#8594;</button>
-                <button id="tail" type="button" onclick="entriesLoadTail();" title="Last Page"/>&#8677;</button>
-                &nbsp;&nbsp;&nbsp;&nbsp;
-                <button id="more" type="button" onclick="entriesMore();" title="More Entries"/>+</button>
-                <button id="less" type="button" onclick="entriesLess();" title="Fewer Entries"/>-</button>
-        </div>
-
-        <div id="keynav">
-                <span class="key">g</span>: First Page &nbsp;&nbsp;&nbsp;&nbsp;
-                <span class="key">&#8592;, k, BACKSPACE</span>: Previous Page &nbsp;&nbsp;&nbsp;&nbsp;
-                <span class="key">&#8594;, j, SPACE</span>: Next Page &nbsp;&nbsp;&nbsp;&nbsp;
-                <span class="key">G</span>: Last Page &nbsp;&nbsp;&nbsp;&nbsp;
-                <span class="key">+</span>: More entries &nbsp;&nbsp;&nbsp;&nbsp;
-                <span class="key">-</span>: Fewer entries
-        </div>
-
-        <script type="text/javascript">
-                var first_cursor = null;
-                var last_cursor = null;
-
-                function getNEntries() {
-                        var n;
-                        n = localStorage["n_entries"];
-                        if (n == null)
-                                return 50;
-                        n = parseInt(n);
-                        if (n < 10)
-                                return 10;
-                        if (n > 1000)
-                                return 1000;
-                        return n;
-                }
-
-                function showNEntries(n) {
-                        var showing = document.getElementById("showing");
-                        showing.innerHTML = "Showing <b>" + n.toString() + "</b> entries.";
-                }
-
-                function setNEntries(n) {
-                        if (n < 10)
-                                return 10;
-                        if (n > 1000)
-                                return 1000;
-                        localStorage["n_entries"] = n.toString();
-                        showNEntries(n);
-                }
-
-                function machineLoad() {
-                        var request = new XMLHttpRequest();
-                        request.open("GET", "/machine");
-                        request.onreadystatechange = machineOnResult;
-                        request.setRequestHeader("Accept", "application/json");
-                        request.send(null);
-                }
-
-                function formatBytes(u) {
-                        if (u >= 1024*1024*1024*1024)
-                                return (u/1024/1024/1024/1024).toFixed(1) + " TiB";
-                        else if (u >= 1024*1024*1024)
-                                return (u/1024/1024/1024).toFixed(1) + " GiB";
-                        else if (u >= 1024*1024)
-                                return (u/1024/1024).toFixed(1) + " MiB";
-                        else if (u >= 1024)
-                                return (u/1024).toFixed(1) + " KiB";
-                        else
-                                return u.toString() + " B";
-                }
-
-                function escapeHTML(s) {
-                        return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-                }
-
-                function machineOnResult(event) {
-                        if ((event.currentTarget.readyState != 4) ||
-                                (event.currentTarget.status != 200 && event.currentTarget.status != 0))
-                                return;
-
-                        var d = JSON.parse(event.currentTarget.responseText);
-
-                        var title = document.getElementById("title");
-                        title.innerHTML = 'Journal of ' + escapeHTML(d.hostname);
-                        document.title = 'Journal of ' + escapeHTML(d.hostname);
-
-                        var machine = document.getElementById("machine");
-                        machine.innerHTML = 'Machine ID is <b>' + d.machine_id + '</b>, current boot ID is <b>' + d.boot_id + '</b>.';
-
-                        var cutoff = document.getElementById("cutoff");
-                        var from = new Date(parseInt(d.cutoff_from_realtime) / 1000);
-                        var to = new Date(parseInt(d.cutoff_to_realtime) / 1000);
-                        cutoff.innerHTML = 'Journal begins at <b>' + from.toLocaleString() + '</b> and ends at <b>' + to.toLocaleString() + '</b>.';
-
-                        var usage = document.getElementById("usage");
-                        usage.innerHTML = 'Disk usage is <b>' + formatBytes(parseInt(d.usage)) + '</b>.';
-
-                        var os = document.getElementById("os");
-                        os.innerHTML = 'Operating system is <b>' + escapeHTML(d.os_pretty_name) + '</b>.';
-
-                        var virtualization = document.getElementById("virtualization");
-                        virtualization.innerHTML = d.virtualization == "bare" ? "Running on <b>bare metal</b>." : "Running on virtualization <b>" + escapeHTML(d.virtualization) + "</b>.";
-                }
-
-                function entriesLoad(range) {
-
-                        if (range == null)
-                                range = localStorage["cursor"] + ":0";
-                        if (range == null)
-                                range = "";
-
-                        var url = "/entries";
-
-                        if (localStorage["filter"] != "" && localStorage["filter"] != null) {
-                                url += "?_SYSTEMD_UNIT=" + escape(localStorage["filter"]);
-
-                                if (localStorage["boot"] == "1")
-                                        url += "&boot";
-                        } else {
-                                if (localStorage["boot"] == "1")
-                                        url += "?boot";
-                        }
-
-                        var request = new XMLHttpRequest();
-                        request.open("GET", url);
-                        request.onreadystatechange = entriesOnResult;
-                        request.setRequestHeader("Accept", "application/json");
-                        request.setRequestHeader("Range", "entries=" + range + ":" + getNEntries().toString());
-                        request.send(null);
-                }
-
-                function entriesLoadNext() {
-                        if (last_cursor == null)
-                                entriesLoad("");
-                        else
-                                entriesLoad(last_cursor + ":1");
-                }
-
-                function entriesLoadPrevious() {
-                        if (first_cursor == null)
-                                entriesLoad("");
-                        else
-                                entriesLoad(first_cursor + ":-" + getNEntries().toString());
-                }
-
-                function entriesLoadHead() {
-                        entriesLoad("");
-                }
-
-                function entriesLoadTail() {
-                        entriesLoad(":-" + getNEntries().toString());
-                }
-
-                function entriesOnResult(event) {
-
-                        if ((event.currentTarget.readyState != 4) ||
-                                (event.currentTarget.status != 200 && event.currentTarget.status != 0))
-                                return;
-
-                        var logs = document.getElementById("tablelogs");
-
-                        var lc = null;
-                        var fc = null;
-
-                        var i, l = event.currentTarget.responseText.split('\n');
-
-                        if (l.length <= 1) {
-                                logs.innerHTML = '<tbody><tr><td colspan="3"><i>No further entries...</i></td></tr></tbody>';
-                                return;
-                        }
-
-                        var buf = '';
-
-                        for (i in l) {
-
-                                if (l[i] == '')
-                                        continue;
-
-                                var d = JSON.parse(l[i]);
-                                if (d.MESSAGE == undefined || d.__CURSOR == undefined)
-                                        continue;
-
-                                if (fc == null)
-                                        fc = d.__CURSOR;
-                                lc = d.__CURSOR;
-
-                                var priority;
-                                if (d.PRIORITY != undefined)
-                                        priority = parseInt(d.PRIORITY);
-                                else
-                                        priority = 6;
-
-                                if (priority <= 3)
-                                        clazz = "message-error";
-                                else if (priority <= 5)
-                                        clazz = "message-highlight";
-                                else
-                                        clazz = "message";
-
-                                buf += '<tr><td class="timestamp">';
-
-                                if (d.__REALTIME_TIMESTAMP != undefined) {
-                                        var timestamp = new Date(parseInt(d.__REALTIME_TIMESTAMP) / 1000);
-                                        buf += timestamp.toLocaleString();
-                                }
-
-                                buf += '</td><td class="process">';
-
-                                if (d.SYSLOG_IDENTIFIER != undefined)
-                                        buf += escapeHTML(d.SYSLOG_IDENTIFIER);
-                                else if (d._COMM != undefined)
-                                        buf += escapeHTML(d._COMM);
-
-                                if (d._PID != undefined)
-                                        buf += "[" + escapeHTML(d._PID) + "]";
-                                else if (d.SYSLOG_PID != undefined)
-                                        buf += "[" + escapeHTML(d.SYSLOG_PID) + "]";
-
-                                buf += '</td><td class="' + clazz + '"><a href="#entry" onclick="onMessageClick(\'' + d.__CURSOR + '\');">';
-
-                                if (d.MESSAGE == null)
-                                        buf += "[blob data]";
-                                else if (d.MESSAGE instanceof Array)
-                                        buf += "[" + formatBytes(d.MESSAGE.length) + " blob data]";
-                                else
-                                        buf += escapeHTML(d.MESSAGE);
-
-                                buf += '</a></td></tr>';
-                        }
-
-                        logs.innerHTML = '<tbody>' + buf + '</tbody>';
-
-                        if (fc != null) {
-                                first_cursor = fc;
-                                localStorage["cursor"] = fc;
-                        }
-                        if (lc != null)
-                                last_cursor = lc;
-                }
-
-                function entriesMore() {
-                        setNEntries(getNEntries() + 10);
-                        entriesLoad(first_cursor);
-                }
-
-                function entriesLess() {
-                        setNEntries(getNEntries() - 10);
-                        entriesLoad(first_cursor);
-                }
-
-                function onResultMessageClick(event) {
-                        if ((event.currentTarget.readyState != 4) ||
-                                (event.currentTarget.status != 200 && event.currentTarget.status != 0))
-                                return;
-
-                        var d = JSON.parse(event.currentTarget.responseText);
-
-                        document.getElementById("diventry").style.display = "block";
-                        entry = document.getElementById("tableentry");
-
-                        var buf = "";
-                        for (var key in d){
-                                var data = d[key];
-
-                                if (data == null)
-                                        data = "[blob data]";
-                                else if (data instanceof Array)
-                                        data = "[" + formatBytes(data.length) + " blob data]";
-                                else
-                                        data = escapeHTML(data);
-
-                                buf += '<tr><td class="field">' + key + '</td><td class="data">' + data + '</td></tr>';
-                        }
-                        entry.innerHTML = '<tbody>' + buf + '</tbody>';
-                }
-
-                function onMessageClick(t) {
-                        var request = new XMLHttpRequest();
-                        request.open("GET", "/entries?discrete");
-                        request.onreadystatechange = onResultMessageClick;
-                        request.setRequestHeader("Accept", "application/json");
-                        request.setRequestHeader("Range", "entries=" + t + ":0:1");
-                        request.send(null);
-                }
-
-                function onKeyUp(event) {
-                        switch (event.keyCode) {
-                                case 8:
-                                case 37:
-                                case 75:
-                                        entriesLoadPrevious();
-                                        break;
-                                case 32:
-                                case 39:
-                                case 74:
-                                        entriesLoadNext();
-                                        break;
-
-                                case 71:
-                                        if (event.shiftKey)
-                                                entriesLoadTail();
-                                        else
-                                                entriesLoadHead();
-                                        break;
-                                case 171:
-                                        entriesMore();
-                                        break;
-                                case 173:
-                                        entriesLess();
-                                        break;
-                        }
-                }
-
-                function onMouseWheel(event) {
-                        if (event.detail < 0 || event.wheelDelta > 0)
-                                entriesLoadPrevious();
-                        else
-                                entriesLoadNext();
-                }
-
-                function onResultFilterFocus(event) {
-                        if ((event.currentTarget.readyState != 4) ||
-                                (event.currentTarget.status != 200 && event.currentTarget.status != 0))
-                                return;
-
-                        f = document.getElementById("filter");
-
-                        var l = event.currentTarget.responseText.split('\n');
-                        var buf = '<option>No filter</option>';
-                        var j = -1;
-
-                        for (i in l) {
-
-                                if (l[i] == '')
-                                      continue;
-
-                                var d = JSON.parse(l[i]);
-                                if (d._SYSTEMD_UNIT == undefined)
-                                      continue;
-
-                                buf += '<option value="' + escape(d._SYSTEMD_UNIT) + '">' + escapeHTML(d._SYSTEMD_UNIT) + '</option>';
-
-                                if (d._SYSTEMD_UNIT == localStorage["filter"])
-                                        j = i;
-                        }
-
-                        if (j < 0) {
-                                if (localStorage["filter"] != null && localStorage["filter"] != "") {
-                                          buf += '<option value="' + escape(localStorage["filter"]) + '">' + escapeHTML(localStorage["filter"]) + '</option>';
-                                          j = i + 1;
-                                } else
-                                          j = 0;
-                        }
-
-                        f.innerHTML = buf;
-                        f.selectedIndex = j;
-                }
-
-                function onFilterFocus(w) {
-                        var request = new XMLHttpRequest();
-                        request.open("GET", "/fields/_SYSTEMD_UNIT");
-                        request.onreadystatechange = onResultFilterFocus;
-                        request.setRequestHeader("Accept", "application/json");
-                        request.send(null);
-                }
-
-                function onFilterChange(w) {
-                        if (w.selectedIndex <= 0)
-                                localStorage["filter"] = "";
-                        else
-                                localStorage["filter"] = unescape(w.options[w.selectedIndex].value);
-
-                        entriesLoadHead();
-                }
-
-                function onBootChange(w) {
-                        localStorage["boot"] = w.checked ? "1" : "0";
-                        entriesLoadHead();
-                }
-
-                function initFilter() {
-                        f = document.getElementById("filter");
-
-                        var buf = '<option>No filter</option>';
-
-                        var filter = localStorage["filter"];
-                        if (filter != null && filter != "") {
-                                buf += '<option value="' + escape(filter) + '">' + escapeHTML(filter) + '</option>';
-                                j = 1;
-                        } else
-                                j = 0;
-
-                        f.innerHTML = buf;
-                        f.selectedIndex = j;
-                }
-
-                function installHandlers() {
-                        document.onkeyup = onKeyUp;
-
-                        logs = document.getElementById("divlogs");
-                        logs.addEventListener("mousewheel", onMouseWheel, false);
-                        logs.addEventListener("DOMMouseScroll", onMouseWheel, false);
-                }
-
-                machineLoad();
-                entriesLoad(null);
-                showNEntries(getNEntries());
-                initFilter();
-                installHandlers();
-        </script>
-</body>
-</html>
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
deleted file mode 100644 (file)
index bba0d12..0000000
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 Lennart Poettering
-
-  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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <getopt.h>
-
-#include <microhttpd.h>
-
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
-#include "sd-journal.h"
-#include "sd-daemon.h"
-#include "sd-bus.h"
-#include "log.h"
-#include "util.h"
-#include "bus-util.h"
-#include "logs-show.h"
-#include "microhttpd-util.h"
-#include "build.h"
-#include "fileio.h"
-#include "sigbus.h"
-
-static char *arg_key_pem = NULL;
-static char *arg_cert_pem = NULL;
-static char *arg_trust_pem = NULL;
-
-typedef struct RequestMeta {
-        sd_journal *journal;
-
-        OutputMode mode;
-
-        char *cursor;
-        int64_t n_skip;
-        uint64_t n_entries;
-        bool n_entries_set;
-
-        FILE *tmp;
-        uint64_t delta, size;
-
-        int argument_parse_error;
-
-        bool follow;
-        bool discrete;
-
-        uint64_t n_fields;
-        bool n_fields_set;
-} RequestMeta;
-
-static const char* const mime_types[_OUTPUT_MODE_MAX] = {
-        [OUTPUT_SHORT] = "text/plain",
-        [OUTPUT_JSON] = "application/json",
-        [OUTPUT_JSON_SSE] = "text/event-stream",
-        [OUTPUT_EXPORT] = "application/vnd.fdo.journal",
-};
-
-static RequestMeta *request_meta(void **connection_cls) {
-        RequestMeta *m;
-
-        assert(connection_cls);
-        if (*connection_cls)
-                return *connection_cls;
-
-        m = new0(RequestMeta, 1);
-        if (!m)
-                return NULL;
-
-        *connection_cls = m;
-        return m;
-}
-
-static void request_meta_free(
-                void *cls,
-                struct MHD_Connection *connection,
-                void **connection_cls,
-                enum MHD_RequestTerminationCode toe) {
-
-        RequestMeta *m = *connection_cls;
-
-        if (!m)
-                return;
-
-        if (m->journal)
-                sd_journal_close(m->journal);
-
-        if (m->tmp)
-                fclose(m->tmp);
-
-        free(m->cursor);
-        free(m);
-}
-
-static int open_journal(RequestMeta *m) {
-        assert(m);
-
-        if (m->journal)
-                return 0;
-
-        return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM);
-}
-
-static int request_meta_ensure_tmp(RequestMeta *m) {
-        if (m->tmp)
-                rewind(m->tmp);
-        else {
-                int fd;
-
-                fd = open_tmpfile("/tmp", O_RDWR|O_CLOEXEC);
-                if (fd < 0)
-                        return fd;
-
-                m->tmp = fdopen(fd, "rw");
-                if (!m->tmp) {
-                        safe_close(fd);
-                        return -errno;
-                }
-        }
-
-        return 0;
-}
-
-static ssize_t request_reader_entries(
-                void *cls,
-                uint64_t pos,
-                char *buf,
-                size_t max) {
-
-        RequestMeta *m = cls;
-        int r;
-        size_t n, k;
-
-        assert(m);
-        assert(buf);
-        assert(max > 0);
-        assert(pos >= m->delta);
-
-        pos -= m->delta;
-
-        while (pos >= m->size) {
-                off_t sz;
-
-                /* End of this entry, so let's serialize the next
-                 * one */
-
-                if (m->n_entries_set &&
-                    m->n_entries <= 0)
-                        return MHD_CONTENT_READER_END_OF_STREAM;
-
-                if (m->n_skip < 0)
-                        r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1);
-                else if (m->n_skip > 0)
-                        r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1);
-                else
-                        r = sd_journal_next(m->journal);
-
-                if (r < 0) {
-                        log_error_errno(r, "Failed to advance journal pointer: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                } else if (r == 0) {
-
-                        if (m->follow) {
-                                r = sd_journal_wait(m->journal, (uint64_t) -1);
-                                if (r < 0) {
-                                        log_error_errno(r, "Couldn't wait for journal event: %m");
-                                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                                }
-
-                                continue;
-                        }
-
-                        return MHD_CONTENT_READER_END_OF_STREAM;
-                }
-
-                if (m->discrete) {
-                        assert(m->cursor);
-
-                        r = sd_journal_test_cursor(m->journal, m->cursor);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to test cursor: %m");
-                                return MHD_CONTENT_READER_END_WITH_ERROR;
-                        }
-
-                        if (r == 0)
-                                return MHD_CONTENT_READER_END_OF_STREAM;
-                }
-
-                pos -= m->size;
-                m->delta += m->size;
-
-                if (m->n_entries_set)
-                        m->n_entries -= 1;
-
-                m->n_skip = 0;
-
-                r = request_meta_ensure_tmp(m);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to create temporary file: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH, NULL);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to serialize item: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                sz = ftello(m->tmp);
-                if (sz == (off_t) -1) {
-                        log_error_errno(errno, "Failed to retrieve file position: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                m->size = (uint64_t) sz;
-        }
-
-        if (fseeko(m->tmp, pos, SEEK_SET) < 0) {
-                log_error_errno(errno, "Failed to seek to position: %m");
-                return MHD_CONTENT_READER_END_WITH_ERROR;
-        }
-
-        n = m->size - pos;
-        if (n > max)
-                n = max;
-
-        errno = 0;
-        k = fread(buf, 1, n, m->tmp);
-        if (k != n) {
-                log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
-                return MHD_CONTENT_READER_END_WITH_ERROR;
-        }
-
-        return (ssize_t) k;
-}
-
-static int request_parse_accept(
-                RequestMeta *m,
-                struct MHD_Connection *connection) {
-
-        const char *header;
-
-        assert(m);
-        assert(connection);
-
-        header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
-        if (!header)
-                return 0;
-
-        if (streq(header, mime_types[OUTPUT_JSON]))
-                m->mode = OUTPUT_JSON;
-        else if (streq(header, mime_types[OUTPUT_JSON_SSE]))
-                m->mode = OUTPUT_JSON_SSE;
-        else if (streq(header, mime_types[OUTPUT_EXPORT]))
-                m->mode = OUTPUT_EXPORT;
-        else
-                m->mode = OUTPUT_SHORT;
-
-        return 0;
-}
-
-static int request_parse_range(
-                RequestMeta *m,
-                struct MHD_Connection *connection) {
-
-        const char *range, *colon, *colon2;
-        int r;
-
-        assert(m);
-        assert(connection);
-
-        range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
-        if (!range)
-                return 0;
-
-        if (!startswith(range, "entries="))
-                return 0;
-
-        range += 8;
-        range += strspn(range, WHITESPACE);
-
-        colon = strchr(range, ':');
-        if (!colon)
-                m->cursor = strdup(range);
-        else {
-                const char *p;
-
-                colon2 = strchr(colon + 1, ':');
-                if (colon2) {
-                        _cleanup_free_ char *t;
-
-                        t = strndup(colon + 1, colon2 - colon - 1);
-                        if (!t)
-                                return -ENOMEM;
-
-                        r = safe_atoi64(t, &m->n_skip);
-                        if (r < 0)
-                                return r;
-                }
-
-                p = (colon2 ? colon2 : colon) + 1;
-                if (*p) {
-                        r = safe_atou64(p, &m->n_entries);
-                        if (r < 0)
-                                return r;
-
-                        if (m->n_entries <= 0)
-                                return -EINVAL;
-
-                        m->n_entries_set = true;
-                }
-
-                m->cursor = strndup(range, colon - range);
-        }
-
-        if (!m->cursor)
-                return -ENOMEM;
-
-        m->cursor[strcspn(m->cursor, WHITESPACE)] = 0;
-        if (isempty(m->cursor)) {
-                free(m->cursor);
-                m->cursor = NULL;
-        }
-
-        return 0;
-}
-
-static int request_parse_arguments_iterator(
-                void *cls,
-                enum MHD_ValueKind kind,
-                const char *key,
-                const char *value) {
-
-        RequestMeta *m = cls;
-        _cleanup_free_ char *p = NULL;
-        int r;
-
-        assert(m);
-
-        if (isempty(key)) {
-                m->argument_parse_error = -EINVAL;
-                return MHD_NO;
-        }
-
-        if (streq(key, "follow")) {
-                if (isempty(value)) {
-                        m->follow = true;
-                        return MHD_YES;
-                }
-
-                r = parse_boolean(value);
-                if (r < 0) {
-                        m->argument_parse_error = r;
-                        return MHD_NO;
-                }
-
-                m->follow = r;
-                return MHD_YES;
-        }
-
-        if (streq(key, "discrete")) {
-                if (isempty(value)) {
-                        m->discrete = true;
-                        return MHD_YES;
-                }
-
-                r = parse_boolean(value);
-                if (r < 0) {
-                        m->argument_parse_error = r;
-                        return MHD_NO;
-                }
-
-                m->discrete = r;
-                return MHD_YES;
-        }
-
-        if (streq(key, "boot")) {
-                if (isempty(value))
-                        r = true;
-                else {
-                        r = parse_boolean(value);
-                        if (r < 0) {
-                                m->argument_parse_error = r;
-                                return MHD_NO;
-                        }
-                }
-
-                if (r) {
-                        char match[9 + 32 + 1] = "_BOOT_ID=";
-                        sd_id128_t bid;
-
-                        r = sd_id128_get_boot(&bid);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to get boot ID: %m");
-                                return MHD_NO;
-                        }
-
-                        sd_id128_to_string(bid, match + 9);
-                        r = sd_journal_add_match(m->journal, match, sizeof(match)-1);
-                        if (r < 0) {
-                                m->argument_parse_error = r;
-                                return MHD_NO;
-                        }
-                }
-
-                return MHD_YES;
-        }
-
-        p = strjoin(key, "=", strempty(value), NULL);
-        if (!p) {
-                m->argument_parse_error = log_oom();
-                return MHD_NO;
-        }
-
-        r = sd_journal_add_match(m->journal, p, 0);
-        if (r < 0) {
-                m->argument_parse_error = r;
-                return MHD_NO;
-        }
-
-        return MHD_YES;
-}
-
-static int request_parse_arguments(
-                RequestMeta *m,
-                struct MHD_Connection *connection) {
-
-        assert(m);
-        assert(connection);
-
-        m->argument_parse_error = 0;
-        MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m);
-
-        return m->argument_parse_error;
-}
-
-static int request_handler_entries(
-                struct MHD_Connection *connection,
-                void *connection_cls) {
-
-        struct MHD_Response *response;
-        RequestMeta *m = connection_cls;
-        int r;
-
-        assert(connection);
-        assert(m);
-
-        r = open_journal(m);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
-        if (request_parse_accept(m, connection) < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n");
-
-        if (request_parse_range(m, connection) < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header.\n");
-
-        if (request_parse_arguments(m, connection) < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n");
-
-        if (m->discrete) {
-                if (!m->cursor)
-                        return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n");
-
-                m->n_entries = 1;
-                m->n_entries_set = true;
-        }
-
-        if (m->cursor)
-                r = sd_journal_seek_cursor(m->journal, m->cursor);
-        else if (m->n_skip >= 0)
-                r = sd_journal_seek_head(m->journal);
-        else if (m->n_skip < 0)
-                r = sd_journal_seek_tail(m->journal);
-        if (r < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.\n");
-
-        response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL);
-        if (!response)
-                return respond_oom(connection);
-
-        MHD_add_response_header(response, "Content-Type", mime_types[m->mode]);
-
-        r = MHD_queue_response(connection, MHD_HTTP_OK, response);
-        MHD_destroy_response(response);
-
-        return r;
-}
-
-static int output_field(FILE *f, OutputMode m, const char *d, size_t l) {
-        const char *eq;
-        size_t j;
-
-        eq = memchr(d, '=', l);
-        if (!eq)
-                return -EINVAL;
-
-        j = l - (eq - d + 1);
-
-        if (m == OUTPUT_JSON) {
-                fprintf(f, "{ \"%.*s\" : ", (int) (eq - d), d);
-                json_escape(f, eq+1, j, OUTPUT_FULL_WIDTH);
-                fputs(" }\n", f);
-        } else {
-                fwrite(eq+1, 1, j, f);
-                fputc('\n', f);
-        }
-
-        return 0;
-}
-
-static ssize_t request_reader_fields(
-                void *cls,
-                uint64_t pos,
-                char *buf,
-                size_t max) {
-
-        RequestMeta *m = cls;
-        int r;
-        size_t n, k;
-
-        assert(m);
-        assert(buf);
-        assert(max > 0);
-        assert(pos >= m->delta);
-
-        pos -= m->delta;
-
-        while (pos >= m->size) {
-                off_t sz;
-                const void *d;
-                size_t l;
-
-                /* End of this field, so let's serialize the next
-                 * one */
-
-                if (m->n_fields_set &&
-                    m->n_fields <= 0)
-                        return MHD_CONTENT_READER_END_OF_STREAM;
-
-                r = sd_journal_enumerate_unique(m->journal, &d, &l);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to advance field index: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                } else if (r == 0)
-                        return MHD_CONTENT_READER_END_OF_STREAM;
-
-                pos -= m->size;
-                m->delta += m->size;
-
-                if (m->n_fields_set)
-                        m->n_fields -= 1;
-
-                r = request_meta_ensure_tmp(m);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to create temporary file: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                r = output_field(m->tmp, m->mode, d, l);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to serialize item: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                sz = ftello(m->tmp);
-                if (sz == (off_t) -1) {
-                        log_error_errno(errno, "Failed to retrieve file position: %m");
-                        return MHD_CONTENT_READER_END_WITH_ERROR;
-                }
-
-                m->size = (uint64_t) sz;
-        }
-
-        if (fseeko(m->tmp, pos, SEEK_SET) < 0) {
-                log_error_errno(errno, "Failed to seek to position: %m");
-                return MHD_CONTENT_READER_END_WITH_ERROR;
-        }
-
-        n = m->size - pos;
-        if (n > max)
-                n = max;
-
-        errno = 0;
-        k = fread(buf, 1, n, m->tmp);
-        if (k != n) {
-                log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
-                return MHD_CONTENT_READER_END_WITH_ERROR;
-        }
-
-        return (ssize_t) k;
-}
-
-static int request_handler_fields(
-                struct MHD_Connection *connection,
-                const char *field,
-                void *connection_cls) {
-
-        struct MHD_Response *response;
-        RequestMeta *m = connection_cls;
-        int r;
-
-        assert(connection);
-        assert(m);
-
-        r = open_journal(m);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
-        if (request_parse_accept(m, connection) < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n");
-
-        r = sd_journal_query_unique(m->journal, field);
-        if (r < 0)
-                return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.\n");
-
-        response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL);
-        if (!response)
-                return respond_oom(connection);
-
-        MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]);
-
-        r = MHD_queue_response(connection, MHD_HTTP_OK, response);
-        MHD_destroy_response(response);
-
-        return r;
-}
-
-static int request_handler_redirect(
-                struct MHD_Connection *connection,
-                const char *target) {
-
-        char *page;
-        struct MHD_Response *response;
-        int ret;
-
-        assert(connection);
-        assert(target);
-
-        if (asprintf(&page, "<html><body>Please continue to the <a href=\"%s\">journal browser</a>.</body></html>", target) < 0)
-                return respond_oom(connection);
-
-        response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE);
-        if (!response) {
-                free(page);
-                return respond_oom(connection);
-        }
-
-        MHD_add_response_header(response, "Content-Type", "text/html");
-        MHD_add_response_header(response, "Location", target);
-
-        ret = MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
-        MHD_destroy_response(response);
-
-        return ret;
-}
-
-static int request_handler_file(
-                struct MHD_Connection *connection,
-                const char *path,
-                const char *mime_type) {
-
-        struct MHD_Response *response;
-        int ret;
-        _cleanup_close_ int fd = -1;
-        struct stat st;
-
-        assert(connection);
-        assert(path);
-        assert(mime_type);
-
-        fd = open(path, O_RDONLY|O_CLOEXEC);
-        if (fd < 0)
-                return mhd_respondf(connection, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path);
-
-        if (fstat(fd, &st) < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n");
-
-        response = MHD_create_response_from_fd_at_offset(st.st_size, fd, 0);
-        if (!response)
-                return respond_oom(connection);
-
-        fd = -1;
-
-        MHD_add_response_header(response, "Content-Type", mime_type);
-
-        ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
-        MHD_destroy_response(response);
-
-        return ret;
-}
-
-static int get_virtualization(char **v) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
-        char *b = NULL;
-        int r;
-
-        r = sd_bus_default_system(&bus);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_get_property_string(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "Virtualization",
-                        NULL,
-                        &b);
-        if (r < 0)
-                return r;
-
-        if (isempty(b)) {
-                free(b);
-                *v = NULL;
-                return 0;
-        }
-
-        *v = b;
-        return 1;
-}
-
-static int request_handler_machine(
-                struct MHD_Connection *connection,
-                void *connection_cls) {
-
-        struct MHD_Response *response;
-        RequestMeta *m = connection_cls;
-        int r;
-        _cleanup_free_ char* hostname = NULL, *os_name = NULL;
-        uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
-        char *json;
-        sd_id128_t mid, bid;
-        _cleanup_free_ char *v = NULL;
-
-        assert(connection);
-        assert(m);
-
-        r = open_journal(m);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
-        r = sd_id128_get_machine(&mid);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r));
-
-        r = sd_id128_get_boot(&bid);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r));
-
-        hostname = gethostname_malloc();
-        if (!hostname)
-                return respond_oom(connection);
-
-        r = sd_journal_get_usage(m->journal, &usage);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
-
-        r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to);
-        if (r < 0)
-                return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
-
-        if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT)
-                parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
-
-        get_virtualization(&v);
-
-        r = asprintf(&json,
-                     "{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\","
-                     "\"boot_id\" : \"" SD_ID128_FORMAT_STR "\","
-                     "\"hostname\" : \"%s\","
-                     "\"os_pretty_name\" : \"%s\","
-                     "\"virtualization\" : \"%s\","
-                     "\"usage\" : \"%"PRIu64"\","
-                     "\"cutoff_from_realtime\" : \"%"PRIu64"\","
-                     "\"cutoff_to_realtime\" : \"%"PRIu64"\" }\n",
-                     SD_ID128_FORMAT_VAL(mid),
-                     SD_ID128_FORMAT_VAL(bid),
-                     hostname_cleanup(hostname, false),
-                     os_name ? os_name : "Linux",
-                     v ? v : "bare",
-                     usage,
-                     cutoff_from,
-                     cutoff_to);
-
-        if (r < 0)
-                return respond_oom(connection);
-
-        response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
-        if (!response) {
-                free(json);
-                return respond_oom(connection);
-        }
-
-        MHD_add_response_header(response, "Content-Type", "application/json");
-        r = MHD_queue_response(connection, MHD_HTTP_OK, response);
-        MHD_destroy_response(response);
-
-        return r;
-}
-
-static int request_handler(
-                void *cls,
-                struct MHD_Connection *connection,
-                const char *url,
-                const char *method,
-                const char *version,
-                const char *upload_data,
-                size_t *upload_data_size,
-                void **connection_cls) {
-        int r, code;
-
-        assert(connection);
-        assert(connection_cls);
-        assert(url);
-        assert(method);
-
-        if (!streq(method, "GET"))
-                return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
-                                   "Unsupported method.\n");
-
-
-        if (!*connection_cls) {
-                if (!request_meta(connection_cls))
-                        return respond_oom(connection);
-                return MHD_YES;
-        }
-
-        if (arg_trust_pem) {
-                r = check_permissions(connection, &code, NULL);
-                if (r < 0)
-                        return code;
-        }
-
-        if (streq(url, "/"))
-                return request_handler_redirect(connection, "/browse");
-
-        if (streq(url, "/entries"))
-                return request_handler_entries(connection, *connection_cls);
-
-        if (startswith(url, "/fields/"))
-                return request_handler_fields(connection, url + 8, *connection_cls);
-
-        if (streq(url, "/browse"))
-                return request_handler_file(connection, DOCUMENT_ROOT "/browse.html", "text/html");
-
-        if (streq(url, "/machine"))
-                return request_handler_machine(connection, *connection_cls);
-
-        return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.\n");
-}
-
-static void help(void) {
-        printf("%s [OPTIONS...] ...\n\n"
-               "HTTP server for journal events.\n\n"
-               "  -h --help           Show this help\n"
-               "     --version        Show package version\n"
-               "     --cert=CERT.PEM  Server certificate in PEM format\n"
-               "     --key=KEY.PEM    Server key in PEM format\n"
-               "     --trust=CERT.PEM Certificat authority certificate in PEM format\n",
-               program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_KEY,
-                ARG_CERT,
-                ARG_TRUST,
-        };
-
-        int r, c;
-
-        static const struct option options[] = {
-                { "help",    no_argument,       NULL, 'h'         },
-                { "version", no_argument,       NULL, ARG_VERSION },
-                { "key",     required_argument, NULL, ARG_KEY     },
-                { "cert",    required_argument, NULL, ARG_CERT    },
-                { "trust",   required_argument, NULL, ARG_TRUST   },
-                {}
-        };
-
-        assert(argc >= 0);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
-                switch(c) {
-
-                case 'h':
-                        help();
-                        return 0;
-
-                case ARG_VERSION:
-                        puts(PACKAGE_STRING);
-                        puts(SYSTEMD_FEATURES);
-                        return 0;
-
-                case ARG_KEY:
-                        if (arg_key_pem) {
-                                log_error("Key file specified twice");
-                                return -EINVAL;
-                        }
-                        r = read_full_file(optarg, &arg_key_pem, NULL);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to read key file: %m");
-                        assert(arg_key_pem);
-                        break;
-
-                case ARG_CERT:
-                        if (arg_cert_pem) {
-                                log_error("Certificate file specified twice");
-                                return -EINVAL;
-                        }
-                        r = read_full_file(optarg, &arg_cert_pem, NULL);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to read certificate file: %m");
-                        assert(arg_cert_pem);
-                        break;
-
-                case ARG_TRUST:
-#ifdef HAVE_GNUTLS
-                        if (arg_trust_pem) {
-                                log_error("CA certificate file specified twice");
-                                return -EINVAL;
-                        }
-                        r = read_full_file(optarg, &arg_trust_pem, NULL);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to read CA certificate file: %m");
-                        assert(arg_trust_pem);
-                        break;
-#else
-                        log_error("Option --trust is not available.");
-#endif
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option");
-                }
-
-        if (optind < argc) {
-                log_error("This program does not take arguments.");
-                return -EINVAL;
-        }
-
-        if (!!arg_key_pem != !!arg_cert_pem) {
-                log_error("Certificate and key files must be specified together");
-                return -EINVAL;
-        }
-
-        if (arg_trust_pem && !arg_key_pem) {
-                log_error("CA certificate can only be used with certificate file");
-                return -EINVAL;
-        }
-
-        return 1;
-}
-
-int main(int argc, char *argv[]) {
-        struct MHD_Daemon *d = NULL;
-        int r, n;
-
-        log_set_target(LOG_TARGET_AUTO);
-        log_parse_environment();
-        log_open();
-
-        r = parse_argv(argc, argv);
-        if (r < 0)
-                return EXIT_FAILURE;
-        if (r == 0)
-                return EXIT_SUCCESS;
-
-        sigbus_install();
-
-        r = setup_gnutls_logger(NULL);
-        if (r < 0)
-                return EXIT_FAILURE;
-
-        n = sd_listen_fds(1);
-        if (n < 0) {
-                log_error_errno(n, "Failed to determine passed sockets: %m");
-                goto finish;
-        } else if (n > 1) {
-                log_error("Can't listen on more than one socket.");
-                goto finish;
-        } else {
-                struct MHD_OptionItem opts[] = {
-                        { MHD_OPTION_NOTIFY_COMPLETED,
-                          (intptr_t) request_meta_free, NULL },
-                        { MHD_OPTION_EXTERNAL_LOGGER,
-                          (intptr_t) microhttpd_logger, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL }};
-                int opts_pos = 2;
-                int flags = MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL|MHD_USE_DEBUG;
-
-                if (n > 0)
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START};
-                if (arg_key_pem) {
-                        assert(arg_cert_pem);
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem};
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem};
-                        flags |= MHD_USE_SSL;
-                }
-                if (arg_trust_pem) {
-                        assert(flags & MHD_USE_SSL);
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem};
-                }
-
-                d = MHD_start_daemon(flags, 19531,
-                                     NULL, NULL,
-                                     request_handler, NULL,
-                                     MHD_OPTION_ARRAY, opts,
-                                     MHD_OPTION_END);
-        }
-
-        if (!d) {
-                log_error("Failed to start daemon!");
-                goto finish;
-        }
-
-        pause();
-
-        r = EXIT_SUCCESS;
-
-finish:
-        if (d)
-                MHD_stop_daemon(d);
-
-        return r;
-}
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
deleted file mode 100644 (file)
index 5ff05d3..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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 "journal-remote-parse.h"
-#include "journald-native.h"
-
-#define LINE_CHUNK 8*1024u
-
-void source_free(RemoteSource *source) {
-        if (!source)
-                return;
-
-        if (source->fd >= 0 && !source->passive_fd) {
-                log_debug("Closing fd:%d (%s)", source->fd, source->name);
-                safe_close(source->fd);
-        }
-
-        free(source->name);
-        free(source->buf);
-        iovw_free_contents(&source->iovw);
-
-        log_debug("Writer ref count %i", source->writer->n_ref);
-        writer_unref(source->writer);
-
-        sd_event_source_unref(source->event);
-        sd_event_source_unref(source->buffer_event);
-
-        free(source);
-}
-
-/**
- * Initialize zero-filled source with given values. On success, takes
- * ownerhship of fd and writer, otherwise does not touch them.
- */
-RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
-
-        RemoteSource *source;
-
-        log_debug("Creating source for %sfd:%d (%s)",
-                  passive_fd ? "passive " : "", fd, name);
-
-        assert(fd >= 0);
-
-        source = new0(RemoteSource, 1);
-        if (!source)
-                return NULL;
-
-        source->fd = fd;
-        source->passive_fd = passive_fd;
-        source->name = name;
-        source->writer = writer;
-
-        return source;
-}
-
-static char* realloc_buffer(RemoteSource *source, size_t size) {
-        char *b, *old = source->buf;
-
-        b = GREEDY_REALLOC(source->buf, source->size, size);
-        if (!b)
-                return NULL;
-
-        iovw_rebase(&source->iovw, old, source->buf);
-
-        return b;
-}
-
-static int get_line(RemoteSource *source, char **line, size_t *size) {
-        ssize_t n;
-        char *c = NULL;
-
-        assert(source);
-        assert(source->state == STATE_LINE);
-        assert(source->offset <= source->filled);
-        assert(source->filled <= source->size);
-        assert(source->buf == NULL || source->size > 0);
-        assert(source->fd >= 0);
-
-        while (true) {
-                if (source->buf) {
-                        size_t start = MAX(source->scanned, source->offset);
-
-                        c = memchr(source->buf + start, '\n',
-                                   source->filled - start);
-                        if (c != NULL)
-                                break;
-                }
-
-                source->scanned = source->filled;
-                if (source->scanned >= DATA_SIZE_MAX) {
-                        log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
-                        return -E2BIG;
-                }
-
-                if (source->passive_fd)
-                        /* we have to wait for some data to come to us */
-                        return -EAGAIN;
-
-                /* We know that source->filled is at most DATA_SIZE_MAX, so if
-                   we reallocate it, we'll increase the size at least a bit. */
-                assert_cc(DATA_SIZE_MAX < ENTRY_SIZE_MAX);
-                if (source->size - source->filled < LINE_CHUNK &&
-                    !realloc_buffer(source, MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX)))
-                                return log_oom();
-
-                assert(source->buf);
-                assert(source->size - source->filled >= LINE_CHUNK ||
-                       source->size == ENTRY_SIZE_MAX);
-
-                n = read(source->fd,
-                         source->buf + source->filled,
-                         source->size - source->filled);
-                if (n < 0) {
-                        if (errno != EAGAIN)
-                                log_error_errno(errno, "read(%d, ..., %zu): %m",
-                                                source->fd,
-                                                source->size - source->filled);
-                        return -errno;
-                } else if (n == 0)
-                        return 0;
-
-                source->filled += n;
-        }
-
-        *line = source->buf + source->offset;
-        *size = c + 1 - source->buf - source->offset;
-        source->offset += *size;
-
-        return 1;
-}
-
-int push_data(RemoteSource *source, const char *data, size_t size) {
-        assert(source);
-        assert(source->state != STATE_EOF);
-
-        if (!realloc_buffer(source, source->filled + size)) {
-                log_error("Failed to store received data of size %zu "
-                          "(in addition to existing %zu bytes with %zu filled): %s",
-                          size, source->size, source->filled, strerror(ENOMEM));
-                return -ENOMEM;
-        }
-
-        memcpy(source->buf + source->filled, data, size);
-        source->filled += size;
-
-        return 0;
-}
-
-static int fill_fixed_size(RemoteSource *source, void **data, size_t size) {
-
-        assert(source);
-        assert(source->state == STATE_DATA_START ||
-               source->state == STATE_DATA ||
-               source->state == STATE_DATA_FINISH);
-        assert(size <= DATA_SIZE_MAX);
-        assert(source->offset <= source->filled);
-        assert(source->filled <= source->size);
-        assert(source->buf != NULL || source->size == 0);
-        assert(source->buf == NULL || source->size > 0);
-        assert(source->fd >= 0);
-        assert(data);
-
-        while (source->filled - source->offset < size) {
-                int n;
-
-                if (source->passive_fd)
-                        /* we have to wait for some data to come to us */
-                        return -EAGAIN;
-
-                if (!realloc_buffer(source, source->offset + size))
-                        return log_oom();
-
-                n = read(source->fd, source->buf + source->filled,
-                         source->size - source->filled);
-                if (n < 0) {
-                        if (errno != EAGAIN)
-                                log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
-                                                source->size - source->filled);
-                        return -errno;
-                } else if (n == 0)
-                        return 0;
-
-                source->filled += n;
-        }
-
-        *data = source->buf + source->offset;
-        source->offset += size;
-
-        return 1;
-}
-
-static int get_data_size(RemoteSource *source) {
-        int r;
-        void *data;
-
-        assert(source);
-        assert(source->state == STATE_DATA_START);
-        assert(source->data_size == 0);
-
-        r = fill_fixed_size(source, &data, sizeof(uint64_t));
-        if (r <= 0)
-                return r;
-
-        source->data_size = le64toh( *(uint64_t *) data );
-        if (source->data_size > DATA_SIZE_MAX) {
-                log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u",
-                          source->data_size, DATA_SIZE_MAX);
-                return -EINVAL;
-        }
-        if (source->data_size == 0)
-                log_warning("Binary field with zero length");
-
-        return 1;
-}
-
-static int get_data_data(RemoteSource *source, void **data) {
-        int r;
-
-        assert(source);
-        assert(data);
-        assert(source->state == STATE_DATA);
-
-        r = fill_fixed_size(source, data, source->data_size);
-        if (r <= 0)
-                return r;
-
-        return 1;
-}
-
-static int get_data_newline(RemoteSource *source) {
-        int r;
-        char *data;
-
-        assert(source);
-        assert(source->state == STATE_DATA_FINISH);
-
-        r = fill_fixed_size(source, (void**) &data, 1);
-        if (r <= 0)
-                return r;
-
-        assert(data);
-        if (*data != '\n') {
-                log_error("expected newline, got '%c'", *data);
-                return -EINVAL;
-        }
-
-        return 1;
-}
-
-static int process_dunder(RemoteSource *source, char *line, size_t n) {
-        const char *timestamp;
-        int r;
-
-        assert(line);
-        assert(n > 0);
-        assert(line[n-1] == '\n');
-
-        /* XXX: is it worth to support timestamps in extended format?
-         * We don't produce them, but who knows... */
-
-        timestamp = startswith(line, "__CURSOR=");
-        if (timestamp)
-                /* ignore __CURSOR */
-                return 1;
-
-        timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
-        if (timestamp) {
-                long long unsigned x;
-                line[n-1] = '\0';
-                r = safe_atollu(timestamp, &x);
-                if (r < 0)
-                        log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
-                else
-                        source->ts.realtime = x;
-                return r < 0 ? r : 1;
-        }
-
-        timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
-        if (timestamp) {
-                long long unsigned x;
-                line[n-1] = '\0';
-                r = safe_atollu(timestamp, &x);
-                if (r < 0)
-                        log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
-                else
-                        source->ts.monotonic = x;
-                return r < 0 ? r : 1;
-        }
-
-        timestamp = startswith(line, "__");
-        if (timestamp) {
-                log_notice("Unknown dunder line %s", line);
-                return 1;
-        }
-
-        /* no dunder */
-        return 0;
-}
-
-static int process_data(RemoteSource *source) {
-        int r;
-
-        switch(source->state) {
-        case STATE_LINE: {
-                char *line, *sep;
-                size_t n = 0;
-
-                assert(source->data_size == 0);
-
-                r = get_line(source, &line, &n);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        source->state = STATE_EOF;
-                        return r;
-                }
-                assert(n > 0);
-                assert(line[n-1] == '\n');
-
-                if (n == 1) {
-                        log_trace("Received empty line, event is ready");
-                        return 1;
-                }
-
-                r = process_dunder(source, line, n);
-                if (r != 0)
-                        return r < 0 ? r : 0;
-
-                /* MESSAGE=xxx\n
-                   or
-                   COREDUMP\n
-                   LLLLLLLL0011223344...\n
-                */
-                sep = memchr(line, '=', n);
-                if (sep) {
-                        /* chomp newline */
-                        n--;
-
-                        r = iovw_put(&source->iovw, line, n);
-                        if (r < 0)
-                                return r;
-                } else {
-                        /* replace \n with = */
-                        line[n-1] = '=';
-
-                        source->field_len = n;
-                        source->state = STATE_DATA_START;
-
-                        /* we cannot put the field in iovec until we have all data */
-                }
-
-                log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary");
-
-                return 0; /* continue */
-        }
-
-        case STATE_DATA_START:
-                assert(source->data_size == 0);
-
-                r = get_data_size(source);
-                // log_debug("get_data_size() -> %d", r);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        source->state = STATE_EOF;
-                        return 0;
-                }
-
-                source->state = source->data_size > 0 ?
-                        STATE_DATA : STATE_DATA_FINISH;
-
-                return 0; /* continue */
-
-        case STATE_DATA: {
-                void *data;
-                char *field;
-
-                assert(source->data_size > 0);
-
-                r = get_data_data(source, &data);
-                // log_debug("get_data_data() -> %d", r);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        source->state = STATE_EOF;
-                        return 0;
-                }
-
-                assert(data);
-
-                field = (char*) data - sizeof(uint64_t) - source->field_len;
-                memmove(field + sizeof(uint64_t), field, source->field_len);
-
-                r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size);
-                if (r < 0)
-                        return r;
-
-                source->state = STATE_DATA_FINISH;
-
-                return 0; /* continue */
-        }
-
-        case STATE_DATA_FINISH:
-                r = get_data_newline(source);
-                // log_debug("get_data_newline() -> %d", r);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        source->state = STATE_EOF;
-                        return 0;
-                }
-
-                source->data_size = 0;
-                source->state = STATE_LINE;
-
-                return 0; /* continue */
-        default:
-                assert_not_reached("wtf?");
-        }
-}
-
-int process_source(RemoteSource *source, bool compress, bool seal) {
-        size_t remain, target;
-        int r;
-
-        assert(source);
-        assert(source->writer);
-
-        r = process_data(source);
-        if (r <= 0)
-                return r;
-
-        /* We have a full event */
-        log_trace("Received full event from source@%p fd:%d (%s)",
-                  source, source->fd, source->name);
-
-        if (!source->iovw.count) {
-                log_warning("Entry with no payload, skipping");
-                goto freeing;
-        }
-
-        assert(source->iovw.iovec);
-        assert(source->iovw.count);
-
-        r = writer_write(source->writer, &source->iovw, &source->ts, compress, seal);
-        if (r < 0)
-                log_error_errno(r, "Failed to write entry of %zu bytes: %m",
-                                iovw_size(&source->iovw));
-        else
-                r = 1;
-
- freeing:
-        iovw_free_contents(&source->iovw);
-
-        /* possibly reset buffer position */
-        remain = source->filled - source->offset;
-
-        if (remain == 0) /* no brainer */
-                source->offset = source->scanned = source->filled = 0;
-        else if (source->offset > source->size - source->filled &&
-                 source->offset > remain) {
-                memcpy(source->buf, source->buf + source->offset, remain);
-                source->offset = source->scanned = 0;
-                source->filled = remain;
-        }
-
-        target = source->size;
-        while (target > 16 * LINE_CHUNK && remain < target / 2)
-                target /= 2;
-        if (target < source->size) {
-                char *tmp;
-
-                tmp = realloc(source->buf, target);
-                if (!tmp)
-                        log_warning("Failed to reallocate buffer to (smaller) size %zu",
-                                    target);
-                else {
-                        log_debug("Reallocated buffer from %zu to %zu bytes",
-                                  source->size, target);
-                        source->buf = tmp;
-                        source->size = target;
-                }
-        }
-
-        return r;
-}
diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h
deleted file mode 100644 (file)
index 14bfadc..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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/>.
-***/
-
-#pragma once
-
-#include "sd-event.h"
-#include "journal-remote-write.h"
-
-typedef enum {
-        STATE_LINE = 0,    /* waiting to read, or reading line */
-        STATE_DATA_START,  /* reading binary data header */
-        STATE_DATA,        /* reading binary data */
-        STATE_DATA_FINISH, /* expecting newline */
-        STATE_EOF,         /* done */
-} source_state;
-
-typedef struct RemoteSource {
-        char *name;
-        int fd;
-        bool passive_fd;
-
-        char *buf;
-        size_t size;       /* total size of the buffer */
-        size_t offset;     /* offset to the beginning of live data in the buffer */
-        size_t scanned;    /* number of bytes since the beginning of data without a newline */
-        size_t filled;     /* total number of bytes in the buffer */
-
-        size_t field_len;  /* used for binary fields: the field name length */
-        size_t data_size;  /* and the size of the binary data chunk being processed */
-
-        struct iovec_wrapper iovw;
-
-        source_state state;
-        dual_timestamp ts;
-
-        Writer *writer;
-
-        sd_event_source *event;
-        sd_event_source *buffer_event;
-} RemoteSource;
-
-RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer);
-
-static inline size_t source_non_empty(RemoteSource *source) {
-        assert(source);
-
-        return source->filled;
-}
-
-void source_free(RemoteSource *source);
-int push_data(RemoteSource *source, const char *data, size_t size);
-int process_source(RemoteSource *source, bool compress, bool seal);
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
deleted file mode 100644 (file)
index 99820fa..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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 "journal-remote.h"
-
-int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) {
-        if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
-                return log_oom();
-
-        iovw->iovec[iovw->count++] = (struct iovec) {data, len};
-        return 0;
-}
-
-void iovw_free_contents(struct iovec_wrapper *iovw) {
-        free(iovw->iovec);
-        iovw->iovec = NULL;
-        iovw->size_bytes = iovw->count = 0;
-}
-
-size_t iovw_size(struct iovec_wrapper *iovw) {
-        size_t n = 0, i;
-
-        for (i = 0; i < iovw->count; i++)
-                n += iovw->iovec[i].iov_len;
-
-        return n;
-}
-
-void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
-        size_t i;
-
-        for (i = 0; i < iovw->count; i++)
-                iovw->iovec[i].iov_base = (char*) iovw->iovec[i].iov_base - old + new;
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int do_rotate(JournalFile **f, bool compress, bool seal) {
-        int r = journal_file_rotate(f, compress, seal);
-        if (r < 0) {
-                if (*f)
-                        log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
-                else
-                        log_error_errno(r, "Failed to create rotated journal: %m");
-        }
-
-        return r;
-}
-
-Writer* writer_new(RemoteServer *server) {
-        Writer *w;
-
-        w = new0(Writer, 1);
-        if (!w)
-                return NULL;
-
-        memset(&w->metrics, 0xFF, sizeof(w->metrics));
-
-        w->mmap = mmap_cache_new();
-        if (!w->mmap) {
-                free(w);
-                return NULL;
-        }
-
-        w->n_ref = 1;
-        w->server = server;
-
-        return w;
-}
-
-Writer* writer_free(Writer *w) {
-        if (!w)
-                return NULL;
-
-        if (w->journal) {
-                log_debug("Closing journal file %s.", w->journal->path);
-                journal_file_close(w->journal);
-        }
-
-        if (w->server && w->hashmap_key)
-                hashmap_remove(w->server->writers, w->hashmap_key);
-
-        free(w->hashmap_key);
-
-        if (w->mmap)
-                mmap_cache_unref(w->mmap);
-
-        free(w);
-
-        return NULL;
-}
-
-Writer* writer_unref(Writer *w) {
-        if (w && (-- w->n_ref <= 0))
-                writer_free(w);
-
-        return NULL;
-}
-
-Writer* writer_ref(Writer *w) {
-        if (w)
-                assert_se(++ w->n_ref >= 2);
-
-        return w;
-}
-
-int writer_write(Writer *w,
-                 struct iovec_wrapper *iovw,
-                 dual_timestamp *ts,
-                 bool compress,
-                 bool seal) {
-        int r;
-
-        assert(w);
-        assert(iovw);
-        assert(iovw->count > 0);
-
-        if (journal_file_rotate_suggested(w->journal, 0)) {
-                log_info("%s: Journal header limits reached or header out-of-date, rotating",
-                         w->journal->path);
-                r = do_rotate(&w->journal, compress, seal);
-                if (r < 0)
-                        return r;
-        }
-
-        r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
-                                      &w->seqnum, NULL, NULL);
-        if (r >= 0) {
-                if (w->server)
-                        w->server->event_count += 1;
-                return 1;
-        }
-
-        log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path);
-        r = do_rotate(&w->journal, compress, seal);
-        if (r < 0)
-                return r;
-        else
-                log_debug("%s: Successfully rotated journal", w->journal->path);
-
-        log_debug("Retrying write.");
-        r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
-                                      &w->seqnum, NULL, NULL);
-        if (r < 0)
-                return r;
-
-        if (w->server)
-                w->server->event_count += 1;
-        return 1;
-}
diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h
deleted file mode 100644 (file)
index 7f47f8b..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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/>.
-***/
-
-#pragma once
-
-
-#include "journal-file.h"
-
-typedef struct RemoteServer RemoteServer;
-
-struct iovec_wrapper {
-        struct iovec *iovec;
-        size_t size_bytes;
-        size_t count;
-};
-
-int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len);
-void iovw_free_contents(struct iovec_wrapper *iovw);
-size_t iovw_size(struct iovec_wrapper *iovw);
-void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new);
-
-typedef struct Writer {
-        JournalFile *journal;
-        JournalMetrics metrics;
-
-        MMapCache *mmap;
-        RemoteServer *server;
-        char *hashmap_key;
-
-        uint64_t seqnum;
-
-        int n_ref;
-} Writer;
-
-Writer* writer_new(RemoteServer* server);
-Writer* writer_free(Writer *w);
-
-Writer* writer_ref(Writer *w);
-Writer* writer_unref(Writer *w);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Writer*, writer_unref);
-#define _cleanup_writer_unref_ _cleanup_(writer_unrefp)
-
-int writer_write(Writer *s,
-                 struct iovec_wrapper *iovw,
-                 dual_timestamp *ts,
-                 bool compress,
-                 bool seal);
-
-typedef enum JournalWriteSplitMode {
-        JOURNAL_WRITE_SPLIT_NONE,
-        JOURNAL_WRITE_SPLIT_HOST,
-        _JOURNAL_WRITE_SPLIT_MAX,
-        _JOURNAL_WRITE_SPLIT_INVALID = -1
-} JournalWriteSplitMode;
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
deleted file mode 100644 (file)
index f87a939..0000000
+++ /dev/null
@@ -1,1574 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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 <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <getopt.h>
-
-#include "sd-daemon.h"
-#include "journal-file.h"
-#include "journald-native.h"
-#include "socket-util.h"
-#include "build.h"
-#include "macro.h"
-#include "strv.h"
-#include "fileio.h"
-#include "conf-parser.h"
-
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
-#include "journal-remote.h"
-#include "journal-remote-write.h"
-
-#define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
-
-#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
-#define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-remote.pem"
-#define TRUST_FILE    CERTIFICATE_ROOT "/ca/trusted.pem"
-
-static char* arg_url = NULL;
-static char* arg_getter = NULL;
-static char* arg_listen_raw = NULL;
-static char* arg_listen_http = NULL;
-static char* arg_listen_https = NULL;
-static char** arg_files = NULL;
-static int arg_compress = true;
-static int arg_seal = false;
-static int http_socket = -1, https_socket = -1;
-static char** arg_gnutls_log = NULL;
-
-static JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
-static char* arg_output = NULL;
-
-static char *arg_key = NULL;
-static char *arg_cert = NULL;
-static char *arg_trust = NULL;
-static bool arg_trust_all = false;
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int spawn_child(const char* child, char** argv) {
-        int fd[2];
-        pid_t parent_pid, child_pid;
-        int r;
-
-        if (pipe(fd) < 0)
-                return log_error_errno(errno, "Failed to create pager pipe: %m");
-
-        parent_pid = getpid();
-
-        child_pid = fork();
-        if (child_pid < 0) {
-                r = -errno;
-                log_error_errno(errno, "Failed to fork: %m");
-                safe_close_pair(fd);
-                return r;
-        }
-
-        /* In the child */
-        if (child_pid == 0) {
-                r = dup2(fd[1], STDOUT_FILENO);
-                if (r < 0) {
-                        log_error_errno(errno, "Failed to dup pipe to stdout: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
-                safe_close_pair(fd);
-
-                /* 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_errno(errno, "Failed to exec child %s: %m", child);
-                _exit(EXIT_FAILURE);
-        }
-
-        r = close(fd[1]);
-        if (r < 0)
-                log_warning_errno(errno, "Failed to close write end of pipe: %m");
-
-        return fd[0];
-}
-
-static int spawn_curl(const char* url) {
-        char **argv = STRV_MAKE("curl",
-                                "-HAccept: application/vnd.fdo.journal",
-                                "--silent",
-                                "--show-error",
-                                url);
-        int r;
-
-        r = spawn_child("curl", argv);
-        if (r < 0)
-                log_error_errno(errno, "Failed to spawn curl: %m");
-        return r;
-}
-
-static int spawn_getter(const char *getter, const char *url) {
-        int r;
-        _cleanup_strv_free_ char **words = NULL;
-
-        assert(getter);
-        r = strv_split_quoted(&words, getter, 0);
-        if (r < 0)
-                return log_error_errno(r, "Failed to split getter option: %m");
-
-        r = strv_extend(&words, url);
-        if (r < 0)
-                return log_error_errno(r, "Failed to create command line: %m");
-
-        r = spawn_child(words[0], words);
-        if (r < 0)
-                log_error_errno(errno, "Failed to spawn getter %s: %m", getter);
-
-        return r;
-}
-
-#define filename_escape(s) xescape((s), "/ ")
-
-static int open_output(Writer *w, const char* host) {
-        _cleanup_free_ char *_output = NULL;
-        const char *output;
-        int r;
-
-        switch (arg_split_mode) {
-        case JOURNAL_WRITE_SPLIT_NONE:
-                output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
-                break;
-
-        case JOURNAL_WRITE_SPLIT_HOST: {
-                _cleanup_free_ char *name;
-
-                assert(host);
-
-                name = filename_escape(host);
-                if (!name)
-                        return log_oom();
-
-                r = asprintf(&_output, "%s/remote-%s.journal",
-                             arg_output ?: REMOTE_JOURNAL_PATH,
-                             name);
-                if (r < 0)
-                        return log_oom();
-
-                output = _output;
-                break;
-        }
-
-        default:
-                assert_not_reached("what?");
-        }
-
-        r = journal_file_open_reliably(output,
-                                       O_RDWR|O_CREAT, 0640,
-                                       arg_compress, arg_seal,
-                                       &w->metrics,
-                                       w->mmap,
-                                       NULL, &w->journal);
-        if (r < 0)
-                log_error_errno(r, "Failed to open output journal %s: %m",
-                                output);
-        else
-                log_debug("Opened output file %s", w->journal->path);
-        return r;
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int init_writer_hashmap(RemoteServer *s) {
-        static const struct hash_ops *hash_ops[] = {
-                [JOURNAL_WRITE_SPLIT_NONE] = NULL,
-                [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
-        };
-
-        assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops));
-
-        s->writers = hashmap_new(hash_ops[arg_split_mode]);
-        if (!s->writers)
-                return log_oom();
-
-        return 0;
-}
-
-static int get_writer(RemoteServer *s, const char *host,
-                      Writer **writer) {
-        const void *key;
-        _cleanup_writer_unref_ Writer *w = NULL;
-        int r;
-
-        switch(arg_split_mode) {
-        case JOURNAL_WRITE_SPLIT_NONE:
-                key = "one and only";
-                break;
-
-        case JOURNAL_WRITE_SPLIT_HOST:
-                assert(host);
-                key = host;
-                break;
-
-        default:
-                assert_not_reached("what split mode?");
-        }
-
-        w = hashmap_get(s->writers, key);
-        if (w)
-                writer_ref(w);
-        else {
-                w = writer_new(s);
-                if (!w)
-                        return log_oom();
-
-                if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
-                        w->hashmap_key = strdup(key);
-                        if (!w->hashmap_key)
-                                return log_oom();
-                }
-
-                r = open_output(w, host);
-                if (r < 0)
-                        return r;
-
-                r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
-                if (r < 0)
-                        return r;
-        }
-
-        *writer = w;
-        w = NULL;
-        return 0;
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-/* This should go away as soon as µhttpd allows state to be passed around. */
-static RemoteServer *server;
-
-static int dispatch_raw_source_event(sd_event_source *event,
-                                     int fd,
-                                     uint32_t revents,
-                                     void *userdata);
-static int dispatch_raw_source_until_block(sd_event_source *event,
-                                           void *userdata);
-static int dispatch_blocking_source_event(sd_event_source *event,
-                                          void *userdata);
-static int dispatch_raw_connection_event(sd_event_source *event,
-                                         int fd,
-                                         uint32_t revents,
-                                         void *userdata);
-static int dispatch_http_event(sd_event_source *event,
-                               int fd,
-                               uint32_t revents,
-                               void *userdata);
-
-static int get_source_for_fd(RemoteServer *s,
-                             int fd, char *name, RemoteSource **source) {
-        Writer *writer;
-        int r;
-
-        /* This takes ownership of name, but only on success. */
-
-        assert(fd >= 0);
-        assert(source);
-
-        if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
-                return log_oom();
-
-        r = get_writer(s, name, &writer);
-        if (r < 0)
-                return log_warning_errno(r, "Failed to get writer for source %s: %m",
-                                         name);
-
-        if (s->sources[fd] == NULL) {
-                s->sources[fd] = source_new(fd, false, name, writer);
-                if (!s->sources[fd]) {
-                        writer_unref(writer);
-                        return log_oom();
-                }
-
-                s->active++;
-        }
-
-        *source = s->sources[fd];
-        return 0;
-}
-
-static int remove_source(RemoteServer *s, int fd) {
-        RemoteSource *source;
-
-        assert(s);
-        assert(fd >= 0 && fd < (ssize_t) s->sources_size);
-
-        source = s->sources[fd];
-        if (source) {
-                /* this closes fd too */
-                source_free(source);
-                s->sources[fd] = NULL;
-                s->active--;
-        }
-
-        return 0;
-}
-
-static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
-
-        RemoteSource *source = NULL;
-        int r;
-
-        /* This takes ownership of name, even on failure, if own_name is true. */
-
-        assert(s);
-        assert(fd >= 0);
-        assert(name);
-
-        if (!own_name) {
-                name = strdup(name);
-                if (!name)
-                        return log_oom();
-        }
-
-        r = get_source_for_fd(s, fd, name, &source);
-        if (r < 0) {
-                log_error_errno(r, "Failed to create source for fd:%d (%s): %m",
-                                fd, name);
-                free(name);
-                return r;
-        }
-
-        r = sd_event_add_io(s->events, &source->event,
-                            fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
-                            dispatch_raw_source_event, source);
-        if (r == 0) {
-                /* Add additional source for buffer processing. It will be
-                 * enabled later. */
-                r = sd_event_add_defer(s->events, &source->buffer_event,
-                                       dispatch_raw_source_until_block, source);
-                if (r == 0)
-                        sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
-        } else if (r == -EPERM) {
-                log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
-                r = sd_event_add_defer(s->events, &source->event,
-                                       dispatch_blocking_source_event, source);
-                if (r == 0)
-                        sd_event_source_set_enabled(source->event, SD_EVENT_ON);
-        }
-        if (r < 0) {
-                log_error_errno(r, "Failed to register event source for fd:%d: %m",
-                                fd);
-                goto error;
-        }
-
-        r = sd_event_source_set_description(source->event, name);
-        if (r < 0) {
-                log_error_errno(r, "Failed to set source name for fd:%d: %m", fd);
-                goto error;
-        }
-
-        return 1; /* work to do */
-
- error:
-        remove_source(s, fd);
-        return r;
-}
-
-static int add_raw_socket(RemoteServer *s, int fd) {
-        int r;
-        _cleanup_close_ int fd_ = fd;
-        char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1];
-
-        assert(fd >= 0);
-
-        r = sd_event_add_io(s->events, &s->listen_event,
-                            fd, EPOLLIN,
-                            dispatch_raw_connection_event, s);
-        if (r < 0)
-                return r;
-
-        xsprintf(name, "raw-socket-%d", fd);
-
-        r = sd_event_source_set_description(s->listen_event, name);
-        if (r < 0)
-                return r;
-
-        fd_ = -1;
-        s->active ++;
-        return 0;
-}
-
-static int setup_raw_socket(RemoteServer *s, const char *address) {
-        int fd;
-
-        fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        return add_raw_socket(s, fd);
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int request_meta(void **connection_cls, int fd, char *hostname) {
-        RemoteSource *source;
-        Writer *writer;
-        int r;
-
-        assert(connection_cls);
-        if (*connection_cls)
-                return 0;
-
-        r = get_writer(server, hostname, &writer);
-        if (r < 0)
-                return log_warning_errno(r, "Failed to get writer for source %s: %m",
-                                         hostname);
-
-        source = source_new(fd, true, hostname, writer);
-        if (!source) {
-                writer_unref(writer);
-                return log_oom();
-        }
-
-        log_debug("Added RemoteSource as connection metadata %p", source);
-
-        *connection_cls = source;
-        return 0;
-}
-
-static void request_meta_free(void *cls,
-                              struct MHD_Connection *connection,
-                              void **connection_cls,
-                              enum MHD_RequestTerminationCode toe) {
-        RemoteSource *s;
-
-        assert(connection_cls);
-        s = *connection_cls;
-
-        if (s) {
-                log_debug("Cleaning up connection metadata %p", s);
-                source_free(s);
-                *connection_cls = NULL;
-        }
-}
-
-static int process_http_upload(
-                struct MHD_Connection *connection,
-                const char *upload_data,
-                size_t *upload_data_size,
-                RemoteSource *source) {
-
-        bool finished = false;
-        size_t remaining;
-        int r;
-
-        assert(source);
-
-        log_trace("%s: connection %p, %zu bytes",
-                  __func__, connection, *upload_data_size);
-
-        if (*upload_data_size) {
-                log_trace("Received %zu bytes", *upload_data_size);
-
-                r = push_data(source, upload_data, *upload_data_size);
-                if (r < 0)
-                        return mhd_respond_oom(connection);
-
-                *upload_data_size = 0;
-        } else
-                finished = true;
-
-        while (true) {
-                r = process_source(source, arg_compress, arg_seal);
-                if (r == -EAGAIN)
-                        break;
-                else if (r < 0) {
-                        log_warning("Failed to process data for connection %p", connection);
-                        if (r == -E2BIG)
-                                return mhd_respondf(connection,
-                                                    MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
-                                                    "Entry is too large, maximum is %u bytes.\n",
-                                                    DATA_SIZE_MAX);
-                        else
-                                return mhd_respondf(connection,
-                                                    MHD_HTTP_UNPROCESSABLE_ENTITY,
-                                                    "Processing failed: %s.", strerror(-r));
-                }
-        }
-
-        if (!finished)
-                return MHD_YES;
-
-        /* The upload is finished */
-
-        remaining = source_non_empty(source);
-        if (remaining > 0) {
-                log_warning("Premature EOFbyte. %zu bytes lost.", remaining);
-                return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED,
-                                    "Premature EOF. %zu bytes of trailing data not processed.",
-                                    remaining);
-        }
-
-        return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
-};
-
-static int request_handler(
-                void *cls,
-                struct MHD_Connection *connection,
-                const char *url,
-                const char *method,
-                const char *version,
-                const char *upload_data,
-                size_t *upload_data_size,
-                void **connection_cls) {
-
-        const char *header;
-        int r, code, fd;
-        _cleanup_free_ char *hostname = NULL;
-
-        assert(connection);
-        assert(connection_cls);
-        assert(url);
-        assert(method);
-
-        log_trace("Handling a connection %s %s %s", method, url, version);
-
-        if (*connection_cls)
-                return process_http_upload(connection,
-                                           upload_data, upload_data_size,
-                                           *connection_cls);
-
-        if (!streq(method, "POST"))
-                return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
-                                   "Unsupported method.\n");
-
-        if (!streq(url, "/upload"))
-                return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
-                                   "Not found.\n");
-
-        header = MHD_lookup_connection_value(connection,
-                                             MHD_HEADER_KIND, "Content-Type");
-        if (!header || !streq(header, "application/vnd.fdo.journal"))
-                return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
-                                   "Content-Type: application/vnd.fdo.journal"
-                                   " is required.\n");
-
-        {
-                const union MHD_ConnectionInfo *ci;
-
-                ci = MHD_get_connection_info(connection,
-                                             MHD_CONNECTION_INFO_CONNECTION_FD);
-                if (!ci) {
-                        log_error("MHD_get_connection_info failed: cannot get remote fd");
-                        return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                           "Cannot check remote address");
-                }
-
-                fd = ci->connect_fd;
-                assert(fd >= 0);
-        }
-
-        if (server->check_trust) {
-                r = check_permissions(connection, &code, &hostname);
-                if (r < 0)
-                        return code;
-        } else {
-                r = getnameinfo_pretty(fd, &hostname);
-                if (r < 0) {
-                        return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                           "Cannot check remote hostname");
-                }
-        }
-
-        assert(hostname);
-
-        r = request_meta(connection_cls, fd, hostname);
-        if (r == -ENOMEM)
-                return respond_oom(connection);
-        else if (r < 0)
-                return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                   strerror(-r));
-
-        hostname = NULL;
-        return MHD_YES;
-}
-
-static int setup_microhttpd_server(RemoteServer *s,
-                                   int fd,
-                                   const char *key,
-                                   const char *cert,
-                                   const char *trust) {
-        struct MHD_OptionItem opts[] = {
-                { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
-                { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
-                { MHD_OPTION_LISTEN_SOCKET, fd},
-                { MHD_OPTION_END},
-                { MHD_OPTION_END},
-                { MHD_OPTION_END},
-                { MHD_OPTION_END}};
-        int opts_pos = 3;
-        int flags =
-                MHD_USE_DEBUG |
-                MHD_USE_PEDANTIC_CHECKS |
-                MHD_USE_EPOLL_LINUX_ONLY |
-                MHD_USE_DUAL_STACK;
-
-        const union MHD_DaemonInfo *info;
-        int r, epoll_fd;
-        MHDDaemonWrapper *d;
-
-        assert(fd >= 0);
-
-        r = fd_nonblock(fd, true);
-        if (r < 0)
-                return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
-
-        if (key) {
-                assert(cert);
-
-                opts[opts_pos++] = (struct MHD_OptionItem)
-                        {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
-                opts[opts_pos++] = (struct MHD_OptionItem)
-                        {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
-
-                flags |= MHD_USE_SSL;
-
-                if (trust)
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
-        }
-
-        d = new(MHDDaemonWrapper, 1);
-        if (!d)
-                return log_oom();
-
-        d->fd = (uint64_t) fd;
-
-        d->daemon = MHD_start_daemon(flags, 0,
-                                     NULL, NULL,
-                                     request_handler, NULL,
-                                     MHD_OPTION_ARRAY, opts,
-                                     MHD_OPTION_END);
-        if (!d->daemon) {
-                log_error("Failed to start µhttp daemon");
-                r = -EINVAL;
-                goto error;
-        }
-
-        log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
-                  key ? "HTTPS" : "HTTP", fd, d);
-
-
-        info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
-        if (!info) {
-                log_error("µhttp returned NULL daemon info");
-                r = -EOPNOTSUPP;
-                goto error;
-        }
-
-        epoll_fd = info->listen_fd;
-        if (epoll_fd < 0) {
-                log_error("µhttp epoll fd is invalid");
-                r = -EUCLEAN;
-                goto error;
-        }
-
-        r = sd_event_add_io(s->events, &d->event,
-                            epoll_fd, EPOLLIN,
-                            dispatch_http_event, d);
-        if (r < 0) {
-                log_error_errno(r, "Failed to add event callback: %m");
-                goto error;
-        }
-
-        r = sd_event_source_set_description(d->event, "epoll-fd");
-        if (r < 0) {
-                log_error_errno(r, "Failed to set source name: %m");
-                goto error;
-        }
-
-        r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
-        if (r < 0) {
-                log_oom();
-                goto error;
-        }
-
-        r = hashmap_put(s->daemons, &d->fd, d);
-        if (r < 0) {
-                log_error_errno(r, "Failed to add daemon to hashmap: %m");
-                goto error;
-        }
-
-        s->active ++;
-        return 0;
-
-error:
-        MHD_stop_daemon(d->daemon);
-        free(d->daemon);
-        free(d);
-        return r;
-}
-
-static int setup_microhttpd_socket(RemoteServer *s,
-                                   const char *address,
-                                   const char *key,
-                                   const char *cert,
-                                   const char *trust) {
-        int fd;
-
-        fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        return setup_microhttpd_server(s, fd, key, cert, trust);
-}
-
-static int dispatch_http_event(sd_event_source *event,
-                               int fd,
-                               uint32_t revents,
-                               void *userdata) {
-        MHDDaemonWrapper *d = userdata;
-        int r;
-
-        assert(d);
-
-        r = MHD_run(d->daemon);
-        if (r == MHD_NO) {
-                log_error("MHD_run failed!");
-                // XXX: unregister daemon
-                return -EINVAL;
-        }
-
-        return 1; /* work to do */
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int setup_signals(RemoteServer *s) {
-        sigset_t mask;
-        int r;
-
-        assert(s);
-
-        assert_se(sigemptyset(&mask) == 0);
-        sigset_add_many(&mask, SIGINT, SIGTERM, -1);
-        assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
-        r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
-        if (r < 0)
-                return r;
-
-        r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
-static int negative_fd(const char *spec) {
-        /* Return a non-positive number as its inverse, -EINVAL otherwise. */
-
-        int fd, r;
-
-        r = safe_atoi(spec, &fd);
-        if (r < 0)
-                return r;
-
-        if (fd > 0)
-                return -EINVAL;
-        else
-                return -fd;
-}
-
-static int remoteserver_init(RemoteServer *s,
-                             const char* key,
-                             const char* cert,
-                             const char* trust) {
-        int r, n, fd;
-        char **file;
-
-        assert(s);
-
-        if ((arg_listen_raw || arg_listen_http) && trust) {
-                log_error("Option --trust makes all non-HTTPS connections untrusted.");
-                return -EINVAL;
-        }
-
-        r = sd_event_default(&s->events);
-        if (r < 0)
-                return log_error_errno(r, "Failed to allocate event loop: %m");
-
-        setup_signals(s);
-
-        assert(server == NULL);
-        server = s;
-
-        r = init_writer_hashmap(s);
-        if (r < 0)
-                return r;
-
-        n = sd_listen_fds(true);
-        if (n < 0)
-                return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
-        else
-                log_debug("Received %d descriptors", n);
-
-        if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
-                log_error("Received fewer sockets than expected");
-                return -EBADFD;
-        }
-
-        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
-                if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
-                        log_debug("Received a listening socket (fd:%d)", fd);
-
-                        if (fd == http_socket)
-                                r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
-                        else if (fd == https_socket)
-                                r = setup_microhttpd_server(s, fd, key, cert, trust);
-                        else
-                                r = add_raw_socket(s, fd);
-                } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
-                        char *hostname;
-
-                        r = getnameinfo_pretty(fd, &hostname);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to retrieve remote name: %m");
-
-                        log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
-
-                        r = add_source(s, fd, hostname, true);
-                } else {
-                        log_error("Unknown socket passed on fd:%d", fd);
-
-                        return -EINVAL;
-                }
-
-                if (r < 0)
-                        return log_error_errno(r, "Failed to register socket (fd:%d): %m",
-                                               fd);
-        }
-
-        if (arg_url) {
-                const char *url, *hostname;
-
-                url = strjoina(arg_url, "/entries");
-
-                if (arg_getter) {
-                        log_info("Spawning getter %s...", url);
-                        fd = spawn_getter(arg_getter, url);
-                } else {
-                        log_info("Spawning curl %s...", url);
-                        fd = spawn_curl(url);
-                }
-                if (fd < 0)
-                        return fd;
-
-                hostname =
-                        startswith(arg_url, "https://") ?:
-                        startswith(arg_url, "http://") ?:
-                        arg_url;
-
-                r = add_source(s, fd, (char*) hostname, false);
-                if (r < 0)
-                        return r;
-        }
-
-        if (arg_listen_raw) {
-                log_debug("Listening on a socket...");
-                r = setup_raw_socket(s, arg_listen_raw);
-                if (r < 0)
-                        return r;
-        }
-
-        if (arg_listen_http) {
-                r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
-                if (r < 0)
-                        return r;
-        }
-
-        if (arg_listen_https) {
-                r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
-                if (r < 0)
-                        return r;
-        }
-
-        STRV_FOREACH(file, arg_files) {
-                const char *output_name;
-
-                if (streq(*file, "-")) {
-                        log_debug("Using standard input as source.");
-
-                        fd = STDIN_FILENO;
-                        output_name = "stdin";
-                } else {
-                        log_debug("Reading file %s...", *file);
-
-                        fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
-                        if (fd < 0)
-                                return log_error_errno(errno, "Failed to open %s: %m", *file);
-                        output_name = *file;
-                }
-
-                r = add_source(s, fd, (char*) output_name, false);
-                if (r < 0)
-                        return r;
-        }
-
-        if (s->active == 0) {
-                log_error("Zarro sources specified");
-                return -EINVAL;
-        }
-
-        if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
-                /* In this case we know what the writer will be
-                   called, so we can create it and verify that we can
-                   create output as expected. */
-                r = get_writer(s, NULL, &s->_single_writer);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-static void server_destroy(RemoteServer *s) {
-        size_t i;
-        MHDDaemonWrapper *d;
-
-        while ((d = hashmap_steal_first(s->daemons))) {
-                MHD_stop_daemon(d->daemon);
-                sd_event_source_unref(d->event);
-                free(d);
-        }
-
-        hashmap_free(s->daemons);
-
-        assert(s->sources_size == 0 || s->sources);
-        for (i = 0; i < s->sources_size; i++)
-                remove_source(s, i);
-        free(s->sources);
-
-        writer_unref(s->_single_writer);
-        hashmap_free(s->writers);
-
-        sd_event_source_unref(s->sigterm_event);
-        sd_event_source_unref(s->sigint_event);
-        sd_event_source_unref(s->listen_event);
-        sd_event_unref(s->events);
-
-        /* fds that we're listening on remain open... */
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int handle_raw_source(sd_event_source *event,
-                             int fd,
-                             uint32_t revents,
-                             RemoteServer *s) {
-
-        RemoteSource *source;
-        int r;
-
-        /* Returns 1 if there might be more data pending,
-         * 0 if data is currently exhausted, negative on error.
-         */
-
-        assert(fd >= 0 && fd < (ssize_t) s->sources_size);
-        source = s->sources[fd];
-        assert(source->fd == fd);
-
-        r = process_source(source, arg_compress, arg_seal);
-        if (source->state == STATE_EOF) {
-                size_t remaining;
-
-                log_debug("EOF reached with source fd:%d (%s)",
-                          source->fd, source->name);
-
-                remaining = source_non_empty(source);
-                if (remaining > 0)
-                        log_notice("Premature EOF. %zu bytes lost.", remaining);
-                remove_source(s, source->fd);
-                log_debug("%zu active sources remaining", s->active);
-                return 0;
-        } else if (r == -E2BIG) {
-                log_notice_errno(E2BIG, "Entry too big, skipped");
-                return 1;
-        } else if (r == -EAGAIN) {
-                return 0;
-        } else if (r < 0) {
-                log_debug_errno(r, "Closing connection: %m");
-                remove_source(server, fd);
-                return 0;
-        } else
-                return 1;
-}
-
-static int dispatch_raw_source_until_block(sd_event_source *event,
-                                           void *userdata) {
-        RemoteSource *source = userdata;
-        int r;
-
-        /* Make sure event stays around even if source is destroyed */
-        sd_event_source_ref(event);
-
-        r = handle_raw_source(event, source->fd, EPOLLIN, server);
-        if (r != 1)
-                /* No more data for now */
-                sd_event_source_set_enabled(event, SD_EVENT_OFF);
-
-        sd_event_source_unref(event);
-
-        return r;
-}
-
-static int dispatch_raw_source_event(sd_event_source *event,
-                                     int fd,
-                                     uint32_t revents,
-                                     void *userdata) {
-        RemoteSource *source = userdata;
-        int r;
-
-        assert(source->event);
-        assert(source->buffer_event);
-
-        r = handle_raw_source(event, fd, EPOLLIN, server);
-        if (r == 1)
-                /* Might have more data. We need to rerun the handler
-                 * until we are sure the buffer is exhausted. */
-                sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON);
-
-        return r;
-}
-
-static int dispatch_blocking_source_event(sd_event_source *event,
-                                          void *userdata) {
-        RemoteSource *source = userdata;
-
-        return handle_raw_source(event, source->fd, EPOLLIN, server);
-}
-
-static int accept_connection(const char* type, int fd,
-                             SocketAddress *addr, char **hostname) {
-        int fd2, r;
-
-        log_debug("Accepting new %s connection on fd:%d", type, fd);
-        fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
-        if (fd2 < 0)
-                return log_error_errno(errno, "accept() on fd:%d failed: %m", fd);
-
-        switch(socket_address_family(addr)) {
-        case AF_INET:
-        case AF_INET6: {
-                _cleanup_free_ char *a = NULL;
-                char *b;
-
-                r = socket_address_print(addr, &a);
-                if (r < 0) {
-                        log_error_errno(r, "socket_address_print(): %m");
-                        close(fd2);
-                        return r;
-                }
-
-                r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
-                if (r < 0) {
-                        close(fd2);
-                        return r;
-                }
-
-                log_debug("Accepted %s %s connection from %s",
-                          type,
-                          socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
-                          a);
-
-                *hostname = b;
-
-                return fd2;
-        };
-        default:
-                log_error("Rejected %s connection with unsupported family %d",
-                          type, socket_address_family(addr));
-                close(fd2);
-
-                return -EINVAL;
-        }
-}
-
-static int dispatch_raw_connection_event(sd_event_source *event,
-                                         int fd,
-                                         uint32_t revents,
-                                         void *userdata) {
-        RemoteServer *s = userdata;
-        int fd2;
-        SocketAddress addr = {
-                .size = sizeof(union sockaddr_union),
-                .type = SOCK_STREAM,
-        };
-        char *hostname = NULL;
-
-        fd2 = accept_connection("raw", fd, &addr, &hostname);
-        if (fd2 < 0)
-                return fd2;
-
-        return add_source(s, fd2, hostname, true);
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
-        [JOURNAL_WRITE_SPLIT_NONE] = "none",
-        [JOURNAL_WRITE_SPLIT_HOST] = "host",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
-static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
-                                journal_write_split_mode,
-                                JournalWriteSplitMode,
-                                "Failed to parse split mode setting");
-
-static int parse_config(void) {
-        const ConfigTableItem items[] = {
-                { "Remote",  "SplitMode",              config_parse_write_split_mode, 0, &arg_split_mode },
-                { "Remote",  "ServerKeyFile",          config_parse_path,             0, &arg_key        },
-                { "Remote",  "ServerCertificateFile",  config_parse_path,             0, &arg_cert       },
-                { "Remote",  "TrustedCertificateFile", config_parse_path,             0, &arg_trust      },
-                {}};
-
-        return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf",
-                                 CONF_DIRS_NULSTR("systemd/journal-remote.conf"),
-                                 "Remote\0", config_item_table_lookup, items,
-                                 false, NULL);
-}
-
-static void help(void) {
-        printf("%s [OPTIONS...] {FILE|-}...\n\n"
-               "Write external journal events to journal file(s).\n\n"
-               "  -h --help                 Show this help\n"
-               "     --version              Show package version\n"
-               "     --url=URL              Read events from systemd-journal-gatewayd at URL\n"
-               "     --getter=COMMAND       Read events from the output of COMMAND\n"
-               "     --listen-raw=ADDR      Listen for connections at ADDR\n"
-               "     --listen-http=ADDR     Listen for HTTP connections at ADDR\n"
-               "     --listen-https=ADDR    Listen for HTTPS connections at ADDR\n"
-               "  -o --output=FILE|DIR      Write output to FILE or DIR/external-*.journal\n"
-               "     --compress[=BOOL]      XZ-compress the output journal (default: yes)\n"
-               "     --seal[=BOOL]          Use event sealing (default: no)\n"
-               "     --key=FILENAME         SSL key in PEM format (default:\n"
-               "                            \"" PRIV_KEY_FILE "\")\n"
-               "     --cert=FILENAME        SSL certificate in PEM format (default:\n"
-               "                            \"" CERT_FILE "\")\n"
-               "     --trust=FILENAME|all   SSL CA certificate or disable checking (default:\n"
-               "                            \"" TRUST_FILE "\")\n"
-               "     --gnutls-log=CATEGORY...\n"
-               "                            Specify a list of gnutls logging categories\n"
-               "     --split-mode=none|host How many output files to create\n"
-               "\n"
-               "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
-               , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_URL,
-                ARG_LISTEN_RAW,
-                ARG_LISTEN_HTTP,
-                ARG_LISTEN_HTTPS,
-                ARG_GETTER,
-                ARG_SPLIT_MODE,
-                ARG_COMPRESS,
-                ARG_SEAL,
-                ARG_KEY,
-                ARG_CERT,
-                ARG_TRUST,
-                ARG_GNUTLS_LOG,
-        };
-
-        static const struct option options[] = {
-                { "help",         no_argument,       NULL, 'h'              },
-                { "version",      no_argument,       NULL, ARG_VERSION      },
-                { "url",          required_argument, NULL, ARG_URL          },
-                { "getter",       required_argument, NULL, ARG_GETTER       },
-                { "listen-raw",   required_argument, NULL, ARG_LISTEN_RAW   },
-                { "listen-http",  required_argument, NULL, ARG_LISTEN_HTTP  },
-                { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
-                { "output",       required_argument, NULL, 'o'              },
-                { "split-mode",   required_argument, NULL, ARG_SPLIT_MODE   },
-                { "compress",     optional_argument, NULL, ARG_COMPRESS     },
-                { "seal",         optional_argument, NULL, ARG_SEAL         },
-                { "key",          required_argument, NULL, ARG_KEY          },
-                { "cert",         required_argument, NULL, ARG_CERT         },
-                { "trust",        required_argument, NULL, ARG_TRUST        },
-                { "gnutls-log",   required_argument, NULL, ARG_GNUTLS_LOG   },
-                {}
-        };
-
-        int c, r;
-        bool type_a, type_b;
-
-        assert(argc >= 0);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
-                switch(c) {
-                case 'h':
-                        help();
-                        return 0 /* done */;
-
-                case ARG_VERSION:
-                        puts(PACKAGE_STRING);
-                        puts(SYSTEMD_FEATURES);
-                        return 0 /* done */;
-
-                case ARG_URL:
-                        if (arg_url) {
-                                log_error("cannot currently set more than one --url");
-                                return -EINVAL;
-                        }
-
-                        arg_url = optarg;
-                        break;
-
-                case ARG_GETTER:
-                        if (arg_getter) {
-                                log_error("cannot currently use --getter more than once");
-                                return -EINVAL;
-                        }
-
-                        arg_getter = optarg;
-                        break;
-
-                case ARG_LISTEN_RAW:
-                        if (arg_listen_raw) {
-                                log_error("cannot currently use --listen-raw more than once");
-                                return -EINVAL;
-                        }
-
-                        arg_listen_raw = optarg;
-                        break;
-
-                case ARG_LISTEN_HTTP:
-                        if (arg_listen_http || http_socket >= 0) {
-                                log_error("cannot currently use --listen-http more than once");
-                                return -EINVAL;
-                        }
-
-                        r = negative_fd(optarg);
-                        if (r >= 0)
-                                http_socket = r;
-                        else
-                                arg_listen_http = optarg;
-                        break;
-
-                case ARG_LISTEN_HTTPS:
-                        if (arg_listen_https || https_socket >= 0) {
-                                log_error("cannot currently use --listen-https more than once");
-                                return -EINVAL;
-                        }
-
-                        r = negative_fd(optarg);
-                        if (r >= 0)
-                                https_socket = r;
-                        else
-                                arg_listen_https = optarg;
-
-                        break;
-
-                case ARG_KEY:
-                        if (arg_key) {
-                                log_error("Key file specified twice");
-                                return -EINVAL;
-                        }
-
-                        arg_key = strdup(optarg);
-                        if (!arg_key)
-                                return log_oom();
-
-                        break;
-
-                case ARG_CERT:
-                        if (arg_cert) {
-                                log_error("Certificate file specified twice");
-                                return -EINVAL;
-                        }
-
-                        arg_cert = strdup(optarg);
-                        if (!arg_cert)
-                                return log_oom();
-
-                        break;
-
-                case ARG_TRUST:
-                        if (arg_trust || arg_trust_all) {
-                                log_error("Confusing trusted CA configuration");
-                                return -EINVAL;
-                        }
-
-                        if (streq(optarg, "all"))
-                                arg_trust_all = true;
-                        else {
-#ifdef HAVE_GNUTLS
-                                arg_trust = strdup(optarg);
-                                if (!arg_trust)
-                                        return log_oom();
-#else
-                                log_error("Option --trust is not available.");
-                                return -EINVAL;
-#endif
-                        }
-
-                        break;
-
-                case 'o':
-                        if (arg_output) {
-                                log_error("cannot use --output/-o more than once");
-                                return -EINVAL;
-                        }
-
-                        arg_output = optarg;
-                        break;
-
-                case ARG_SPLIT_MODE:
-                        arg_split_mode = journal_write_split_mode_from_string(optarg);
-                        if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
-                                log_error("Invalid split mode: %s", optarg);
-                                return -EINVAL;
-                        }
-                        break;
-
-                case ARG_COMPRESS:
-                        if (optarg) {
-                                r = parse_boolean(optarg);
-                                if (r < 0) {
-                                        log_error("Failed to parse --compress= parameter.");
-                                        return -EINVAL;
-                                }
-
-                                arg_compress = !!r;
-                        } else
-                                arg_compress = true;
-
-                        break;
-
-                case ARG_SEAL:
-                        if (optarg) {
-                                r = parse_boolean(optarg);
-                                if (r < 0) {
-                                        log_error("Failed to parse --seal= parameter.");
-                                        return -EINVAL;
-                                }
-
-                                arg_seal = !!r;
-                        } else
-                                arg_seal = true;
-
-                        break;
-
-                case ARG_GNUTLS_LOG: {
-#ifdef HAVE_GNUTLS
-                        const char *word, *state;
-                        size_t size;
-
-                        FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
-                                char *cat;
-
-                                cat = strndup(word, size);
-                                if (!cat)
-                                        return log_oom();
-
-                                if (strv_consume(&arg_gnutls_log, cat) < 0)
-                                        return log_oom();
-                        }
-                        break;
-#else
-                        log_error("Option --gnutls-log is not available.");
-                        return -EINVAL;
-#endif
-                }
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unknown option code.");
-                }
-
-        if (optind < argc)
-                arg_files = argv + optind;
-
-        type_a = arg_getter || !strv_isempty(arg_files);
-        type_b = arg_url
-                || arg_listen_raw
-                || arg_listen_http || arg_listen_https
-                || sd_listen_fds(false) > 0;
-        if (type_a && type_b) {
-                log_error("Cannot use file input or --getter with "
-                          "--arg-listen-... or socket activation.");
-                return -EINVAL;
-        }
-        if (type_a) {
-                if (!arg_output) {
-                        log_error("Option --output must be specified with file input or --getter.");
-                        return -EINVAL;
-                }
-
-                arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
-        }
-
-        if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE
-            && arg_output && is_dir(arg_output, true) > 0) {
-                log_error("For SplitMode=none, output must be a file.");
-                return -EINVAL;
-        }
-
-        if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
-            && arg_output && is_dir(arg_output, true) <= 0) {
-                log_error("For SplitMode=host, output must be a directory.");
-                return -EINVAL;
-        }
-
-        log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
-                  journal_write_split_mode_to_string(arg_split_mode),
-                  strna(arg_key),
-                  strna(arg_cert),
-                  strna(arg_trust));
-
-        return 1 /* work to do */;
-}
-
-static int load_certificates(char **key, char **cert, char **trust) {
-        int r;
-
-        r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Failed to read key from file '%s': %m",
-                                       arg_key ?: PRIV_KEY_FILE);
-
-        r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Failed to read certificate from file '%s': %m",
-                                       arg_cert ?: CERT_FILE);
-
-        if (arg_trust_all)
-                log_info("Certificate checking disabled.");
-        else {
-                r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
-                                               arg_trust ?: TRUST_FILE);
-        }
-
-        return 0;
-}
-
-int main(int argc, char **argv) {
-        RemoteServer s = {};
-        int r;
-        _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
-
-        log_show_color(true);
-        log_parse_environment();
-
-        r = parse_config();
-        if (r < 0)
-                return EXIT_FAILURE;
-
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-
-
-        if (arg_listen_http || arg_listen_https) {
-                r = setup_gnutls_logger(arg_gnutls_log);
-                if (r < 0)
-                        return EXIT_FAILURE;
-        }
-
-        if (arg_listen_https || https_socket >= 0)
-                if (load_certificates(&key, &cert, &trust) < 0)
-                        return EXIT_FAILURE;
-
-        if (remoteserver_init(&s, key, cert, trust) < 0)
-                return EXIT_FAILURE;
-
-        r = sd_event_set_watchdog(s.events, true);
-        if (r < 0)
-                log_error_errno(r, "Failed to enable watchdog: %m");
-        else
-                log_debug("Watchdog is %s.", r > 0 ? "enabled" : "disabled");
-
-        log_debug("%s running as pid "PID_FMT,
-                  program_invocation_short_name, getpid());
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing requests...");
-
-        while (s.active) {
-                r = sd_event_get_state(s.events);
-                if (r < 0)
-                        break;
-                if (r == SD_EVENT_FINISHED)
-                        break;
-
-                r = sd_event_run(s.events, -1);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to run event loop: %m");
-                        break;
-                }
-        }
-
-        sd_notifyf(false,
-                   "STOPPING=1\n"
-                   "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
-        log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
-
-        server_destroy(&s);
-
-        free(arg_key);
-        free(arg_cert);
-        free(arg_trust);
-
-        return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/src/journal-remote/journal-remote.conf.in b/src/journal-remote/journal-remote.conf.in
deleted file mode 100644 (file)
index 3e32f34..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-[Remote]
-# SplitMode=host
-# ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem
-# ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem
-# TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem
diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h
deleted file mode 100644 (file)
index 6c2ccb9..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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/>.
-***/
-
-#pragma once
-
-
-#include "sd-event.h"
-#include "hashmap.h"
-#include "microhttpd-util.h"
-
-#include "journal-remote-parse.h"
-#include "journal-remote-write.h"
-
-typedef struct MHDDaemonWrapper MHDDaemonWrapper;
-
-struct MHDDaemonWrapper {
-        uint64_t fd;
-        struct MHD_Daemon *daemon;
-
-        sd_event_source *event;
-};
-
-struct RemoteServer {
-        RemoteSource **sources;
-        size_t sources_size;
-        size_t active;
-
-        sd_event *events;
-        sd_event_source *sigterm_event, *sigint_event, *listen_event;
-
-        Hashmap *writers;
-        Writer *_single_writer;
-        uint64_t event_count;
-
-        bool check_trust;
-        Hashmap *daemons;
-};
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
deleted file mode 100644 (file)
index 5fd639a..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-#include <stdbool.h>
-
-#include <curl/curl.h>
-
-#include "util.h"
-#include "log.h"
-#include "utf8.h"
-#include "journal-upload.h"
-
-/**
- * Write up to size bytes to buf. Return negative on error, and number of
- * bytes written otherwise. The last case is a kind of an error too.
- */
-static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
-        int r;
-        size_t pos = 0;
-
-        assert(size <= SSIZE_MAX);
-
-        while (true) {
-
-                switch(u->entry_state) {
-                case ENTRY_CURSOR: {
-                        free(u->current_cursor);
-                        u->current_cursor = NULL;
-
-                        r = sd_journal_get_cursor(u->journal, &u->current_cursor);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get cursor: %m");
-
-                        r = snprintf(buf + pos, size - pos,
-                                     "__CURSOR=%s\n", u->current_cursor);
-                        if (pos + r > size)
-                                /* not enough space */
-                                return pos;
-
-                        u->entry_state ++;
-
-                        if (pos + r == size) {
-                                /* exactly one character short, but we don't need it */
-                                buf[size - 1] = '\n';
-                                return size;
-                        }
-
-                        pos += r;
-                }       /* fall through */
-
-                case ENTRY_REALTIME: {
-                        usec_t realtime;
-
-                        r = sd_journal_get_realtime_usec(u->journal, &realtime);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get realtime timestamp: %m");
-
-                        r = snprintf(buf + pos, size - pos,
-                                     "__REALTIME_TIMESTAMP="USEC_FMT"\n", realtime);
-                        if (r + pos > size)
-                                /* not enough space */
-                                return pos;
-
-                        u->entry_state ++;
-
-                        if (r + pos == size) {
-                                /* exactly one character short, but we don't need it */
-                                buf[size - 1] = '\n';
-                                return size;
-                        }
-
-                        pos += r;
-                }       /* fall through */
-
-                case ENTRY_MONOTONIC: {
-                        usec_t monotonic;
-                        sd_id128_t boot_id;
-
-                        r = sd_journal_get_monotonic_usec(u->journal, &monotonic, &boot_id);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get monotonic timestamp: %m");
-
-                        r = snprintf(buf + pos, size - pos,
-                                     "__MONOTONIC_TIMESTAMP="USEC_FMT"\n", monotonic);
-                        if (r + pos > size)
-                                /* not enough space */
-                                return pos;
-
-                        u->entry_state ++;
-
-                        if (r + pos == size) {
-                                /* exactly one character short, but we don't need it */
-                                buf[size - 1] = '\n';
-                                return size;
-                        }
-
-                        pos += r;
-                }       /* fall through */
-
-                case ENTRY_BOOT_ID: {
-                        sd_id128_t boot_id;
-                        char sid[33];
-
-                        r = sd_journal_get_monotonic_usec(u->journal, NULL, &boot_id);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get monotonic timestamp: %m");
-
-                        r = snprintf(buf + pos, size - pos,
-                                     "_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid));
-                        if (r + pos > size)
-                                /* not enough space */
-                                return pos;
-
-                        u->entry_state ++;
-
-                        if (r + pos == size) {
-                                /* exactly one character short, but we don't need it */
-                                buf[size - 1] = '\n';
-                                return size;
-                        }
-
-                        pos += r;
-                }       /* fall through */
-
-                case ENTRY_NEW_FIELD: {
-                        u->field_pos = 0;
-
-                        r = sd_journal_enumerate_data(u->journal,
-                                                      &u->field_data,
-                                                      &u->field_length);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to move to next field in entry: %m");
-                        else if (r == 0) {
-                                u->entry_state = ENTRY_OUTRO;
-                                continue;
-                        }
-
-                        if (!utf8_is_printable_newline(u->field_data,
-                                                       u->field_length, false)) {
-                                u->entry_state = ENTRY_BINARY_FIELD_START;
-                                continue;
-                        }
-
-                        u->entry_state ++;
-                }       /* fall through */
-
-                case ENTRY_TEXT_FIELD:
-                case ENTRY_BINARY_FIELD: {
-                        bool done;
-                        size_t tocopy;
-
-                        done = size - pos > u->field_length - u->field_pos;
-                        if (done)
-                                tocopy = u->field_length - u->field_pos;
-                        else
-                                tocopy = size - pos;
-
-                        memcpy(buf + pos,
-                               (char*) u->field_data + u->field_pos,
-                               tocopy);
-
-                        if (done) {
-                                buf[pos + tocopy] = '\n';
-                                pos += tocopy + 1;
-                                u->entry_state = ENTRY_NEW_FIELD;
-                                continue;
-                        } else {
-                                u->field_pos += tocopy;
-                                return size;
-                        }
-                }
-
-                case ENTRY_BINARY_FIELD_START: {
-                        const char *c;
-                        size_t len;
-
-                        c = memchr(u->field_data, '=', u->field_length);
-                        if (!c || c == u->field_data) {
-                                log_error("Invalid field.");
-                                return -EINVAL;
-                        }
-
-                        len = c - (const char*)u->field_data;
-
-                        /* need space for label + '\n' */
-                        if (size - pos < len + 1)
-                                return pos;
-
-                        memcpy(buf + pos, u->field_data, len);
-                        buf[pos + len] = '\n';
-                        pos += len + 1;
-
-                        u->field_pos = len + 1;
-                        u->entry_state ++;
-                }       /* fall through */
-
-                case ENTRY_BINARY_FIELD_SIZE: {
-                        uint64_t le64;
-
-                        /* need space for uint64_t */
-                        if (size - pos < 8)
-                                return pos;
-
-                        le64 = htole64(u->field_length - u->field_pos);
-                        memcpy(buf + pos, &le64, 8);
-                        pos += 8;
-
-                        u->entry_state ++;
-                        continue;
-                }
-
-                case ENTRY_OUTRO:
-                        /* need space for '\n' */
-                        if (size - pos < 1)
-                                return pos;
-
-                        buf[pos++] = '\n';
-                        u->entry_state ++;
-                        u->entries_sent ++;
-
-                        return pos;
-
-                default:
-                        assert_not_reached("WTF?");
-                }
-        }
-        assert_not_reached("WTF?");
-}
-
-static size_t journal_input_callback(void *buf, size_t size, size_t nmemb, void *userp) {
-        Uploader *u = userp;
-        int r;
-        sd_journal *j;
-        size_t filled = 0;
-        ssize_t w;
-
-        assert(u);
-        assert(nmemb <= SSIZE_MAX / size);
-
-        j = u->journal;
-
-        while (j && filled < size * nmemb) {
-                if (u->entry_state == ENTRY_DONE) {
-                        r = sd_journal_next(j);
-                        if (r < 0) {
-                                log_error_errno(r, "Failed to move to next entry in journal: %m");
-                                return CURL_READFUNC_ABORT;
-                        } else if (r == 0) {
-                                if (u->input_event)
-                                        log_debug("No more entries, waiting for journal.");
-                                else {
-                                        log_info("No more entries, closing journal.");
-                                        close_journal_input(u);
-                                }
-
-                                u->uploading = false;
-
-                                break;
-                        }
-
-                        u->entry_state = ENTRY_CURSOR;
-                }
-
-                w = write_entry((char*)buf + filled, size * nmemb - filled, u);
-                if (w < 0)
-                        return CURL_READFUNC_ABORT;
-                filled += w;
-
-                if (filled == 0) {
-                        log_error("Buffer space is too small to write entry.");
-                        return CURL_READFUNC_ABORT;
-                } else if (u->entry_state != ENTRY_DONE)
-                        /* This means that all available space was used up */
-                        break;
-
-                log_debug("Entry %zu (%s) has been uploaded.",
-                          u->entries_sent, u->current_cursor);
-        }
-
-        return filled;
-}
-
-void close_journal_input(Uploader *u) {
-        assert(u);
-
-        if (u->journal) {
-                log_debug("Closing journal input.");
-
-                sd_journal_close(u->journal);
-                u->journal = NULL;
-        }
-        u->timeout = 0;
-}
-
-static int process_journal_input(Uploader *u, int skip) {
-        int r;
-
-        r = sd_journal_next_skip(u->journal, skip);
-        if (r < 0)
-                return log_error_errno(r, "Failed to skip to next entry: %m");
-        else if (r < skip)
-                return 0;
-
-        /* have data */
-        u->entry_state = ENTRY_CURSOR;
-        return start_upload(u, journal_input_callback, u);
-}
-
-int check_journal_input(Uploader *u) {
-        if (u->input_event) {
-                int r;
-
-                r = sd_journal_process(u->journal);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to process journal: %m");
-                        close_journal_input(u);
-                        return r;
-                }
-
-                if (r == SD_JOURNAL_NOP)
-                        return 0;
-        }
-
-        return process_journal_input(u, 1);
-}
-
-static int dispatch_journal_input(sd_event_source *event,
-                                  int fd,
-                                  uint32_t revents,
-                                  void *userp) {
-        Uploader *u = userp;
-
-        assert(u);
-
-        if (u->uploading) {
-                log_warning("dispatch_journal_input called when uploading, ignoring.");
-                return 0;
-        }
-
-        log_debug("Detected journal input, checking for new data.");
-        return check_journal_input(u);
-}
-
-int open_journal_for_upload(Uploader *u,
-                            sd_journal *j,
-                            const char *cursor,
-                            bool after_cursor,
-                            bool follow) {
-        int fd, r, events;
-
-        u->journal = j;
-
-        sd_journal_set_data_threshold(j, 0);
-
-        if (follow) {
-                fd = sd_journal_get_fd(j);
-                if (fd < 0)
-                        return log_error_errno(fd, "sd_journal_get_fd failed: %m");
-
-                events = sd_journal_get_events(j);
-
-                r = sd_journal_reliable_fd(j);
-                assert(r >= 0);
-                if (r > 0)
-                        u->timeout = -1;
-                else
-                        u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT;
-
-                r = sd_event_add_io(u->events, &u->input_event,
-                                    fd, events, dispatch_journal_input, u);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to register input event: %m");
-
-                log_debug("Listening for journal events on fd:%d, timeout %d",
-                          fd, u->timeout == (uint64_t) -1 ? -1 : (int) u->timeout);
-        } else
-                log_debug("Not listening for journal events.");
-
-        if (cursor) {
-                r = sd_journal_seek_cursor(j, cursor);
-                if (r < 0) {
-                        return log_error_errno(r, "Failed to seek to cursor %s: %m",
-                                               cursor);
-                }
-        }
-
-        return process_journal_input(u, 1 + !!after_cursor);
-}
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
deleted file mode 100644 (file)
index 75bb434..0000000
+++ /dev/null
@@ -1,871 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 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 <stdio.h>
-#include <curl/curl.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <getopt.h>
-
-#include "sd-daemon.h"
-#include "log.h"
-#include "util.h"
-#include "build.h"
-#include "fileio.h"
-#include "mkdir.h"
-#include "conf-parser.h"
-#include "sigbus.h"
-#include "journal-upload.h"
-
-#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem"
-#define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-upload.pem"
-#define TRUST_FILE    CERTIFICATE_ROOT "/ca/trusted.pem"
-#define DEFAULT_PORT  19532
-
-static const char* arg_url = NULL;
-static const char *arg_key = NULL;
-static const char *arg_cert = NULL;
-static const char *arg_trust = NULL;
-static const char *arg_directory = NULL;
-static char **arg_file = NULL;
-static const char *arg_cursor = NULL;
-static bool arg_after_cursor = false;
-static int arg_journal_type = 0;
-static const char *arg_machine = NULL;
-static bool arg_merge = false;
-static int arg_follow = -1;
-static const char *arg_save_state = NULL;
-
-static void close_fd_input(Uploader *u);
-
-#define SERVER_ANSWER_KEEP 2048
-
-#define STATE_FILE "/var/lib/systemd/journal-upload/state"
-
-#define easy_setopt(curl, opt, value, level, cmd)                       \
-        do {                                                            \
-                code = curl_easy_setopt(curl, opt, value);              \
-                if (code) {                                             \
-                        log_full(level,                                 \
-                                 "curl_easy_setopt " #opt " failed: %s", \
-                                  curl_easy_strerror(code));            \
-                        cmd;                                            \
-                }                                                       \
-        } while(0)
-
-static size_t output_callback(char *buf,
-                              size_t size,
-                              size_t nmemb,
-                              void *userp) {
-        Uploader *u = userp;
-
-        assert(u);
-
-        log_debug("The server answers (%zu bytes): %.*s",
-                  size*nmemb, (int)(size*nmemb), buf);
-
-        if (nmemb && !u->answer) {
-                u->answer = strndup(buf, size*nmemb);
-                if (!u->answer)
-                        log_warning_errno(ENOMEM, "Failed to store server answer (%zu bytes): %m",
-                                          size*nmemb);
-        }
-
-        return size * nmemb;
-}
-
-static int check_cursor_updating(Uploader *u) {
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        int r;
-
-        if (!u->state_file)
-                return 0;
-
-        r = mkdir_parents(u->state_file, 0755);
-        if (r < 0)
-                return log_error_errno(r, "Cannot create parent directory of state file %s: %m",
-                                       u->state_file);
-
-        r = fopen_temporary(u->state_file, &f, &temp_path);
-        if (r < 0)
-                return log_error_errno(r, "Cannot save state to %s: %m",
-                                       u->state_file);
-        unlink(temp_path);
-
-        return 0;
-}
-
-static int update_cursor_state(Uploader *u) {
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        int r;
-
-        if (!u->state_file || !u->last_cursor)
-                return 0;
-
-        r = fopen_temporary(u->state_file, &f, &temp_path);
-        if (r < 0)
-                goto finish;
-
-        fprintf(f,
-                "# This is private data. Do not parse.\n"
-                "LAST_CURSOR=%s\n",
-                u->last_cursor);
-
-        fflush(f);
-
-        if (ferror(f) || rename(temp_path, u->state_file) < 0) {
-                r = -errno;
-                unlink(u->state_file);
-                unlink(temp_path);
-        }
-
-finish:
-        if (r < 0)
-                log_error_errno(r, "Failed to save state %s: %m", u->state_file);
-
-        return r;
-}
-
-static int load_cursor_state(Uploader *u) {
-        int r;
-
-        if (!u->state_file)
-                return 0;
-
-        r = parse_env_file(u->state_file, NEWLINE,
-                           "LAST_CURSOR",  &u->last_cursor,
-                           NULL);
-
-        if (r == -ENOENT)
-                log_debug("State file %s is not present.", u->state_file);
-        else if (r < 0)
-                return log_error_errno(r, "Failed to read state file %s: %m",
-                                       u->state_file);
-        else
-                log_debug("Last cursor was %s", u->last_cursor);
-
-        return 0;
-}
-
-
-
-int start_upload(Uploader *u,
-                 size_t (*input_callback)(void *ptr,
-                                          size_t size,
-                                          size_t nmemb,
-                                          void *userdata),
-                 void *data) {
-        CURLcode code;
-
-        assert(u);
-        assert(input_callback);
-
-        if (!u->header) {
-                struct curl_slist *h;
-
-                h = curl_slist_append(NULL, "Content-Type: application/vnd.fdo.journal");
-                if (!h)
-                        return log_oom();
-
-                h = curl_slist_append(h, "Transfer-Encoding: chunked");
-                if (!h) {
-                        curl_slist_free_all(h);
-                        return log_oom();
-                }
-
-                h = curl_slist_append(h, "Accept: text/plain");
-                if (!h) {
-                        curl_slist_free_all(h);
-                        return log_oom();
-                }
-
-                u->header = h;
-        }
-
-        if (!u->easy) {
-                CURL *curl;
-
-                curl = curl_easy_init();
-                if (!curl) {
-                        log_error("Call to curl_easy_init failed.");
-                        return -ENOSR;
-                }
-
-                /* tell it to POST to the URL */
-                easy_setopt(curl, CURLOPT_POST, 1L,
-                            LOG_ERR, return -EXFULL);
-
-                easy_setopt(curl, CURLOPT_ERRORBUFFER, u->error,
-                            LOG_ERR, return -EXFULL);
-
-                /* set where to write to */
-                easy_setopt(curl, CURLOPT_WRITEFUNCTION, output_callback,
-                            LOG_ERR, return -EXFULL);
-
-                easy_setopt(curl, CURLOPT_WRITEDATA, data,
-                            LOG_ERR, return -EXFULL);
-
-                /* set where to read from */
-                easy_setopt(curl, CURLOPT_READFUNCTION, input_callback,
-                            LOG_ERR, return -EXFULL);
-
-                easy_setopt(curl, CURLOPT_READDATA, data,
-                            LOG_ERR, return -EXFULL);
-
-                /* use our special own mime type and chunked transfer */
-                easy_setopt(curl, CURLOPT_HTTPHEADER, u->header,
-                            LOG_ERR, return -EXFULL);
-
-                if (_unlikely_(log_get_max_level() >= LOG_DEBUG))
-                        /* enable verbose for easier tracing */
-                        easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, );
-
-                easy_setopt(curl, CURLOPT_USERAGENT,
-                            "systemd-journal-upload " PACKAGE_STRING,
-                            LOG_WARNING, );
-
-                if (arg_key || startswith(u->url, "https://")) {
-                        easy_setopt(curl, CURLOPT_SSLKEY, arg_key ?: PRIV_KEY_FILE,
-                                    LOG_ERR, return -EXFULL);
-                        easy_setopt(curl, CURLOPT_SSLCERT, arg_cert ?: CERT_FILE,
-                                    LOG_ERR, return -EXFULL);
-                }
-
-                if (streq_ptr(arg_trust, "all"))
-                        easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0,
-                                    LOG_ERR, return -EUCLEAN);
-                else if (arg_trust || startswith(u->url, "https://"))
-                        easy_setopt(curl, CURLOPT_CAINFO, arg_trust ?: TRUST_FILE,
-                                    LOG_ERR, return -EXFULL);
-
-                if (arg_key || arg_trust)
-                        easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1,
-                                    LOG_WARNING, );
-
-                u->easy = curl;
-        } else {
-                /* truncate the potential old error message */
-                u->error[0] = '\0';
-
-                free(u->answer);
-                u->answer = 0;
-        }
-
-        /* upload to this place */
-        code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url);
-        if (code) {
-                log_error("curl_easy_setopt CURLOPT_URL failed: %s",
-                          curl_easy_strerror(code));
-                return -EXFULL;
-        }
-
-        u->uploading = true;
-
-        return 0;
-}
-
-static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) {
-        Uploader *u = userp;
-
-        ssize_t r;
-
-        assert(u);
-        assert(nmemb <= SSIZE_MAX / size);
-
-        if (u->input < 0)
-                return 0;
-
-        r = read(u->input, buf, size * nmemb);
-        log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, r);
-
-        if (r > 0)
-                return r;
-
-        u->uploading = false;
-        if (r == 0) {
-                log_debug("Reached EOF");
-                close_fd_input(u);
-                return 0;
-        } else {
-                log_error_errno(errno, "Aborting transfer after read error on input: %m.");
-                return CURL_READFUNC_ABORT;
-        }
-}
-
-static void close_fd_input(Uploader *u) {
-        assert(u);
-
-        if (u->input >= 0)
-                close_nointr(u->input);
-        u->input = -1;
-        u->timeout = 0;
-}
-
-static int dispatch_fd_input(sd_event_source *event,
-                             int fd,
-                             uint32_t revents,
-                             void *userp) {
-        Uploader *u = userp;
-
-        assert(u);
-        assert(fd >= 0);
-
-        if (revents & EPOLLHUP) {
-                log_debug("Received HUP");
-                close_fd_input(u);
-                return 0;
-        }
-
-        if (!(revents & EPOLLIN)) {
-                log_warning("Unexpected poll event %"PRIu32".", revents);
-                return -EINVAL;
-        }
-
-        if (u->uploading) {
-                log_warning("dispatch_fd_input called when uploading, ignoring.");
-                return 0;
-        }
-
-        return start_upload(u, fd_input_callback, u);
-}
-
-static int open_file_for_upload(Uploader *u, const char *filename) {
-        int fd, r = 0;
-
-        if (streq(filename, "-"))
-                fd = STDIN_FILENO;
-        else {
-                fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
-                if (fd < 0)
-                        return log_error_errno(errno, "Failed to open %s: %m", filename);
-        }
-
-        u->input = fd;
-
-        if (arg_follow) {
-                r = sd_event_add_io(u->events, &u->input_event,
-                                    fd, EPOLLIN, dispatch_fd_input, u);
-                if (r < 0) {
-                        if (r != -EPERM || arg_follow > 0)
-                                return log_error_errno(r, "Failed to register input event: %m");
-
-                        /* Normal files should just be consumed without polling. */
-                        r = start_upload(u, fd_input_callback, u);
-                }
-        }
-
-        return r;
-}
-
-static int dispatch_sigterm(sd_event_source *event,
-                            const struct signalfd_siginfo *si,
-                            void *userdata) {
-        Uploader *u = userdata;
-
-        assert(u);
-
-        log_received_signal(LOG_INFO, si);
-
-        close_fd_input(u);
-        close_journal_input(u);
-
-        sd_event_exit(u->events, 0);
-        return 0;
-}
-
-static int setup_signals(Uploader *u) {
-        sigset_t mask;
-        int r;
-
-        assert(u);
-
-        assert_se(sigemptyset(&mask) == 0);
-        sigset_add_many(&mask, SIGINT, SIGTERM, -1);
-        assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
-        r = sd_event_add_signal(u->events, &u->sigterm_event, SIGTERM, dispatch_sigterm, u);
-        if (r < 0)
-                return r;
-
-        r = sd_event_add_signal(u->events, &u->sigint_event, SIGINT, dispatch_sigterm, u);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
-static int setup_uploader(Uploader *u, const char *url, const char *state_file) {
-        int r;
-        const char *host, *proto = "";
-
-        assert(u);
-        assert(url);
-
-        memzero(u, sizeof(Uploader));
-        u->input = -1;
-
-        if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) {
-                host = url;
-                proto = "https://";
-        }
-
-        if (strchr(host, ':'))
-                u->url = strjoin(proto, url, "/upload", NULL);
-        else {
-                char *t;
-                size_t x;
-
-                t = strdupa(url);
-                x = strlen(t);
-                while (x > 0 && t[x - 1] == '/')
-                        t[x - 1] = '\0';
-
-                u->url = strjoin(proto, t, ":" STRINGIFY(DEFAULT_PORT), "/upload", NULL);
-        }
-        if (!u->url)
-                return log_oom();
-
-        u->state_file = state_file;
-
-        r = sd_event_default(&u->events);
-        if (r < 0)
-                return log_error_errno(r, "sd_event_default failed: %m");
-
-        r = setup_signals(u);
-        if (r < 0)
-                return log_error_errno(r, "Failed to set up signals: %m");
-
-        return load_cursor_state(u);
-}
-
-static void destroy_uploader(Uploader *u) {
-        assert(u);
-
-        curl_easy_cleanup(u->easy);
-        curl_slist_free_all(u->header);
-        free(u->answer);
-
-        free(u->last_cursor);
-        free(u->current_cursor);
-
-        free(u->url);
-
-        u->input_event = sd_event_source_unref(u->input_event);
-
-        close_fd_input(u);
-        close_journal_input(u);
-
-        sd_event_source_unref(u->sigterm_event);
-        sd_event_source_unref(u->sigint_event);
-        sd_event_unref(u->events);
-}
-
-static int perform_upload(Uploader *u) {
-        CURLcode code;
-        long status;
-
-        assert(u);
-
-        code = curl_easy_perform(u->easy);
-        if (code) {
-                if (u->error[0])
-                        log_error("Upload to %s failed: %.*s",
-                                  u->url, (int) sizeof(u->error), u->error);
-                else
-                        log_error("Upload to %s failed: %s",
-                                  u->url, curl_easy_strerror(code));
-                return -EIO;
-        }
-
-        code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status);
-        if (code) {
-                log_error("Failed to retrieve response code: %s",
-                          curl_easy_strerror(code));
-                return -EUCLEAN;
-        }
-
-        if (status >= 300) {
-                log_error("Upload to %s failed with code %ld: %s",
-                          u->url, status, strna(u->answer));
-                return -EIO;
-        } else if (status < 200) {
-                log_error("Upload to %s finished with unexpected code %ld: %s",
-                          u->url, status, strna(u->answer));
-                return -EIO;
-        } else
-                log_debug("Upload finished successfully with code %ld: %s",
-                          status, strna(u->answer));
-
-        free(u->last_cursor);
-        u->last_cursor = u->current_cursor;
-        u->current_cursor = NULL;
-
-        return update_cursor_state(u);
-}
-
-static int parse_config(void) {
-        const ConfigTableItem items[] = {
-                { "Upload",  "URL",                    config_parse_string, 0, &arg_url    },
-                { "Upload",  "ServerKeyFile",          config_parse_path,   0, &arg_key    },
-                { "Upload",  "ServerCertificateFile",  config_parse_path,   0, &arg_cert   },
-                { "Upload",  "TrustedCertificateFile", config_parse_path,   0, &arg_trust  },
-                {}};
-
-        return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf",
-                                 CONF_DIRS_NULSTR("systemd/journal-upload.conf"),
-                                 "Upload\0", config_item_table_lookup, items,
-                                 false, NULL);
-}
-
-static void help(void) {
-        printf("%s -u URL {FILE|-}...\n\n"
-               "Upload journal events to a remote server.\n\n"
-               "  -h --help                 Show this help\n"
-               "     --version              Show package version\n"
-               "  -u --url=URL              Upload to this address (default port "
-                                            STRINGIFY(DEFAULT_PORT) ")\n"
-               "     --key=FILENAME         Specify key in PEM format (default:\n"
-               "                            \"" PRIV_KEY_FILE "\")\n"
-               "     --cert=FILENAME        Specify certificate in PEM format (default:\n"
-               "                            \"" CERT_FILE "\")\n"
-               "     --trust=FILENAME|all   Specify CA certificate or disable checking (default:\n"
-               "                            \"" TRUST_FILE "\")\n"
-               "     --system               Use the system journal\n"
-               "     --user                 Use the user journal for the current user\n"
-               "  -m --merge                Use  all available journals\n"
-               "  -M --machine=CONTAINER    Operate on local container\n"
-               "  -D --directory=PATH       Use journal files from directory\n"
-               "     --file=PATH            Use this journal file\n"
-               "     --cursor=CURSOR        Start at the specified cursor\n"
-               "     --after-cursor=CURSOR  Start after the specified cursor\n"
-               "     --follow[=BOOL]        Do [not] wait for input\n"
-               "     --save-state[=FILE]    Save uploaded cursors (default \n"
-               "                            " STATE_FILE ")\n"
-               "  -h --help                 Show this help and exit\n"
-               "     --version              Print version string and exit\n"
-               , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_KEY,
-                ARG_CERT,
-                ARG_TRUST,
-                ARG_USER,
-                ARG_SYSTEM,
-                ARG_FILE,
-                ARG_CURSOR,
-                ARG_AFTER_CURSOR,
-                ARG_FOLLOW,
-                ARG_SAVE_STATE,
-        };
-
-        static const struct option options[] = {
-                { "help",         no_argument,       NULL, 'h'                },
-                { "version",      no_argument,       NULL, ARG_VERSION        },
-                { "url",          required_argument, NULL, 'u'                },
-                { "key",          required_argument, NULL, ARG_KEY            },
-                { "cert",         required_argument, NULL, ARG_CERT           },
-                { "trust",        required_argument, NULL, ARG_TRUST          },
-                { "system",       no_argument,       NULL, ARG_SYSTEM         },
-                { "user",         no_argument,       NULL, ARG_USER           },
-                { "merge",        no_argument,       NULL, 'm'                },
-                { "machine",      required_argument, NULL, 'M'                },
-                { "directory",    required_argument, NULL, 'D'                },
-                { "file",         required_argument, NULL, ARG_FILE           },
-                { "cursor",       required_argument, NULL, ARG_CURSOR         },
-                { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR   },
-                { "follow",       optional_argument, NULL, ARG_FOLLOW         },
-                { "save-state",   optional_argument, NULL, ARG_SAVE_STATE     },
-                {}
-        };
-
-        int c, r;
-
-        assert(argc >= 0);
-        assert(argv);
-
-        opterr = 0;
-
-        while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0)
-                switch(c) {
-                case 'h':
-                        help();
-                        return 0 /* done */;
-
-                case ARG_VERSION:
-                        puts(PACKAGE_STRING);
-                        puts(SYSTEMD_FEATURES);
-                        return 0 /* done */;
-
-                case 'u':
-                        if (arg_url) {
-                                log_error("cannot use more than one --url");
-                                return -EINVAL;
-                        }
-
-                        arg_url = optarg;
-                        break;
-
-                case ARG_KEY:
-                        if (arg_key) {
-                                log_error("cannot use more than one --key");
-                                return -EINVAL;
-                        }
-
-                        arg_key = optarg;
-                        break;
-
-                case ARG_CERT:
-                        if (arg_cert) {
-                                log_error("cannot use more than one --cert");
-                                return -EINVAL;
-                        }
-
-                        arg_cert = optarg;
-                        break;
-
-                case ARG_TRUST:
-                        if (arg_trust) {
-                                log_error("cannot use more than one --trust");
-                                return -EINVAL;
-                        }
-
-                        arg_trust = optarg;
-                        break;
-
-                case ARG_SYSTEM:
-                        arg_journal_type |= SD_JOURNAL_SYSTEM;
-                        break;
-
-                case ARG_USER:
-                        arg_journal_type |= SD_JOURNAL_CURRENT_USER;
-                        break;
-
-                case 'm':
-                        arg_merge = true;
-                        break;
-
-                case 'M':
-                        if (arg_machine) {
-                                log_error("cannot use more than one --machine/-M");
-                                return -EINVAL;
-                        }
-
-                        arg_machine = optarg;
-                        break;
-
-                case 'D':
-                        if (arg_directory) {
-                                log_error("cannot use more than one --directory/-D");
-                                return -EINVAL;
-                        }
-
-                        arg_directory = optarg;
-                        break;
-
-                case ARG_FILE:
-                        r = glob_extend(&arg_file, optarg);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to add paths: %m");
-                        break;
-
-                case ARG_CURSOR:
-                        if (arg_cursor) {
-                                log_error("cannot use more than one --cursor/--after-cursor");
-                                return -EINVAL;
-                        }
-
-                        arg_cursor = optarg;
-                        break;
-
-                case ARG_AFTER_CURSOR:
-                        if (arg_cursor) {
-                                log_error("cannot use more than one --cursor/--after-cursor");
-                                return -EINVAL;
-                        }
-
-                        arg_cursor = optarg;
-                        arg_after_cursor = true;
-                        break;
-
-                case ARG_FOLLOW:
-                        if (optarg) {
-                                r = parse_boolean(optarg);
-                                if (r < 0) {
-                                        log_error("Failed to parse --follow= parameter.");
-                                        return -EINVAL;
-                                }
-
-                                arg_follow = !!r;
-                        } else
-                                arg_follow = true;
-
-                        break;
-
-                case ARG_SAVE_STATE:
-                        arg_save_state = optarg ?: STATE_FILE;
-                        break;
-
-                case '?':
-                        log_error("Unknown option %s.", argv[optind-1]);
-                        return -EINVAL;
-
-                case ':':
-                        log_error("Missing argument to %s.", argv[optind-1]);
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option code.");
-                }
-
-        if (!arg_url) {
-                log_error("Required --url/-u option missing.");
-                return -EINVAL;
-        }
-
-        if (!!arg_key != !!arg_cert) {
-                log_error("Options --key and --cert must be used together.");
-                return -EINVAL;
-        }
-
-        if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) {
-                log_error("Input arguments make no sense with journal input.");
-                return -EINVAL;
-        }
-
-        return 1;
-}
-
-static int open_journal(sd_journal **j) {
-        int r;
-
-        if (arg_directory)
-                r = sd_journal_open_directory(j, arg_directory, arg_journal_type);
-        else if (arg_file)
-                r = sd_journal_open_files(j, (const char**) arg_file, 0);
-        else if (arg_machine)
-                r = sd_journal_open_container(j, arg_machine, 0);
-        else
-                r = sd_journal_open(j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
-        if (r < 0)
-                log_error_errno(r, "Failed to open %s: %m",
-                                arg_directory ? arg_directory : arg_file ? "files" : "journal");
-        return r;
-}
-
-int main(int argc, char **argv) {
-        Uploader u;
-        int r;
-        bool use_journal;
-
-        log_show_color(true);
-        log_parse_environment();
-
-        r = parse_config();
-        if (r < 0)
-                goto finish;
-
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                goto finish;
-
-        sigbus_install();
-
-        r = setup_uploader(&u, arg_url, arg_save_state);
-        if (r < 0)
-                goto cleanup;
-
-        sd_event_set_watchdog(u.events, true);
-
-        r = check_cursor_updating(&u);
-        if (r < 0)
-                goto cleanup;
-
-        log_debug("%s running as pid "PID_FMT,
-                  program_invocation_short_name, getpid());
-
-        use_journal = optind >= argc;
-        if (use_journal) {
-                sd_journal *j;
-                r = open_journal(&j);
-                if (r < 0)
-                        goto finish;
-                r = open_journal_for_upload(&u, j,
-                                            arg_cursor ?: u.last_cursor,
-                                            arg_cursor ? arg_after_cursor : true,
-                                            !!arg_follow);
-                if (r < 0)
-                        goto finish;
-        }
-
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing input...");
-
-        while (true) {
-                r = sd_event_get_state(u.events);
-                if (r < 0)
-                        break;
-                if (r == SD_EVENT_FINISHED)
-                        break;
-
-                if (use_journal) {
-                        if (!u.journal)
-                                break;
-
-                        r = check_journal_input(&u);
-                } else if (u.input < 0 && !use_journal) {
-                        if (optind >= argc)
-                                break;
-
-                        log_debug("Using %s as input.", argv[optind]);
-                        r = open_file_for_upload(&u, argv[optind++]);
-                }
-                if (r < 0)
-                        goto cleanup;
-
-                if (u.uploading) {
-                        r = perform_upload(&u);
-                        if (r < 0)
-                                break;
-                }
-
-                r = sd_event_run(u.events, u.timeout);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to run event loop: %m");
-                        break;
-                }
-        }
-
-cleanup:
-        sd_notify(false,
-                  "STOPPING=1\n"
-                  "STATUS=Shutting down...");
-
-        destroy_uploader(&u);
-
-finish:
-        return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/src/journal-remote/journal-upload.conf.in b/src/journal-remote/journal-upload.conf.in
deleted file mode 100644 (file)
index c567068..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-[Upload]
-# URL=
-# ServerKeyFile=@CERTIFICATEROOT@/private/journal-upload.pem
-# ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-upload.pem
-# TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem
diff --git a/src/journal-remote/journal-upload.h b/src/journal-remote/journal-upload.h
deleted file mode 100644 (file)
index 3b46fa8..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#pragma once
-
-#include <inttypes.h>
-
-#include "sd-journal.h"
-#include "sd-event.h"
-
-typedef enum {
-        ENTRY_CURSOR = 0,           /* Nothing actually written yet. */
-        ENTRY_REALTIME,
-        ENTRY_MONOTONIC,
-        ENTRY_BOOT_ID,
-        ENTRY_NEW_FIELD,            /* In between fields. */
-        ENTRY_TEXT_FIELD,           /* In the middle of a text field. */
-        ENTRY_BINARY_FIELD_START,   /* Writing the name of a binary field. */
-        ENTRY_BINARY_FIELD_SIZE,    /* Writing the size of a binary field. */
-        ENTRY_BINARY_FIELD,         /* In the middle of a binary field. */
-        ENTRY_OUTRO,                /* Writing '\n' */
-        ENTRY_DONE,                 /* Need to move to a new field. */
-} entry_state;
-
-typedef struct Uploader {
-        sd_event *events;
-        sd_event_source *sigint_event, *sigterm_event;
-
-        char *url;
-        CURL *easy;
-        bool uploading;
-        char error[CURL_ERROR_SIZE];
-        struct curl_slist *header;
-        char *answer;
-
-        sd_event_source *input_event;
-        uint64_t timeout;
-
-        /* fd stuff */
-        int input;
-
-        /* journal stuff */
-        sd_journal* journal;
-
-        entry_state entry_state;
-        const void *field_data;
-        size_t field_pos, field_length;
-
-        /* general metrics */
-        const char *state_file;
-
-        size_t entries_sent;
-        char *last_cursor, *current_cursor;
-} Uploader;
-
-#define JOURNAL_UPLOAD_POLL_TIMEOUT (10 * USEC_PER_SEC)
-
-int start_upload(Uploader *u,
-                 size_t (*input_callback)(void *ptr,
-                                          size_t size,
-                                          size_t nmemb,
-                                          void *userdata),
-                 void *data);
-
-int open_journal_for_upload(Uploader *u,
-                            sd_journal *j,
-                            const char *cursor,
-                            bool after_cursor,
-                            bool follow);
-void close_journal_input(Uploader *u);
-int check_journal_input(Uploader *u);
diff --git a/src/journal-remote/log-generator.py b/src/journal-remote/log-generator.py
deleted file mode 100755 (executable)
index 9a8fb07..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/python
-from __future__ import print_function
-import sys
-import argparse
-
-PARSER = argparse.ArgumentParser()
-PARSER.add_argument('n', type=int)
-PARSER.add_argument('--dots', action='store_true')
-OPTIONS = PARSER.parse_args()
-
-template = """\
-__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m={m:x};t=4fd05c
-__REALTIME_TIMESTAMP={realtime_ts}
-__MONOTONIC_TIMESTAMP={monotonic_ts}
-_BOOT_ID=f446871715504074bf7049ef0718fa93
-_TRANSPORT=syslog
-PRIORITY={priority}
-SYSLOG_FACILITY={facility}
-SYSLOG_IDENTIFIER=/USR/SBIN/CRON
-MESSAGE={message}
-_UID=0
-_GID=0
-_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
-_HOSTNAME=hostname
-SYSLOG_PID=25721
-_PID=25721
-_SOURCE_REALTIME_TIMESTAMP={source_realtime_ts}
-DATA={data}
-"""
-
-m  = 0x198603b12d7
-realtime_ts = 1404101101501873
-monotonic_ts = 1753961140951
-source_realtime_ts = 1404101101483516
-priority = 3
-facility = 6
-
-src = open('/dev/urandom', 'rb')
-
-bytes = 0
-
-for i in range(OPTIONS.n):
-    message = repr(src.read(2000))
-    data = repr(src.read(4000))
-
-    entry = template.format(m=m,
-                            realtime_ts=realtime_ts,
-                            monotonic_ts=monotonic_ts,
-                            source_realtime_ts=source_realtime_ts,
-                            priority=priority,
-                            facility=facility,
-                            message=message,
-                            data=data)
-    m += 1
-    realtime_ts += 1
-    monotonic_ts += 1
-    source_realtime_ts += 1
-
-    bytes += len(entry)
-
-    print(entry)
-
-    if OPTIONS.dots:
-        print('.', file=sys.stderr, end='', flush=True)
-
-if OPTIONS.dots:
-        print(file=sys.stderr)
-print('Wrote {} bytes'.format(bytes), file=sys.stderr)
diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c
deleted file mode 100644 (file)
index 8a11fba..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 Lennart Poettering
-  Copyright 2012 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 <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "microhttpd-util.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "strv.h"
-
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-#endif
-
-void microhttpd_logger(void *arg, const char *fmt, va_list ap) {
-        char *f;
-
-        f = strjoina("microhttpd: ", fmt);
-
-        DISABLE_WARNING_FORMAT_NONLITERAL;
-        log_internalv(LOG_INFO, 0, NULL, 0, NULL, f, ap);
-        REENABLE_WARNING;
-}
-
-
-static int mhd_respond_internal(struct MHD_Connection *connection,
-                                enum MHD_RequestTerminationCode code,
-                                char *buffer,
-                                size_t size,
-                                enum MHD_ResponseMemoryMode mode) {
-        struct MHD_Response *response;
-        int r;
-
-        assert(connection);
-
-        response = MHD_create_response_from_buffer(size, buffer, mode);
-        if (!response)
-                return MHD_NO;
-
-        log_debug("Queing response %u: %s", code, buffer);
-        MHD_add_response_header(response, "Content-Type", "text/plain");
-        r = MHD_queue_response(connection, code, response);
-        MHD_destroy_response(response);
-
-        return r;
-}
-
-int mhd_respond(struct MHD_Connection *connection,
-                enum MHD_RequestTerminationCode code,
-                const char *message) {
-
-        return mhd_respond_internal(connection, code,
-                                    (char*) message, strlen(message),
-                                    MHD_RESPMEM_PERSISTENT);
-}
-
-int mhd_respond_oom(struct MHD_Connection *connection) {
-        return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE,  "Out of memory.\n");
-}
-
-int mhd_respondf(struct MHD_Connection *connection,
-                 enum MHD_RequestTerminationCode code,
-                 const char *format, ...) {
-
-        char *m;
-        int r;
-        va_list ap;
-
-        assert(connection);
-        assert(format);
-
-        va_start(ap, format);
-        r = vasprintf(&m, format, ap);
-        va_end(ap);
-
-        if (r < 0)
-                return respond_oom(connection);
-
-        return mhd_respond_internal(connection, code, m, r, MHD_RESPMEM_MUST_FREE);
-}
-
-#ifdef HAVE_GNUTLS
-
-static struct {
-        const char *const names[4];
-        int level;
-        bool enabled;
-} gnutls_log_map[] = {
-        { {"0"},                  LOG_DEBUG },
-        { {"1", "audit"},         LOG_WARNING, true}, /* gnutls session audit */
-        { {"2", "assert"},        LOG_DEBUG },        /* gnutls assert log */
-        { {"3", "hsk", "ext"},    LOG_DEBUG },        /* gnutls handshake log */
-        { {"4", "rec"},           LOG_DEBUG },        /* gnutls record log */
-        { {"5", "dtls"},          LOG_DEBUG },        /* gnutls DTLS log */
-        { {"6", "buf"},           LOG_DEBUG },
-        { {"7", "write", "read"}, LOG_DEBUG },
-        { {"8"},                  LOG_DEBUG },
-        { {"9", "enc", "int"},    LOG_DEBUG },
-};
-
-static void log_func_gnutls(int level, const char *message) {
-        assert_se(message);
-
-        if (0 <= level && level < (int) ELEMENTSOF(gnutls_log_map)) {
-                if (gnutls_log_map[level].enabled)
-                        log_internal(gnutls_log_map[level].level, 0, NULL, 0, NULL, "gnutls %d/%s: %s", level, gnutls_log_map[level].names[1], message);
-        } else {
-                log_debug("Received GNUTLS message with unknown level %d.", level);
-                log_internal(LOG_DEBUG, 0, NULL, 0, NULL, "gnutls: %s", message);
-        }
-}
-
-static void log_reset_gnutls_level(void) {
-        int i;
-
-        for (i = ELEMENTSOF(gnutls_log_map) - 1; i >= 0; i--)
-                if (gnutls_log_map[i].enabled) {
-                        log_debug("Setting gnutls log level to %d", i);
-                        gnutls_global_set_log_level(i);
-                        break;
-                }
-}
-
-static int log_enable_gnutls_category(const char *cat) {
-        unsigned i;
-
-        if (streq(cat, "all")) {
-                for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++)
-                        gnutls_log_map[i].enabled = true;
-                log_reset_gnutls_level();
-                return 0;
-        } else
-                for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++)
-                        if (strv_contains((char**)gnutls_log_map[i].names, cat)) {
-                                gnutls_log_map[i].enabled = true;
-                                log_reset_gnutls_level();
-                                return 0;
-                        }
-        log_error("No such log category: %s", cat);
-        return -EINVAL;
-}
-
-int setup_gnutls_logger(char **categories) {
-        char **cat;
-        int r;
-
-        gnutls_global_set_log_function(log_func_gnutls);
-
-        if (categories) {
-                STRV_FOREACH(cat, categories) {
-                        r = log_enable_gnutls_category(*cat);
-                        if (r < 0)
-                                return r;
-                }
-        } else
-                log_reset_gnutls_level();
-
-        return 0;
-}
-
-static int verify_cert_authorized(gnutls_session_t session) {
-        unsigned status;
-        gnutls_certificate_type_t type;
-        gnutls_datum_t out;
-        int r;
-
-        r = gnutls_certificate_verify_peers2(session, &status);
-        if (r < 0)
-                return log_error_errno(r, "gnutls_certificate_verify_peers2 failed: %m");
-
-        type = gnutls_certificate_type_get(session);
-        r = gnutls_certificate_verification_status_print(status, type, &out, 0);
-        if (r < 0)
-                return log_error_errno(r, "gnutls_certificate_verification_status_print failed: %m");
-
-        log_debug("Certificate status: %s", out.data);
-        gnutls_free(out.data);
-
-        return status == 0 ? 0 : -EPERM;
-}
-
-static int get_client_cert(gnutls_session_t session, gnutls_x509_crt_t *client_cert) {
-        const gnutls_datum_t *pcert;
-        unsigned listsize;
-        gnutls_x509_crt_t cert;
-        int r;
-
-        assert(session);
-        assert(client_cert);
-
-        pcert = gnutls_certificate_get_peers(session, &listsize);
-        if (!pcert || !listsize) {
-                log_error("Failed to retrieve certificate chain");
-                return -EINVAL;
-        }
-
-        r = gnutls_x509_crt_init(&cert);
-        if (r < 0) {
-                log_error("Failed to initialize client certificate");
-                return r;
-        }
-
-        /* Note that by passing values between 0 and listsize here, you
-           can get access to the CA's certs */
-        r = gnutls_x509_crt_import(cert, &pcert[0], GNUTLS_X509_FMT_DER);
-        if (r < 0) {
-                log_error("Failed to import client certificate");
-                gnutls_x509_crt_deinit(cert);
-                return r;
-        }
-
-        *client_cert = cert;
-        return 0;
-}
-
-static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) {
-        size_t len = 0;
-        int r;
-
-        assert(buf);
-        assert(*buf == NULL);
-
-        r = gnutls_x509_crt_get_dn(client_cert, NULL, &len);
-        if (r != GNUTLS_E_SHORT_MEMORY_BUFFER) {
-                log_error("gnutls_x509_crt_get_dn failed");
-                return r;
-        }
-
-        *buf = malloc(len);
-        if (!*buf)
-                return log_oom();
-
-        gnutls_x509_crt_get_dn(client_cert, *buf, &len);
-        return 0;
-}
-
-static inline void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) {
-        gnutls_x509_crt_deinit(*p);
-}
-
-int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) {
-        const union MHD_ConnectionInfo *ci;
-        gnutls_session_t session;
-        _cleanup_(gnutls_x509_crt_deinitp) gnutls_x509_crt_t client_cert = NULL;
-        _cleanup_free_ char *buf = NULL;
-        int r;
-
-        assert(connection);
-        assert(code);
-
-        *code = 0;
-
-        ci = MHD_get_connection_info(connection,
-                                     MHD_CONNECTION_INFO_GNUTLS_SESSION);
-        if (!ci) {
-                log_error("MHD_get_connection_info failed: session is unencrypted");
-                *code = mhd_respond(connection, MHD_HTTP_FORBIDDEN,
-                                    "Encrypted connection is required");
-                return -EPERM;
-        }
-        session = ci->tls_session;
-        assert(session);
-
-        r = get_client_cert(session, &client_cert);
-        if (r < 0) {
-                *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED,
-                                    "Authorization through certificate is required");
-                return -EPERM;
-        }
-
-        r = get_auth_dn(client_cert, &buf);
-        if (r < 0) {
-                *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED,
-                                    "Failed to determine distinguished name from certificate");
-                return -EPERM;
-        }
-
-        log_debug("Connection from %s", buf);
-
-        if (hostname) {
-                *hostname = buf;
-                buf = NULL;
-        }
-
-        r = verify_cert_authorized(session);
-        if (r < 0) {
-                log_warning("Client is not authorized");
-                *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED,
-                                    "Client certificate not signed by recognized authority");
-        }
-        return r;
-}
-
-#else
-int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) {
-        return -EPERM;
-}
-
-int setup_gnutls_logger(char **categories) {
-        if (categories)
-                log_notice("Ignoring specified gnutls logging categories — gnutls not available.");
-        return 0;
-}
-#endif
diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
deleted file mode 100644 (file)
index b2feb91..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2012 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/>.
-***/
-
-#pragma once
-
-#include <stdarg.h>
-#include <microhttpd.h>
-
-#include "macro.h"
-
-void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0);
-
-/* respond_oom() must be usable with return, hence this form. */
-#define respond_oom(connection) log_oom(), mhd_respond_oom(connection)
-
-int mhd_respondf(struct MHD_Connection *connection,
-                 unsigned code,
-                 const char *format, ...) _printf_(3,4);
-
-int mhd_respond(struct MHD_Connection *connection,
-                unsigned code,
-                const char *message);
-
-int mhd_respond_oom(struct MHD_Connection *connection);
-
-int check_permissions(struct MHD_Connection *connection, int *code, char **hostname);
-
-/* Set gnutls internal logging function to a callback which uses our
- * own logging framework.
- *
- * gnutls categories are additionally filtered by our internal log
- * level, so it should be set fairly high to capture all potentially
- * interesting events without overwhelming detail.
- */
-int setup_gnutls_logger(char **categories);