journal-gatewayd.c revision a7f7d1bde43fc825c49afea3f946f5b4b3d563e0
f0528cfc93da36692a5fb7898d7e4a9e95150318nd/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f0528cfc93da36692a5fb7898d7e4a9e95150318nd This file is part of systemd.
f0528cfc93da36692a5fb7898d7e4a9e95150318nd Copyright 2012 Lennart Poettering
f0528cfc93da36692a5fb7898d7e4a9e95150318nd systemd is free software; you can redistribute it and/or modify it
f0528cfc93da36692a5fb7898d7e4a9e95150318nd under the terms of the GNU Lesser General Public License as published by
f0528cfc93da36692a5fb7898d7e4a9e95150318nd the Free Software Foundation; either version 2.1 of the License, or
f0528cfc93da36692a5fb7898d7e4a9e95150318nd (at your option) any later version.
f0528cfc93da36692a5fb7898d7e4a9e95150318nd systemd is distributed in the hope that it will be useful, but
f0528cfc93da36692a5fb7898d7e4a9e95150318nd WITHOUT ANY WARRANTY; without even the implied warranty of
f0528cfc93da36692a5fb7898d7e4a9e95150318nd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f0528cfc93da36692a5fb7898d7e4a9e95150318nd Lesser General Public License for more details.
f0528cfc93da36692a5fb7898d7e4a9e95150318nd You should have received a copy of the GNU Lesser General Public License
f0528cfc93da36692a5fb7898d7e4a9e95150318nd along with systemd; If not, see <http://www.gnu.org/licenses/>.
typedef struct RequestMeta {
char *cursor;
bool n_entries_set;
int argument_parse_error;
bool follow;
bool discrete;
bool n_fields_set;
} RequestMeta;
RequestMeta *m;
if (*connection_cls)
return *connection_cls;
return NULL;
*connection_cls = m;
static void request_meta_free(
void *cls,
void **connection_cls,
if (m->journal)
if (m->tmp)
free(m);
assert(m);
if (m->journal)
if (m->tmp)
int fd;
if (fd < 0)
return fd;
if (!m->tmp) {
return -errno;
void *cls,
char *buf,
size_t n, k;
assert(m);
if (m->n_entries_set &&
m->n_entries <= 0)
return MHD_CONTENT_READER_END_OF_STREAM;
if (m->n_skip < 0)
else if (m->n_skip > 0)
if (m->follow) {
return MHD_CONTENT_READER_END_OF_STREAM;
if (m->discrete) {
return MHD_CONTENT_READER_END_OF_STREAM;
if (m->n_entries_set)
m->n_skip = 0;
r = request_meta_ensure_tmp(m);
if (n > max)
n = max;
errno = 0;
return (ssize_t) k;
static int request_parse_accept(
RequestMeta *m,
const char *header;
assert(m);
if (!header)
static int request_parse_range(
RequestMeta *m,
assert(m);
if (!range)
if (!colon)
if (colon2) {
_cleanup_free_ char *t;
return -ENOMEM;
if (m->n_entries <= 0)
return -EINVAL;
m->n_entries_set = true;
if (!m->cursor)
return -ENOMEM;
static int request_parse_arguments_iterator(
void *cls,
const char *key,
const char *value) {
assert(m);
return MHD_NO;
m->follow = true;
return MHD_YES;
m->argument_parse_error = r;
return MHD_NO;
m->follow = r;
return MHD_YES;
m->discrete = true;
return MHD_YES;
m->argument_parse_error = r;
return MHD_NO;
m->discrete = r;
return MHD_YES;
m->argument_parse_error = r;
return MHD_NO;
return MHD_NO;
m->argument_parse_error = r;
return MHD_NO;
return MHD_YES;
return MHD_NO;
m->argument_parse_error = r;
return MHD_NO;
return MHD_YES;
static int request_parse_arguments(
RequestMeta *m,
assert(m);
m->argument_parse_error = 0;
return m->argument_parse_error;
static int request_handler_entries(
void *connection_cls) {
assert(m);
r = open_journal(m);
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
if (m->discrete) {
if (!m->cursor)
return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n");
m->n_entries_set = true;
if (m->cursor)
else if (m->n_skip >= 0)
else if (m->n_skip < 0)
response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL);
if (!response)
const char *eq;
size_t j;
if (!eq)
return -EINVAL;
if (m == OUTPUT_JSON) {
void *cls,
char *buf,
size_t n, k;
assert(m);
size_t l;
if (m->n_fields_set &&
m->n_fields <= 0)
return MHD_CONTENT_READER_END_OF_STREAM;
return MHD_CONTENT_READER_END_OF_STREAM;
if (m->n_fields_set)
r = request_meta_ensure_tmp(m);
if (n > max)
n = max;
errno = 0;
return (ssize_t) k;
static int request_handler_fields(
const char *field,
void *connection_cls) {
assert(m);
r = open_journal(m);
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL);
if (!response)
MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]);
static int request_handler_redirect(
const char *target) {
char *page;
int ret;
if (asprintf(&page, "<html><body>Please continue to the <a href=\"%s\">journal browser</a>.</body></html>", target) < 0)
if (!response) {
return ret;
static int request_handler_file(
const char *path,
const char *mime_type) {
int ret;
if (fd < 0)
if (!response)
return ret;
static int get_virtualization(char **v) {
char *b = NULL;
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
if (isempty(b)) {
free(b);
*v = NULL;
static int request_handler_machine(
void *connection_cls) {
char *json;
assert(m);
r = open_journal(m);
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r));
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r));
if (!hostname)
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
get_virtualization(&v);
if (!response) {
static int request_handler(
void *cls,
const char *url,
const char *method,
const char *version,
const char *upload_data,
void **connection_cls) {
int r, code;
if (!*connection_cls) {
return MHD_YES;
if (arg_trust_pem) {
return code;
static void help(void) {
help();
case ARG_VERSION:
case ARG_KEY:
if (arg_key_pem) {
return -EINVAL;
case ARG_CERT:
if (arg_cert_pem) {
return -EINVAL;
case ARG_TRUST:
#ifdef HAVE_GNUTLS
if (arg_trust_pem) {
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
log_open();
return EXIT_FAILURE;
return EXIT_SUCCESS;
return EXIT_FAILURE;
goto finish;
goto finish;
if (arg_key_pem) {
if (arg_trust_pem) {
goto finish;
pause();
r = EXIT_SUCCESS;
MHD_stop_daemon(d);