This commit is contained in:
senchpimy 2025-09-06 16:04:27 -06:00 committed by GitHub
commit cbcf748a12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 194 additions and 56 deletions

View File

@ -0,0 +1,129 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const Animation = @import("../tui/Animation.zig");
const Cell = @import("../tui/Cell.zig");
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
const Metaballs = @This();
const math = std.math;
const Vec2 = @Vector(2, f32);
const num_metaballs = 5;
const min_radius: f32 = 5.0;
const max_radius: f32 = 12.0;
const max_speed: f32 = 0.2;
const threshold: f32 = 0.7;
const Metaball = struct {
pos: Vec2,
vel: Vec2,
radius: f32,
};
allocator: Allocator,
terminal_buffer: *TerminalBuffer,
balls: [num_metaballs]Metaball,
palette: [5]Cell,
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer) !Metaballs {
var self = Metaballs{
.allocator = allocator,
.terminal_buffer = terminal_buffer,
.balls = undefined,
.palette = [_]Cell{
Cell.init(' ', 0x2c0000, 0x4f0000),
Cell.init(0x2591, 0x8b0000, 0xae0000),
Cell.init(0x2592, 0xff4500, 0xff6347),
Cell.init(0x2593, 0xffa500, 0xffd700),
Cell.init(0x2588, 0xffff00, 0xffffe0),
},
};
self.initBalls();
return self;
}
fn initBalls(self: *Metaballs) void {
const width_f = @as(f32, @floatFromInt(self.terminal_buffer.width));
const height_f = @as(f32, @floatFromInt(self.terminal_buffer.height));
const rand = self.terminal_buffer.random;
for (&self.balls) |*ball| {
ball.* = .{
.pos = .{
rand.float(f32) * width_f,
rand.float(f32) * height_f,
},
.vel = .{
(rand.float(f32) - 0.5) * 2.0 * max_speed,
(rand.float(f32) - 0.5) * 2.0 * max_speed,
},
.radius = min_radius + (rand.float(f32) * (max_radius - min_radius)),
};
}
}
pub fn animation(self: *Metaballs) Animation {
return Animation.init(self, deinit, realloc, draw);
}
fn deinit(_: *Metaballs) void {}
fn realloc(self: *Metaballs) anyerror!void {
self.initBalls();
}
fn draw(self: *Metaballs) void {
const width = self.terminal_buffer.width;
const height = self.terminal_buffer.height;
const width_f = @as(f32, @floatFromInt(width));
const height_f = @as(f32, @floatFromInt(height));
for (&self.balls) |*ball| {
ball.pos += ball.vel;
if (ball.pos[0] < 0 or ball.pos[0] > width_f) {
ball.vel[0] *= -1.0;
ball.pos[0] = math.clamp(ball.pos[0], 0, width_f);
}
if (ball.pos[1] < 0 or ball.pos[1] > height_f) {
ball.vel[1] *= -1.0;
ball.pos[1] = math.clamp(ball.pos[1], 0, height_f);
}
}
for (0..height) |y| {
for (0..width) |x| {
const cell_pos = Vec2{
@as(f32, @floatFromInt(x)) + 0.5,
@as(f32, @floatFromInt(y)) + 0.5,
};
var sum_influence: f32 = 0.0;
for (self.balls) |ball| {
const dist_vec = cell_pos - ball.pos;
const dist_sq = (dist_vec[0] * dist_vec[0]) + (dist_vec[1] * dist_vec[1]);
if (dist_sq == 0) {
sum_influence += 1000.0;
} else {
sum_influence += (ball.radius * ball.radius) / dist_sq;
}
}
if (sum_influence > threshold * 1.1) {
self.palette[4].put(x, y);
} else if (sum_influence > threshold * 1.0) {
self.palette[3].put(x, y);
} else if (sum_influence > threshold * 0.9) {
self.palette[2].put(x, y);
} else if (sum_influence > threshold * 0.8) {
self.palette[1].put(x, y);
} else {
self.palette[0].put(x, y);
}
}
}
}

View File

