8 Commits
Author SHA1 Message Date
AnErrupTion edbb982c91 [Backport] Recursively create xauth file directory if non-existent
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 20:55:41 +01:00
AnErrupTion 80fb07daa8 [Backport] Fix invalid XDG_RUNTIME_DIR if D-Bus isn't used
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 20:54:47 +01:00
AnErrupTion 93388159bc [Backport] Clamp user session index if invalid
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 18:12:28 +01:00
AnErrupTion 08b4a49729 [Backport] Check for session file name in autologin
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 17:45:29 +01:00
AnErrupTion 066acf91e6 [Backport] Create session log directory if non-existent
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 17:29:31 +01:00
AnErrupTion 2660486fde [Backport] Escape TTY in systemd service
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 17:28:50 +01:00
AnErrupTion a3b249ded8 [Backport] Fix session not being saved correctly
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 17:27:04 +01:00
AnErrupTion 3c22597054 Start Ly v1.3.1 development cycle
Signed-off-by: AnErrupTion <anerruption@disroot.org>
2025-12-30 17:26:53 +01:00
9 changed files with 47 additions and 32 deletions

No files matched your search

+1 -1
View File
@@ -23,7 +23,7 @@ comptime {
} }
} }
const ly_version = std.SemanticVersion{ .major = 1, .minor = 3, .patch = 0 }; const ly_version = std.SemanticVersion{ .major = 1, .minor = 3, .patch = 1 };
var dest_directory: []const u8 = undefined; var dest_directory: []const u8 = undefined;
var config_directory: []const u8 = undefined; var config_directory: []const u8 = undefined;
+1 -1
View File
@@ -1,6 +1,6 @@
.{ .{
.name = .ly, .name = .ly,
.version = "1.3.0", .version = "1.3.1",
.fingerprint = 0xa148ffcc5dc2cb59, .fingerprint = 0xa148ffcc5dc2cb59,
.minimum_zig_version = "0.15.0", .minimum_zig_version = "0.15.0",
.dependencies = .{ .dependencies = .{
+9 -3
View File
@@ -121,9 +121,15 @@ that Ly will run on, otherwise bad things will happen. For example, to disable `
# systemctl disable getty@tty2.service # systemctl disable getty@tty2.service
``` ```
You can change the TTY Ly will run on by editing the corresponding On platforms that use systemd-logind to dynamically start `autovt@.service` instances when the switch to a new tty occurs, any ly instances for ttys *except the default tty* need to be enabled using a different mechanism: To autostart ly on switch to `tty2`, do not enable any `ly` unit directly, instead symlink `autovt@tty2.service` to `ly@tty2.service` within `/usr/lib/systemd/system/` (analogous for every other tty you want to enable ly on).
service file for your platform, or on systemd, by enabling the service on
different TTYs, as is done above. The target of the symlink, `ly@ttyN.service`, does not actually exist, but systemd nevertheless recognizes that the instanciation of `autovt@.service` with `%I` equal to `ttyN` now points to an instanciation of `ly@.service` with `%I` set to `ttyN`.
Compare to `man 5 logind.conf`, especially regarding the `NAutoVTs=` and `ReserveVT=` parameters.
On non-systemd systems, you can change the TTY Ly will run on by editing the corresponding
service file for your platform.
### OpenRC ### OpenRC
+2 -2
View File
@@ -1,8 +1,8 @@
[Unit] [Unit]
Description=TUI display manager Description=TUI display manager
After=systemd-user-sessions.service plymouth-quit-wait.service After=systemd-user-sessions.service plymouth-quit-wait.service
After=getty@%I.service After=getty@%i.service
Conflicts=getty@%I.service Conflicts=getty@%i.service
[Service] [Service]
Type=idle Type=idle
+1 -1
View File
@@ -14,9 +14,9 @@ pub const DesktopEntry = struct {
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} }; pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
entry_ini: ?Ini(Entry) = null, entry_ini: ?Ini(Entry) = null,
file_name: []const u8 = "",
name: []const u8 = "", name: []const u8 = "",
xdg_session_desktop: ?[]const u8 = null, xdg_session_desktop: ?[]const u8 = null,
xdg_session_desktop_owned: bool = false,
xdg_desktop_names: ?[]const u8 = null, xdg_desktop_names: ?[]const u8 = null,
cmd: ?[]const u8 = null, cmd: ?[]const u8 = null,
specifier: []const u8 = "", specifier: []const u8 = "",
+19 -8
View File
@@ -169,6 +169,7 @@ fn startSession(
// Reset the XDG environment variables // Reset the XDG environment variables
try setXdgEnv(allocator, tty_str, current_environment); try setXdgEnv(allocator, tty_str, current_environment);
try setXdgRuntimeDir(allocator);
// Set the PAM variables // Set the PAM variables
const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle); const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle);
@@ -217,6 +218,15 @@ fn setXdgEnv(allocator: std.mem.Allocator, tty_str: []u8, environment: Environme
.custom => if (environment.is_terminal) "tty" else "unspecified", .custom => if (environment.is_terminal) "tty" else "unspecified",
}, false); }, false);
if (environment.xdg_desktop_names) |xdg_desktop_names| try interop.setEnvironmentVariable(allocator, "XDG_CURRENT_DESKTOP", xdg_desktop_names, false);
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_CLASS", "user", false);
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_ID", "1", false);
if (environment.xdg_session_desktop) |desktop_name| try interop.setEnvironmentVariable(allocator, "XDG_SESSION_DESKTOP", desktop_name, false);
try interop.setEnvironmentVariable(allocator, "XDG_SEAT", "seat0", false);
try interop.setEnvironmentVariable(allocator, "XDG_VTNR", tty_str, false);
}
fn setXdgRuntimeDir(allocator: std.mem.Allocator) !void {
// The "/run/user/%d" directory is not available on FreeBSD. It is much // The "/run/user/%d" directory is not available on FreeBSD. It is much
// better to stick to the defaults and let applications using // better to stick to the defaults and let applications using
// XDG_RUNTIME_DIR to fall back to directories inside user's home // XDG_RUNTIME_DIR to fall back to directories inside user's home
@@ -228,13 +238,6 @@ fn setXdgEnv(allocator: std.mem.Allocator, tty_str: []u8, environment: Environme
try interop.setEnvironmentVariable(allocator, "XDG_RUNTIME_DIR", uid_str, false); try interop.setEnvironmentVariable(allocator, "XDG_RUNTIME_DIR", uid_str, false);
} }
if (environment.xdg_desktop_names) |xdg_desktop_names| try interop.setEnvironmentVariable(allocator, "XDG_CURRENT_DESKTOP", xdg_desktop_names, false);
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_CLASS", "user", false);
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_ID", "1", false);
if (environment.xdg_session_desktop) |desktop_name| try interop.setEnvironmentVariable(allocator, "XDG_SESSION_DESKTOP", desktop_name, false);
try interop.setEnvironmentVariable(allocator, "XDG_SEAT", "seat0", false);
try interop.setEnvironmentVariable(allocator, "XDG_VTNR", tty_str, false);
} }
fn loginConv( fn loginConv(
@@ -366,7 +369,7 @@ fn createXauthFile(pwd: []const u8, buffer: []u8) ![]const u8 {
const xauthority: []u8 = try std.fmt.bufPrint(buffer, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file }); const xauthority: []u8 = try std.fmt.bufPrint(buffer, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file });
std.fs.makeDirAbsolute(trimmed_xauth_dir) catch {}; std.fs.cwd().makePath(trimmed_xauth_dir) catch {};
const file = try std.fs.createFileAbsolute(xauthority, .{}); const file = try std.fs.createFileAbsolute(xauthority, .{});
file.close(); file.close();
@@ -502,6 +505,14 @@ fn executeCmd(global_log_file: *LogFile, allocator: std.mem.Allocator, shell: []
} }
fn redirectStandardStreams(global_log_file: *LogFile, session_log: []const u8, create: bool) !std.fs.File { fn redirectStandardStreams(global_log_file: *LogFile, session_log: []const u8, create: bool) !std.fs.File {
create_session_log_dir: {
const session_log_dir = std.fs.path.dirname(session_log) orelse break :create_session_log_dir;
std.fs.cwd().makePath(session_log_dir) catch |err| {
try global_log_file.file_writer.interface.print("failed to create session log file directory: {s}\n", .{@errorName(err)});
return err;
};
}
const log_file = if (create) (std.fs.cwd().createFile(session_log, .{ .mode = 0o666 }) catch |err| { const log_file = if (create) (std.fs.cwd().createFile(session_log, .{ .mode = 0o666 }) catch |err| {
try global_log_file.file_writer.interface.print("failed to create new session log file: {s}\n", .{@errorName(err)}); try global_log_file.file_writer.interface.print("failed to create new session log file: {s}\n", .{@errorName(err)});
return err; return err;
+5 -8
View File
@@ -529,7 +529,7 @@ pub fn main() !void {
active_input = .password; active_input = .password;
if (user.session_index < session.label.list.items.len) session.label.current = user.session_index; session.label.current = @min(user.session_index, session.label.list.items.len - 1);
} }
} }
@@ -1251,10 +1251,10 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
}); });
errdefer entry_ini.deinit(); errdefer entry_ini.deinit();
const file_name = try session.label.allocator.dupe(u8, std.fs.path.stem(item.name));
const entry = entry_ini.data.@"Desktop Entry"; const entry = entry_ini.data.@"Desktop Entry";
var maybe_xdg_session_desktop: ?[]const u8 = null; var maybe_xdg_session_desktop: ?[]const u8 = null;
var maybe_xdg_desktop_names: ?[]const u8 = null; var maybe_xdg_desktop_names: ?[]const u8 = null;
var xdg_session_desktop_owned = false;
// Prepare the XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP environment // Prepare the XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP environment
// variables here // variables here
@@ -1268,18 +1268,14 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
} else if (display_server != .custom) { } else if (display_server != .custom) {
// If DesktopNames is empty, and this isn't a custom session entry, // If DesktopNames is empty, and this isn't a custom session entry,
// we'll take the name of the session file // we'll take the name of the session file
const stem = std.fs.path.stem(item.name); if (file_name.len > 0) maybe_xdg_session_desktop = file_name;
if (stem.len > 0) {
maybe_xdg_session_desktop = try session.label.allocator.dupe(u8, stem);
xdg_session_desktop_owned = true;
}
} }
try session.addEnvironment(.{ try session.addEnvironment(.{
.entry_ini = entry_ini, .entry_ini = entry_ini,
.file_name = file_name,
.name = entry.Name, .name = entry.Name,
.xdg_session_desktop = maybe_xdg_session_desktop, .xdg_session_desktop = maybe_xdg_session_desktop,
.xdg_session_desktop_owned = xdg_session_desktop_owned,
.xdg_desktop_names = maybe_xdg_desktop_names, .xdg_desktop_names = maybe_xdg_desktop_names,
.cmd = entry.Exec, .cmd = entry.Exec,
.specifier = switch (display_server) { .specifier = switch (display_server) {
@@ -1310,6 +1306,7 @@ fn findSessionByName(session: *Session, name: []const u8) ?usize {
if (std.ascii.eqlIgnoreCase(session_desktop_name, name)) return i; if (std.ascii.eqlIgnoreCase(session_desktop_name, name)) return i;
} }
if (std.ascii.eqlIgnoreCase(env.environment.name, name)) return i; if (std.ascii.eqlIgnoreCase(env.environment.name, name)) return i;
if (std.ascii.eqlIgnoreCase(env.environment.file_name, name)) return i;
} }
return null; return null;
} }
+8 -6
View File
@@ -29,9 +29,7 @@ pub fn init(allocator: Allocator, buffer: *TerminalBuffer, user_list: *UserList)
pub fn deinit(self: *Session) void { pub fn deinit(self: *Session) void {
for (self.label.list.items) |*env| { for (self.label.list.items) |*env| {
if (env.environment.entry_ini) |*entry_ini| entry_ini.deinit(); if (env.environment.entry_ini) |*entry_ini| entry_ini.deinit();
if (env.environment.xdg_session_desktop_owned) { self.label.allocator.free(env.environment.file_name);
self.label.allocator.free(env.environment.xdg_session_desktop.?);
}
} }
self.label.deinit(); self.label.deinit();
@@ -41,16 +39,20 @@ pub fn addEnvironment(self: *Session, environment: Environment) !void {
const env = Env{ .environment = environment, .index = self.label.list.items.len }; const env = Env{ .environment = environment, .index = self.label.list.items.len };
try self.label.addItem(env); try self.label.addItem(env);
sessionChanged(env, self.user_list); addedSession(env, self.user_list);
} }
fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void { fn addedSession(env: Env, user_list: *UserList) void {
if (maybe_user_list) |user_list| {
const user = user_list.label.list.items[user_list.label.current]; const user = user_list.label.list.items[user_list.label.current];
if (!user.first_run) return; if (!user.first_run) return;
user.session_index.* = env.index; user.session_index.* = env.index;
} }
fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void {
if (maybe_user_list) |user_list| {
user_list.label.list.items[user_list.label.current].session_index.* = env.index;
}
} }
fn drawItem(label: *EnvironmentLabel, env: Env, x: usize, y: usize) bool { fn drawItem(label: *EnvironmentLabel, env: Env, x: usize, y: usize) bool {
+1 -2
View File
@@ -71,8 +71,7 @@ pub fn getCurrentUsername(self: UserList) []const u8 {
fn usernameChanged(user: User, maybe_session: ?*Session) void { fn usernameChanged(user: User, maybe_session: ?*Session) void {
if (maybe_session) |session| { if (maybe_session) |session| {
if (user.session_index.* >= session.label.list.items.len) return; session.label.current = @min(user.session_index.*, session.label.list.items.len - 1);
session.label.current = user.session_index.*;
} }
} }