mirror of https://github.com/fairyglade/ly.git
Separate platform code from C interop code
Also, don't use isBSD() because we'll only support FreeBSD for now. Other BSDs may not necessarily support Unicode characters or the same ioctl constants as we do (or even ioctl at all). Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
parent
230874abd1
commit
f9553655a3
143
src/interop.zig
143
src/interop.zig
|
@ -1,19 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
pub const TimeOfDay = struct {
|
|
||||||
seconds: i64,
|
|
||||||
microseconds: i64,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const UsernameEntry = struct {
|
|
||||||
username: ?[]const u8,
|
|
||||||
uid: std.posix.uid_t,
|
|
||||||
gid: std.posix.gid_t,
|
|
||||||
home: ?[]const u8,
|
|
||||||
shell: ?[]const u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const termbox = @import("termbox2");
|
pub const termbox = @import("termbox2");
|
||||||
|
|
||||||
|
@ -57,29 +43,83 @@ const time = @cImport({
|
||||||
@cInclude("time.h");
|
@cInclude("time.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
// BSD-specific headers
|
pub const TimeOfDay = struct {
|
||||||
const kbio = @cImport({
|
seconds: i64,
|
||||||
@cInclude("sys/kbio.h");
|
microseconds: i64,
|
||||||
});
|
};
|
||||||
|
|
||||||
// Linux-specific headers
|
pub const UsernameEntry = struct {
|
||||||
const kd = @cImport({
|
username: ?[]const u8,
|
||||||
@cInclude("sys/kd.h");
|
uid: std.posix.uid_t,
|
||||||
});
|
gid: std.posix.gid_t,
|
||||||
|
home: ?[]const u8,
|
||||||
|
shell: ?[]const u8,
|
||||||
|
passwd_struct: [*c]pwd.passwd,
|
||||||
|
};
|
||||||
|
|
||||||
const vt = @cImport({
|
// Contains the platform-specific code
|
||||||
@cInclude("sys/vt.h");
|
fn PlatformStruct() type {
|
||||||
});
|
return switch (builtin.os.tag) {
|
||||||
|
.linux => struct {
|
||||||
|
pub const kd = @cImport({
|
||||||
|
@cInclude("sys/kd.h");
|
||||||
|
});
|
||||||
|
|
||||||
// Used for getting & setting the lock state
|
pub const vt = @cImport({
|
||||||
const LedState = if (builtin.os.tag.isBSD()) c_int else c_char;
|
@cInclude("sys/vt.h");
|
||||||
const get_led_state = if (builtin.os.tag.isBSD()) kbio.KDGETLED else kd.KDGKBLED;
|
});
|
||||||
const set_led_state = if (builtin.os.tag.isBSD()) kbio.KDSETLED else kd.KDSKBLED;
|
|
||||||
const numlock_led = if (builtin.os.tag.isBSD()) kbio.LED_NUM else kd.K_NUMLOCK;
|
pub const LedState = c_char;
|
||||||
const capslock_led = if (builtin.os.tag.isBSD()) kbio.LED_CAP else kd.K_CAPSLOCK;
|
pub const get_led_state = kd.KDGKBLED;
|
||||||
|
pub const set_led_state = kd.KDSKBLED;
|
||||||
|
pub const numlock_led = kd.K_NUMLOCK;
|
||||||
|
pub const capslock_led = kd.K_CAPSLOCK;
|
||||||
|
pub const vt_activate = vt.VT_ACTIVATE;
|
||||||
|
pub const vt_waitactive = vt.VT_WAITACTIVE;
|
||||||
|
|
||||||
|
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
||||||
|
const status = grp.initgroups(username, @intCast(entry.gid));
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
|
std.posix.setgid(@intCast(entry.gid)) catch return error.SetUserGidFailed;
|
||||||
|
std.posix.setuid(@intCast(entry.uid)) catch return error.SetUserUidFailed;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.freebsd => struct {
|
||||||
|
pub const kbio = @cImport({
|
||||||
|
@cInclude("sys/kbio.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const consio = @cImport({
|
||||||
|
@cInclude("sys/consio.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const LedState = c_int;
|
||||||
|
pub const get_led_state = kbio.KDGETLED;
|
||||||
|
pub const set_led_state = kbio.KDSETLED;
|
||||||
|
pub const numlock_led = kbio.LED_NUM;
|
||||||
|
pub const capslock_led = kbio.LED_CAP;
|
||||||
|
pub const vt_activate = consio.VT_ACTIVATE;
|
||||||
|
pub const vt_waitactive = consio.VT_WAITACTIVE;
|
||||||
|
|
||||||
|
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
||||||
|
// FreeBSD has initgroups() in unistd
|
||||||
|
const status = unistd.initgroups(username, @intCast(entry.gid));
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
|
// FreeBSD sets the GID and UID with setusercontext()
|
||||||
|
const result = pwd.setusercontext(null, entry.passwd_struct, @intCast(entry.uid), pwd.LOGIN_SETALL);
|
||||||
|
if (result != 0) return error.SetUserUidFailed;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => @compileError("Unsupported target: " ++ builtin.os.tag),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const platform_struct = PlatformStruct();
|
||||||
|
|
||||||
pub fn supportsUnicode() bool {
|
pub fn supportsUnicode() bool {
|
||||||
return builtin.os.tag == .linux or builtin.os.tag.isBSD();
|
return builtin.os.tag == .linux or builtin.os.tag == .freebsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) []u8 {
|
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) []u8 {
|
||||||
|
@ -103,10 +143,10 @@ pub fn getTimeOfDay() !TimeOfDay {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switchTty(tty: u8) !void {
|
pub fn switchTty(tty: u8) !void {
|
||||||
var status = std.c.ioctl(std.posix.STDIN_FILENO, vt.VT_ACTIVATE, tty);
|
var status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.vt_activate, tty);
|
||||||
if (status != 0) return error.FailedToActivateTty;
|
if (status != 0) return error.FailedToActivateTty;
|
||||||
|
|
||||||
status = std.c.ioctl(std.posix.STDIN_FILENO, vt.VT_WAITACTIVE, tty);
|
status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.vt_waitactive, tty);
|
||||||
if (status != 0) return error.FailedToWaitForActiveTty;
|
if (status != 0) return error.FailedToWaitForActiveTty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,24 +154,24 @@ pub fn getLockState() !struct {
|
||||||
numlock: bool,
|
numlock: bool,
|
||||||
capslock: bool,
|
capslock: bool,
|
||||||
} {
|
} {
|
||||||
var led: LedState = undefined;
|
var led: platform_struct.LedState = undefined;
|
||||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, get_led_state, &led);
|
const status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.get_led_state, &led);
|
||||||
if (status != 0) return error.FailedToGetLockState;
|
if (status != 0) return error.FailedToGetLockState;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.numlock = (led & numlock_led) != 0,
|
.numlock = (led & platform_struct.numlock_led) != 0,
|
||||||
.capslock = (led & capslock_led) != 0,
|
.capslock = (led & platform_struct.capslock_led) != 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setNumlock(val: bool) !void {
|
pub fn setNumlock(val: bool) !void {
|
||||||
var led: LedState = undefined;
|
var led: platform_struct.LedState = undefined;
|
||||||
var status = std.c.ioctl(std.posix.STDIN_FILENO, get_led_state, &led);
|
var status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.get_led_state, &led);
|
||||||
if (status != 0) return error.FailedToGetNumlock;
|
if (status != 0) return error.FailedToGetNumlock;
|
||||||
|
|
||||||
const numlock = (led & numlock_led) != 0;
|
const numlock = (led & platform_struct.numlock_led) != 0;
|
||||||
if (numlock != val) {
|
if (numlock != val) {
|
||||||
status = std.c.ioctl(std.posix.STDIN_FILENO, set_led_state, led ^ numlock_led);
|
status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.set_led_state, led ^ platform_struct.numlock_led);
|
||||||
if (status != 0) return error.FailedToSetNumlock;
|
if (status != 0) return error.FailedToSetNumlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,22 +180,7 @@ pub fn setUserContext(allocator: std.mem.Allocator, entry: UsernameEntry) !void
|
||||||
const username_z = try allocator.dupeZ(u8, entry.username.?);
|
const username_z = try allocator.dupeZ(u8, entry.username.?);
|
||||||
defer allocator.free(username_z);
|
defer allocator.free(username_z);
|
||||||
|
|
||||||
if (builtin.os.tag == .freebsd) {
|
return platform_struct.setUserContextImpl(username_z.ptr, entry);
|
||||||
// FreeBSD has initgroups() in unistd
|
|
||||||
const status = unistd.initgroups(username_z.ptr, @intCast(entry.gid));
|
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
|
||||||
|
|
||||||
// FreeBSD sets the GID and UID with setusercontext()
|
|
||||||
// TODO
|
|
||||||
const result = pwd.setusercontext(null, entry, @intCast(entry.uid), pwd.LOGIN_SETALL);
|
|
||||||
if (result != 0) return error.SetUserUidFailed;
|
|
||||||
} else {
|
|
||||||
const status = grp.initgroups(username_z.ptr, @intCast(entry.gid));
|
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
|
||||||
|
|
||||||
std.posix.setgid(@intCast(entry.gid)) catch return error.SetUserGidFailed;
|
|
||||||
std.posix.setuid(@intCast(entry.uid)) catch return error.SetUserUidFailed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setUserShell(entry: *UsernameEntry) void {
|
pub fn setUserShell(entry: *UsernameEntry) void {
|
||||||
|
@ -193,6 +218,7 @@ pub fn getNextUsernameEntry() ?UsernameEntry {
|
||||||
.gid = @intCast(entry.*.pw_gid),
|
.gid = @intCast(entry.*.pw_gid),
|
||||||
.home = if (entry.*.pw_dir) |dir| dir[0..std.mem.len(dir)] else null,
|
.home = if (entry.*.pw_dir) |dir| dir[0..std.mem.len(dir)] else null,
|
||||||
.shell = if (entry.*.pw_shell) |shell| shell[0..std.mem.len(shell)] else null,
|
.shell = if (entry.*.pw_shell) |shell| shell[0..std.mem.len(shell)] else null,
|
||||||
|
.passwd_struct = entry,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +232,7 @@ pub fn getUsernameEntry(username: [:0]const u8) ?UsernameEntry {
|
||||||
.gid = @intCast(entry.*.pw_gid),
|
.gid = @intCast(entry.*.pw_gid),
|
||||||
.home = if (entry.*.pw_dir) |dir| dir[0..std.mem.len(dir)] else null,
|
.home = if (entry.*.pw_dir) |dir| dir[0..std.mem.len(dir)] else null,
|
||||||
.shell = if (entry.*.pw_shell) |shell| shell[0..std.mem.len(shell)] else null,
|
.shell = if (entry.*.pw_shell) |shell| shell[0..std.mem.len(shell)] else null,
|
||||||
|
.passwd_struct = entry,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue