feat: added config

This commit is contained in:
LordMZTE 2022-05-26 20:15:52 +02:00
parent 346196903b
commit 9e9295426a
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
8 changed files with 128 additions and 7 deletions

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "libs/tomlc99"]
path = libs/tomlc99
url = https://github.com/cktan/tomlc99.git
[submodule "libs/known-folders"]
path = libs/known-folders
url = https://github.com/ziglibs/known-folders.git

View file

@ -16,7 +16,14 @@ pub fn build(b: *std.build.Builder) void {
exe.setBuildMode(mode);
exe.linkLibC();
exe.addPackagePath("known-folders", "libs/known-folders/known-folders.zig");
exe.linkSystemLibrary("gtk4");
exe.addIncludeDir("libs/tomlc99");
exe.addCSourceFile("libs/tomlc99/toml.c", &[0][]u8{});
// needed to prevent crash caused by UBSAN because the tomlc99 has some UB
exe.disable_sanitize_c = true;
exe.strip = mode != .Debug;
exe.install();

1
libs/known-folders Submodule

@ -0,0 +1 @@
Subproject commit 9db1b99219c767d5e24994b1525273fe4031e464

1
libs/tomlc99 Submodule

@ -0,0 +1 @@
Subproject commit 034b23ed3e4e5ee5345040eabed470f204d7f668

View file

@ -1,4 +1,5 @@
const std = @import("std");
const cfg = @import("config.zig");
pub const Action = enum {
shutdown,
@ -12,14 +13,15 @@ pub const Action = enum {
alloc: std.mem.Allocator,
) !void {
std.log.info("Executing action {s}", .{@tagName(self)});
var argv = [_][]const u8{ "systemctl", switch (self) {
.shutdown => "poweroff",
.reboot => "reboot",
.@"suspend" => "suspend",
.hibernate => "hibernate",
} };
var child = try std.ChildProcess.init(&argv, alloc);
const argv = switch (self) {
.shutdown => cfg.global_config.?.shutdown_command,
.reboot => cfg.global_config.?.reboot_command,
.@"suspend" => cfg.global_config.?.suspend_command,
.hibernate => cfg.global_config.?.hibernate_command,
};
var child = try std.ChildProcess.init(argv, alloc);
try child.spawn();
handle_out.* = child;
}

98
src/config.zig Normal file
View file

@ -0,0 +1,98 @@
const std = @import("std");
const kf = @import("known-folders");
const c = @import("ffi.zig").c;
pub var global_config: ?*Config = null;
pub const Config = struct {
shutdown_command: []const []const u8 = &[_][]const u8{ "systemctl", "poweroff" },
reboot_command: []const []const u8 = &[_][]const u8{ "systemctl", "reboot" },
suspend_command: []const []const u8 = &[_][]const u8{ "systemctl", "suspend" },
hibernate_command: []const []const u8 = &[_][]const u8{ "systemctl", "hibernate" },
alloc: std.mem.Allocator,
command_arena: std.heap.ArenaAllocator,
toml: ?*c.toml_table_t,
pub fn parse(alloc: std.mem.Allocator) !Config {
var toml: ?*c.toml_table_t = null;
toml: {
var config_dir = kf.open(
alloc,
.roaming_configuration,
.{},
) catch break :toml orelse break :toml;
defer config_dir.close();
const config = try config_dir.realpathAlloc(alloc, "gpower2/config.toml");
defer alloc.free(config);
const config_z = try std.cstr.addNullByte(alloc, config);
defer alloc.free(config_z);
const c_file = c.fopen(config_z, "r");
std.log.debug("{x}", .{@ptrToInt(c_file)});
if (c_file == null) {
std.log.warn("Opening config failed, skipping config", .{});
break :toml;
}
defer _ = c.fclose(c_file);
var errbuf: [50:0]u8 = undefined;
toml = c.toml_parse_file(c_file, &errbuf, errbuf.len);
if (toml == null) {
std.log.err("Failed to parse TOML config: {s}", .{errbuf});
return error.TomlError;
}
}
var arena = std.heap.ArenaAllocator.init(alloc);
errdefer arena.deinit();
var self = Config{
.alloc = alloc,
.command_arena = arena,
.toml = toml,
};
if (toml) |t| {
errdefer c.toml_free(t);
inline for (.{
.shutdown_command,
.reboot_command,
.suspend_command,
.hibernate_command,
}) |f_tag| {
const f = @tagName(f_tag);
const array = c.toml_array_in(t, f);
if (array) |a| {
var len = c.toml_array_nelem(a);
var i: usize = 0;
var cmd = try arena.allocator().alloc([]u8, @intCast(usize, len));
while (i < len) : (i += 1) {
const maybe_s = c.toml_string_at(a, @intCast(c_int, i));
if (maybe_s.ok == 0) {
std.log.err("{s} in config contains non-string value!", .{f});
return error.InvalidConfig;
}
cmd[i] = try arena.allocator().dupe(u8, std.mem.sliceTo(maybe_s.u.s, 0));
}
@field(self, f) = cmd;
}
}
}
return self;
}
pub fn deinit(self: *Config) void {
if (self.toml) |t| {
c.toml_free(t);
}
}
};

View file

@ -1,6 +1,7 @@
// partially yoinked from https://github.com/Swoogan/ziggtk
pub const c = @cImport({
@cInclude("gtk/gtk.h");
@cInclude("toml.h");
});
/// Could not get `g_signal_connect` to work. Zig says "use of undeclared identifier". Reimplemented here

View file

@ -1,4 +1,5 @@
const std = @import("std");
const cfg = @import("config.zig");
const ffi = @import("ffi.zig");
const c = ffi.c;
const gui = @import("gui.zig");
@ -44,6 +45,10 @@ pub fn log(
}
pub fn main() !u8 {
var conf = try cfg.Config.parse(std.heap.c_allocator);
defer conf.deinit();
cfg.global_config = &conf;
var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
defer arena.deinit();