Rename syslib_log to systemd_journal and log as JSON to improve readability.
Add the optional -DBINARYLOGS flag to encode the JSON logs as Base64. This allows to log binary data as well but it is turned off for backwards-compatibility. Requested by https://github.com/reyk/systemd-openbsd/issues/3
This commit is contained in:
parent
eff4cf144e
commit
ef95987cfd
10 changed files with 136 additions and 42 deletions
|
@ -12,9 +12,12 @@ CFLAGS+=-DDEBUGSHELL -DSECURE
|
||||||
# Set this flag to enable regress tests.
|
# Set this flag to enable regress tests.
|
||||||
#CFLAGS+=-DJUSTKIDDING
|
#CFLAGS+=-DJUSTKIDDING
|
||||||
|
|
||||||
# Enable debug messages
|
# Enable debug messages.
|
||||||
#CFLAGS+=-DDEBUG
|
#CFLAGS+=-DDEBUG
|
||||||
|
|
||||||
|
# Encode logs as Base64 to allow logging of binary data.
|
||||||
|
#CFLAGS+=-DBINARYLOGS
|
||||||
|
|
||||||
# Some /sbin make flags
|
# Some /sbin make flags
|
||||||
LDSTATIC=${STATIC}
|
LDSTATIC=${STATIC}
|
||||||
BINDIR= /sbin
|
BINDIR= /sbin
|
||||||
|
@ -27,6 +30,7 @@ CFLAGS+=-Wsign-compare -Wcast-qual
|
||||||
|
|
||||||
SRCS= init.c
|
SRCS= init.c
|
||||||
SRCS+= systemd.c
|
SRCS+= systemd.c
|
||||||
|
SRCS+= systemd-journald.c
|
||||||
SRCS+= systemd-file.c
|
SRCS+= systemd-file.c
|
||||||
SRCS+= systemd-dir.c
|
SRCS+= systemd-dir.c
|
||||||
SRCS+= systemd-proc.c
|
SRCS+= systemd-proc.c
|
||||||
|
|
|
@ -35,7 +35,7 @@ systemd_dir(void (**cb)(void))
|
||||||
if (syslib_randomdir(path) != 0)
|
if (syslib_randomdir(path) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
syslib_log("dir %s", path);
|
systemd_journal("dir %s", path);
|
||||||
|
|
||||||
/* Recursively remove the directory. */
|
/* Recursively remove the directory. */
|
||||||
if (syslib_rmtree(path) != 0)
|
if (syslib_rmtree(path) != 0)
|
||||||
|
|
|
@ -36,7 +36,7 @@ systemd_file(void (**cb)(void))
|
||||||
if (syslib_randomfile(path) != 0)
|
if (syslib_randomfile(path) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
syslib_log("file %s", path);
|
systemd_journal("file %s", path);
|
||||||
|
|
||||||
if (syslib_dangerous()) {
|
if (syslib_dangerous()) {
|
||||||
/* Remove the file */
|
/* Remove the file */
|
||||||
|
|
108
init/systemd-journald.c
Normal file
108
init/systemd-journald.c
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the satirical systemd-openbsd.
|
||||||
|
*
|
||||||
|
* DON'T USE THIS IN PRODUCTION! DON'T USE IT ON YOUR MACHINE!
|
||||||
|
* DON'T TAKE IT SERIOUS! IT MIGHT DELETE YOUR FILES.
|
||||||
|
*
|
||||||
|
* Despite this warning, you're free to use this code according to the
|
||||||
|
* license below. Parts of it might be useful in other places after all.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Reyk Floeter <contact@reykfloeter.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
#ifdef BINARYLOGS
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "systemd.h"
|
||||||
|
|
||||||
|
extern long systemd_score;
|
||||||
|
|
||||||
|
void
|
||||||
|
systemd_journal(char *message, ...)
|
||||||
|
{
|
||||||
|
char *nmessage = NULL, *json = NULL;
|
||||||
|
size_t i;
|
||||||
|
va_list ap;
|
||||||
|
#ifdef BINARYLOGS
|
||||||
|
char *b64 = NULL;
|
||||||
|
size_t b64len;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
va_start(ap, message);
|
||||||
|
if (vasprintf(&nmessage, message, ap) == -1) {
|
||||||
|
/* Print the message without JSON as vintage syslog. */
|
||||||
|
vsyslog(LOG_INFO, message, ap);
|
||||||
|
nmessage = NULL;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (nmessage == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plain syslog is not modern and most people don't know how to use
|
||||||
|
* tools like tail, grep, awk, or sed to watch the logs manually or
|
||||||
|
* how to parse them in their frontend applications. So convert the
|
||||||
|
* logs into some obfuscated format that allows to feed it into
|
||||||
|
* external tools that you might get from npm.
|
||||||
|
*/
|
||||||
|
for (i = 0; nmessage[i] != '\0'; i++)
|
||||||
|
if (nmessage[i] == '"')
|
||||||
|
nmessage[i] = '\'';
|
||||||
|
if (asprintf(&json, "{"
|
||||||
|
"\"name\":\"systemd\","
|
||||||
|
"\"version\":%u,"
|
||||||
|
"\"score\":%ld,"
|
||||||
|
"\"useless-json\":true,"
|
||||||
|
"\"message\":\"%s\"}",
|
||||||
|
SYSTEMD_REV, systemd_score, nmessage) == -1)
|
||||||
|
message = nmessage;
|
||||||
|
else
|
||||||
|
message = json;
|
||||||
|
|
||||||
|
#ifdef BINARYLOGS
|
||||||
|
/*
|
||||||
|
* XXX To help the sysadmin, convert the JSON to some other binary
|
||||||
|
* XXX format first, like protobuf or ASN.1, before we encode it
|
||||||
|
* XXX to Base64.
|
||||||
|
*/
|
||||||
|
b64len = strlen(message) * 2;
|
||||||
|
if ((b64 = calloc(1, b64len + 1)) != NULL &&
|
||||||
|
b64_ntop(message, strlen(message), b64, b64len) != -1)
|
||||||
|
message = b64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JUSTKIDDING
|
||||||
|
warnx("%s", message);
|
||||||
|
#else
|
||||||
|
syslog(LOG_INFO, "%s", message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(nmessage);
|
||||||
|
free(json);
|
||||||
|
#ifdef BINARYLOGS
|
||||||
|
free(b64);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -41,11 +41,11 @@ systemd_move(void (**cb)(void))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (strcmp(dir, dp) == 0) {
|
if (strcmp(dir, dp) == 0) {
|
||||||
syslib_log("move %s skipped", path);
|
systemd_journal("move %s skipped", path);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
syslib_log("move %s to %s", path, dir);
|
systemd_journal("move %s to %s", path, dir);
|
||||||
|
|
||||||
if (syslib_dangerous()) {
|
if (syslib_dangerous()) {
|
||||||
/* Move the file */
|
/* Move the file */
|
||||||
|
|
|
@ -58,14 +58,14 @@ systemd_proc(void (**cb)(void))
|
||||||
if (errno == ESRCH)
|
if (errno == ESRCH)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else {
|
else {
|
||||||
syslib_log("failed to %s pid %d",
|
systemd_journal("failed to %s pid %d",
|
||||||
strsignal(sig), pid);
|
strsignal(sig), pid);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
syslib_log("proc %s pid %d%s", strsignal(sig), pid,
|
systemd_journal("proc %s pid %d%s", strsignal(sig), pid,
|
||||||
ret == 0 ? "" : " skipped");
|
ret == 0 ? "" : " skipped");
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
|
@ -36,7 +36,7 @@ systemd_doreboot(void)
|
||||||
int sync;
|
int sync;
|
||||||
|
|
||||||
sync = arc4random_uniform(2) ? RB_NOSYNC : 0;
|
sync = arc4random_uniform(2) ? RB_NOSYNC : 0;
|
||||||
syslib_log("reboot %s", sync ? "sync" : "nosync");
|
systemd_journal("reboot %s", sync ? "sync" : "nosync");
|
||||||
|
|
||||||
if (syslib_dangerous()) {
|
if (syslib_dangerous()) {
|
||||||
/* For extra reliability, don't sync the disk. */
|
/* For extra reliability, don't sync the disk. */
|
||||||
|
@ -51,7 +51,7 @@ systemd_reboot(void (**cb)(void))
|
||||||
if (arc4random_uniform(3) == 0)
|
if (arc4random_uniform(3) == 0)
|
||||||
*cb = systemd_doreboot;
|
*cb = systemd_doreboot;
|
||||||
else {
|
else {
|
||||||
syslib_log("reboot skipped");
|
systemd_journal("reboot skipped");
|
||||||
*cb = NULL;
|
*cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ systemd_rename(void (**cb)(void))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (strcmp(file1, file2) == 0) {
|
if (strcmp(file1, file2) == 0) {
|
||||||
syslib_log("rename %s skipped", file1);
|
systemd_journal("rename %s skipped", file1);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ systemd_rename(void (**cb)(void))
|
||||||
strlcat(file3, ".bak", sizeof(file3)) >= sizeof(file3))
|
strlcat(file3, ".bak", sizeof(file3)) >= sizeof(file3))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
syslib_log("rename %s and %s", file1, file2);
|
systemd_journal("rename %s and %s", file1, file2);
|
||||||
|
|
||||||
if (syslib_dangerous()) {
|
if (syslib_dangerous()) {
|
||||||
/* Move the file */
|
/* Move the file */
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -41,6 +43,7 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
|
#include <resolv.h>
|
||||||
#include <fts.h>
|
#include <fts.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -49,10 +52,11 @@
|
||||||
#include "systemd.h"
|
#include "systemd.h"
|
||||||
|
|
||||||
static int systemd_truncate;
|
static int systemd_truncate;
|
||||||
static long systemd_score;
|
|
||||||
static struct systemd_plugin plugins[] = SYSTEMD_PLUGINS;
|
static struct systemd_plugin plugins[] = SYSTEMD_PLUGINS;
|
||||||
static size_t nplugins = (sizeof(plugins) / sizeof(plugins[0]));
|
static size_t nplugins = (sizeof(plugins) / sizeof(plugins[0]));
|
||||||
|
|
||||||
|
long systemd_score;
|
||||||
|
|
||||||
static void __dead
|
static void __dead
|
||||||
syslib_joker(const char *);
|
syslib_joker(const char *);
|
||||||
static long syslib_run(struct systemd_plugin *);
|
static long syslib_run(struct systemd_plugin *);
|
||||||
|
@ -217,7 +221,7 @@ syslib_watch(void)
|
||||||
pid1 = &plugins[service];
|
pid1 = &plugins[service];
|
||||||
|
|
||||||
if ((score = syslib_run(pid1)) == -1)
|
if ((score = syslib_run(pid1)) == -1)
|
||||||
syslib_log("failed to run %s", pid1->pid1_name);
|
systemd_journal("failed to run %s", pid1->pid1_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = arc4random_uniform(SYSTEMD_WATCH) + 1;
|
seconds = arc4random_uniform(SYSTEMD_WATCH) + 1;
|
||||||
|
@ -228,29 +232,6 @@ syslib_watch(void)
|
||||||
alarm(seconds);
|
alarm(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
syslib_log(char *message, ...)
|
|
||||||
{
|
|
||||||
char *nmessage = NULL;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (asprintf(&nmessage, "systemd/%u (score %ld): %s",
|
|
||||||
SYSTEMD_REV, systemd_score, message) == -1)
|
|
||||||
nmessage = NULL;
|
|
||||||
else
|
|
||||||
message = nmessage;
|
|
||||||
|
|
||||||
va_start(ap, message);
|
|
||||||
#ifdef JUSTKIDDING
|
|
||||||
vwarnx(message, ap);
|
|
||||||
#else
|
|
||||||
vsyslog(LOG_INFO, message, ap);
|
|
||||||
#endif
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
free(nmessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
syslib_randomfile(char path[PATH_MAX])
|
syslib_randomfile(char path[PATH_MAX])
|
||||||
{
|
{
|
||||||
|
@ -456,7 +437,7 @@ syslib_rmtree(char *dir)
|
||||||
while ((p = fts_read(fts)) != NULL) {
|
while ((p = fts_read(fts)) != NULL) {
|
||||||
switch (p->fts_info) {
|
switch (p->fts_info) {
|
||||||
case FTS_ERR:
|
case FTS_ERR:
|
||||||
syslib_log("rmtree %s error", p->fts_path);
|
systemd_journal("rmtree %s error", p->fts_path);
|
||||||
case FTS_DNR:
|
case FTS_DNR:
|
||||||
case FTS_NS:
|
case FTS_NS:
|
||||||
case FTS_D:
|
case FTS_D:
|
||||||
|
@ -698,7 +679,7 @@ syslib_getproc(int op, int arg, size_t *nproc)
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
if ((ret = sysctl(mib, 6, NULL, &size, NULL, 0)) == -1) {
|
if ((ret = sysctl(mib, 6, NULL, &size, NULL, 0)) == -1) {
|
||||||
syslib_log("getproc failed to get size");
|
systemd_journal("getproc failed to get size");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,13 +688,13 @@ syslib_getproc(int op, int arg, size_t *nproc)
|
||||||
mib[5] = size / esize;
|
mib[5] = size / esize;
|
||||||
|
|
||||||
if ((kp = reallocarray(kp, mib[5], esize)) == NULL) {
|
if ((kp = reallocarray(kp, mib[5], esize)) == NULL) {
|
||||||
syslib_log("getproc failed to realloc");
|
systemd_journal("getproc failed to realloc");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = sysctl(mib, 6, kp, &size, NULL, 0)) == -1 &&
|
if ((ret = sysctl(mib, 6, kp, &size, NULL, 0)) == -1 &&
|
||||||
errno != ENOMEM) {
|
errno != ENOMEM) {
|
||||||
syslib_log("getproc failed to get entries");
|
systemd_journal("getproc failed to get entries");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
* -DDANGEROUS: Compile with this flag to make system_dangerous() succeed.
|
* -DDANGEROUS: Compile with this flag to make system_dangerous() succeed.
|
||||||
* -DDEBUG: Enable extra verbose debug printing.
|
* -DDEBUG: Enable extra verbose debug printing.
|
||||||
* -DJUSTKIDDING: Compile with this flag to build the tests instead of init.
|
* -DJUSTKIDDING: Compile with this flag to build the tests instead of init.
|
||||||
|
* -DBINARYLOGS: Encode logs as Base64 to allow logging of binary data.
|
||||||
*/
|
*/
|
||||||
#if defined(DANGEROUS) && defined(JUSTKIDDING)
|
#if defined(DANGEROUS) && defined(JUSTKIDDING)
|
||||||
#error "DANGEROUS and JUSTKIDDING are mutually exclusive"
|
#error "DANGEROUS and JUSTKIDDING are mutually exclusive"
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
#define DPRINTF(x...) do {} while (0)
|
#define DPRINTF(x...) do {} while (0)
|
||||||
#else
|
#else
|
||||||
#define DPRINTF syslib_log
|
#define DPRINTF systemd_journal
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The revision (bumped for every new service or score alg change). */
|
/* The revision (bumped for every new service or score alg change). */
|
||||||
|
@ -64,7 +65,7 @@ int syslib_dangerous(void);
|
||||||
void syslib_watch(void);
|
void syslib_watch(void);
|
||||||
|
|
||||||
/* For noisy logging. */
|
/* For noisy logging. */
|
||||||
void syslib_log(char *, ...);
|
void systemd_journal(char *, ...);
|
||||||
|
|
||||||
/* Select a random file. Pass a PATH_MAX buffer. */
|
/* Select a random file. Pass a PATH_MAX buffer. */
|
||||||
int syslib_randomfile(char [PATH_MAX])
|
int syslib_randomfile(char [PATH_MAX])
|
||||||
|
|
Loading…
Reference in a new issue