Merge branch 'master' into support-xorg

This commit is contained in:
2026-01-16 00:44:58 +01:00
12 changed files with 170 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
// TODO: handle `fork() == -1`s
// TODO: handle `fork() == -1`// TODO: handle `fork() == -1`s
#include <errno.h>
#include <grp.h>
@@ -240,9 +240,10 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
pam_handle_t* pamh = get_pamh(user, passwd);
if (pamh == NULL) {
print_err("error on pam authentication");
print_pam_msg("authentication failed", PAM_ERROR_MSG);
return false;
}
clear_pam_msg();
struct pamh_getenv_status env_ret =
pamh_get_complete_env(pamh, pw, session.type);

View File

@@ -9,6 +9,7 @@
#include "macros.h"
#include "pam.h"
#include "sessions.h"
#include "ui.h"
struct envpair {
const char* NNULLABLE name;
@@ -113,19 +114,45 @@ struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
///////////////
struct pam_conv_data {
char* password;
void (*display_pam_msg)(const char* msg, int msg_style);
};
int pam_conversation(int num_msg, const struct pam_message** msg,
struct pam_response** resp, void* appdata_ptr) {
struct pam_response* reply = malloc(sizeof(struct pam_response) * num_msg);
if (!reply) {
return PAM_BUF_ERR;
}
struct pam_conv_data* conv_data = (struct pam_conv_data*)appdata_ptr;
for (int i = 0; i < num_msg; i++) {
reply[i].resp = NULL;
reply[i].resp_retcode = 0;
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
msg[i]->msg_style == PAM_PROMPT_ECHO_ON) {
char* input = (char*)appdata_ptr;
reply[i].resp = strdup(input);
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
reply[i].resp = strdup(conv_data->password);
if (!reply[i].resp) {
for (int j = 0; j < i; j++)
free(reply[j].resp);
free(reply);
return PAM_BUF_ERR;
}
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
if (conv_data->display_pam_msg && msg[i]->msg) {
conv_data->display_pam_msg(msg[i]->msg, msg[i]->msg_style);
}
break;
default:
break;
}
}
*resp = reply;
@@ -144,7 +171,9 @@ int pam_conversation(int num_msg, const struct pam_message** msg,
}
pam_handle_t* get_pamh(char* user, char* passwd) {
pam_handle_t* pamh = NULL;
struct pam_conv pamc = {pam_conversation, (void*)passwd};
struct pam_conv_data conv_data = {.password = passwd,
.display_pam_msg = print_pam_msg};
struct pam_conv pamc = {pam_conversation, (void*)&conv_data};
int ret;
char* pam_service_override = getenv("LIDM_PAM_SERVICE");

110
src/ui.c
View File

@@ -5,6 +5,7 @@
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <security/pam_appl.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
@@ -111,8 +112,8 @@ static char* fmt_time(const char* fmt) {
}
}
char* trunc_gethostname(const size_t MAXLEN, const char* const ELLIPSIS) {
if (utf8len(ELLIPSIS) > MAXLEN) return NULL;
char* trunc_gethostname(size_t maxlen, const char* const ELLIPSIS) {
if (utf8len(ELLIPSIS) > maxlen) return NULL;
size_t alloc_size = HOST_NAME_MAX + strlen(ELLIPSIS) + 1;
char* buf = malloc(alloc_size);
if (!buf) return NULL;
@@ -122,8 +123,8 @@ char* trunc_gethostname(const size_t MAXLEN, const char* const ELLIPSIS) {
return NULL;
}
if (utf8len(buf) > MAXLEN) {
size_t end = utf8trunc(buf, MAXLEN - utf8len(ELLIPSIS));
if (utf8len(buf) > maxlen) {
size_t end = utf8trunc(buf, maxlen - utf8len(ELLIPSIS));
strcpy(&buf[end], ELLIPSIS);
}
return buf;
@@ -298,6 +299,21 @@ int load(struct Vector* users, struct Vector* sessions) {
restore_all();
reboot(RB_POWER_OFF);
exit(0);
} else if (g_config->functions.fido != NONE &&
ansi_key == g_config->functions.fido) {
bool successful_write = write_launch_state((struct LaunchState){
.username = st_user().username,
.session_opt =
st_session(g_config->behavior.include_defshell).name,
});
if (!successful_write) log_puts("[E] failed to write launch state");
if (!launch(st_user().username, "",
st_session(g_config->behavior.include_defshell),
&restore_all, g_config)) {
print_passwd(utf8len(of_passwd.efield.content), true);
ui_update_cursor_focus();
}
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
} else if (ansi_key == A_RIGHT || ansi_key == A_LEFT) {
@@ -344,25 +360,40 @@ u_char get_render_pos_offset(struct opts_field* self, u_char maxlen) {
return pos - ofield_display_cursor_col(self, maxlen);
}
#define HOSTNAME_SIZE (VALUES_COL - VALUES_SEPR - BOX_HMARGIN - 1)
void print_head() {
// hostname doesn't just change on runtime
static char* hostname = NULL;
if (!hostname)
hostname = trunc_gethostname(HOSTNAME_SIZE, g_config->strings.ellipsis);
if (!hostname) hostname = "unknown";
char* fmtd_time = fmt_time(g_config->behavior.timefmt);
size_t len_tm = utf8len(fmtd_time);
// calculate the space available for the host name
ssize_t hostname_size = BOX_WIDTH - (BOX_HMARGIN * 2) - len_tm - VALUES_SEPR;
if (hostname_size < 0) hostname_size = 0;
// hostname doesn't just change on runtime,
// but the length of the time string might
static char* NULLABLE hostname = NULL;
static ssize_t hostname_calcd_size;
// save the truncated hostname and the length it truncated to,
// if said length changes recalculate this (and free previous str)
if (!hostname || hostname_calcd_size != hostname_size) {
if (hostname) free(hostname);
hostname = trunc_gethostname(hostname_size, g_config->strings.ellipsis);
hostname_calcd_size = hostname_size;
}
clean_line(box_start, HEAD_ROW);
// put hostname
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm",
box_start.x + VALUES_COL - VALUES_SEPR - (uint)utf8len(hostname),
g_config->colors.e_hostname, hostname, g_config->colors.fg);
if (hostname_size)
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm", box_start.x + 1 + BOX_HMARGIN,
g_config->colors.e_hostname, hostname ? hostname : "unknown",
g_config->colors.fg);
// put date
char* fmtd_time = fmt_time(g_config->behavior.timefmt);
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm",
box_start.x + BOX_WIDTH - 1 - BOX_HMARGIN - (uint)utf8len(fmtd_time),
box_start.x + BOX_WIDTH - 1 - BOX_HMARGIN - (uint)len_tm,
g_config->colors.e_date, fmtd_time, g_config->colors.fg);
free(fmtd_time);
}
@@ -497,6 +528,8 @@ static void print_box() {
}
static void print_footer() {
bool fido_enabled = g_config->functions.fido != NONE;
size_t bsize = utf8len(g_config->strings.f_poweroff) +
utf8len(KEY_NAMES[g_config->functions.poweroff]) +
utf8len(g_config->strings.f_reboot) +
@@ -504,19 +537,31 @@ static void print_footer() {
utf8len(g_config->strings.f_refresh) +
utf8len(KEY_NAMES[g_config->functions.refresh]);
bsize += 2 * 2 + // 2 wide separators between 3 items
3 * 1; // 3 thin separators inside every item
bsize += 2 * 2 + 3 * 1;
if (fido_enabled) {
bsize += utf8len(g_config->strings.f_fido) +
utf8len(KEY_NAMES[g_config->functions.fido]) + 2 + 1;
}
uint row = window.ws_row - 1;
uint col = window.ws_col - 2 - bsize;
printf(
"\x1b[%3$d;%4$dH%8$s \x1b[%1$sm%5$s\x1b[%2$sm %9$s "
"\x1b[%1$sm%6$s\x1b[%2$sm %10$s \x1b[%1$sm%7$s\x1b[%2$sm",
g_config->colors.e_key, g_config->colors.fg, row, col,
KEY_NAMES[g_config->functions.poweroff],
KEY_NAMES[g_config->functions.reboot],
KEY_NAMES[g_config->functions.refresh], g_config->strings.f_poweroff,
g_config->strings.f_reboot, g_config->strings.f_refresh);
printf("\x1b[%d;%dH%s \x1b[%sm%s\x1b[%sm %s \x1b[%sm%s\x1b[%sm ", row, col,
g_config->strings.f_poweroff, g_config->colors.e_key,
KEY_NAMES[g_config->functions.poweroff], g_config->colors.fg,
g_config->strings.f_reboot, g_config->colors.e_key,
KEY_NAMES[g_config->functions.reboot], g_config->colors.fg);
if (fido_enabled) {
printf("%s \x1b[%sm%s\x1b[%sm ", g_config->strings.f_fido,
g_config->colors.e_key, KEY_NAMES[g_config->functions.fido],
g_config->colors.fg);
}
printf("%s \x1b[%sm%s\x1b[%sm", g_config->strings.f_refresh,
g_config->colors.e_key, KEY_NAMES[g_config->functions.refresh],
g_config->colors.fg);
}
void print_err(const char* msg) {
@@ -524,6 +569,21 @@ void print_err(const char* msg) {
msg, errno, strerror(errno));
}
void print_pam_msg(const char* msg, int msg_style) {
uint row = box_start.y + BOX_HEIGHT + 1;
const char* color =
(msg_style == PAM_ERROR_MSG) ? g_config->colors.err : g_config->colors.fg;
printf("\x1b[%d;%dH\x1b[K\x1b[%sm%.*s\x1b[%sm", row, box_start.x, color,
BOX_WIDTH, msg, g_config->colors.fg);
(void)fflush(stdout);
}
void clear_pam_msg(void) {
uint row = box_start.y + BOX_HEIGHT + 1;
printf("\x1b[%d;%dH\x1b[K", row, box_start.x);
(void)fflush(stdout);
}
void print_errno(const char* descr) {
if (descr == NULL)
(void)fprintf(stderr, "\x1b[%d;%dH\x1b[%smunknown error(%d): %s",