summaryrefslogtreecommitdiff
path: root/cmd/statrep/main.ha
diff options
context:
space:
mode:
authorJulian Hurst <julian.hurst@digdash.com>2024-10-23 10:04:58 +0200
committerJulian Hurst <julian.hurst@digdash.com>2024-10-23 10:04:58 +0200
commit31cd2a3450eafbe0d22af41449276a90ea3dcb28 (patch)
treedea69f12b776a3aad0c0d86649d1307deae91f88 /cmd/statrep/main.ha
parent0235e95c72181c640c9f19b1c134cc171fb435f9 (diff)
downloadstatusdaemon-31cd2a3450eafbe0d22af41449276a90ea3dcb28.tar.gz
statrep -> statusdaemonHEADmaster
Diffstat (limited to 'cmd/statrep/main.ha')
-rw-r--r--cmd/statrep/main.ha287
1 files changed, 0 insertions, 287 deletions
diff --git a/cmd/statrep/main.ha b/cmd/statrep/main.ha
deleted file mode 100644
index bbe2864..0000000
--- a/cmd/statrep/main.ha
+++ /dev/null
@@ -1,287 +0,0 @@
-use fmt;
-use log;
-use os;
-use net;
-use ev;
-use unix::signal;
-use io;
-use memio;
-use encoding::utf8;
-use strings;
-use bytes;
-use shlex;
-use time;
-use getopt;
-use dirs;
-use path;
-
-type server = struct {
- status: *status,
- loop: *ev::loop,
- sock: *ev::file,
- clients: []*client,
- socketpath: str,
- exit: int,
-};
-
-type client = struct {
- server: *server,
- sock: *ev::file,
- buf: [os::BUFSZ]u8,
- wbuf: []u8,
-};
-
-type status = struct {
- clock: clock,
- host: hostname,
- generics: []generic,
-};
-
-type section = struct {
- label: str,
-};
-
-type hostname = struct {
- section: section,
- value: str,
-};
-
-export fn main() void = {
- const cmd = getopt::parse(os::args,
- "status daemon",
- ('s', "path", "unix socket location")
- );
- defer getopt::finish(&cmd);
-
- let socketpath = path::string(&path::init(dirs::runtime()!, "statrepsocket")!);
- log::println(socketpath);
- for (let opt .. cmd.opts) {
- switch (opt.0) {
- case 's' =>
- socketpath = opt.1;
- case =>
- abort();
- };
- };
-
- const loop = ev::newloop()!;
- defer ev::finish(&loop);
- const sock = ev::listen_unix(&loop, socketpath)!;
- defer ev::close(sock);
-
- let status = newstatus()!;
- defer finishstatus(&status);
-
- let state = server {
- status = &status,
- loop = &loop,
- sock = sock,
- socketpath = socketpath,
- ...
- };
-
- const clocktimer = ev::newtimer(&loop, &clocktimerf, time::clock::MONOTONIC)!;
- ev::timer_configure(clocktimer, 1 * time::SECOND, 1 * time::SECOND);
-
- ev::setuser(clocktimer, &state);
- ev::setuser(sock, &state);
- ev::accept(sock, &accept);
-
- const sig = ev::signal(&loop, &signal, signal::sig::INT,
- signal::sig::TERM)!;
- ev::setuser(sig, &state);
- defer ev::close(sig);
-
- for (ev::dispatch(&loop, -1)!) void;
- os::exit(state.exit);
-};
-
-fn newstatus() (status | io::error | utf8::invalid) = {
- return status {
- clock = buildclock()?,
- host = buildhostname(),
- generics = alloc([
- buildgeneric("/home/jhurst/.local/share/statusbar/vol.sh"),
- ]),
- };
-};
-
-fn finishstatus(status: *status) void = {
- finishclock(&status.clock);
- for (let gen &.. status.generics) {
- finishgeneric(gen);
- };
- free(status.generics);
-};
-
-fn buildhostname() hostname = {
- return hostname {
- section = section {
- label = "hostname: ",
- },
- value = os::hostname(),
- };
-};
-
-fn printstatus(state: *status) str = {
- const s = getstatus(state);
- defer free(s);
- fmt::println(strings::trim(s))!;
- return s;
-};
-
-// Must free return value
-fn getstatus(state: *status) str = {
- const st = memio::dynamic();
- defer io::close(&st)!;
- for (let gen .. state.generics) {
- memio::concat(&st, gen.value)!;
- memio::concat(&st, " | ")!;
- };
- memio::concat(&st,
- state.host.section.label, state.host.value, " | ",
- state.clock.section.label, state.clock.value, "\n"
- )!;
- //const s = strings::concat(
- // state.generic.section.label, state.generic.value, " | ",
- // state.host.section.label, state.host.value, " | ",
- // state.clock.section.label, state.clock.value, "\n");
- const s = strings::dup(memio::string(&st)!);
- return s;
-};
-
-fn accept(sock: *ev::file, result: (*ev::file | net::error)) void = {
- let server = ev::getuser(sock): *server;
- const sock = match (result) {
- case let sock: *ev::file =>
- yield sock;
- case let err: net::error =>
- log::printfln("Error: accept: {}", net::strerror(err));
- ev::stop(server.loop);
- server.exit = 1;
- return;
- };
- log::println("accepted");
- const client = alloc(client {
- server = server,
- sock = sock,
- ...
- });
- append(server.clients, client);
- ev::setuser(client.sock, client);
- ev::read(client.sock, &read, client.buf);
- ev::accept(server.sock, &accept);
-};
-
-fn execmd(s: *status, cmd: []str) (void | str) = {
- switch (cmd[0]) {
- case "print" =>
- printstatus(s);
- case "status" =>
- return getstatus(s);
- case "clock" =>
- updateclock(&s.clock)!;
- case "generic" =>
- for (let gen &.. s.generics) {
- updategeneric(gen)!;
- };
- case =>
- assert(false);
- };
-};
-
-fn write(file: *ev::file, result: (size | io::error)) void = {
- const client = ev::getuser(file): *client;
- const n = match (result) {
- case let err: io::error =>
- log::printfln("Error: write: {}",
- io::strerror(err));
- client_close(client);
- return;
- case let n: size =>
- yield n;
- };
- static delete(client.wbuf[..n]);
- if (len(client.wbuf) != 0) {
- ev::write(client.sock, &write, client.wbuf);
- } else {
- ev::read(client.sock, &read, client.buf);
- };
-};
-
-fn read(file: *ev::file, result: (size | io::EOF | io::error)) void = {
- const client = ev::getuser(file): *client;
- const n = match (result) {
- case let err: io::error =>
- log::printfln("Error: read: {}",
- io::strerror(err));
- client_close(client);
- return;
- case io::EOF =>
- client_close(client);
- return;
- case let n: size =>
- yield n;
- };
- const b = client.buf[..n];
- if (!bytes::contains(b, strings::toutf8("\n"))) {
- ev::read(client.sock, &read, client.buf);
- } else {
- const s = match (strings::fromutf8(b)) {
- case let s: str =>
- yield s;
- case let e: utf8::invalid =>
- log::printfln("Error: read: {}", utf8::strerror(e));
- client_close(client);
- return;
- };
- const i = strings::index(s, "\n") as size;
- const cmd = strings::sub(s, 0z, i);
- log::println(cmd);
-
- const spl = match (shlex::split(cmd)) {
- case let e: shlex::syntaxerr =>
- log::printfln("Error: read: {}", shlex::strerror(e));
- client_close(client);
- return;
- case let spl: []str =>
- yield spl;
- };
- defer strings::freeall(spl);
- match (execmd(client.server.status, spl)) {
- case let s: str =>
- defer free(s);
- log::println(strings::trim(s));
- append(client.wbuf, strings::toutf8(s)...);
- case =>
- void;
- };
-
- if (len(client.wbuf) != 0) {
- ev::write(client.sock, &write, client.wbuf);
- } else {
- ev::read(client.sock, &read, client.buf);
- };
- };
-};
-
-fn client_close(client: *client) void = {
- const server = client.server;
- for (let i = 0z; i < len(server.clients); i += 1) {
- if (server.clients[i] == client) {
- delete(server.clients[i]);
- break;
- };
- };
- log::println("Connection closed");
- ev::close(client.sock);
- free(client);
-};
-
-fn signal(file: *ev::file, sig: signal::sig) void = {
- let server = ev::getuser(file): *server;
- log::printfln("Exiting due to {}", signal::signame(sig));
- const l = ev::getloop(file);
- ev::stop(l);
- os::remove(server.socketpath)!;
-};