Add basic KMSCON support (closes #886)

It's not perfect yet, but at least it works!

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-02-05 15:01:45 +01:00
parent 72f43fbc56
commit 2b46a81796
5 changed files with 36 additions and 5 deletions

View File

@@ -269,6 +269,9 @@ fn install_service(allocator: std.mem.Allocator, patch_map: PatchMap) !void {
const patched_service = try patchFile(allocator, "res/ly@.service", patch_map);
try installText(patched_service, service_dir, service_path, "ly@.service", .{ .mode = 0o644 });
const patched_kmsconvt_service = try patchFile(allocator, "res/ly-kmsconvt@.service", patch_map);
try installText(patched_kmsconvt_service, service_dir, service_path, "ly-kmsconvt@.service", .{ .mode = 0o644 });
},
.openrc => {
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/init.d" });

View File

@@ -316,8 +316,9 @@ service_name = ly
# Session log file path
# This will contain stdout and stderr of Wayland sessions
# By default it's saved in the user's home directory
# Important: due to technical limitations, X11 and shell sessions aren't supported, which
# means you won't get any logs from those sessions.
# Important: due to technical limitations, X11, shell sessions as well as
# launching session via KMSCON aren't supported, which means you won't get any
# logs from those sessions.
# If null, no session log will be created
session_log = .local/state/ly-session.log

17
res/ly-kmsconvt@.service Normal file
View File

@@ -0,0 +1,17 @@
[Unit]
Description=TUI display manager using KMSCON
After=systemd-user-sessions.service plymouth-quit-wait.service
After=kmsconvt@%i.service
Conflicts=kmsconvt@%i.service
[Service]
ExecStart=$PREFIX_DIRECTORY/bin/kmscon --vt=%I --seats=seat0 --login -- $PREFIX_DIRECTORY/bin/ly --use-kmscon-vt
StandardInput=tty
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
[Install]
WantedBy=multi-user.target

View File

@@ -22,6 +22,7 @@ pub const AuthOptions = struct {
x_cmd: []const u8,
x_vt: ?u8,
session_pid: std.posix.pid_t,
use_kmscon_vt: bool,
};
var xorg_pid: std.posix.pid_t = 0;
@@ -475,7 +476,7 @@ fn executeX11Cmd(log_file: *LogFile, allocator: std.mem.Allocator, shell: []cons
xorg_pid = try std.posix.fork();
if (xorg_pid == 0) {
var cmd_buffer: [1024]u8 = undefined;
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd }) catch std.process.exit(1);
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s} {s}", .{ if (options.use_kmscon_vt) "kmscon-launch-gui" else "", options.setup_cmd, options.login_cmd orelse "", desktop_cmd }) catch std.process.exit(1);
try log_file.info("auth/x11", "executing: {s} -c {s}", .{ shell, cmd_str });
const args = [_:null]?[*:0]const u8{ shell_z, "-c", cmd_str };
@@ -508,7 +509,12 @@ fn executeCmd(global_log_file: *LogFile, allocator: std.mem.Allocator, shell: []
try global_log_file.info("auth/sys", "launching wayland/shell/custom session", .{});
var maybe_log_file: ?std.fs.File = null;
if (!is_terminal) {
if (!is_terminal) redirect_streams: {
if (options.use_kmscon_vt) {
try global_log_file.err("auth/sys", "cannot redirect stdio & stderr with kmscon", .{});
break :redirect_streams;
}
// For custom desktop entries, the "Terminal" value here determines if
// we redirect standard output & error or not. That is, we redirect only
// if it's equal to false (so if it's not running in a TTY).
@@ -523,7 +529,7 @@ fn executeCmd(global_log_file: *LogFile, allocator: std.mem.Allocator, shell: []
defer allocator.free(shell_z);
var cmd_buffer: [1024]u8 = undefined;
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", exec_cmd orelse shell });
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s} {s}", .{ if (!is_terminal and options.use_kmscon_vt) "kmscon-launch-gui" else "", options.setup_cmd, options.login_cmd orelse "", exec_cmd orelse shell });
try global_log_file.info("auth/sys", "executing: {s} -c {s}", .{ shell, cmd_str });
const args = [_:null]?[*:0]const u8{ shell_z, "-c", cmd_str };

View File

@@ -126,6 +126,7 @@ pub fn main() !void {
\\-h, --help Shows all commands.
\\-v, --version Shows the version of Ly.
\\-c, --config <str> Overrides the default configuration path. Example: --config /usr/share/ly
\\--use-kmscon-vt Use KMSCON instead of kernel VT
);
var diag = clap.Diagnostic{};
@@ -141,6 +142,7 @@ pub fn main() !void {
var old_save_parser: ?IniParser(OldSave) = null;
defer if (old_save_parser) |*str| str.deinit();
var use_kmscon_vt = false;
var start_cmd_exit_code: u8 = 0;
var saved_users = SavedUsers.init();
@@ -161,6 +163,7 @@ pub fn main() !void {
std.process.exit(0);
}
if (res.args.config) |path| config_parent_path = path;
if (res.args.@"use-kmscon-vt" != 0) use_kmscon_vt = true;
}
// Load configuration file
@@ -845,6 +848,7 @@ pub fn main() !void {
.x_cmd = config.x_cmd,
.x_vt = config.x_vt,
.session_pid = session_pid,
.use_kmscon_vt = use_kmscon_vt,
};
// Signal action to give up control on the TTY