mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-21 11:44:55 +00:00
Compare commits
5 Commits
peterc-s/m
...
JAicewizar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bf4de816e | ||
|
|
c42cf125d3 | ||
|
|
2db48c50c9 | ||
|
|
cc15ab35d0 | ||
|
|
6bf9b928f2 |
@@ -25,7 +25,7 @@ Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
|
|||||||
It is recommended to add a rule for Ly as it currently does not ship one.
|
It is recommended to add a rule for Ly as it currently does not ship one.
|
||||||
|
|
||||||
```
|
```
|
||||||
# dnf install kernel-devel pam-devel libxcb-devel zig
|
# dnf install kernel-devel pam-devel libxcb-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
@@ -40,7 +40,6 @@ The following desktop environments were tested with success:
|
|||||||
- dwm
|
- dwm
|
||||||
- enlightenment
|
- enlightenment
|
||||||
- gnome
|
- gnome
|
||||||
- hyprland
|
|
||||||
- i3
|
- i3
|
||||||
- kde
|
- kde
|
||||||
- labwc
|
- labwc
|
||||||
|
|||||||
@@ -35,14 +35,6 @@
|
|||||||
# matrix -> CMatrix
|
# matrix -> CMatrix
|
||||||
animation = none
|
animation = none
|
||||||
|
|
||||||
# The minimum time between animation frames
|
|
||||||
# 32 -> ~30fps
|
|
||||||
# 16 -> ~60fps
|
|
||||||
# 8 -> ~120fps
|
|
||||||
# 6 -> ~144fps
|
|
||||||
# 4 -> ~240fps
|
|
||||||
animation_refresh_ms = 16
|
|
||||||
|
|
||||||
# Stop the animation after some time
|
# Stop the animation after some time
|
||||||
# 0 -> Run forever
|
# 0 -> Run forever
|
||||||
# 1..2e12 -> Stop the animation after this many seconds
|
# 1..2e12 -> Stop the animation after this many seconds
|
||||||
|
|||||||
@@ -1,60 +1,45 @@
|
|||||||
authenticating = autenticant...
|
|
||||||
brightness_down = abaixar brillantor
|
|
||||||
brightness_up = apujar brillantor
|
|
||||||
capslock = Bloq Majús
|
capslock = Bloq Majús
|
||||||
err_alloc = assignació de memòria fallida
|
err_alloc = falla d'assignació de memòria
|
||||||
err_bounds = índex fora de límits
|
err_bounds = índex fora de límit
|
||||||
err_brightness_change = error en canviar la brillantor
|
err_chdir = error al obrir carpeta home
|
||||||
err_chdir = error en obrir la carpeta home
|
err_console_dev = error al accedir a la consola
|
||||||
err_console_dev = error en accedir a la consola
|
|
||||||
err_dgn_oob = missatge de registre
|
err_dgn_oob = missatge de registre
|
||||||
err_domain = domini invàlid
|
err_domain = domini invàlid
|
||||||
err_envlist = error en obtenir l'envlist
|
err_hostname = error al obtenir el nom del host
|
||||||
err_hostname = error en obtenir el nom de l'amfitrió
|
err_mlock = error al bloquejar la clau de memòria
|
||||||
err_mlock = error en bloquejar la memòria de clau
|
|
||||||
err_null = punter nul
|
err_null = punter nul
|
||||||
err_numlock = error en establir el Bloq num
|
|
||||||
err_pam = error en la transacció pam
|
err_pam = error en la transacció pam
|
||||||
err_pam_abort = transacció pam avortada
|
err_pam_abort = transacció pam avortada
|
||||||
err_pam_acct_expired = compte expirat
|
err_pam_acct_expired = compte expirat
|
||||||
err_pam_auth = error d'autenticació
|
err_pam_auth = error d'autenticació
|
||||||
err_pam_authinfo_unavail = error en obtenir la informació de l'usuari
|
err_pam_authinfo_unavail = error al obtenir informació de l'usuari
|
||||||
err_pam_authok_reqd = token expirat
|
err_pam_authok_reqd = token expirat
|
||||||
err_pam_buf = error en la memòria intermèdia
|
err_pam_buf = error de la memòria intermitja
|
||||||
err_pam_cred_err = error en establir les credencials
|
err_pam_cred_err = error al establir les credencials
|
||||||
err_pam_cred_expired = credencials expirades
|
err_pam_cred_expired = credencials expirades
|
||||||
err_pam_cred_insufficient = credencials insuficients
|
err_pam_cred_insufficient = credencials insuficients
|
||||||
err_pam_cred_unavail = error en obtenir credencials
|
err_pam_cred_unavail = error al obtenir credencials
|
||||||
err_pam_maxtries = s'ha assolit al nombre màxim d'intents
|
err_pam_maxtries = s'ha assolit al màxim nombre d'intents
|
||||||
err_pam_perm_denied = permís denegat
|
err_pam_perm_denied = permís denegat
|
||||||
err_pam_session = error de sessió
|
err_pam_session = error de sessió
|
||||||
err_pam_sys = error de sistema
|
err_pam_sys = error de sistema
|
||||||
err_pam_user_unknown = usuari desconegut
|
err_pam_user_unknown = usuari desconegut
|
||||||
err_path = error en establir la ruta
|
err_path = error al establir la ruta
|
||||||
err_perm_dir = error en canviar el directori actual
|
err_perm_dir = error al canviar de directori actual
|
||||||
err_perm_group = error en degradar els permisos de grup
|
err_perm_group = error al degradar els permisos de grup
|
||||||
err_perm_user = error en degradar els permisos de l'usuari
|
err_perm_user = error al degradar els permisos de l'usuari
|
||||||
err_pwnam = error en obtenir la informació de l'usuari
|
err_pwnam = error al obtenir la informació de l'usuari
|
||||||
err_unknown = ha ocorregut un error desconegut
|
err_user_gid = error al establir el GID de l'usuari
|
||||||
err_user_gid = error en establir el GID de l'usuari
|
err_user_init = error al inicialitzar usuari
|
||||||
err_user_init = error en inicialitzar usuari
|
err_user_uid = error al establir el UID de l'usuari
|
||||||
err_user_uid = error en establir l'UID de l'usuari
|
err_xsessions_dir = error al cercar la carpeta de sessions
|
||||||
err_xauth = error en la comanda xauth
|
err_xsessions_open = error al obrir la carpeta de sessions
|
||||||
err_xcb_conn = error en la connexió xcb
|
|
||||||
err_xsessions_dir = error en trobar la carpeta de sessions
|
|
||||||
err_xsessions_open = error en obrir la carpeta de sessions
|
|
||||||
insert = inserir
|
|
||||||
login = iniciar sessió
|
login = iniciar sessió
|
||||||
logout = sessió tancada
|
logout = tancar sessió
|
||||||
no_x11_support = x11 support disabled at compile-time
|
|
||||||
no_x11_support = el suport per x11 ha estat desactivat en la compilació
|
|
||||||
normal = normal
|
|
||||||
numlock = Bloq Num
|
numlock = Bloq Num
|
||||||
password = Clau
|
password = Clau
|
||||||
restart = reiniciar
|
restart = reiniciar
|
||||||
shell = shell
|
shell = shell
|
||||||
shutdown = aturar
|
shutdown = aturar
|
||||||
sleep = suspendre
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
x11 = x11
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ err_perm_dir = failed to change current directory
|
|||||||
err_perm_group = failed to downgrade group permissions
|
err_perm_group = failed to downgrade group permissions
|
||||||
err_perm_user = failed to downgrade user permissions
|
err_perm_user = failed to downgrade user permissions
|
||||||
err_pwnam = failed to get user info
|
err_pwnam = failed to get user info
|
||||||
err_sleep = failed to execute sleep command
|
|
||||||
err_unknown = an unknown error occurred
|
err_unknown = an unknown error occurred
|
||||||
err_user_gid = failed to set user GID
|
err_user_gid = failed to set user GID
|
||||||
err_user_init = failed to initialize user
|
err_user_init = failed to initialize user
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#%PAM-1.0
|
#%PAM-1.0
|
||||||
|
|
||||||
|
auth sufficient pam_unix.so try_first_pass likeauth nullok # empty-password will not pass this, but will not fail causing the next line to get executed
|
||||||
|
-auth sufficient pam_fprintd.so # We do not want to get errors when pam_fprintd.so is not present
|
||||||
auth include login
|
auth include login
|
||||||
-auth optional pam_gnome_keyring.so
|
-auth optional pam_gnome_keyring.so
|
||||||
-auth optional pam_kwallet5.so
|
-auth optional pam_kwallet5.so
|
||||||
|
|||||||
@@ -50,57 +50,35 @@ pub fn realloc(self: *Doom) !void {
|
|||||||
self.buffer = buffer;
|
self.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawWithUpdate(self: Doom) void {
|
pub fn draw(self: Doom) void {
|
||||||
for (0..self.terminal_buffer.width) |x| {
|
for (0..self.terminal_buffer.width) |x| {
|
||||||
for (1..self.terminal_buffer.height) |y| {
|
for (1..self.terminal_buffer.height) |y| {
|
||||||
// get source index
|
|
||||||
const source = y * self.terminal_buffer.width + x;
|
const source = y * self.terminal_buffer.width + x;
|
||||||
|
|
||||||
// random number between 0 and 3 inclusive
|
|
||||||
const random = (self.terminal_buffer.random.int(u16) % 7) & 3;
|
const random = (self.terminal_buffer.random.int(u16) % 7) & 3;
|
||||||
|
|
||||||
// adjust destination index based on random value
|
|
||||||
var dest = (source - @min(source, random)) + 1;
|
var dest = (source - @min(source, random)) + 1;
|
||||||
if (self.terminal_buffer.width > dest) dest = 0 else dest -= self.terminal_buffer.width;
|
if (self.terminal_buffer.width > dest) dest = 0 else dest -= self.terminal_buffer.width;
|
||||||
|
|
||||||
// get source intensity and destination offset
|
|
||||||
const buffer_source = self.buffer[source];
|
const buffer_source = self.buffer[source];
|
||||||
const buffer_dest_offset = random & 1;
|
const buffer_dest_offset = random & 1;
|
||||||
|
|
||||||
if (buffer_source < buffer_dest_offset) continue;
|
if (buffer_source < buffer_dest_offset) continue;
|
||||||
|
|
||||||
// calculate the destination intensity
|
|
||||||
var buffer_dest = buffer_source - buffer_dest_offset;
|
var buffer_dest = buffer_source - buffer_dest_offset;
|
||||||
if (buffer_dest > 12) buffer_dest = 0;
|
if (buffer_dest > 12) buffer_dest = 0;
|
||||||
self.buffer[dest] = @intCast(buffer_dest);
|
self.buffer[dest] = @intCast(buffer_dest);
|
||||||
|
|
||||||
// update terminal
|
|
||||||
self.terminal_buffer.buffer[dest] = toTermboxCell(FIRE[buffer_dest]);
|
self.terminal_buffer.buffer[dest] = toTermboxCell(FIRE[buffer_dest]);
|
||||||
self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]);
|
self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: Doom) void {
|
|
||||||
for (0..self.terminal_buffer.width) |x| {
|
|
||||||
for (1..self.terminal_buffer.height) |y| {
|
|
||||||
// get source index
|
|
||||||
const source = y * self.terminal_buffer.width + x;
|
|
||||||
|
|
||||||
// get intensity from buffer
|
|
||||||
const buffer_source = self.buffer[source];
|
|
||||||
|
|
||||||
// set cell to correct fire char
|
|
||||||
self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initBuffer(buffer: []u8, width: usize) void {
|
fn initBuffer(buffer: []u8, width: usize) void {
|
||||||
const slice_start = buffer[0..buffer.len];
|
const length = buffer.len - width;
|
||||||
const slice_end = buffer[buffer.len - width .. buffer.len];
|
const slice_start = buffer[0..length];
|
||||||
|
const slice_end = buffer[length..];
|
||||||
|
|
||||||
// set cell initial values to 0, set bottom row to be fire sources
|
|
||||||
@memset(slice_start, 0);
|
@memset(slice_start, 0);
|
||||||
@memset(slice_end, STEPS - 1);
|
@memset(slice_end, STEPS - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,83 +68,80 @@ pub fn realloc(self: *Matrix) !void {
|
|||||||
self.lines = lines;
|
self.lines = lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawWithUpdate(self: *Matrix) void {
|
pub fn draw(self: *Matrix) void {
|
||||||
const buf_height = self.terminal_buffer.height;
|
const buf_height = self.terminal_buffer.height;
|
||||||
const buf_width = self.terminal_buffer.width;
|
const buf_width = self.terminal_buffer.width;
|
||||||
|
self.count += 1;
|
||||||
|
if (self.count > FRAME_DELAY) {
|
||||||
|
self.frame += 1;
|
||||||
|
if (self.frame > 4) self.frame = 1;
|
||||||
|
self.count = 0;
|
||||||
|
|
||||||
self.frame += 1;
|
var x: usize = 0;
|
||||||
if (self.frame > 4) self.frame = 1;
|
while (x < self.terminal_buffer.width) : (x += 2) {
|
||||||
|
var tail: usize = 0;
|
||||||
|
var line = &self.lines[x];
|
||||||
|
if (self.frame <= line.update) continue;
|
||||||
|
|
||||||
var x: usize = 0;
|
if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') {
|
||||||
while (x < self.terminal_buffer.width) : (x += 2) {
|
if (line.space > 0) {
|
||||||
var tail: usize = 0;
|
line.space -= 1;
|
||||||
var line = &self.lines[x];
|
} else {
|
||||||
if (self.frame <= line.update) continue;
|
|
||||||
|
|
||||||
if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') {
|
|
||||||
if (line.space > 0) {
|
|
||||||
line.space -= 1;
|
|
||||||
} else {
|
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
|
||||||
const h: isize = @intCast(self.terminal_buffer.height);
|
|
||||||
line.length = @mod(randint, h - 3) + 3;
|
|
||||||
self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
|
||||||
line.space = @mod(randint, h + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var y: usize = 0;
|
|
||||||
var first_col = true;
|
|
||||||
var seg_len: u64 = 0;
|
|
||||||
height_it: while (y <= buf_height) : (y += 1) {
|
|
||||||
var dot = &self.dots[buf_width * y + x];
|
|
||||||
// Skip over spaces
|
|
||||||
while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) {
|
|
||||||
y += 1;
|
|
||||||
if (y > buf_height) break :height_it;
|
|
||||||
dot = &self.dots[buf_width * y + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the head of this column
|
|
||||||
tail = y;
|
|
||||||
seg_len = 0;
|
|
||||||
while (y <= buf_height and dot.value != ' ' and dot.value != -1) {
|
|
||||||
dot.is_head = false;
|
|
||||||
if (MID_SCROLL_CHANGE) {
|
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
const randint = self.terminal_buffer.random.int(i16);
|
||||||
if (@mod(randint, 8) == 0) {
|
const h: isize = @intCast(self.terminal_buffer.height);
|
||||||
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
line.length = @mod(randint, h - 3) + 3;
|
||||||
|
self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
||||||
|
line.space = @mod(randint, h + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var y: usize = 0;
|
||||||
|
var first_col = true;
|
||||||
|
var seg_len: u64 = 0;
|
||||||
|
height_it: while (y <= buf_height) : (y += 1) {
|
||||||
|
var dot = &self.dots[buf_width * y + x];
|
||||||
|
// Skip over spaces
|
||||||
|
while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) {
|
||||||
|
y += 1;
|
||||||
|
if (y > buf_height) break :height_it;
|
||||||
|
dot = &self.dots[buf_width * y + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the head of this column
|
||||||
|
tail = y;
|
||||||
|
seg_len = 0;
|
||||||
|
while (y <= buf_height and dot.value != ' ' and dot.value != -1) {
|
||||||
|
dot.is_head = false;
|
||||||
|
if (MID_SCROLL_CHANGE) {
|
||||||
|
const randint = self.terminal_buffer.random.int(i16);
|
||||||
|
if (@mod(randint, 8) == 0) {
|
||||||
|
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
y += 1;
|
||||||
|
seg_len += 1;
|
||||||
|
// Head's down offscreen
|
||||||
|
if (y > buf_height) {
|
||||||
|
self.dots[buf_width * tail + x].value = ' ';
|
||||||
|
break :height_it;
|
||||||
|
}
|
||||||
|
dot = &self.dots[buf_width * y + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
y += 1;
|
const randint = self.terminal_buffer.random.int(i16);
|
||||||
seg_len += 1;
|
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
||||||
// Head's down offscreen
|
dot.is_head = true;
|
||||||
if (y > buf_height) {
|
|
||||||
|
if (seg_len > line.length or !first_col) {
|
||||||
self.dots[buf_width * tail + x].value = ' ';
|
self.dots[buf_width * tail + x].value = ' ';
|
||||||
break :height_it;
|
self.dots[x].value = -1;
|
||||||
}
|
}
|
||||||
dot = &self.dots[buf_width * y + x];
|
first_col = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const randint = self.terminal_buffer.random.int(i16);
|
|
||||||
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
|
|
||||||
dot.is_head = true;
|
|
||||||
|
|
||||||
if (seg_len > line.length or !first_col) {
|
|
||||||
self.dots[buf_width * tail + x].value = ' ';
|
|
||||||
self.dots[x].value = -1;
|
|
||||||
}
|
|
||||||
first_col = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(self: *Matrix) void {
|
|
||||||
const buf_width = self.terminal_buffer.width;
|
|
||||||
|
|
||||||
var x: usize = 0;
|
var x: usize = 0;
|
||||||
while (x < buf_width) : (x += 2) {
|
while (x < buf_width) : (x += 2) {
|
||||||
var y: usize = 1;
|
var y: usize = 1;
|
||||||
|
|||||||
101
src/auth.zig
101
src/auth.zig
@@ -13,6 +13,66 @@ const utmp = interop.utmp;
|
|||||||
const Utmp = utmp.utmpx;
|
const Utmp = utmp.utmpx;
|
||||||
const SharedError = @import("SharedError.zig");
|
const SharedError = @import("SharedError.zig");
|
||||||
|
|
||||||
|
// When setting the currentLogin you must deallocate the previous currentLogin first
|
||||||
|
pub var currentLogin: ?[:0]const u8 = null;
|
||||||
|
pub var asyncPamHandle: ?*interop.pam.pam_handle = null;
|
||||||
|
pub var current_environment: ?Session.Environment = null;
|
||||||
|
|
||||||
|
fn environment_equals(e0: Session.Environment, e1: Session.Environment) bool {
|
||||||
|
if (!std.mem.eql(u8, e0.cmd, e1.cmd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!std.mem.eql(u8, e0.name, e1.name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!std.mem.eql(u8, e0.specifier, e1.specifier)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(e0.xdg_desktop_names == null and e1.xdg_desktop_names == null) or
|
||||||
|
(e0.xdg_desktop_names != null and e1.xdg_desktop_names != null and !std.mem.eql(u8, e0.xdg_desktop_names.?, e1.xdg_desktop_names.?)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(e0.xdg_session_desktop == null and e1.xdg_session_desktop == null) or
|
||||||
|
(e0.xdg_session_desktop != null and e1.xdg_session_desktop != null and !std.mem.eql(u8, e0.xdg_session_desktop.?, e1.xdg_session_desktop.?)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e0.display_server != e1.display_server) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn automaticLogin(config: Config, login: [:0]const u8, environment: Session.Environment, wakesem: *std.Thread.Semaphore) !void {
|
||||||
|
while (asyncPamHandle == null and currentLogin != null and std.mem.eql(u8, currentLogin.?, login)) {
|
||||||
|
if (authenticate(config, login, "", environment)) |handle| {
|
||||||
|
if (currentLogin != null and !std.mem.eql(u8, currentLogin.?, login) and environment_equals(current_environment.?, environment)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
asyncPamHandle = handle;
|
||||||
|
wakesem.post();
|
||||||
|
return;
|
||||||
|
} else |_| {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn startAutomaticLogin(allocator: std.mem.Allocator, config: Config, login: Text, environment: Session.Environment, wakesem: *std.Thread.Semaphore) !void {
|
||||||
|
if (currentLogin) |clogin| {
|
||||||
|
allocator.free(clogin);
|
||||||
|
currentLogin = null;
|
||||||
|
}
|
||||||
|
const login_text = try allocator.dupeZ(u8, login.text.items);
|
||||||
|
currentLogin = login_text;
|
||||||
|
var handle = try std.Thread.spawn(.{}, automaticLogin, .{
|
||||||
|
config,
|
||||||
|
login_text,
|
||||||
|
environment,
|
||||||
|
wakesem,
|
||||||
|
});
|
||||||
|
handle.detach();
|
||||||
|
}
|
||||||
|
|
||||||
var xorg_pid: std.posix.pid_t = 0;
|
var xorg_pid: std.posix.pid_t = 0;
|
||||||
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
|
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
|
||||||
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
||||||
@@ -23,16 +83,20 @@ pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
|
|||||||
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn authenticate(config: Config, current_environment: Session.Environment, login: [:0]const u8, password: [:0]const u8) !void {
|
pub fn authenticate(
|
||||||
var tty_buffer: [3]u8 = undefined;
|
config: Config,
|
||||||
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
login: [:0]const u8,
|
||||||
|
password: [:0]const u8,
|
||||||
|
environment: Session.Environment,
|
||||||
|
) !*interop.pam.pam_handle {
|
||||||
var pam_tty_buffer: [6]u8 = undefined;
|
var pam_tty_buffer: [6]u8 = undefined;
|
||||||
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{config.tty});
|
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{config.tty});
|
||||||
|
var tty_buffer: [2]u8 = undefined;
|
||||||
|
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
||||||
|
|
||||||
// Set the XDG environment variables
|
// Set the XDG environment variables
|
||||||
setXdgSessionEnv(current_environment.display_server);
|
setXdgSessionEnv(environment.display_server);
|
||||||
try setXdgEnv(tty_str, current_environment.xdg_session_desktop orelse "", current_environment.xdg_desktop_names orelse "");
|
try setXdgEnv(tty_str, environment.xdg_session_desktop orelse "", environment.xdg_desktop_names orelse "");
|
||||||
|
|
||||||
// Open the PAM session
|
// Open the PAM session
|
||||||
var credentials = [_:null]?[*:0]const u8{ login, password };
|
var credentials = [_:null]?[*:0]const u8{ login, password };
|
||||||
@@ -43,15 +107,15 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||||||
};
|
};
|
||||||
var handle: ?*interop.pam.pam_handle = undefined;
|
var handle: ?*interop.pam.pam_handle = undefined;
|
||||||
|
|
||||||
|
// Do the PAM routine
|
||||||
var status = interop.pam.pam_start(config.service_name, null, &conv, &handle);
|
var status = interop.pam.pam_start(config.service_name, null, &conv, &handle);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer _ = interop.pam.pam_end(handle, status);
|
errdefer _ = interop.pam.pam_end(handle, status);
|
||||||
|
|
||||||
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
||||||
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
// Do the PAM routine
|
|
||||||
status = interop.pam.pam_authenticate(handle, 0);
|
status = interop.pam.pam_authenticate(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
@@ -59,12 +123,21 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
||||||
|
errdefer _ = interop.pam.pam_end(handle, status);
|
||||||
|
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
return handle.?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finaliseAuth(config: Config, environment: Session.Environment, handle: ?*interop.pam.pam_handle, login: [:0]const u8) !void {
|
||||||
|
var status: c_int = undefined;
|
||||||
|
defer status = interop.pam.pam_end(handle, status);
|
||||||
defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
||||||
|
|
||||||
|
// Open the PAM session
|
||||||
status = interop.pam.pam_open_session(handle, 0);
|
status = interop.pam.pam_open_session(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer status = interop.pam.pam_close_session(handle, 0);
|
defer status = interop.pam.pam_close_session(handle, status);
|
||||||
|
|
||||||
var pwd: *interop.pwd.passwd = undefined;
|
var pwd: *interop.pwd.passwd = undefined;
|
||||||
{
|
{
|
||||||
@@ -86,7 +159,7 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||||||
|
|
||||||
child_pid = try std.posix.fork();
|
child_pid = try std.posix.fork();
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
startSession(config, pwd, handle, current_environment) catch |e| {
|
startSession(config, pwd, handle, environment) catch |e| {
|
||||||
shared_err.writeError(e);
|
shared_err.writeError(e);
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
};
|
};
|
||||||
@@ -124,7 +197,7 @@ fn startSession(
|
|||||||
config: Config,
|
config: Config,
|
||||||
pwd: *interop.pwd.passwd,
|
pwd: *interop.pwd.passwd,
|
||||||
handle: ?*interop.pam.pam_handle,
|
handle: ?*interop.pam.pam_handle,
|
||||||
current_environment: Session.Environment,
|
environment: Session.Environment,
|
||||||
) !void {
|
) !void {
|
||||||
if (builtin.os.tag == .freebsd) {
|
if (builtin.os.tag == .freebsd) {
|
||||||
// FreeBSD has initgroups() in unistd
|
// FreeBSD has initgroups() in unistd
|
||||||
@@ -156,13 +229,13 @@ fn startSession(
|
|||||||
std.posix.chdirZ(pwd.pw_dir.?) catch return error.ChangeDirectoryFailed;
|
std.posix.chdirZ(pwd.pw_dir.?) catch return error.ChangeDirectoryFailed;
|
||||||
|
|
||||||
// Execute what the user requested
|
// Execute what the user requested
|
||||||
switch (current_environment.display_server) {
|
switch (environment.display_server) {
|
||||||
.wayland => try executeWaylandCmd(pwd.pw_shell.?, config, current_environment.cmd),
|
.wayland => try executeWaylandCmd(pwd.pw_shell.?, config, environment.cmd),
|
||||||
.shell => try executeShellCmd(pwd.pw_shell.?, config),
|
.shell => try executeShellCmd(pwd.pw_shell.?, config),
|
||||||
.xinitrc, .x11 => if (build_options.enable_x11_support) {
|
.xinitrc, .x11 => if (build_options.enable_x11_support) {
|
||||||
var vt_buf: [5]u8 = undefined;
|
var vt_buf: [5]u8 = undefined;
|
||||||
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{config.tty});
|
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{config.tty});
|
||||||
try executeX11Cmd(pwd.pw_shell.?, pwd.pw_dir.?, config, current_environment.cmd, vt);
|
try executeX11Cmd(pwd.pw_shell.?, pwd.pw_dir.?, config, environment.cmd, vt);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ const Bigclock = enums.Bigclock;
|
|||||||
|
|
||||||
animation: Animation = .none,
|
animation: Animation = .none,
|
||||||
animation_timeout_sec: u12 = 0,
|
animation_timeout_sec: u12 = 0,
|
||||||
animation_refresh_ms: u16 = 16,
|
|
||||||
asterisk: ?u8 = '*',
|
asterisk: ?u8 = '*',
|
||||||
auth_fails: u64 = 10,
|
auth_fails: u64 = 10,
|
||||||
bg: u16 = 0,
|
bg: u16 = 0,
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ err_perm_dir: []const u8 = "failed to change current directory",
|
|||||||
err_perm_group: []const u8 = "failed to downgrade group permissions",
|
err_perm_group: []const u8 = "failed to downgrade group permissions",
|
||||||
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
||||||
err_pwnam: []const u8 = "failed to get user info",
|
err_pwnam: []const u8 = "failed to get user info",
|
||||||
err_sleep: []const u8 = "failed to execute sleep command",
|
|
||||||
err_unknown: []const u8 = "an unknown error occurred",
|
err_unknown: []const u8 = "an unknown error occurred",
|
||||||
err_user_gid: []const u8 = "failed to set user GID",
|
err_user_gid: []const u8 = "failed to set user GID",
|
||||||
err_user_init: []const u8 = "failed to initialize user",
|
err_user_init: []const u8 = "failed to initialize user",
|
||||||
|
|||||||
491
src/main.zig
491
src/main.zig
@@ -39,6 +39,16 @@ pub fn signalHandler(i: c_int) callconv(.C) void {
|
|||||||
std.c.exit(i);
|
std.c.exit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eventThreadMain(event: *?termbox.tb_event, event_error: *c_int, timeout: *c_int, wake: *std.Thread.Semaphore, cont: *std.Thread.Semaphore) void {
|
||||||
|
while (true) {
|
||||||
|
cont.wait();
|
||||||
|
var e: termbox.tb_event = undefined;
|
||||||
|
event_error.* = termbox.tb_peek_event(&e, timeout.*);
|
||||||
|
event.* = e;
|
||||||
|
wake.post();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var shutdown = false;
|
var shutdown = false;
|
||||||
var restart = false;
|
var restart = false;
|
||||||
@@ -317,11 +327,6 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var animation_timer = switch (config.animation) {
|
|
||||||
.none => undefined,
|
|
||||||
else => try std.time.Timer.start(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const animate = config.animation != .none;
|
const animate = config.animation != .none;
|
||||||
const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10);
|
const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10);
|
||||||
const shutdown_len = try utils.strWidth(lang.shutdown);
|
const shutdown_len = try utils.strWidth(lang.shutdown);
|
||||||
@@ -334,7 +339,11 @@ pub fn main() !void {
|
|||||||
const brightness_up_key = try std.fmt.parseInt(u8, config.brightness_up_key[1..], 10);
|
const brightness_up_key = try std.fmt.parseInt(u8, config.brightness_up_key[1..], 10);
|
||||||
const brightness_up_len = try utils.strWidth(lang.brightness_up);
|
const brightness_up_len = try utils.strWidth(lang.brightness_up);
|
||||||
|
|
||||||
var event: termbox.tb_event = undefined;
|
var event_timeout: c_int = std.math.maxInt(c_int);
|
||||||
|
var event_error: c_int = undefined;
|
||||||
|
var event: ?termbox.tb_event = null;
|
||||||
|
var wake: std.Thread.Semaphore = .{};
|
||||||
|
var doneEvent: std.Thread.Semaphore = .{};
|
||||||
var run = true;
|
var run = true;
|
||||||
var update = true;
|
var update = true;
|
||||||
var resolution_changed = false;
|
var resolution_changed = false;
|
||||||
@@ -345,6 +354,16 @@ pub fn main() !void {
|
|||||||
try info_line.addMessage(lang.err_console_dev, config.error_bg, config.error_fg);
|
try info_line.addMessage(lang.err_console_dev, config.error_bg, config.error_fg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
doneEvent.post();
|
||||||
|
const thandle = try std.Thread.spawn(.{}, eventThreadMain, .{ &event, &event_error, &event_timeout, &wake, &doneEvent });
|
||||||
|
|
||||||
|
thandle.detach();
|
||||||
|
|
||||||
|
{
|
||||||
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
|
}
|
||||||
|
defer allocator.free(auth.currentLogin.?);
|
||||||
while (run) {
|
while (run) {
|
||||||
// If there's no input or there's an animation, a resolution change needs to be checked
|
// If there's no input or there's an animation, a resolution change needs to be checked
|
||||||
if (!update or config.animation != .none) {
|
if (!update or config.animation != .none) {
|
||||||
@@ -385,22 +404,8 @@ pub fn main() !void {
|
|||||||
if (!animation_timed_out) {
|
if (!animation_timed_out) {
|
||||||
switch (config.animation) {
|
switch (config.animation) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.doom => {
|
.doom => doom.draw(),
|
||||||
if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) {
|
.matrix => matrix.draw(),
|
||||||
animation_timer.reset();
|
|
||||||
doom.drawWithUpdate();
|
|
||||||
} else {
|
|
||||||
doom.draw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.matrix => {
|
|
||||||
if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) {
|
|
||||||
animation_timer.reset();
|
|
||||||
matrix.drawWithUpdate();
|
|
||||||
} else {
|
|
||||||
matrix.draw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,9 +550,9 @@ pub fn main() !void {
|
|||||||
_ = termbox.tb_present();
|
_ = termbox.tb_present();
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeout: i32 = -1;
|
var timeout: u64 = std.math.maxInt(u64);
|
||||||
|
|
||||||
// Calculate the maximum timeout based on current animations, or the (big) clock. If there's none, we wait for the event indefinitely instead
|
// Calculate the maximum timeout based on current animations, or the (big) clock. If there's none, we wait for 100ms instead
|
||||||
if (animate and !animation_timed_out) {
|
if (animate and !animation_timed_out) {
|
||||||
timeout = config.min_refresh_delta;
|
timeout = config.min_refresh_delta;
|
||||||
|
|
||||||
@@ -575,226 +580,280 @@ pub fn main() !void {
|
|||||||
timeout = @intCast(1000 - @divTrunc(tv.tv_usec, 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);
|
var skipEvent: bool = false;
|
||||||
|
_ = wake.timedWait(timeout) catch .{};
|
||||||
|
if (auth.asyncPamHandle) |handle| {
|
||||||
|
var shared_err = try SharedError.init();
|
||||||
|
defer shared_err.deinit();
|
||||||
|
|
||||||
update = timeout != -1;
|
{
|
||||||
|
const login_text = try allocator.dupeZ(u8, login.text.items);
|
||||||
|
defer allocator.free(login_text);
|
||||||
|
|
||||||
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
try info_line.addMessage(lang.authenticating, config.error_bg, config.error_fg);
|
||||||
|
|
||||||
switch (event.key) {
|
|
||||||
termbox.TB_KEY_ESC => {
|
|
||||||
if (config.vi_mode and insert_mode) {
|
|
||||||
insert_mode = false;
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_F12...termbox.TB_KEY_F1 => {
|
|
||||||
const pressed_key = 0xFFFF - event.key + 1;
|
|
||||||
if (pressed_key == shutdown_key) {
|
|
||||||
shutdown = true;
|
|
||||||
run = false;
|
|
||||||
} else if (pressed_key == restart_key) {
|
|
||||||
restart = true;
|
|
||||||
run = false;
|
|
||||||
} else if (pressed_key == sleep_key) {
|
|
||||||
if (config.sleep_cmd) |sleep_cmd| {
|
|
||||||
var sleep = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", sleep_cmd }, allocator);
|
|
||||||
sleep.stdout_behavior = .Ignore;
|
|
||||||
sleep.stderr_behavior = .Ignore;
|
|
||||||
|
|
||||||
handle_sleep_cmd: {
|
|
||||||
const process_result = sleep.spawnAndWait() catch {
|
|
||||||
break :handle_sleep_cmd;
|
|
||||||
};
|
|
||||||
if (process_result.Exited != 0) {
|
|
||||||
try info_line.addMessage(lang.err_sleep, config.error_bg, config.error_fg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (pressed_key == brightness_down_key or pressed_key == brightness_up_key) {
|
|
||||||
const cmd = if (pressed_key == brightness_down_key) config.brightness_down_cmd else config.brightness_up_cmd;
|
|
||||||
|
|
||||||
var brightness = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, allocator);
|
|
||||||
brightness.stdout_behavior = .Ignore;
|
|
||||||
brightness.stderr_behavior = .Ignore;
|
|
||||||
|
|
||||||
handle_brightness_cmd: {
|
|
||||||
const process_result = brightness.spawnAndWait() catch {
|
|
||||||
break :handle_brightness_cmd;
|
|
||||||
};
|
|
||||||
if (process_result.Exited != 0) {
|
|
||||||
try info_line.addMessage(lang.err_brightness_change, config.error_bg, config.error_fg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_CTRL_C => run = false,
|
|
||||||
termbox.TB_KEY_CTRL_U => {
|
|
||||||
if (active_input == .login) {
|
|
||||||
login.clear();
|
|
||||||
update = true;
|
|
||||||
} else if (active_input == .password) {
|
|
||||||
password.clear();
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_CTRL_K, termbox.TB_KEY_ARROW_UP => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.session, .info_line => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
update = true;
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_CTRL_J, termbox.TB_KEY_ARROW_DOWN => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login, .password => .password,
|
|
||||||
};
|
|
||||||
update = true;
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_TAB => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login => .password,
|
|
||||||
.password => .info_line,
|
|
||||||
};
|
|
||||||
update = true;
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_BACK_TAB => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.info_line => .password,
|
|
||||||
.session => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
|
|
||||||
update = true;
|
|
||||||
},
|
|
||||||
termbox.TB_KEY_ENTER => {
|
|
||||||
try info_line.addMessage(lang.authenticating, config.bg, config.fg);
|
|
||||||
InfoLine.clearRendered(allocator, buffer) catch {
|
InfoLine.clearRendered(allocator, buffer) catch {
|
||||||
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
||||||
};
|
};
|
||||||
info_line.label.draw();
|
info_line.label.draw();
|
||||||
_ = termbox.tb_present();
|
_ = termbox.tb_present();
|
||||||
|
|
||||||
if (config.save) save_last_settings: {
|
session_pid = try std.posix.fork();
|
||||||
var file = std.fs.cwd().createFile(save_path, .{}) catch break :save_last_settings;
|
if (session_pid == 0) {
|
||||||
defer file.close();
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
auth.finaliseAuth(config, current_environment, handle, login_text) catch |err| {
|
||||||
const save_data = Save{
|
shared_err.writeError(err);
|
||||||
.user = login.text.items,
|
std.process.exit(1);
|
||||||
.session_index = session.label.current,
|
|
||||||
};
|
};
|
||||||
ini.writeFromStruct(save_data, file.writer(), null, true, .{}) catch break :save_last_settings;
|
|
||||||
|
|
||||||
// Delete previous save file if it exists
|
std.process.exit(0);
|
||||||
if (migrator.maybe_save_file) |path| std.fs.cwd().deleteFile(path) catch {};
|
|
||||||
}
|
}
|
||||||
|
_ = std.posix.waitpid(session_pid, 0);
|
||||||
|
|
||||||
var shared_err = try SharedError.init();
|
session_pid = -1;
|
||||||
defer shared_err.deinit();
|
}
|
||||||
|
|
||||||
{
|
auth.asyncPamHandle = null;
|
||||||
const login_text = try allocator.dupeZ(u8, login.text.items);
|
|
||||||
defer allocator.free(login_text);
|
|
||||||
const password_text = try allocator.dupeZ(u8, password.text.items);
|
|
||||||
defer allocator.free(password_text);
|
|
||||||
|
|
||||||
// Give up TTY
|
const auth_err = shared_err.readError();
|
||||||
_ = termbox.tb_shutdown();
|
if (auth_err) |err| {
|
||||||
|
try info_line.addMessage(getAuthErrorMsg(err, lang), config.error_bg, config.error_fg);
|
||||||
|
// We don't want to start login back in instantly. The user must first edit
|
||||||
|
// the login/desktop in order to login. Only in case of a failed login (so not a logout)
|
||||||
|
// should we automatically restart it.
|
||||||
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
|
} else {
|
||||||
|
try info_line.addMessage(lang.logout, config.error_bg, config.error_fg);
|
||||||
|
}
|
||||||
|
|
||||||
session_pid = try std.posix.fork();
|
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
||||||
if (session_pid == 0) {
|
_ = termbox.tb_clear();
|
||||||
|
_ = termbox.tb_present();
|
||||||
|
|
||||||
|
update = true;
|
||||||
|
|
||||||
|
_ = termbox.tb_set_cursor(0, 0);
|
||||||
|
_ = termbox.tb_present();
|
||||||
|
} else if (event) |e| {
|
||||||
|
defer doneEvent.post();
|
||||||
|
update = timeout != -1;
|
||||||
|
skipEvent = event_error < 0;
|
||||||
|
if (skipEvent or e.type != termbox.TB_EVENT_KEY) continue;
|
||||||
|
|
||||||
|
switch (e.key) {
|
||||||
|
termbox.TB_KEY_ESC => {
|
||||||
|
if (config.vi_mode and insert_mode) {
|
||||||
|
insert_mode = false;
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_F12...termbox.TB_KEY_F1 => {
|
||||||
|
const pressed_key = 0xFFFF - e.key + 1;
|
||||||
|
if (pressed_key == shutdown_key) {
|
||||||
|
shutdown = true;
|
||||||
|
run = false;
|
||||||
|
} else if (pressed_key == restart_key) {
|
||||||
|
restart = true;
|
||||||
|
run = false;
|
||||||
|
} else if (pressed_key == sleep_key) {
|
||||||
|
if (config.sleep_cmd) |sleep_cmd| {
|
||||||
|
var sleep = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", sleep_cmd }, allocator);
|
||||||
|
_ = sleep.spawnAndWait() catch .{};
|
||||||
|
}
|
||||||
|
} else if (pressed_key == brightness_down_key) {
|
||||||
|
var brightness = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", config.brightness_down_cmd }, allocator);
|
||||||
|
_ = brightness.spawnAndWait() catch .{};
|
||||||
|
} else if (pressed_key == brightness_up_key) {
|
||||||
|
var brightness = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", config.brightness_up_cmd }, allocator);
|
||||||
|
_ = brightness.spawnAndWait() catch .{};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_CTRL_C => run = false,
|
||||||
|
termbox.TB_KEY_CTRL_U => {
|
||||||
|
if (active_input == .login) {
|
||||||
|
login.clear();
|
||||||
|
update = true;
|
||||||
|
} else if (active_input == .password) {
|
||||||
|
password.clear();
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_CTRL_K, termbox.TB_KEY_ARROW_UP => {
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.session, .info_line => .info_line,
|
||||||
|
.login => .session,
|
||||||
|
.password => .login,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_CTRL_J, termbox.TB_KEY_ARROW_DOWN => {
|
||||||
|
if (active_input == .login) {
|
||||||
const current_environment = session.label.list.items[session.label.current];
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
auth.authenticate(config, current_environment, login_text, password_text) catch |err| {
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
shared_err.writeError(err);
|
}
|
||||||
std.process.exit(1);
|
active_input = switch (active_input) {
|
||||||
|
.info_line => .session,
|
||||||
|
.session => .login,
|
||||||
|
.login, .password => .password,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_TAB => {
|
||||||
|
if (active_input == .login) {
|
||||||
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
|
}
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.info_line => .session,
|
||||||
|
.session => .login,
|
||||||
|
.login => .password,
|
||||||
|
.password => .info_line,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_BACK_TAB => {
|
||||||
|
if (active_input == .info_line) {
|
||||||
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
|
}
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.info_line => .password,
|
||||||
|
.session => .info_line,
|
||||||
|
.login => .session,
|
||||||
|
.password => .login,
|
||||||
|
};
|
||||||
|
|
||||||
|
update = true;
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_ENTER => {
|
||||||
|
try info_line.addMessage(lang.authenticating, config.bg, config.fg);
|
||||||
|
InfoLine.clearRendered(allocator, buffer) catch {
|
||||||
|
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
||||||
|
};
|
||||||
|
info_line.label.draw();
|
||||||
|
_ = termbox.tb_present();
|
||||||
|
|
||||||
|
if (config.save) save_last_settings: {
|
||||||
|
var file = std.fs.cwd().createFile(save_path, .{}) catch break :save_last_settings;
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const save_data = Save{
|
||||||
|
.user = login.text.items,
|
||||||
|
.session_index = session.label.current,
|
||||||
};
|
};
|
||||||
std.process.exit(0);
|
ini.writeFromStruct(save_data, file.writer(), null, true, .{}) catch break :save_last_settings;
|
||||||
|
|
||||||
|
// Delete previous save file if it exists
|
||||||
|
if (migrator.maybe_save_file) |path| std.fs.cwd().deleteFile(path) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = std.posix.waitpid(session_pid, 0);
|
var shared_err = try SharedError.init();
|
||||||
session_pid = -1;
|
defer shared_err.deinit();
|
||||||
}
|
|
||||||
|
|
||||||
// Take back TTY
|
{
|
||||||
_ = termbox.tb_init();
|
const login_text = try allocator.dupeZ(u8, login.text.items);
|
||||||
_ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_NORMAL);
|
defer allocator.free(login_text);
|
||||||
|
const password_text = try allocator.dupeZ(u8, password.text.items);
|
||||||
|
defer allocator.free(password_text);
|
||||||
|
|
||||||
// Reinitialise buffer to avoid use after free
|
// Give up control on the TTY
|
||||||
buffer = TerminalBuffer.init(config, labels_max_length, random);
|
_ = termbox.tb_shutdown();
|
||||||
|
|
||||||
const auth_err = shared_err.readError();
|
session_pid = try std.posix.fork();
|
||||||
if (auth_err) |err| {
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
auth_fails += 1;
|
if (auth.authenticate(config, login_text, password_text, current_environment)) |handle| {
|
||||||
active_input = .password;
|
if (session_pid == 0) {
|
||||||
try info_line.addMessage(getAuthErrorMsg(err, lang), config.error_bg, config.error_fg);
|
auth.finaliseAuth(config, current_environment, handle, login_text) catch |err| {
|
||||||
if (config.clear_password or err != error.PamAuthError) password.clear();
|
shared_err.writeError(err);
|
||||||
} else {
|
std.process.exit(1);
|
||||||
if (config.logout_cmd) |logout_cmd| {
|
};
|
||||||
var logout_process = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", logout_cmd }, allocator);
|
|
||||||
_ = logout_process.spawnAndWait() catch .{};
|
std.process.exit(0);
|
||||||
|
}
|
||||||
|
_ = std.posix.waitpid(session_pid, 0);
|
||||||
|
} else |err| {
|
||||||
|
shared_err.writeError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
session_pid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
password.clear();
|
// Take back control of the TTY
|
||||||
try info_line.addMessage(lang.logout, config.bg, config.fg);
|
_ = termbox.tb_init();
|
||||||
}
|
_ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_NORMAL);
|
||||||
|
|
||||||
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
const auth_err = shared_err.readError();
|
||||||
if (auth_fails < config.auth_fails) _ = termbox.tb_clear();
|
if (auth_err) |err| {
|
||||||
|
auth_fails += 1;
|
||||||
|
active_input = .password;
|
||||||
|
try info_line.addMessage(getAuthErrorMsg(err, lang), config.error_bg, config.error_fg);
|
||||||
|
if (config.clear_password or err != error.PamAuthError) password.clear();
|
||||||
|
} else {
|
||||||
|
if (config.logout_cmd) |logout_cmd| {
|
||||||
|
var logout_process = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", logout_cmd }, allocator);
|
||||||
|
_ = logout_process.spawnAndWait() catch .{};
|
||||||
|
}
|
||||||
|
|
||||||
update = true;
|
password.clear();
|
||||||
|
try info_line.addMessage(lang.logout, config.bg, config.fg);
|
||||||
// Restore the cursor
|
|
||||||
_ = termbox.tb_set_cursor(0, 0);
|
|
||||||
_ = termbox.tb_present();
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
if (!insert_mode) {
|
|
||||||
switch (event.ch) {
|
|
||||||
'k' => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.session, .info_line => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
update = true;
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
'j' => {
|
|
||||||
active_input = switch (active_input) {
|
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login, .password => .password,
|
|
||||||
};
|
|
||||||
update = true;
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
'i' => {
|
|
||||||
insert_mode = true;
|
|
||||||
update = true;
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (active_input) {
|
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
||||||
.info_line => info_line.label.handle(&event, insert_mode),
|
if (auth_fails < config.auth_fails) _ = termbox.tb_clear();
|
||||||
.session => session.label.handle(&event, insert_mode),
|
|
||||||
.login => login.handle(&event, insert_mode) catch {
|
update = true;
|
||||||
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
|
||||||
},
|
// Restore the cursor
|
||||||
.password => password.handle(&event, insert_mode) catch {
|
_ = termbox.tb_set_cursor(0, 0);
|
||||||
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
_ = termbox.tb_present();
|
||||||
},
|
},
|
||||||
}
|
else => {
|
||||||
update = true;
|
if (!insert_mode) {
|
||||||
},
|
switch (e.ch) {
|
||||||
|
'k' => {
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.session, .info_line => .info_line,
|
||||||
|
.login => .session,
|
||||||
|
.password => .login,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
'j' => {
|
||||||
|
if (active_input == .login) {
|
||||||
|
const current_environment = session.label.list.items[session.label.current];
|
||||||
|
try auth.startAutomaticLogin(allocator, config, login, current_environment, &wake);
|
||||||
|
}
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.info_line => .session,
|
||||||
|
.session => .login,
|
||||||
|
.login, .password => .password,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
'i' => {
|
||||||
|
insert_mode = true;
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (active_input) {
|
||||||
|
.info_line => info_line.label.handle(&event.?, insert_mode),
|
||||||
|
.session => session.label.handle(&event.?, insert_mode),
|
||||||
|
.login => login.handle(&event.?, insert_mode) catch {
|
||||||
|
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
||||||
|
},
|
||||||
|
.password => password.handle(&event.?, insert_mode) catch {
|
||||||
|
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
update = true;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user