mirror of https://github.com/fairyglade/ly.git
Merge 5755550e84
into 5924db58e1
This commit is contained in:
commit
cbcf748a12
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ pub const Animation = enum {
|
||||||
matrix,
|
matrix,
|
||||||
colormix,
|
colormix,
|
||||||
gameoflife,
|
gameoflife,
|
||||||
|
metaballs,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DisplayServer = enum {
|
pub const DisplayServer = enum {
|
||||||
|
|
120
src/main.zig
120
src/main.zig
|
@ -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, ¶ms, clap.parsers.default, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| {
|
var res = clap.parse(clap.Help, ¶ms, 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, ¶ms, .{});
|
try clap.help(stderr, clap.Help, ¶ms, .{});
|
||||||
|
|
||||||
_ = 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue