From 31cd2a3450eafbe0d22af41449276a90ea3dcb28 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Wed, 23 Oct 2024 10:04:58 +0200 Subject: statrep -> statusdaemon --- cmd/statrep/main.ha | 287 ---------------------------------------------------- 1 file changed, 287 deletions(-) delete mode 100644 cmd/statrep/main.ha (limited to 'cmd/statrep/main.ha') 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)!; -}; -- cgit v1.2.3