commit: 0a2550bb0a741c3e7ac34726939564aeab76b71b
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Fri, 1 Apr 2022 20:35:19 +0200
Initial Commit
Diffstat:
5 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+/rc-status-page
+\ No newline at end of file
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2022 Haelwenn (lanodan) Monnier <contact+rc-status-page@hacktivis.me>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,15 @@
+CC ?= cc
+CFLAGS ?= -O2 -ggdb -Wall -Wextra
+PKG_CONFIG ?= pkg-config
+
+CFLAGS_openrc = `$(PKG_CONFIG) --cflags openrc`
+LIBS_openrc = `$(PKG_CONFIG) --libs openrc`
+
+all: rc-status-page
+
+rc-status-page: rc-status-page.c
+ $(CC) -std=c11 $(CFLAGS) $(CFLAGS_openrc) -o $@ $< $(LDFLAGS) $(LIBS_openrc)
+
+.PHONY: clean
+clean:
+ rm rc-status-page
diff --git a/rc-status-page.c b/rc-status-page.c
@@ -0,0 +1,100 @@
+// rc-status-page: Basic HTML status page based on OpenRC
+// Copyright © 2022 Haelwenn (lanodan) Monnier <contact+rc-status-page@hacktivis.me>
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include <sys/queue.h> /* TAILQ_FOREACH() */
+#include <rc.h> /* rc_ / RC_ */
+#include <stdlib.h> /* printf */
+#include <errno.h> /* errno */
+
+#include <time.h> /* time(), gmtime(), strftime() */
+
+static RC_DEPTREE *deptree;
+static RC_STRINGLIST *types;
+RC_STRINGLIST *levels, *services;
+
+static void
+print_service(const char *service)
+{
+ RC_SERVICE state = rc_service_state(service);
+ char *status;
+
+ if(state & RC_SERVICE_STOPPING) {
+ status = "stopping";
+ } else if(state & RC_SERVICE_STARTING) {
+ status = "starting";
+ } else if(state & RC_SERVICE_INACTIVE) {
+ status = "inactive";
+ } else if(state & RC_SERVICE_SCHEDULED) {
+ status = "scheduled";
+ } else if(state & RC_SERVICE_STARTED) {
+ errno = 0;
+ if (rc_service_daemons_crashed(service) && errno != EACCES) {
+ status = "crashed";
+ } else {
+ status = "started";
+ }
+ } else {
+ status = "stopped";
+ }
+
+ printf("\t<li class=\"service service-%s\">%s: %s</li>\n", status, service, status);
+}
+
+static void
+print_services(const char *runlevel, RC_STRINGLIST *svcs)
+{
+ RC_STRINGLIST *l = NULL;
+ RC_STRING *s;
+ char *r = NULL;
+
+ if (!svcs) { return; }
+ if (!deptree) { deptree = rc_deptree_load(); }
+ if (!types) {
+ types = rc_stringlist_new();
+ rc_stringlist_add(types, "ineed");
+ rc_stringlist_add(types, "iuse");
+ rc_stringlist_add(types, "iafter");
+ }
+ if (!runlevel) { r = rc_runlevel_get(); }
+
+ l = rc_deptree_depends(deptree, types, svcs, r ? r : runlevel, RC_DEP_STRICT | RC_DEP_TRACE | RC_DEP_START);
+ free(r);
+ if (!l) return;
+
+ printf("<ul>\n");
+ TAILQ_FOREACH(s, l, entries) {
+ if (!rc_stringlist_find(svcs, s->value)) continue;
+ if (!runlevel || rc_service_in_runlevel(s->value, runlevel)) print_service(s->value);
+ }
+ rc_stringlist_free(l);
+ printf("</ul>\n");
+}
+
+int
+main() {
+ RC_STRING *l;
+ char timestamp[BUFSIZ];
+ time_t now = time(NULL);
+ struct tm *tm = gmtime(&now);
+
+ strftime(timestamp, sizeof(timestamp), "%FT%TZ", tm);
+
+ levels = rc_stringlist_new();
+ rc_stringlist_add(levels, "hacktivism");
+
+ printf("<html><head><link rel=stylesheet href=\"rc-status-page.css\"/></head><body>");
+ printf("<h1>Status page of hacktivis.me</h1>");
+
+ TAILQ_FOREACH(l, levels, entries) {
+ services = rc_services_in_runlevel(l->value);
+ print_services(l->value, services);
+ }
+
+ printf("<footer>Generated at %s</footer>", timestamp);
+
+ printf("</body></html>\n");
+
+ rc_stringlist_free(levels);
+ return 0;
+}
diff --git a/rc-status-page.css b/rc-status-page.css
@@ -0,0 +1,7 @@
+.service-started { color:green; }
+.service-stopped { color:red; }
+.service-crashed { color:red; }
+body {
+ display: table;
+ margin: 0 auto;
+}