Split session crawling from TUI component

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion 2025-03-16 00:24:56 +01:00
parent 9efb734fd5
commit 86ea38f460
No known key found for this signature in database
4 changed files with 117 additions and 114 deletions

21
src/Environment.zig Normal file
View File

@ -0,0 +1,21 @@
const enums = @import("enums.zig");
const ini = @import("zigini");
const DisplayServer = enums.DisplayServer;
const Ini = ini.Ini;
pub const DesktopEntry = struct {
Exec: []const u8 = "",
Name: [:0]const u8 = "",
DesktopNames: ?[:0]u8 = null,
};
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
entry_ini: ?Ini(Entry) = null,
name: [:0]const u8 = "",
xdg_session_desktop: ?[:0]const u8 = null,
xdg_desktop_names: ?[:0]const u8 = null,
cmd: []const u8 = "",
specifier: []const u8 = "",
display_server: DisplayServer = .wayland,

View File

@ -2,8 +2,8 @@ const std = @import("std");
const build_options = @import("build_options");
const builtin = @import("builtin");
const enums = @import("enums.zig");
const Environment = @import("Environment.zig");
const interop = @import("interop.zig");
const Session = @import("tui/components/Session.zig");
const SharedError = @import("SharedError.zig");
const Allocator = std.mem.Allocator;
@ -33,7 +33,7 @@ pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
if (child_pid > 0) _ = std.c.kill(child_pid, i);
}
pub fn authenticate(options: AuthOptions, current_environment: Session.Environment, login: [:0]const u8, password: [:0]const u8) !void {
pub fn authenticate(options: AuthOptions, current_environment: Environment, login: [:0]const u8, password: [:0]const u8) !void {
var tty_buffer: [3]u8 = undefined;
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{options.tty});
@ -134,7 +134,7 @@ fn startSession(
options: AuthOptions,
pwd: *interop.pwd.passwd,
handle: ?*interop.pam.pam_handle,
current_environment: Session.Environment,
current_environment: Environment,
) !void {
if (builtin.os.tag == .freebsd) {
// FreeBSD has initgroups() in unistd

View File

@ -5,6 +5,8 @@ const clap = @import("clap");
const ini = @import("zigini");
const auth = @import("auth.zig");
const bigclock = @import("bigclock.zig");
const enums = @import("enums.zig");
const Environment = @import("Environment.zig");
const interop = @import("interop.zig");
const Doom = @import("animations/Doom.zig");
const Matrix = @import("animations/Matrix.zig");
@ -21,6 +23,8 @@ const SharedError = @import("SharedError.zig");
const utils = @import("tui/utils.zig");
const Ini = ini.Ini;
const DisplayServer = enums.DisplayServer;
const Entry = Environment.Entry;
const termbox = interop.termbox;
const unistd = interop.unistd;
const temporary_allocator = std.heap.page_allocator;
@ -254,16 +258,16 @@ pub fn main() !void {
try info_line.addMessage(lang.err_numlock, config.error_bg, config.error_fg);
};
var session = Session.init(allocator, &buffer, lang);
var session = Session.init(allocator, &buffer);
defer session.deinit();
session.addEnvironment(.{ .Name = lang.shell }, null, .shell) catch {
addOtherEnvironment(&session, lang, .shell, null) catch {
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
};
if (build_options.enable_x11_support) {
if (config.xinitrc) |xinitrc| {
session.addEnvironment(.{ .Name = lang.xinitrc, .Exec = xinitrc }, null, .xinitrc) catch {
if (config.xinitrc) |xinitrc_cmd| {
addOtherEnvironment(&session, lang, .xinitrc, xinitrc_cmd) catch {
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
};
}
@ -283,8 +287,8 @@ pub fn main() !void {
try info_line.addMessage(hostname, config.bg, config.fg);
}
try session.crawl(config.waylandsessions, .wayland);
if (build_options.enable_x11_support) try session.crawl(config.xsessions, .x11);
try crawl(&session, lang, config.waylandsessions, .wayland);
if (build_options.enable_x11_support) try crawl(&session, lang, config.xsessions, .x11);
var login = Text.init(allocator, &buffer, false, null);
defer login.deinit();
@ -844,6 +848,83 @@ pub fn main() !void {
}
}
fn addOtherEnvironment(session: *Session, lang: Lang, display_server: DisplayServer, exec: ?[]const u8) !void {
const name = switch (display_server) {
.shell => lang.shell,
.xinitrc => lang.xinitrc,
else => unreachable,
};
try session.addEnvironment(.{
.entry_ini = null,
.name = name,
.xdg_session_desktop = null,
.xdg_desktop_names = null,
.cmd = exec orelse "",
.specifier = switch (display_server) {
.wayland => lang.wayland,
.x11 => lang.x11,
else => lang.other,
},
.display_server = display_server,
});
}
fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: DisplayServer) !void {
var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return;
defer iterable_directory.close();
var iterator = iterable_directory.iterate();
while (try iterator.next()) |item| {
if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue;
const entry_path = try std.fmt.allocPrint(session.label.allocator, "{s}/{s}", .{ path, item.name });
defer session.label.allocator.free(entry_path);
var entry_ini = Ini(Entry).init(session.label.allocator);
_ = try entry_ini.readFileToStruct(entry_path, .{
.fieldHandler = null,
.comment_characters = "#",
});
errdefer entry_ini.deinit();
var xdg_session_desktop: []const u8 = undefined;
const maybe_desktop_names = entry_ini.data.@"Desktop Entry".DesktopNames;
if (maybe_desktop_names) |desktop_names| {
xdg_session_desktop = std.mem.sliceTo(desktop_names, ';');
} else {
// if DesktopNames is empty, we'll take the name of the session file
xdg_session_desktop = std.fs.path.stem(item.name);
}
// Prepare the XDG_CURRENT_DESKTOP environment variable here
const entry = entry_ini.data.@"Desktop Entry";
var xdg_desktop_names: ?[:0]const u8 = null;
if (entry.DesktopNames) |desktop_names| {
for (desktop_names) |*c| {
if (c.* == ';') c.* = ':';
}
xdg_desktop_names = desktop_names;
}
const session_desktop = try session.label.allocator.dupeZ(u8, xdg_session_desktop);
errdefer session.label.allocator.free(session_desktop);
try session.addEnvironment(.{
.entry_ini = entry_ini,
.name = entry.Name,
.xdg_session_desktop = session_desktop,
.xdg_desktop_names = xdg_desktop_names,
.cmd = entry.Exec,
.specifier = switch (display_server) {
.wayland => lang.wayland,
.x11 => lang.x11,
else => lang.other,
},
.display_server = display_server,
});
}
}
fn adjustBrightness(allocator: std.mem.Allocator, cmd: []const u8) !void {
var brightness = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, allocator);
brightness.stdout_behavior = .Ignore;

View File

@ -1,43 +1,22 @@
const std = @import("std");
const TerminalBuffer = @import("../TerminalBuffer.zig");
const enums = @import("../../enums.zig");
const ini = @import("zigini");
const Environment = @import("../../Environment.zig");
const generic = @import("generic.zig");
const Ini = @import("zigini").Ini;
const Lang = @import("../../config/Lang.zig");
const Allocator = std.mem.Allocator;
const DisplayServer = enums.DisplayServer;
const Ini = ini.Ini;
const EnvironmentLabel = generic.CyclableLabel(Environment);
const Session = @This();
pub const Environment = struct {
entry_ini: ?Ini(Entry) = null,
name: [:0]const u8 = "",
xdg_session_desktop: ?[:0]const u8 = null,
xdg_desktop_names: ?[:0]const u8 = null,
cmd: []const u8 = "",
specifier: []const u8 = "",
display_server: DisplayServer = .wayland,
};
const DesktopEntry = struct {
Exec: []const u8 = "",
Name: [:0]const u8 = "",
DesktopNames: ?[:0]u8 = null,
};
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
label: EnvironmentLabel,
lang: Lang,
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, lang: Lang) Session {
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) Session {
return .{
.label = EnvironmentLabel.init(allocator, buffer, drawItem),
.lang = lang,
};
}
@ -50,86 +29,8 @@ pub fn deinit(self: Session) void {
self.label.deinit();
}
pub fn addEnvironment(self: *Session, entry: DesktopEntry, xdg_session_desktop: ?[:0]const u8, display_server: DisplayServer) !void {
var xdg_desktop_names: ?[:0]const u8 = null;
if (entry.DesktopNames) |desktop_names| {
for (desktop_names) |*c| {
if (c.* == ';') c.* = ':';
}
xdg_desktop_names = desktop_names;
}
try self.label.addItem(.{
.entry_ini = null,
.name = entry.Name,
.xdg_session_desktop = xdg_session_desktop,
.xdg_desktop_names = xdg_desktop_names,
.cmd = entry.Exec,
.specifier = switch (display_server) {
.wayland => self.lang.wayland,
.x11 => self.lang.x11,
else => self.lang.other,
},
.display_server = display_server,
});
}
pub fn addEnvironmentWithIni(self: *Session, entry_ini: Ini(Entry), xdg_session_desktop: ?[:0]const u8, display_server: DisplayServer) !void {
const entry = entry_ini.data.@"Desktop Entry";
var xdg_desktop_names: ?[:0]const u8 = null;
if (entry.DesktopNames) |desktop_names| {
for (desktop_names) |*c| {
if (c.* == ';') c.* = ':';
}
xdg_desktop_names = desktop_names;
}
try self.label.addItem(.{
.entry_ini = entry_ini,
.name = entry.Name,
.xdg_session_desktop = xdg_session_desktop,
.xdg_desktop_names = xdg_desktop_names,
.cmd = entry.Exec,
.specifier = switch (display_server) {
.wayland => self.lang.wayland,
.x11 => self.lang.x11,
else => self.lang.other,
},
.display_server = display_server,
});
}
pub fn crawl(self: *Session, path: []const u8, display_server: DisplayServer) !void {
var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return;
defer iterable_directory.close();
var iterator = iterable_directory.iterate();
while (try iterator.next()) |item| {
if (!std.mem.eql(u8, std.fs.path.extension(item.name), ".desktop")) continue;
const entry_path = try std.fmt.allocPrint(self.label.allocator, "{s}/{s}", .{ path, item.name });
defer self.label.allocator.free(entry_path);
var entry_ini = Ini(Entry).init(self.label.allocator);
_ = try entry_ini.readFileToStruct(entry_path, .{
.fieldHandler = null,
.comment_characters = "#",
});
errdefer entry_ini.deinit();
var xdg_session_desktop: []const u8 = undefined;
const maybe_desktop_names = entry_ini.data.@"Desktop Entry".DesktopNames;
if (maybe_desktop_names) |desktop_names| {
xdg_session_desktop = std.mem.sliceTo(desktop_names, ';');
} else {
// if DesktopNames is empty, we'll take the name of the session file
xdg_session_desktop = std.fs.path.stem(item.name);
}
const session_desktop = try self.label.allocator.dupeZ(u8, xdg_session_desktop);
errdefer self.label.allocator.free(session_desktop);
try self.addEnvironmentWithIni(entry_ini, session_desktop, display_server);
}
pub fn addEnvironment(self: *Session, environment: Environment) !void {
try self.label.addItem(environment);
}
fn drawItem(label: *EnvironmentLabel, environment: Environment, x: usize, y: usize) bool {