@ -4,6 +4,7 @@ pub const Animation = enum {
matrix, matrix,
colormix, colormix,
gameoflife, gameoflife,
metaballs,
}; };
pub const DisplayServer = enum { pub const DisplayServer = enum {

View File

@ -10,6 +10,7 @@ const Environment = @import("Environment.zig");
const interop = @import("interop.zig"); const interop = @import("interop.zig");
const ColorMix = @import("animations/ColorMix.zig"); const ColorMix = @import("animations/ColorMix.zig");
const Doom = @import("animations/Doom.zig"); const Doom = @import("animations/Doom.zig");
const Metaballs = @import("animations/Metaballs.zig");
const Dummy = @import("animations/Dummy.zig"); const Dummy = @import("animations/Dummy.zig");
const Matrix = @import("animations/Matrix.zig"); const Matrix = @import("animations/Matrix.zig");
const GameOfLife = @import("animations/GameOfLife.zig"); const GameOfLife = @import("animations/GameOfLife.zig");
@ -31,11 +32,12 @@ const Ini = ini.Ini;
const DisplayServer = enums.DisplayServer; const DisplayServer = enums.DisplayServer;
const Entry = Environment.Entry; const Entry = Environment.Entry;
const termbox = interop.termbox; const termbox = interop.termbox;
const unistd = interop.unistd;
const temporary_allocator = std.heap.page_allocator; const temporary_allocator = std.heap.page_allocator;
const ly_top_str = "Ly version " ++ build_options.version; const ly_top_str = "Ly version " ++ build_options.version;
var session_pid: std.posix.pid_t = -1; var session_pid: std.posix.pid_t = -1;
fn signalHandler(i: c_int) callconv(.c) void { fn signalHandler(i: c_int) callconv(.C) void {
if (session_pid == 0) return; if (session_pid == 0) return;
// Forward signal to session to clean up // Forward signal to session to clean up
@ -49,7 +51,7 @@ fn signalHandler(i: c_int) callconv(.c) void {
std.c.exit(i); std.c.exit(i);
} }
fn ttyControlTransferSignalHandler(_: c_int) callconv(.c) void { fn ttyControlTransferSignalHandler(_: c_int) callconv(.C) void {
_ = termbox.tb_shutdown(); _ = termbox.tb_shutdown();
} }
@ -59,20 +61,16 @@ pub fn main() !void {
var shutdown_cmd: []const u8 = undefined; var shutdown_cmd: []const u8 = undefined;
var restart_cmd: []const u8 = undefined; var restart_cmd: []const u8 = undefined;
var stderr_buffer: [128]u8 = undefined; const stderr = std.io.getStdErr().writer();
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
var stderr = &stderr_writer.interface;
defer { defer {
// If we can't shutdown or restart due to an error, we print it to standard error. If that fails, just bail out // If we can't shutdown or restart due to an error, we print it to standard error. If that fails, just bail out
if (shutdown) { if (shutdown) {
const shutdown_error = std.process.execv(temporary_allocator, &[_][]const u8{ "/bin/sh", "-c", shutdown_cmd }); const shutdown_error = std.process.execv(temporary_allocator, &[_][]const u8{ "/bin/sh", "-c", shutdown_cmd });
stderr.print("error: couldn't shutdown: {s}\n", .{@errorName(shutdown_error)}) catch std.process.exit(1); stderr.print("error: couldn't shutdown: {s}\n", .{@errorName(shutdown_error)}) catch std.process.exit(1);
stderr.flush() catch std.process.exit(1);
} else if (restart) { } else if (restart) {
const restart_error = std.process.execv(temporary_allocator, &[_][]const u8{ "/bin/sh", "-c", restart_cmd }); const restart_error = std.process.execv(temporary_allocator, &[_][]const u8{ "/bin/sh", "-c", restart_cmd });
stderr.print("error: couldn't restart: {s}\n", .{@errorName(restart_error)}) catch std.process.exit(1); stderr.print("error: couldn't restart: {s}\n", .{@errorName(restart_error)}) catch std.process.exit(1);
stderr.flush() catch std.process.exit(1);
} else { } else {
// The user has quit Ly using Ctrl+C // The user has quit Ly using Ctrl+C
temporary_allocator.free(shutdown_cmd); temporary_allocator.free(shutdown_cmd);
@ -84,7 +82,8 @@ pub fn main() !void {
defer _ = gpa.deinit(); defer _ = gpa.deinit();
// Allows stopping an animation after some time // Allows stopping an animation after some time
const time_start = try interop.getTimeOfDay(); var tv_zero: interop.system_time.timeval = undefined;
_ = interop.system_time.gettimeofday(&tv_zero, null);
var animation_timed_out: bool = false; var animation_timed_out: bool = false;
const allocator = gpa.allocator(); const allocator = gpa.allocator();
@ -99,7 +98,6 @@ pub fn main() !void {
var diag = clap.Diagnostic{}; var diag = clap.Diagnostic{};
var res = clap.parse(clap.Help, &params, clap.parsers.default, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| { var res = clap.parse(clap.Help, &params, clap.parsers.default, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| {
diag.report(stderr, err) catch {}; diag.report(stderr, err) catch {};
try stderr.flush();
return err; return err;
}; };
defer res.deinit(); defer res.deinit();
@ -115,12 +113,10 @@ pub fn main() !void {
try clap.help(stderr, clap.Help, &params, .{}); try clap.help(stderr, clap.Help, &params, .{});
_ = try stderr.write("Note: if you want to configure Ly, please check the config file, which is located at " ++ build_options.config_directory ++ "/ly/config.ini.\n"); _ = try stderr.write("Note: if you want to configure Ly, please check the config file, which is located at " ++ build_options.config_directory ++ "/ly/config.ini.\n");
try stderr.flush();
std.process.exit(0); std.process.exit(0);
} }
if (res.args.version != 0) { if (res.args.version != 0) {
_ = try stderr.write("Ly version " ++ build_options.version ++ "\n"); _ = try stderr.write("Ly version " ++ build_options.version ++ "\n");
try stderr.flush();
std.process.exit(0); std.process.exit(0);
} }
@ -164,7 +160,7 @@ pub fn main() !void {
.comment_characters = comment_characters, .comment_characters = comment_characters,
}) catch Lang{}; }) catch Lang{};
if (config.save) { if (config.load) {
save_path = try std.fmt.allocPrint(allocator, "{s}{s}save.ini", .{ s, trailing_slash }); save_path = try std.fmt.allocPrint(allocator, "{s}{s}save.ini", .{ s, trailing_slash });
save_path_alloc = true; save_path_alloc = true;
@ -197,7 +193,7 @@ pub fn main() !void {
.comment_characters = comment_characters, .comment_characters = comment_characters,
}) catch Lang{}; }) catch Lang{};
if (config.save) { if (config.load) {
var user_buf: [32]u8 = undefined; var user_buf: [32]u8 = undefined;
save = save_ini.readFileToStruct(save_path, .{ save = save_ini.readFileToStruct(save_path, .{
.fieldHandler = null, .fieldHandler = null,
@ -227,16 +223,17 @@ pub fn main() !void {
log_file = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only }); log_file = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only });
} }
var log_buffer: [1024]u8 = undefined; const log_writer = log_file.writer();
var log_file_writer = log_file.writer(&log_buffer);
// Seek to the end of the log file // if (migrator.mapped_config_fields) save_migrated_config: {
if (could_open_log_file) { // var file = try std.fs.cwd().createFile(config_path, .{});
const stat = try log_file.stat(); // defer file.close();
try log_file_writer.seekTo(stat.size);
}
var log_writer = &log_file_writer.interface; // const writer = file.writer();
// ini.writeFromStruct(config, writer, null, true, .{}) catch {
// break :save_migrated_config;
// };
// }
// These strings only end up getting freed if the user quits Ly using Ctrl+C, which is fine since in the other cases // These strings only end up getting freed if the user quits Ly using Ctrl+C, which is fine since in the other cases
// we end up shutting down or restarting the system // we end up shutting down or restarting the system
@ -253,7 +250,7 @@ pub fn main() !void {
const act = std.posix.Sigaction{ const act = std.posix.Sigaction{
.handler = .{ .handler = &signalHandler }, .handler = .{ .handler = &signalHandler },
.mask = std.posix.sigemptyset(), .mask = std.posix.empty_sigset,
.flags = 0, .flags = 0,
}; };
std.posix.sigaction(std.posix.SIG.TERM, &act, null); std.posix.sigaction(std.posix.SIG.TERM, &act, null);
@ -390,7 +387,7 @@ pub fn main() !void {
var insert_mode = !config.vi_mode or config.vi_default_mode == .insert; var insert_mode = !config.vi_mode or config.vi_default_mode == .insert;
// Load last saved username and desktop selection, if any // Load last saved username and desktop selection, if any
if (config.save) { if (config.load) {
if (save.user) |user| { if (save.user) |user| {
// Find user with saved name, and switch over to it // Find user with saved name, and switch over to it
// If it doesn't exist (anymore), we don't change the value // If it doesn't exist (anymore), we don't change the value
@ -456,6 +453,10 @@ pub fn main() !void {
var game_of_life = try GameOfLife.init(allocator, &buffer, config.gameoflife_fg, config.gameoflife_entropy_interval, config.gameoflife_frame_delay, config.gameoflife_initial_density); var game_of_life = try GameOfLife.init(allocator, &buffer, config.gameoflife_fg, config.gameoflife_entropy_interval, config.gameoflife_frame_delay, config.gameoflife_initial_density);
animation = game_of_life.animation(); animation = game_of_life.animation();
}, },
.metaballs => {
var metaballs = try Metaballs.init(allocator, &buffer);
animation = metaballs.animation();
},
} }
defer animation.deinit(); defer animation.deinit();
@ -540,7 +541,7 @@ pub fn main() !void {
var format_buf: [16:0]u8 = undefined; var format_buf: [16:0]u8 = undefined;
var clock_buf: [32:0]u8 = undefined; var clock_buf: [32:0]u8 = undefined;
// We need the slice/c-string returned by `bufPrintZ`. // We need the slice/c-string returned by `bufPrintZ`.
const format = try std.fmt.bufPrintZ(&format_buf, "{s}{s}{s}{s}", .{ const format: [:0]const u8 = try std.fmt.bufPrintZ(&format_buf, "{s}{s}{s}{s}", .{
if (config.bigclock_12hr) "%I" else "%H", if (config.bigclock_12hr) "%I" else "%H",
":%M", ":%M",
if (config.bigclock_seconds) ":%S" else "", if (config.bigclock_seconds) ":%S" else "",
@ -552,8 +553,7 @@ pub fn main() !void {
const clock_str = interop.timeAsString(&clock_buf, format); const clock_str = interop.timeAsString(&clock_buf, format);
for (clock_str, 0..) |c, i| { for (clock_str, 0..) |c, i| {
// TODO: Show error const clock_cell = bigclock.clockCell(animate, c, buffer.fg, buffer.bg, config.bigclock);
const clock_cell = try bigclock.clockCell(animate, c, buffer.fg, buffer.bg, config.bigclock);
bigclock.alphaBlit(xo + i * (bigclock.WIDTH + 1), yo, buffer.width, buffer.height, clock_cell); bigclock.alphaBlit(xo + i * (bigclock.WIDTH + 1), yo, buffer.width, buffer.height, clock_cell);
} }
} }
@ -688,21 +688,24 @@ pub fn main() !void {
if (animate and !animation_timed_out) { if (animate and !animation_timed_out) {
timeout = config.min_refresh_delta; timeout = config.min_refresh_delta;
// Check how long we've been running so we can turn off the animation // check how long we have been running so we can turn off the animation
const time = try interop.getTimeOfDay(); var tv: interop.system_time.timeval = undefined;
_ = interop.system_time.gettimeofday(&tv, null);
if (config.animation_timeout_sec > 0 and time.seconds - time_start.seconds > config.animation_timeout_sec) { if (config.animation_timeout_sec > 0 and tv.tv_sec - tv_zero.tv_sec > config.animation_timeout_sec) {
animation_timed_out = true; animation_timed_out = true;
animation.deinit(); animation.deinit();
} }
} else if (config.bigclock != .none and config.clock == null) { } else if (config.bigclock != .none and config.clock == null) {
const time = try interop.getTimeOfDay(); var tv: interop.system_time.timeval = undefined;
_ = interop.system_time.gettimeofday(&tv, null);
timeout = @intCast((60 - @rem(time.seconds, 60)) * 1000 - @divTrunc(time.microseconds, 1000) + 1); timeout = @intCast((60 - @rem(tv.tv_sec, 60)) * 1000 - @divTrunc(tv.tv_usec, 1000) + 1);
} else if (config.clock != null or auth_fails >= config.auth_fails) { } else if (config.clock != null or auth_fails >= config.auth_fails) {
const time = try interop.getTimeOfDay(); var tv: interop.system_time.timeval = undefined;
_ = interop.system_time.gettimeofday(&tv, null);
timeout = @intCast(1000 - @divTrunc(time.microseconds, 1000) + 1); timeout = @intCast(1000 - @divTrunc(tv.tv_usec, 1000) + 1);
} }
const event_error = if (timeout == -1) termbox.tb_poll_event(&event) else termbox.tb_peek_event(&event, timeout); const event_error = if (timeout == -1) termbox.tb_poll_event(&event) else termbox.tb_peek_event(&event, timeout);
@ -794,7 +797,7 @@ pub fn main() !void {
update = true; update = true;
}, },
termbox.TB_KEY_ENTER => authenticate: { termbox.TB_KEY_ENTER => authenticate: {
try log_writer.writeAll("authenticating...\n"); try log_writer.writeAll("authenticating...");
if (!config.allow_empty_password and password.text.items.len == 0) { if (!config.allow_empty_password and password.text.items.len == 0) {
// Let's not log this message for security reasons // Let's not log this message for security reasons
@ -820,16 +823,11 @@ pub fn main() !void {
var file = std.fs.cwd().createFile(save_path, .{}) catch break :save_last_settings; var file = std.fs.cwd().createFile(save_path, .{}) catch break :save_last_settings;
defer file.close(); defer file.close();
var file_buffer: [64]u8 = undefined;
var file_writer = file.writer(&file_buffer);
var writer = &file_writer.interface;
const save_data = Save{ const save_data = Save{
.user = login.getCurrentUser(), .user = login.getCurrentUser(),
.session_index = session.label.current, .session_index = session.label.current,
}; };
ini.writeFromStruct(save_data, writer, null, .{}) catch break :save_last_settings; ini.writeFromStruct(save_data, file.writer(), null, .{}) catch break :save_last_settings;
try writer.flush();
// Delete previous save file if it exists // Delete previous save file if it exists
if (migrator.maybe_save_file) |path| std.fs.cwd().deleteFile(path) catch {}; if (migrator.maybe_save_file) |path| std.fs.cwd().deleteFile(path) catch {};
@ -839,6 +837,11 @@ pub fn main() !void {
defer shared_err.deinit(); defer shared_err.deinit();
{ {
const login_text = try allocator.dupeZ(u8, login.getCurrentUser());
defer allocator.free(login_text);
const password_text = try allocator.dupeZ(u8, password.text.items);
defer allocator.free(password_text);
session_pid = try std.posix.fork(); session_pid = try std.posix.fork();
if (session_pid == 0) { if (session_pid == 0) {
const current_environment = session.label.list.items[session.label.current]; const current_environment = session.label.list.items[session.label.current];
@ -857,12 +860,12 @@ pub fn main() !void {
// Signal action to give up control on the TTY // Signal action to give up control on the TTY
const tty_control_transfer_act = std.posix.Sigaction{ const tty_control_transfer_act = std.posix.Sigaction{
.handler = .{ .handler = &ttyControlTransferSignalHandler }, .handler = .{ .handler = &ttyControlTransferSignalHandler },
.mask = std.posix.sigemptyset(), .mask = std.posix.empty_sigset,
.flags = 0, .flags = 0,
}; };
std.posix.sigaction(std.posix.SIG.CHLD, &tty_control_transfer_act, null); std.posix.sigaction(std.posix.SIG.CHLD, &tty_control_transfer_act, null);
auth.authenticate(allocator, log_writer, auth_options, current_environment, login.getCurrentUser(), password.text.items) catch |err| { auth.authenticate(auth_options, current_environment, login_text, password_text) catch |err| {
shared_err.writeError(err); shared_err.writeError(err);
std.process.exit(1); std.process.exit(1);
}; };
@ -900,7 +903,7 @@ pub fn main() !void {
password.clear(); password.clear();
try info_line.addMessage(lang.logout, config.bg, config.fg); try info_line.addMessage(lang.logout, config.bg, config.fg);
try log_writer.writeAll("logged out\n"); try log_writer.writeAll("logged out");
} }
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios); try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
@ -957,15 +960,13 @@ pub fn main() !void {
update = true; update = true;
}, },
} }
try log_writer.flush();
} }
} }
fn ttyClearScreen() !void { fn ttyClearScreen() !void {
// Clear the TTY because termbox2 doesn't seem to do it properly // Clear the TTY because termbox2 doesn't seem to do it properly
const capability = termbox.global.caps[termbox.TB_CAP_CLEAR_SCREEN]; const capability = termbox.global.caps[termbox.TB_CAP_CLEAR_SCREEN];
const capability_slice = std.mem.span(capability); const capability_slice = capability[0..std.mem.len(capability)];
_ = try std.posix.write(termbox.global.ttyfd, capability_slice); _ = try std.posix.write(termbox.global.ttyfd, capability_slice);
} }
@ -1016,7 +1017,7 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
// Prepare the XDG_CURRENT_DESKTOP environment variable here // Prepare the XDG_CURRENT_DESKTOP environment variable here
const entry = entry_ini.data.@"Desktop Entry"; const entry = entry_ini.data.@"Desktop Entry";
var maybe_xdg_desktop_names: ?[]const u8 = null; var maybe_xdg_desktop_names: ?[:0]const u8 = null;
if (entry.DesktopNames) |desktop_names| { if (entry.DesktopNames) |desktop_names| {
for (desktop_names) |*c| { for (desktop_names) |*c| {
if (c.* == ';') c.* = ':'; if (c.* == ';') c.* = ':';
@ -1024,10 +1025,13 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
maybe_xdg_desktop_names = desktop_names; maybe_xdg_desktop_names = desktop_names;
} }
const maybe_session_desktop = if (maybe_xdg_session_desktop) |xdg_session_desktop| try session.label.allocator.dupeZ(u8, xdg_session_desktop) else null;
errdefer if (maybe_session_desktop) |session_desktop| session.label.allocator.free(session_desktop);
try session.addEnvironment(.{ try session.addEnvironment(.{
.entry_ini = entry_ini, .entry_ini = entry_ini,
.name = entry.Name, .name = entry.Name,
.xdg_session_desktop = maybe_xdg_session_desktop, .xdg_session_desktop = maybe_session_desktop,
.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) {
@ -1046,20 +1050,24 @@ fn getAllUsernames(allocator: std.mem.Allocator, login_defs_path: []const u8) !S
const uid_range = try getUserIdRange(allocator, login_defs_path); const uid_range = try getUserIdRange(allocator, login_defs_path);
var usernames: StringList = .empty; var usernames: StringList = .empty;
var maybe_entry = interop.getNextUsernameEntry(); var maybe_entry = interop.pwd.getpwent();
while (maybe_entry != null) {
const entry = maybe_entry.*;
while (maybe_entry) |entry| {
// We check if the UID is equal to 0 because we always want to add root // We check if the UID is equal to 0 because we always want to add root
// as a username (even if you can't log into it) // as a username (even if you can't log into it)
if (entry.uid >= uid_range.uid_min and entry.uid <= uid_range.uid_max or entry.uid == 0 and entry.username != null) { if (entry.pw_uid >= uid_range.uid_min and entry.pw_uid <= uid_range.uid_max or entry.pw_uid == 0) {
const username = try allocator.dupe(u8, entry.username.?); const pw_name_slice = entry.pw_name[0..std.mem.len(entry.pw_name)];
const username = try allocator.dupe(u8, pw_name_slice);
try usernames.append(allocator, username); try usernames.append(allocator, username);
} }
maybe_entry = interop.getNextUsernameEntry(); maybe_entry = interop.pwd.getpwent();
} }
interop.closePasswordDatabase(); interop.pwd.endpwent();
return usernames; return usernames;
} }
@ -1079,9 +1087,9 @@ fn getUserIdRange(allocator: std.mem.Allocator, login_defs_path: []const u8) !Ui
const trimmed_line = std.mem.trim(u8, line, " \n\r\t"); const trimmed_line = std.mem.trim(u8, line, " \n\r\t");
if (std.mem.startsWith(u8, trimmed_line, "UID_MIN")) { if (std.mem.startsWith(u8, trimmed_line, "UID_MIN")) {
uid_range.uid_min = try parseValue(std.posix.uid_t, "UID_MIN", trimmed_line); uid_range.uid_min = try parseValue(std.c.uid_t, "UID_MIN", trimmed_line);
} else if (std.mem.startsWith(u8, trimmed_line, "UID_MAX")) { } else if (std.mem.startsWith(u8, trimmed_line, "UID_MAX")) {
uid_range.uid_max = try parseValue(std.posix.uid_t, "UID_MAX", trimmed_line); uid_range.uid_max = try parseValue(std.c.uid_t, "UID_MAX", trimmed_line);
} }
} }