M .gitignore => .gitignore +1 -0
@@ 1,2 1,3 @@
config.h
iboot
+zig-cache
M Makefile => Makefile +10 -3
@@ 1,13 1,20 @@
+PREFIX := /usr/local
+ZFLAGS := -I. --release-small --strip --single-threaded
CFLAGS := -Wall -Wpedantic -Os -std=c99
+SRC := $(if $(ZIG),iboot.zig,iboot.c)
-iboot: iboot.c config.h
+iboot: $(SRC) config.h
+ifneq ($(ZIG),)
+ zig build-exe $(ZFLAGS) --name $@ $<
+else
$(CC) $(CFLAGS) -o $@ $<
+endif
config.h: config.def.h
cp $< $@
install:
- install -m 0755 iboot /usr/local/bin/
+ install -m 0755 iboot $(PREFIX)/bin/
clean:
- rm -rf iboot
+ rm -rf iboot iboot.o
M iboot.c => iboot.c +1 -1
@@ 50,7 50,7 @@ int create_socket()
void send_command(int sockfd, enum action action)
{
char buf[BUF_SIZE];
- sprintf(buf, "%s%c\r", PASSWORD, action);
+ sprintf(buf, "\x1b%s\x1b%c\r", PASSWORD, action);
if (write(sockfd, buf, BUF_SIZE) != BUF_SIZE) {
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
A iboot.zig => iboot.zig +69 -0
@@ 0,0 1,69 @@
+const std = @import("std");
+const fmt = std.fmt;
+const mem = std.mem;
+const net = std.net;
+
+const config = @cImport(@cInclude("config.h"));
+
+const Action = enum(u8) {
+ ON = 'n',
+ OFF = 'f',
+ CYCLE = 'c',
+ QUERY = 'q',
+
+ fn parse(str: []const u8) !Action {
+ if (mem.eql(u8, str, "on")) {
+ return .ON;
+ }
+
+ if (mem.eql(u8, str, "off")) {
+ return .OFF;
+ }
+
+ if (mem.eql(u8, str, "cycle")) {
+ return .CYCLE;
+ }
+
+ if (mem.eql(u8, str, "query")) {
+ return .QUERY;
+ }
+
+ return error.InvalidAction;
+ }
+};
+
+inline fn usage() noreturn {
+ std.debug.warn("Usage: iboot <on|off|cycle|query>\n", .{});
+ std.process.exit(1);
+}
+
+pub fn main() anyerror!void {
+ var args = std.process.args();
+ _ = args.skip();
+
+ const action = if (args.nextPosix()) |arg|
+ Action.parse(arg) catch {
+ std.debug.warn("Invalid action: {}\n", .{arg});
+ usage();
+ }
+ else
+ usage();
+
+ const addr = try net.Address.parseIp4(mem.span(config.ADDRESS), config.PORT);
+ const sock = try net.tcpConnectToAddress(addr);
+
+ // 4 extra bytes for the two escape characters, the action character, and
+ // the carriage return
+ comptime var size = mem.span(config.PASSWORD).len + 4;
+ var buf: [size]u8 = undefined;
+ _ = try fmt.bufPrint(&buf, "\x1b{}\x1b{c}\r", .{
+ mem.span(config.PASSWORD),
+ @enumToInt(action),
+ });
+
+ try sock.writeAll(&buf);
+ mem.set(u8, &buf, 0);
+ _ = try sock.read(&buf);
+
+ std.debug.warn("{}\n", .{buf});
+}