From 42393f46d149bc748f76e4e5c1c6768dc900894b Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Fri, 30 May 2025 19:14:25 +0200 Subject: [PATCH 01/11] Only support Ly v1.1.x in bug reports Signed-off-by: AnErrupTion --- .github/ISSUE_TEMPLATE/bug.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 3314a84..d9762ef 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -15,7 +15,7 @@ body: id: version attributes: label: Ly version - description: The output of `ly --version`. Please note that only Ly v1.0.0 and above are supported. + description: The output of `ly --version`. Please note that only Ly v1.1.0 and above are supported. placeholder: 1.1.0-dev.12+2b0301c validations: required: true From d12850889cbb1e39faed6ac8296ca89151ce28c4 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 31 May 2025 10:39:03 +0200 Subject: [PATCH 02/11] Start v1.1.1 development cycle Signed-off-by: AnErrupTion --- build.zig | 2 +- build.zig.zon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 36635d8..194fff5 100644 --- a/build.zig +++ b/build.zig @@ -21,7 +21,7 @@ comptime { } } -const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 0 }; +const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 1 }; var dest_directory: []const u8 = undefined; var config_directory: []const u8 = undefined; diff --git a/build.zig.zon b/build.zig.zon index 48c58f3..8e66a31 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .ly, - .version = "1.1.0", + .version = "1.1.1", .fingerprint = 0xa148ffcc5dc2cb59, .minimum_zig_version = "0.14.0", .dependencies = .{ From f983c6b19b15477acaa66de878b0e260094e6c44 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 31 May 2025 10:39:15 +0200 Subject: [PATCH 03/11] Backport: Fix big clock UB in ReleaseSafe Signed-off-by: AnErrupTion --- src/bigclock.zig | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/bigclock.zig b/src/bigclock.zig index d63f0fd..4fae3a4 100644 --- a/src/bigclock.zig +++ b/src/bigclock.zig @@ -34,24 +34,24 @@ pub fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [ } } -fn toBigNumber(char: u8, bigclock: Bigclock) []const u21 { +fn toBigNumber(char: u8, bigclock: Bigclock) [SIZE]u21 { const locale_chars = switch (bigclock) { .fa => fa.locale_chars, .en => en.locale_chars, .none => unreachable, }; return switch (char) { - '0' => &locale_chars.ZERO, - '1' => &locale_chars.ONE, - '2' => &locale_chars.TWO, - '3' => &locale_chars.THREE, - '4' => &locale_chars.FOUR, - '5' => &locale_chars.FIVE, - '6' => &locale_chars.SIX, - '7' => &locale_chars.SEVEN, - '8' => &locale_chars.EIGHT, - '9' => &locale_chars.NINE, - ':' => &locale_chars.S, - else => &locale_chars.E, + '0' => locale_chars.ZERO, + '1' => locale_chars.ONE, + '2' => locale_chars.TWO, + '3' => locale_chars.THREE, + '4' => locale_chars.FOUR, + '5' => locale_chars.FIVE, + '6' => locale_chars.SIX, + '7' => locale_chars.SEVEN, + '8' => locale_chars.EIGHT, + '9' => locale_chars.NINE, + ':' => locale_chars.S, + else => locale_chars.E, }; } From 170e5238239d71fd8ee9e00e572e991f0b1f3ebb Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sun, 6 Jul 2025 09:31:56 +0200 Subject: [PATCH 04/11] Backport: Fix XDG_RUNTIME_DIR not being set properly Signed-off-by: AnErrupTion --- src/auth.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/auth.zig b/src/auth.zig index 35eee5e..721516f 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -96,7 +96,7 @@ pub fn authenticate(options: AuthOptions, current_environment: Environment, logi child_pid = try std.posix.fork(); if (child_pid == 0) { - startSession(options, pwd, handle, current_environment) catch |e| { + startSession(options, tty_str, pwd, handle, current_environment) catch |e| { shared_err.writeError(e); std.process.exit(1); }; @@ -132,6 +132,7 @@ pub fn authenticate(options: AuthOptions, current_environment: Environment, logi fn startSession( options: AuthOptions, + tty_str: [:0]u8, pwd: *interop.pwd.passwd, handle: ?*interop.pam.pam_handle, current_environment: Environment, @@ -155,6 +156,10 @@ fn startSession( // Set up the environment try initEnv(pwd, options.path); + // Reset the XDG environment variables + setXdgSessionEnv(current_environment.display_server); + try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names); + // Set the PAM variables const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle); if (pam_env_vars == null) return error.GetEnvListFailed; From 9d23209ca30b13f1f97942952138b8e9bdb17ec9 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Tue, 8 Jul 2025 16:36:02 +0200 Subject: [PATCH 05/11] Backport: Fix character width calculation Signed-off-by: AnErrupTion --- src/tui/TerminalBuffer.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tui/TerminalBuffer.zig b/src/tui/TerminalBuffer.zig index ca072f6..c173280 100644 --- a/src/tui/TerminalBuffer.zig +++ b/src/tui/TerminalBuffer.zig @@ -207,9 +207,9 @@ pub fn drawColorLabel(text: []const u8, x: usize, y: usize, fg: u32, bg: u32) vo const utf8view = std.unicode.Utf8View.init(text) catch return; var utf8 = utf8view.iterator(); - var i = x; - while (utf8.nextCodepoint()) |codepoint| : (i += 1) { - _ = termbox.tb_set_cell(@intCast(i), yc, codepoint, fg, bg); + var i: c_int = @intCast(x); + while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) { + _ = termbox.tb_set_cell(i, yc, codepoint, fg, bg); } } @@ -218,10 +218,10 @@ pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: us const utf8view = std.unicode.Utf8View.init(text) catch return; var utf8 = utf8view.iterator(); - var i: usize = 0; - while (utf8.nextCodepoint()) |codepoint| : (i += 1) { + var i: c_int = @intCast(x); + while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) { if (i >= max_length) break; - _ = termbox.tb_set_cell(@intCast(i + x), yc, codepoint, self.fg, self.bg); + _ = termbox.tb_set_cell(i, yc, codepoint, self.fg, self.bg); } } @@ -235,7 +235,7 @@ pub fn drawCharMultiple(self: TerminalBuffer, char: u32, x: usize, y: usize, len pub fn strWidth(str: []const u8) !u8 { const utf8view = try std.unicode.Utf8View.init(str); var utf8 = utf8view.iterator(); - var i: u8 = 0; - while (utf8.nextCodepoint()) |_| i += 1; - return i; + var i: c_int = 0; + while (utf8.nextCodepoint()) |codepoint| i += termbox.tb_wcwidth(codepoint); + return @intCast(i); } From faa2636c9963a71799c45363a868da71c42243fc Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Tue, 8 Jul 2025 16:37:48 +0200 Subject: [PATCH 06/11] Start Ly v1.1.2 development cycle Signed-off-by: AnErrupTion --- build.zig | 2 +- build.zig.zon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 194fff5..c7cb249 100644 --- a/build.zig +++ b/build.zig @@ -21,7 +21,7 @@ comptime { } } -const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 1 }; +const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 2 }; var dest_directory: []const u8 = undefined; var config_directory: []const u8 = undefined; diff --git a/build.zig.zon b/build.zig.zon index 8e66a31..fe71ef9 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .ly, - .version = "1.1.1", + .version = "1.1.2", .fingerprint = 0xa148ffcc5dc2cb59, .minimum_zig_version = "0.14.0", .dependencies = .{ From 3359127a06dfdf8e3d9d5de89aa61bd421d3aa0d Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 2 Aug 2025 01:00:10 +0200 Subject: [PATCH 07/11] Backport: Reorder default PATH to prioritize /usr/local directories to solve Signed-off-by: AnErrupTion --- res/config.ini | 2 +- src/config/Config.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/config.ini b/res/config.ini index 53050e4..f8f768f 100644 --- a/res/config.ini +++ b/res/config.ini @@ -171,7 +171,7 @@ numlock = false # Default path # If null, ly doesn't set a path -path = /sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin +path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Command executed when pressing restart_key restart_cmd = /sbin/shutdown -r now diff --git a/src/config/Config.zig b/src/config/Config.zig index c0f3411..0d2cc5f 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -48,7 +48,7 @@ margin_box_h: u8 = 2, margin_box_v: u8 = 1, min_refresh_delta: u16 = 5, numlock: bool = false, -path: ?[:0]const u8 = "/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", +path: ?[:0]const u8 = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", restart_cmd: []const u8 = "/sbin/shutdown -r now", restart_key: []const u8 = "F2", save: bool = true, From b7d81a9b51dc9008f0678e4ecf98447cfe79b37d Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 2 Aug 2025 01:00:56 +0200 Subject: [PATCH 08/11] Backport: Fix possible overflow with 5-digit+ UIDs Signed-off-by: AnErrupTion --- src/auth.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth.zig b/src/auth.zig index 721516f..68204e2 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -213,7 +213,7 @@ fn setXdgEnv(tty_str: [:0]u8, maybe_desktop_name: ?[:0]const u8, maybe_xdg_deskt // directory. if (builtin.os.tag != .freebsd) { const uid = interop.unistd.getuid(); - var uid_buffer: [10 + @sizeOf(u32) + 1]u8 = undefined; + var uid_buffer: [32]u8 = undefined; // No UID can be larger than this const uid_str = try std.fmt.bufPrintZ(&uid_buffer, "/run/user/{d}", .{uid}); _ = interop.stdlib.setenv("XDG_RUNTIME_DIR", uid_str, 0); From a4dd5b3c4493bcbc6320ece2d46170e9954cc4fc Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 2 Aug 2025 13:16:35 +0200 Subject: [PATCH 09/11] Backport: Fix clock string length issues Co-authored-by: Plash Signed-off-by: AnErrupTion --- src/interop.zig | 4 +--- src/main.zig | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/interop.zig b/src/interop.zig index 9fc5017..c153f35 100644 --- a/src/interop.zig +++ b/src/interop.zig @@ -65,12 +65,10 @@ 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; const capslock_led = if (builtin.os.tag.isBSD()) kbio.LED_CAP else kd.K_CAPSLOCK; -pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) ![]u8 { +pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) []u8 { const timer = std.time.timestamp(); const tm_info = time.localtime(&timer); - const len = time.strftime(buf, buf.len, format, tm_info); - if (len < 0) return error.CannotGetFormattedTime; return buf[0..len]; } diff --git a/src/main.zig b/src/main.zig index a182d89..8697f28 100644 --- a/src/main.zig +++ b/src/main.zig @@ -101,6 +101,7 @@ pub fn main() !void { var lang: Lang = undefined; var save: Save = undefined; var config_load_failed = false; + var can_draw_clock = true; if (res.args.help != 0) { try clap.help(stderr, clap.Help, ¶ms, .{}); @@ -426,15 +427,13 @@ pub fn main() !void { buffer.drawLabel(ly_top_str, 0, 0); - if (config.bigclock != .none and buffer.box_height + (bigclock.HEIGHT + 2) * 2 < buffer.height) draw_big_clock: { + if (config.bigclock != .none and buffer.box_height + (bigclock.HEIGHT + 2) * 2 < buffer.height) { const format = "%H:%M"; const xo = buffer.width / 2 - @min(buffer.width, (format.len * (bigclock.WIDTH + 1))) / 2; const yo = (buffer.height - buffer.box_height) / 2 - bigclock.HEIGHT - 2; var clock_buf: [format.len + 1:0]u8 = undefined; - const clock_str = interop.timeAsString(&clock_buf, format) catch { - break :draw_big_clock; - }; + const clock_str = interop.timeAsString(&clock_buf, format); for (clock_str, 0..) |c, i| { const clock_cell = bigclock.clockCell(animate, c, buffer.fg, buffer.bg, config.bigclock); @@ -466,12 +465,17 @@ pub fn main() !void { } if (config.clock) |clock| draw_clock: { - var clock_buf: [32:0]u8 = undefined; - const clock_str = interop.timeAsString(&clock_buf, clock) catch { - break :draw_clock; - }; + if (!can_draw_clock) break :draw_clock; - if (clock_str.len == 0) return error.FormattedTimeEmpty; + var clock_buf: [64:0]u8 = undefined; + const clock_str = interop.timeAsString(&clock_buf, clock); + + if (clock_str.len == 0) { + // Backport: I've decided not to localize the error message + try info_line.addMessage("clock string too long", config.error_bg, config.error_fg); + can_draw_clock = false; + break :draw_clock; + } buffer.drawLabel(clock_str, buffer.width - @min(buffer.width, clock_str.len), 0); } From 32d0de3d2d8eeb3c5d3cf04774dd23a26063b960 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Mon, 4 Aug 2025 00:04:55 +0200 Subject: [PATCH 10/11] Backport: Workaround for session process not exiting immediately Signed-off-by: AnErrupTion --- src/main.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.zig b/src/main.zig index 8697f28..8c4c993 100644 --- a/src/main.zig +++ b/src/main.zig @@ -764,6 +764,9 @@ pub fn main() !void { } _ = std.posix.waitpid(session_pid, 0); + // HACK: It seems like the session process is not exiting immediately after the waitpid call. + // This is a workaround to ensure the session process has exited before re-initializing the TTY. + std.Thread.sleep(std.time.ns_per_s * 1); session_pid = -1; } From a9b6bfc62a6b22e4408ceff4f95ea8a6c8e74fda Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Tue, 5 Aug 2025 21:49:38 +0200 Subject: [PATCH 11/11] Backport: Prevent Ly from zombifying when X.org is terminated Signed-off-by: AnErrupTion --- src/auth.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/auth.zig b/src/auth.zig index 68204e2..595f18c 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -459,8 +459,9 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, options: AuthOptio _ = std.posix.waitpid(xorg_pid, 0); interop.xcb.xcb_disconnect(xcb); - std.posix.kill(x_pid, 0) catch return; - std.posix.kill(x_pid, std.posix.SIG.KILL) catch {}; + std.posix.kill(x_pid, std.posix.SIG.TERM) catch {}; + std.Thread.sleep(std.time.ns_per_s * 1); // Wait 1 second before sending SIGKILL + std.posix.kill(x_pid, std.posix.SIG.KILL) catch return; var status: c_int = 0; _ = std.c.waitpid(x_pid, &status, 0);