diff --git a/res/config.ini b/res/config.ini index a290773..6948a5c 100644 --- a/res/config.ini +++ b/res/config.ini @@ -292,6 +292,10 @@ login_cmd = null # Linux) login_defs_path = /etc/login.defs +# If true, user need to manually type username instead of selecting from the list +# of discovered users +type_username = false + # Command executed when logging out # If null, no command will be executed # Important: the session will already be terminated when this command is executed, so diff --git a/src/config/Config.zig b/src/config/Config.zig index a592faa..fd3ee3d 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -73,6 +73,7 @@ input_len: u8 = 34, lang: []const u8 = "en", login_cmd: ?[]const u8 = null, login_defs_path: []const u8 = "/etc/login.defs", +type_username: bool = false, logout_cmd: ?[]const u8 = null, ly_log: ?[]const u8 = "/var/log/ly.log", margin_box_h: u8 = 2, diff --git a/src/main.zig b/src/main.zig index 0f6f1e0..0dfeaed 100644 --- a/src/main.zig +++ b/src/main.zig @@ -108,6 +108,7 @@ const UiState = struct { session: Session, saved_users: SavedUsers, login: UserList, + login_text: ?*Text, password: *Text, password_widget: *Widget, insert_mode: bool, @@ -781,8 +782,10 @@ pub fn main(init: std.process.Init) !void { ); defer state.login.deinit(); - try state.buffer.registerKeybind(state.io, &state.login.label.keybinds, "H", &viGoLeft, &state); - try state.buffer.registerKeybind(state.io, &state.login.label.keybinds, "L", &viGoRight, &state); + if (!state.config.type_username) { + try state.buffer.registerKeybind(state.io, &state.login.label.keybinds, "H", &viGoLeft, &state); + try state.buffer.registerKeybind(state.io, &state.login.label.keybinds, "L", &viGoRight, &state); + } if (state.config.shell) { addOtherEnvironment(&state.session, state.lang, .shell, null) catch |err| { @@ -886,7 +889,7 @@ pub fn main(init: std.process.Init) !void { ); } - if (usernames.items.len == 0) { + if (usernames.items.len == 0 and !state.config.type_username) { // If we have no usernames, simply add an error to the info line. // This effectively means you can't login, since there would be no local // accounts *and* no root account...but at this point, if that's the @@ -925,6 +928,23 @@ pub fn main(init: std.process.Init) !void { state.password_widget = state.password.widget(); + if (state.config.type_username) { + state.login_text = try Text.init( + state.allocator, + state.io, + &state.buffer, + state.insert_mode, + false, + null, + state.box.width - 2 * state.box.horizontal_margin - state.labels_max_length - 1, + state.buffer.fg, + state.buffer.bg, + ); + } else { + state.login_text = null; + } + defer if (state.login_text) |lt| lt.deinit(); + state.version_label = Label.init( ly_version_str, null, @@ -938,6 +958,8 @@ pub fn main(init: std.process.Init) !void { state.is_autologin = false; check_autologin: { + if (state.config.type_username) break :check_autologin; + const auto_user = state.config.auto_login_user orelse break :check_autologin; const auto_session = state.config.auto_login_session orelse break :check_autologin; @@ -1119,7 +1141,7 @@ pub fn main(init: std.process.Init) !void { // Skip if autologin is active to prevent overriding autologin session var default_input = state.config.default_input; - if (state.config.save and !state.is_autologin) { + if (state.config.save and !state.is_autologin and !state.config.type_username) { if (state.saved_users.last_username_index) |index| load_last_user: { // If the saved index isn't valid, bail out if (index >= state.saved_users.user_list.items.len) break :load_last_user; @@ -1143,7 +1165,7 @@ pub fn main(init: std.process.Init) !void { const info_line_widget = state.info_line.widget(); const session_widget = state.session.widget(); - const login_widget = state.login.widget(); + const login_widget = if (state.config.type_username) state.login_text.?.widget() else state.login.widget(); var widgets: std.ArrayList([]*Widget) = .empty; defer widgets.deinit(state.allocator); @@ -1387,6 +1409,7 @@ fn disableInsertMode(ptr: *anyopaque) !bool { if (state.config.vi_mode and state.insert_mode) { state.insert_mode = false; state.password.should_insert = false; + if (state.login_text) |lt| lt.should_insert = false; state.buffer.drawNextFrame(true); } return false; @@ -1398,6 +1421,7 @@ fn enableInsertMode(ptr: *anyopaque) !bool { state.insert_mode = true; state.password.should_insert = true; + if (state.login_text) |lt| lt.should_insert = true; state.buffer.drawNextFrame(true); return false; } @@ -1509,7 +1533,7 @@ fn authenticate(ptr: *anyopaque) !bool { state.info_line.label.draw(); try TerminalBuffer.presentBuffer(); - if (state.config.save) save_last_settings: { + if (state.config.save and !state.config.type_username) save_last_settings: { // It isn't worth cluttering the code with precise error // handling, so let's just report a generic error message, // that should be good enough for debugging anyway. @@ -1593,7 +1617,7 @@ fn authenticate(ptr: *anyopaque) !bool { &state.log_file, auth_options, current_environment, - state.login.getCurrentUsername(), + if (state.config.type_username) state.login_text.?.text.items else state.login.getCurrentUsername(), password_text, ) catch |err| { shared_err.writeError(err); @@ -2118,12 +2142,22 @@ fn positionWidgets(ptr: *anyopaque) !void { .childrenPosition() .resetXFrom(state.info_line.label.childrenPosition()) .addY(1)); - state.login.label.positionY(state.login_label - .childrenPosition() - .addX(state.labels_max_length - TerminalBuffer.strWidth(state.login_label.text) + 1)); + if (state.config.type_username) { + state.login_text.?.positionY(state.login_label + .childrenPosition() + .addX(state.labels_max_length - TerminalBuffer.strWidth(state.login_label.text) + 1)); + } else { + state.login.label.positionY(state.login_label + .childrenPosition() + .addX(state.labels_max_length - TerminalBuffer.strWidth(state.login_label.text) + 1)); + } - state.password_label.positionX(state.login.label - .childrenPosition() + const login_children_pos = if (state.config.type_username) + state.login_text.?.childrenPosition() + else + state.login.label.childrenPosition(); + + state.password_label.positionX(login_children_pos .resetXFrom(state.info_line.label.childrenPosition()) .addY(1)); state.password.positionY(state.password_label