mirror of
https://github.com/javalsai/lidm.git
synced 2026-02-27 20:10:44 +01:00
Compare commits
10 Commits
2dfd2e5eaf
...
583ff1ae0c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
583ff1ae0c | ||
|
|
9253381d72 | ||
|
|
424b3930a2 | ||
|
|
9ce7cd61e1 | ||
|
|
b0d0a2e890 | ||
|
|
ded6a119b0 | ||
|
|
d07395c325 | ||
|
|
e615968a17 | ||
|
|
d65ed54578 | ||
|
|
b2019c7934 |
4
Makefile
4
Makefile
@@ -17,10 +17,10 @@ LDFLAGS?=-Wl,--gc-sections
|
|||||||
|
|
||||||
LIBS=-lpam
|
LIBS=-lpam
|
||||||
|
|
||||||
_DEPS = version.h log.h util.h ui.h ui_state.h config.h pam.h desktop.h desktop_exec.h auth.h ofield.h efield.h keys.h users.h sessions.h chvt.h macros.h launch_state.h
|
_DEPS = version.h log.h util.h ui.h ui_state.h config.h pam.h desktop.h desktop_exec.h auth.h ofield.h efield.h keys.h users.h sessions.h chvt.h macros.h launch_state.h signal_handler.h
|
||||||
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
||||||
|
|
||||||
_OBJ = main.o log.o util.o ui.o ui_state.o config.o pam.o desktop.o desktop_exec.o auth.o ofield.o efield.o users.o sessions.o chvt.o launch_state.o
|
_OBJ = main.o log.o util.o ui.o ui_state.o config.o pam.o desktop.o desktop_exec.o auth.o ofield.o efield.o users.o sessions.o chvt.o launch_state.o signal_handler.o
|
||||||
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
||||||
|
|
||||||
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
|
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
|
||||||
|
char* NULLABLE search_path(const char* NNULLABLE for_binary);
|
||||||
int execvpe_desktop(char** args, char* NNULLABLE* NNULLABLE envlist);
|
int execvpe_desktop(char** args, char* NNULLABLE* NNULLABLE envlist);
|
||||||
int parse_exec_string(const char* exec_s, int* arg_count, char*** args);
|
int parse_exec_string(const char* exec_s, int* arg_count, char*** args);
|
||||||
void free_parsed_args(int arg_count, char** args);
|
void free_parsed_args(int arg_count, char** args);
|
||||||
|
|||||||
3
include/signal_handler.h
Normal file
3
include/signal_handler.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// handle SIGTERM by sending SIGTERM to all children, resulting
|
||||||
|
// in a graceful graphical shutdown
|
||||||
|
void setup_sigterm();
|
||||||
158
src/auth.c
158
src/auth.c
@@ -23,9 +23,7 @@
|
|||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define DEFAULT_XORG_DISPLAY 0
|
#define XORG_MESSAGE_LENGTH 16
|
||||||
// no PATH search for now
|
|
||||||
#define XORG_COMMAND "/usr/bin/X"
|
|
||||||
|
|
||||||
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
||||||
char* NNULLABLE filepath) {
|
char* NNULLABLE filepath) {
|
||||||
@@ -98,64 +96,121 @@ struct child_msg {
|
|||||||
bool err;
|
bool err;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: OR check if xorg_pid fail exited
|
/// block until X returns the display number or an error occurs
|
||||||
static int wait_for_x_ready(const int xorg_pipefd[1], __pid_t xorg_pid) {
|
static bool x_get_display(const int xorg_pipefd[2], int* display) {
|
||||||
// TODO
|
char buffer[XORG_MESSAGE_LENGTH];
|
||||||
UNUSED(xorg_pipefd);
|
bool status;
|
||||||
UNUSED(xorg_pid);
|
|
||||||
sleep(2);
|
close(xorg_pipefd[1]);
|
||||||
return 0;
|
ssize_t bytes_read = read(xorg_pipefd[0], buffer, sizeof(buffer) - 1);
|
||||||
|
buffer[bytes_read] = '\0';
|
||||||
|
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
char* endptr;
|
||||||
|
int val = (int)strtol(buffer, &endptr, 10);
|
||||||
|
if (endptr == buffer) {
|
||||||
|
(void)fputs("failed to parse Xorg display response\n", stderr);
|
||||||
|
status = false;
|
||||||
|
} else {
|
||||||
|
*display = val;
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
} else if (bytes_read == 0) {
|
||||||
|
(void)fputs("Xorg pipe closed\n", stderr);
|
||||||
|
status = false;
|
||||||
|
} else {
|
||||||
|
perror("read");
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(xorg_pipefd[0]);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// small helper to push dyn arr
|
||||||
|
static void push_dyn_arr(void*** arr, void* item) {
|
||||||
|
struct Vector vec = vec_from_raw(*arr);
|
||||||
|
vec_push(&vec, item);
|
||||||
|
*arr = vec_as_raw(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: properly pass this down
|
// TODO: properly pass this down
|
||||||
extern int vt;
|
extern int vt;
|
||||||
// TODO: add error msgs
|
|
||||||
static void launch_with_xorg_server(struct session_exec* NNULLABLE exec,
|
static void start_xorg_server(struct passwd* pw, char** NNULLABLE envlist,
|
||||||
struct passwd* pw,
|
int xorg_pipefd[2]) {
|
||||||
char** NNULLABLE envlist) {
|
close(xorg_pipefd[0]);
|
||||||
int xorg_pipefd[2];
|
|
||||||
pipe(xorg_pipefd);
|
|
||||||
(void)fflush(NULL);
|
|
||||||
__pid_t xorg_pid = fork();
|
|
||||||
if (xorg_pid == 0) {
|
|
||||||
if (!pw->pw_dir) _exit(EXIT_FAILURE);
|
if (!pw->pw_dir) _exit(EXIT_FAILURE);
|
||||||
// !!!!!!!!!! ATTENTION: this fails silently, of course add failure msgs but
|
// !!!!!!!!!! ATTENTION: this fails silently, of course add failure msgs but
|
||||||
// for now I can't so be careful
|
// for now I can't so be careful
|
||||||
if (vt == -1) _exit(EXIT_FAILURE);
|
if (vt == -1) _exit(EXIT_FAILURE);
|
||||||
|
|
||||||
char* display_thing;
|
// pass the pipe so Xorg can write the DISPLAY value in there
|
||||||
asprintf(&display_thing, ":%d", DEFAULT_XORG_DISPLAY);
|
char* fd_str;
|
||||||
if (!display_thing) _exit(EXIT_FAILURE);
|
asprintf(&fd_str, "%d", xorg_pipefd[1]);
|
||||||
|
if (!fd_str) _exit(EXIT_FAILURE);
|
||||||
|
|
||||||
char* vt_path;
|
char* vt_path;
|
||||||
asprintf(&vt_path, "vt%d", vt);
|
asprintf(&vt_path, "vt%d", vt);
|
||||||
if (!vt_path) {
|
if (!vt_path) {
|
||||||
free(display_thing);
|
free(fd_str);
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dup2(xorg_pipefd[1], STDERR_FILENO);
|
char* xorg_path = search_path("Xorg");
|
||||||
// dup2(xorg_pipefd[1], STDOUT_FILENO);
|
if (!xorg_path) {
|
||||||
// close(xorg_pipefd[0]);
|
(void)fputs("couldn't find Xorg binary in PATH, sure it's installed?\n",
|
||||||
// close(xorg_pipefd[1]);
|
stderr);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
int exit = execle(XORG_COMMAND, XORG_COMMAND, display_thing, vt_path, NULL,
|
|
||||||
envlist);
|
|
||||||
perror("exec");
|
|
||||||
// execle("X", "X", display_thing, vt_path, "-auth", xauth_path,
|
|
||||||
// "-nolisten", "tcp", "-background", "none", NULL, envlist);
|
|
||||||
|
|
||||||
printf("wtf3\n");
|
|
||||||
(void)fflush(stdout);
|
|
||||||
|
|
||||||
free(vt_path);
|
|
||||||
free(display_thing);
|
|
||||||
_exit(exit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_x_ready(xorg_pipefd, xorg_pid);
|
int exit = execle(xorg_path, xorg_path, "-displayfd", fd_str, vt_path, NULL,
|
||||||
|
envlist);
|
||||||
|
perror("exec");
|
||||||
|
|
||||||
__pid_t xorg_session_pid = fork();
|
free(vt_path);
|
||||||
|
free(fd_str);
|
||||||
|
free(xorg_path);
|
||||||
|
_exit(exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add error msgs
|
||||||
|
/// returns on completion
|
||||||
|
static void launch_with_xorg_server(struct session_exec* NNULLABLE exec,
|
||||||
|
struct passwd* pw,
|
||||||
|
char** NNULLABLE envlist) {
|
||||||
|
int xorg_pipefd[2];
|
||||||
|
if (pipe(xorg_pipefd) == -1) _exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
(void)fflush(NULL);
|
||||||
|
pid_t xorg_pid = fork();
|
||||||
|
if (xorg_pid == 0) {
|
||||||
|
start_xorg_server(pw, envlist, xorg_pipefd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int display = 0;
|
||||||
|
if (!x_get_display(xorg_pipefd, &display)) {
|
||||||
|
(void)fputs("failed to get X display, aborting\n", stderr);
|
||||||
|
int status;
|
||||||
|
waitpid(xorg_pid, &status, 0);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* display_env;
|
||||||
|
asprintf(&display_env, "DISPLAY=:%d", display);
|
||||||
|
if (!display_env) {
|
||||||
|
(void)fputs("failure allocating memory for DISPLAY string\n", stderr);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// convert back for convenient push-ing
|
||||||
|
push_dyn_arr((void***)&envlist, display_env);
|
||||||
|
if (!envlist) {
|
||||||
|
(void)fputs("failure allocating memory for DISPLAY env\n", stderr);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)fflush(NULL);
|
||||||
|
pid_t xorg_session_pid = fork();
|
||||||
if (xorg_session_pid == 0) {
|
if (xorg_session_pid == 0) {
|
||||||
int exit = session_exec_exec(exec, envlist);
|
int exit = session_exec_exec(exec, envlist);
|
||||||
perror("exec error");
|
perror("exec error");
|
||||||
@@ -165,20 +220,16 @@ static void launch_with_xorg_server(struct session_exec* NNULLABLE exec,
|
|||||||
|
|
||||||
// looks weird, waiting on -1 should wait on any child and then just check if
|
// looks weird, waiting on -1 should wait on any child and then just check if
|
||||||
// its xorg server or the session and kill the other waiting on it
|
// its xorg server or the session and kill the other waiting on it
|
||||||
__pid_t pid;
|
pid_t pid;
|
||||||
int status; // not even read for now
|
int status; // not even read for now
|
||||||
while ((pid = waitpid(-1, &status, 0)) > 0) {
|
while ((pid = waitpid(-1, &status, 0)) > 0) {
|
||||||
if (pid == xorg_pid || pid == xorg_session_pid) {
|
if (pid == xorg_pid || pid == xorg_session_pid) {
|
||||||
__pid_t pid_to_kill = pid ^ xorg_pid ^ xorg_session_pid;
|
pid_t pid_to_kill = pid ^ xorg_pid ^ xorg_session_pid;
|
||||||
if (pid == xorg_pid) printf("Xorg server died\n");
|
if (pid == xorg_pid) printf("Xorg server died\n");
|
||||||
if (pid == xorg_session_pid) printf("Xorg session died\n");
|
if (pid == xorg_session_pid) printf("Xorg session died\n");
|
||||||
|
|
||||||
kill(pid_to_kill, SIGTERM);
|
kill(pid_to_kill, SIGTERM);
|
||||||
waitpid(pid_to_kill, &status, 0);
|
waitpid(pid_to_kill, &status, 0);
|
||||||
printf("wtf %d, x%d s%d - k%d\n", status, xorg_pid, xorg_session_pid,
|
|
||||||
pid_to_kill);
|
|
||||||
(void)fflush(stdout);
|
|
||||||
sleep(10);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -218,6 +269,7 @@ inline static void forked(int pipefd[2], struct passwd* pw,
|
|||||||
|
|
||||||
if (session->type == XORG) {
|
if (session->type == XORG) {
|
||||||
launch_with_xorg_server(&session->exec, pw, envlist);
|
launch_with_xorg_server(&session->exec, pw, envlist);
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
int exit = session_exec_exec(&session->exec, envlist);
|
int exit = session_exec_exec(&session->exec, envlist);
|
||||||
perror("exec error");
|
perror("exec error");
|
||||||
@@ -260,16 +312,6 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
|||||||
|
|
||||||
struct Vector envlist_vec = vec_from_raw((void**)env_ret.envlist);
|
struct Vector envlist_vec = vec_from_raw((void**)env_ret.envlist);
|
||||||
|
|
||||||
if (session.type == XORG) {
|
|
||||||
char* display_env;
|
|
||||||
asprintf(&display_env, "DISPLAY=:%d", DEFAULT_XORG_DISPLAY);
|
|
||||||
if (!display_env) {
|
|
||||||
print_err("alloc error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
vec_push(&envlist_vec, display_env);
|
|
||||||
}
|
|
||||||
|
|
||||||
source_paths(&envlist_vec, &config->behavior.source, pw->pw_dir,
|
source_paths(&envlist_vec, &config->behavior.source, pw->pw_dir,
|
||||||
&config->behavior.user_source);
|
&config->behavior.user_source);
|
||||||
char** envlist = (char**)vec_as_raw(envlist_vec);
|
char** envlist = (char**)vec_as_raw(envlist_vec);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
// returns NULL on any error
|
// returns NULL on any error
|
||||||
// otherwise it returns the absolute path of the program that MUST BE FREED
|
// otherwise it returns the absolute path of the program that MUST BE FREED
|
||||||
static char* NULLABLE search_path(const char* NNULLABLE for_binary) {
|
char* NULLABLE search_path(const char* NNULLABLE for_binary) {
|
||||||
if (strchr(for_binary, '/') != NULL) {
|
if (strchr(for_binary, '/') != NULL) {
|
||||||
// skip absolute paths
|
// skip absolute paths
|
||||||
return strdup(for_binary);
|
return strdup(for_binary);
|
||||||
|
|||||||
@@ -21,19 +21,17 @@ int read_launch_state(struct LaunchState* NNULLABLE state) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
if (getline(&state->username, &num, state_fd) < 0) goto fail;
|
ssize_t chars = getline(&state->username, &num, state_fd);
|
||||||
// not sure I can actually prove it but ughh, getline < 0 will ensure there's
|
if (chars < 0) goto fail;
|
||||||
// something in the string and then I think strcspn is bounded to the final
|
if (state->username[chars] == '\n') state->username[chars] = 0;
|
||||||
// null byte, so it shouldn't go over
|
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.ArrayBound)
|
|
||||||
state->username[strcspn(state->username, "\n")] = 0;
|
|
||||||
|
|
||||||
num = 0;
|
num = 0;
|
||||||
if (getline(&state->session_opt, &num, state_fd) < 0) {
|
chars = getline(&state->session_opt, &num, state_fd);
|
||||||
|
if (chars < 0) {
|
||||||
free(state->session_opt);
|
free(state->session_opt);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
state->session_opt[strcspn(state->session_opt, "\n")] = 0;
|
if (state->session_opt[chars] == '\n') state->session_opt[chars] = 0;
|
||||||
|
|
||||||
(void)fclose(state_fd);
|
(void)fclose(state_fd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
|
#include "signal_handler.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "users.h"
|
#include "users.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define DATESTR_MAXBUFSIZE 0x20
|
#define DATESTR_MAXBUFSIZE 0x20
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// Logger
|
// Logger
|
||||||
char* log_output = getenv("LIDM_LOG");
|
char* log_output = getenv("LIDM_LOG");
|
||||||
@@ -85,6 +87,8 @@ int main(int argc, char* argv[]) {
|
|||||||
struct Vector users = get_human_users();
|
struct Vector users = get_human_users();
|
||||||
struct Vector sessions = get_avaliable_sessions();
|
struct Vector sessions = get_avaliable_sessions();
|
||||||
|
|
||||||
|
setup_sigterm();
|
||||||
|
|
||||||
int ret = load(&users, &sessions);
|
int ret = load(&users, &sessions);
|
||||||
if (ret == 0) execl(argv[0], argv[0], NULL);
|
if (ret == 0) execl(argv[0], argv[0], NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/signal_handler.c
Normal file
27
src/signal_handler.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void handle_sigterm(int sig) {
|
||||||
|
(void)sig;
|
||||||
|
|
||||||
|
(void)signal(SIGTERM, SIG_IGN);
|
||||||
|
kill(-getpgrp(), SIGTERM);
|
||||||
|
|
||||||
|
int status;
|
||||||
|
while (waitpid(-1, &status, 0) > 0 || errno == EINTR) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_sigterm() {
|
||||||
|
setpgid(0, 0);
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = handle_sigterm;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
}
|
||||||
7
src/ui.c
7
src/ui.c
@@ -186,6 +186,7 @@ void ui_update_ofield(struct opts_field* NNULLABLE self) {
|
|||||||
ui_update_field(input);
|
ui_update_field(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// draw everything
|
||||||
void scratch_print_ui() {
|
void scratch_print_ui() {
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &window);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &window);
|
||||||
box_start = (struct uint_point){
|
box_start = (struct uint_point){
|
||||||
@@ -201,7 +202,7 @@ void scratch_print_ui() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\033[2J\033[H"); // Clear screen
|
printf("\033[2J\033[H\033c"); // Clear screen
|
||||||
|
|
||||||
/// PRINTING
|
/// PRINTING
|
||||||
// printf box
|
// printf box
|
||||||
@@ -313,6 +314,8 @@ int load(struct Vector* users, struct Vector* sessions) {
|
|||||||
&restore_all, g_config)) {
|
&restore_all, g_config)) {
|
||||||
print_passwd(utf8len(of_passwd.efield.content), true);
|
print_passwd(utf8len(of_passwd.efield.content), true);
|
||||||
ui_update_cursor_focus();
|
ui_update_cursor_focus();
|
||||||
|
} else {
|
||||||
|
scratch_print_ui();
|
||||||
}
|
}
|
||||||
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
|
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
|
||||||
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
|
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
|
||||||
@@ -336,6 +339,8 @@ int load(struct Vector* users, struct Vector* sessions) {
|
|||||||
&restore_all, g_config)) {
|
&restore_all, g_config)) {
|
||||||
print_passwd(utf8len(of_passwd.efield.content), true);
|
print_passwd(utf8len(of_passwd.efield.content), true);
|
||||||
ui_update_cursor_focus();
|
ui_update_cursor_focus();
|
||||||
|
} else {
|
||||||
|
scratch_print_ui();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
st_kbd_type(seq, g_config->behavior.include_defshell);
|
st_kbd_type(seq, g_config->behavior.include_defshell);
|
||||||
|
|||||||
Reference in New Issue
Block a user