mirror of
https://github.com/javalsai/lidm.git
synced 2025-08-31 02:18:00 +02:00
chore: organize code
add -Wextra by default pipefd to communicate better with parent and forked process rustify some stuff add the desktop parser to the file read
This commit is contained in:
2
Makefile
2
Makefile
@@ -9,7 +9,7 @@ ODIR=dist
|
|||||||
PREFIX=/usr
|
PREFIX=/usr
|
||||||
|
|
||||||
CC?=gcc
|
CC?=gcc
|
||||||
CFLAGS?=-O3 -Wall -fdata-sections -ffunction-sections
|
CFLAGS?=-O3 -Wall -Wextra -fdata-sections -ffunction-sections
|
||||||
# C PreProcessor flags, not C Plus Plus
|
# C PreProcessor flags, not C Plus Plus
|
||||||
CPPFLAGS?=
|
CPPFLAGS?=
|
||||||
ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
||||||
|
@@ -6,7 +6,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
|
|
||||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
bool launch(char* NNULLABLE user, char* NNULLABLE passwd,
|
||||||
struct config* config);
|
struct session session, void (*NULLABLE cb)(void),
|
||||||
|
struct config* NNULLABLE config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -150,15 +150,15 @@ struct introspection_table {
|
|||||||
|
|
||||||
static const struct introspection_table CONFIG_INSTROSPECTION[] = {
|
static const struct introspection_table CONFIG_INSTROSPECTION[] = {
|
||||||
{"colors", offsetof(struct config, colors), INTROS_TABLE_COLORS,
|
{"colors", offsetof(struct config, colors), INTROS_TABLE_COLORS,
|
||||||
sizeof(INTROS_TABLE_COLORS) / sizeof(INTROS_TABLE_COLORS[0])},
|
LEN(INTROS_TABLE_COLORS)},
|
||||||
{"chars", offsetof(struct config, chars), INTROS_TABLE_CHARS,
|
{"chars", offsetof(struct config, chars), INTROS_TABLE_CHARS,
|
||||||
sizeof(INTROS_TABLE_CHARS) / sizeof(INTROS_TABLE_CHARS[0])},
|
LEN(INTROS_TABLE_CHARS)},
|
||||||
{"functions", offsetof(struct config, functions), INTROS_TABLE_FUNCTIONS,
|
{"functions", offsetof(struct config, functions), INTROS_TABLE_FUNCTIONS,
|
||||||
sizeof(INTROS_TABLE_FUNCTIONS) / sizeof(INTROS_TABLE_FUNCTIONS[0])},
|
LEN(INTROS_TABLE_FUNCTIONS)},
|
||||||
{"strings", offsetof(struct config, strings), INTROS_TABLE_STRINGS,
|
{"strings", offsetof(struct config, strings), INTROS_TABLE_STRINGS,
|
||||||
sizeof(INTROS_TABLE_STRINGS) / sizeof(INTROS_TABLE_STRINGS[0])},
|
LEN(INTROS_TABLE_STRINGS)},
|
||||||
{"behavior", offsetof(struct config, behavior), INTROS_TABLE_BEHAVIOR,
|
{"behavior", offsetof(struct config, behavior), INTROS_TABLE_BEHAVIOR,
|
||||||
sizeof(INTROS_TABLE_BEHAVIOR) / sizeof(INTROS_TABLE_BEHAVIOR[0])},
|
LEN(INTROS_TABLE_BEHAVIOR)},
|
||||||
};
|
};
|
||||||
|
|
||||||
//// FUNCTIONS
|
//// FUNCTIONS
|
||||||
|
@@ -36,5 +36,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LEN(X) (sizeof(X) / sizeof((X)[0]))
|
#define LEN(X) (sizeof(X) / sizeof((X)[0]))
|
||||||
|
#define UNUSED(x) ((void)(x))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -24,7 +24,6 @@ struct pamh_getenv_status {
|
|||||||
|
|
||||||
// Doesn't include `source`s
|
// Doesn't include `source`s
|
||||||
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
||||||
char* NNULLABLE user,
|
|
||||||
struct passwd* NNULLABLE pw,
|
struct passwd* NNULLABLE pw,
|
||||||
enum SessionType session_typ);
|
enum SessionType session_typ);
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#define SESSIONSH_
|
#define SESSIONSH_
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -12,10 +13,58 @@ enum SessionType {
|
|||||||
SHELL,
|
SHELL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ExecType {
|
||||||
|
EXEC_SHELL,
|
||||||
|
EXEC_DESKTOP,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct desktop_exec {
|
||||||
|
char** args;
|
||||||
|
int arg_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct session_exec {
|
||||||
|
enum ExecType typ;
|
||||||
|
union {
|
||||||
|
char* shell;
|
||||||
|
struct desktop_exec desktop;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct session_exec session_exec_shell(char* shell) {
|
||||||
|
return (struct session_exec){
|
||||||
|
.typ = EXEC_SHELL,
|
||||||
|
.shell = shell,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct session_exec session_exec_desktop(int arg_count,
|
||||||
|
char** args) {
|
||||||
|
return (struct session_exec){
|
||||||
|
.typ = EXEC_DESKTOP,
|
||||||
|
.desktop =
|
||||||
|
{
|
||||||
|
.args = args,
|
||||||
|
.arg_count = arg_count,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int session_exec_exec(struct session_exec* exec,
|
||||||
|
char** NNULLABLE envlist) {
|
||||||
|
switch (exec->typ) {
|
||||||
|
case EXEC_SHELL:
|
||||||
|
return execle(exec->shell, exec->shell, NULL, envlist);
|
||||||
|
case EXEC_DESKTOP:
|
||||||
|
return execve(exec->desktop.args[0], exec->desktop.args, envlist);
|
||||||
|
default:
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
char* NNULLABLE name;
|
char* NNULLABLE name;
|
||||||
char* NNULLABLE exec;
|
struct session_exec exec;
|
||||||
char* NULLABLE tryexec;
|
|
||||||
enum SessionType type;
|
enum SessionType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -11,11 +11,17 @@
|
|||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
|
||||||
int find_keyname(enum Keys* at, const char* name);
|
int find_keyname(enum Keys* at, const char* name);
|
||||||
enum Keys find_ansi(const char* seq);
|
struct option_keys {
|
||||||
|
bool is_some;
|
||||||
|
enum Keys key;
|
||||||
|
};
|
||||||
|
struct option_keys find_ansi(const char* seq);
|
||||||
void read_press(u_char* length, char* out);
|
void read_press(u_char* length, char* out);
|
||||||
// non blocking, waits up to tv or interrupt, returns true if actually read
|
// non blocking, waits up to tv or interrupt, returns true if actually read
|
||||||
bool read_press_nb(u_char* length, char* out, struct timeval* tv);
|
bool read_press_nb(u_char* length, char* out, struct timeval* tv);
|
||||||
|
|
||||||
|
// UTF8
|
||||||
|
//
|
||||||
bool utf8_iscont(char byte);
|
bool utf8_iscont(char byte);
|
||||||
size_t utf8len(const char* str);
|
size_t utf8len(const char* str);
|
||||||
size_t utf8len_until(const char* str, const char* until);
|
size_t utf8len_until(const char* str, const char* until);
|
||||||
@@ -24,6 +30,8 @@ const char* utf8back(const char* str);
|
|||||||
const char* utf8seek(const char* str);
|
const char* utf8seek(const char* str);
|
||||||
const char* utf8seekn(const char* str, size_t n);
|
const char* utf8seekn(const char* str, size_t n);
|
||||||
|
|
||||||
|
// Vector
|
||||||
|
//
|
||||||
struct Vector {
|
struct Vector {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
|
122
src/auth.c
122
src/auth.c
@@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "desktop_exec.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pam.h"
|
#include "pam.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void try_source_file(struct Vector* NNULLABLE vec_envlist, char* filepath) {
|
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
||||||
|
char* NNULLABLE filepath) {
|
||||||
log_printf("sourcing %s\n", filepath);
|
log_printf("sourcing %s\n", filepath);
|
||||||
FILE* file2source = fopen(filepath, "r");
|
FILE* file2source = fopen(filepath, "r");
|
||||||
if (file2source == NULL) {
|
if (file2source == NULL) {
|
||||||
@@ -35,7 +35,7 @@ void try_source_file(struct Vector* NNULLABLE vec_envlist, char* filepath) {
|
|||||||
if (read == 0 || (read > 0 && *line == '#')) continue;
|
if (read == 0 || (read > 0 && *line == '#')) continue;
|
||||||
if (line[read - 1] == '\n') line[read - 1] = '\0';
|
if (line[read - 1] == '\n') line[read - 1] = '\0';
|
||||||
|
|
||||||
for (size_t i = 1; i < read; i++) {
|
for (ssize_t i = 1; i < read; i++) {
|
||||||
if (line[i] == '=') {
|
if (line[i] == '=') {
|
||||||
vec_push(vec_envlist, (void*)line);
|
vec_push(vec_envlist, (void*)line);
|
||||||
line = NULL;
|
line = NULL;
|
||||||
@@ -48,7 +48,7 @@ void try_source_file(struct Vector* NNULLABLE vec_envlist, char* filepath) {
|
|||||||
(void)fclose(file2source);
|
(void)fclose(file2source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void source_paths(struct Vector* NNULLABLE vec_envlist,
|
static void source_paths(struct Vector* NNULLABLE vec_envlist,
|
||||||
struct Vector* NNULLABLE abs_source,
|
struct Vector* NNULLABLE abs_source,
|
||||||
const char* NULLABLE user_home,
|
const char* NULLABLE user_home,
|
||||||
struct Vector* NNULLABLE user_source) {
|
struct Vector* NNULLABLE user_source) {
|
||||||
@@ -66,6 +66,7 @@ void source_paths(struct Vector* NNULLABLE vec_envlist,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try_source_file(vec_envlist, path);
|
try_source_file(vec_envlist, path);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_puts("user has no home\n");
|
log_puts("user has no home\n");
|
||||||
@@ -88,25 +89,51 @@ struct child_msg {
|
|||||||
bool err;
|
bool err;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SEND_MSG(MSG) \
|
||||||
|
{ \
|
||||||
|
write(pipefd[1], &(MSG), sizeof(struct child_msg)); \
|
||||||
|
close(pipefd[1]); \
|
||||||
|
}
|
||||||
|
#define SEND_ERR(MSG) \
|
||||||
|
{ \
|
||||||
|
write(pipefd[1], \
|
||||||
|
&(struct child_msg){.msg = (MSG), ._errno = errno, .err = true}, \
|
||||||
|
sizeof(struct child_msg)); \
|
||||||
|
close(pipefd[1]); \
|
||||||
|
_exit(EXIT_FAILURE); \
|
||||||
|
}
|
||||||
|
#define DUMMY_READ() \
|
||||||
|
{ \
|
||||||
|
char _dummy; \
|
||||||
|
read(pipefd[0], &_dummy, sizeof(_dummy)); \
|
||||||
|
}
|
||||||
|
inline static void forked(int pipefd[2], struct passwd* pw,
|
||||||
|
char* NNULLABLE user,
|
||||||
|
struct session_exec* NNULLABLE exec,
|
||||||
|
char** NNULLABLE envlist) {
|
||||||
|
if (chdir(pw->pw_dir) == -1) SEND_ERR("chdir");
|
||||||
|
if (setgid(pw->pw_gid) == -1) SEND_ERR("setgid");
|
||||||
|
if (initgroups(user, pw->pw_gid) == -1) SEND_ERR("initgroups");
|
||||||
|
if (setuid(pw->pw_uid) == -1) SEND_ERR("setuid");
|
||||||
|
|
||||||
|
// or maybe Xorg fork should happen here
|
||||||
|
|
||||||
|
SEND_MSG((struct child_msg){.err = false});
|
||||||
|
DUMMY_READ();
|
||||||
|
close(pipefd[0]);
|
||||||
|
|
||||||
|
int exit = session_exec_exec(exec, envlist);
|
||||||
|
perror("exec error");
|
||||||
|
(void)fputs("failure calling session\n", stderr);
|
||||||
|
_exit(exit);
|
||||||
|
}
|
||||||
|
#undef SEND_MSG
|
||||||
|
#undef SEND_ERR
|
||||||
|
#undef DUMMY_READ
|
||||||
|
|
||||||
// NOLINTBEGIN(readability-function-cognitive-complexity)
|
// NOLINTBEGIN(readability-function-cognitive-complexity)
|
||||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||||
struct config* config) {
|
struct config* config) {
|
||||||
char** desktop_exec;
|
|
||||||
int desktop_count;
|
|
||||||
|
|
||||||
if (session.type != SHELL) {
|
|
||||||
desktop_exec = NULL;
|
|
||||||
int parse_status =
|
|
||||||
parse_exec_string(session.exec, &desktop_count, &desktop_exec);
|
|
||||||
if (parse_status != 0 || desktop_count == 0 || !desktop_exec[0]) {
|
|
||||||
print_err("failure parsing exec string");
|
|
||||||
log_printf("failure parsing exec string '%s': %d\n",
|
|
||||||
session.exec ? session.exec : "NULL", parse_status);
|
|
||||||
free_parsed_args(desktop_count, desktop_exec);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct passwd* pw = getpwnam(user);
|
struct passwd* pw = getpwnam(user);
|
||||||
if (pw == NULL) {
|
if (pw == NULL) {
|
||||||
print_err("could not get user info");
|
print_err("could not get user info");
|
||||||
@@ -120,7 +147,7 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct pamh_getenv_status env_ret =
|
struct pamh_getenv_status env_ret =
|
||||||
pamh_get_complete_env(pamh, user, pw, session.type);
|
pamh_get_complete_env(pamh, pw, session.type);
|
||||||
if (env_ret.error_flag != PAMH_ERR_NOERR) {
|
if (env_ret.error_flag != PAMH_ERR_NOERR) {
|
||||||
if (env_ret.error_flag == PAMH_ERR_ALLOC) {
|
if (env_ret.error_flag == PAMH_ERR_ALLOC) {
|
||||||
print_err("allocator error");
|
print_err("allocator error");
|
||||||
@@ -141,53 +168,20 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: start X server here if needed
|
||||||
|
// e.g. spawn (also after downgrading privs):
|
||||||
|
//
|
||||||
|
// `X :0 tty<X> -auth <user-home>/.Xauthority -nolisten tcp -background none`
|
||||||
|
//
|
||||||
|
// Then `DISPLAY=:0 <xsession>`
|
||||||
|
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
pipe(pipefd);
|
pipe(pipefd);
|
||||||
|
|
||||||
uint pid = fork();
|
uint pid = fork();
|
||||||
if (pid == 0) { // child
|
if (pid == 0)
|
||||||
|
forked(pipefd, pw, user, &session.exec, envlist);
|
||||||
#define SEND_MSG(MSG) \
|
else {
|
||||||
{ \
|
|
||||||
write(pipefd[1], &(MSG), sizeof(struct child_msg)); \
|
|
||||||
close(pipefd[1]); \
|
|
||||||
}
|
|
||||||
#define SEND_ERR(MSG) \
|
|
||||||
{ \
|
|
||||||
write(pipefd[1], \
|
|
||||||
&(struct child_msg){.msg = (MSG), ._errno = errno, .err = true}, \
|
|
||||||
sizeof(struct child_msg)); \
|
|
||||||
close(pipefd[1]); \
|
|
||||||
_exit(EXIT_FAILURE); \
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chdir(pw->pw_dir) == -1) SEND_ERR("chdir");
|
|
||||||
if (setgid(pw->pw_gid) == -1) SEND_ERR("setgid");
|
|
||||||
if (initgroups(user, pw->pw_gid) == -1) SEND_ERR("initgroups");
|
|
||||||
if (setuid(pw->pw_uid) == -1) SEND_ERR("setuid");
|
|
||||||
|
|
||||||
SEND_MSG((struct child_msg){.err = false});
|
|
||||||
#undef SEND_MSG
|
|
||||||
#undef SEND_ERR
|
|
||||||
char _;
|
|
||||||
read(pipefd[0], &_, sizeof(_));
|
|
||||||
close(pipefd[0]);
|
|
||||||
|
|
||||||
int exit;
|
|
||||||
if (session.type == SHELL) {
|
|
||||||
exit = execle(session.exec, session.exec, NULL, envlist);
|
|
||||||
} else if (session.type == XORG || session.type == WAYLAND) {
|
|
||||||
// TODO: test existence of executable with TryExec
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
exit = execve(desktop_exec[0], desktop_exec, envlist);
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
free_parsed_args(desktop_count, desktop_exec);
|
|
||||||
} else
|
|
||||||
exit = -1;
|
|
||||||
perror("exec error");
|
|
||||||
(void)fputs("failure calling session\n", stderr);
|
|
||||||
_exit(exit);
|
|
||||||
} else {
|
|
||||||
struct child_msg msg;
|
struct child_msg msg;
|
||||||
read(pipefd[0], &msg, sizeof(struct child_msg));
|
read(pipefd[0], &msg, sizeof(struct child_msg));
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "chvt.h"
|
#include "chvt.h"
|
||||||
|
#include "macros.h"
|
||||||
|
|
||||||
static char* vterms[] = {"/dev/tty", "/dev/tty0", "/dev/vc/0", "/dev/systty",
|
static char* vterms[] = {"/dev/tty", "/dev/tty0", "/dev/vc/0", "/dev/systty",
|
||||||
"/dev/console"};
|
"/dev/console"};
|
||||||
@@ -24,15 +25,13 @@ int chvt_str(char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int chvt(int n) {
|
int chvt(int n) {
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
(void)fprintf(stderr, "activating vt %d\n", n);
|
(void)fprintf(stderr, "activating vt %d\n", n);
|
||||||
// NOLINTNEXTLINE(readability-identifier-length)
|
// NOLINTNEXTLINE(readability-identifier-length)
|
||||||
char c = 0;
|
char c = 0;
|
||||||
for (size_t i = 0; i < sizeof(vterms) / sizeof(vterms[0]); i++) {
|
for (size_t i = 0; i < LEN(vterms); i++) {
|
||||||
int fd = open(vterms[i], O_RDWR);
|
int fd = open(vterms[i], O_RDWR);
|
||||||
if (fd >= 0 && isatty(fd) && ioctl(fd, KDGKBTYPE, &c) == 0 && c < 3) {
|
if (fd >= 0 && isatty(fd) && ioctl(fd, KDGKBTYPE, &c) == 0 && c < 3) {
|
||||||
if (ioctl(fd, VT_ACTIVATE, n) < 0 || ioctl(fd, VT_WAITACTIVE, n) < 0) {
|
if (ioctl(fd, VT_ACTIVATE, n) < 0 || ioctl(fd, VT_WAITACTIVE, n) < 0) {
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
(void)fprintf(stderr, "Couldn't activate vt %d\n", n);
|
(void)fprintf(stderr, "Couldn't activate vt %d\n", n);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -122,7 +122,7 @@ union typ_ptr {
|
|||||||
uintptr_t ptr;
|
uintptr_t ptr;
|
||||||
};
|
};
|
||||||
struct parser_error parse_key(enum IntrospectionType typ, union typ_ptr at,
|
struct parser_error parse_key(enum IntrospectionType typ, union typ_ptr at,
|
||||||
char* key, size_t offset) {
|
char* key) {
|
||||||
char* aux_str = NULL;
|
char* aux_str = NULL;
|
||||||
struct parser_error aux_err;
|
struct parser_error aux_err;
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ struct status config_line_handler(void* _config, char* table, char* k,
|
|||||||
|
|
||||||
log_printf("[I] parsing [%s.%s] as %s\n", table, k,
|
log_printf("[I] parsing [%s.%s] as %s\n", table, k,
|
||||||
INTROS_TYS_NAMES[this_intros_key->typ]);
|
INTROS_TYS_NAMES[this_intros_key->typ]);
|
||||||
struct parser_error err = parse_key(this_intros_key->typ, k_addr, v, offset);
|
struct parser_error err = parse_key(this_intros_key->typ, k_addr, v);
|
||||||
if (err.msg != NULL) {
|
if (err.msg != NULL) {
|
||||||
log_printf("[E] cfg parser, failed to parse [%s.%s] (%s): %s\n", table, k,
|
log_printf("[E] cfg parser, failed to parse [%s.%s] (%s): %s\n", table, k,
|
||||||
INTROS_TYS_NAMES[this_intros_key->typ], err.msg);
|
INTROS_TYS_NAMES[this_intros_key->typ], err.msg);
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -82,4 +81,3 @@ int read_desktop(FILE* fd, void* ctx,
|
|||||||
if (buf != NULL) free(buf);
|
if (buf != NULL) free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
|
||||||
|
@@ -4,8 +4,6 @@
|
|||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
|
|
||||||
struct editable_field efield_new(char* content) {
|
struct editable_field efield_new(char* content) {
|
||||||
struct editable_field efield;
|
struct editable_field efield;
|
||||||
if (content != NULL) {
|
if (content != NULL) {
|
||||||
@@ -80,5 +78,3 @@ bool efield_seek(struct editable_field* self, char seek) {
|
|||||||
self->pos = (u_char)(ptr - self->content);
|
self->pos = (u_char)(ptr - self->content);
|
||||||
return ptr != start;
|
return ptr != start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
|
@@ -89,7 +89,6 @@ char* NULLABLE xdg_ssession_type_str(enum SessionType typ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
||||||
char* NNULLABLE user,
|
|
||||||
struct passwd* NNULLABLE pw,
|
struct passwd* NNULLABLE pw,
|
||||||
enum SessionType session_typ) {
|
enum SessionType session_typ) {
|
||||||
struct pamh_getenv_status status;
|
struct pamh_getenv_status status;
|
||||||
@@ -123,7 +122,7 @@ int pam_conversation(int num_msg, const struct pam_message** msg,
|
|||||||
if (!reply) {
|
if (!reply) {
|
||||||
return PAM_BUF_ERR;
|
return PAM_BUF_ERR;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < num_msg; i++) {
|
for (int i = 0; i < num_msg; i++) {
|
||||||
reply[i].resp = NULL;
|
reply[i].resp = NULL;
|
||||||
reply[i].resp_retcode = 0;
|
reply[i].resp_retcode = 0;
|
||||||
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
|
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
|
||||||
|
@@ -8,7 +8,9 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
|
#include "desktop_exec.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -75,6 +77,8 @@ struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) {
|
|||||||
static enum SessionType session_type;
|
static enum SessionType session_type;
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
||||||
|
UNUSED(sb);
|
||||||
|
|
||||||
// guessing symlink behavior
|
// guessing symlink behavior
|
||||||
// - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it
|
// - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it
|
||||||
// follows symlinks, we should never get to handle that
|
// follows symlinks, we should never get to handle that
|
||||||
@@ -95,22 +99,32 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ret = read_desktop(fd, &ctx, &cb);
|
int ret = read_desktop(fd, &ctx, &cb);
|
||||||
if (ret < 0) { // any error
|
// any error
|
||||||
log_printf("[E] format error parsing %s", fpath);
|
if (ret < 0) goto err_close;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)fclose(fd);
|
(void)fclose(fd);
|
||||||
|
|
||||||
|
// TODO: filter based on tryexec
|
||||||
|
// https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html
|
||||||
|
free(ctx.tryexec);
|
||||||
|
|
||||||
// just add this to the list
|
// just add this to the list
|
||||||
if (ctx.name != NULL && ctx.exec != NULL) {
|
if (ctx.name != NULL && ctx.exec != NULL) {
|
||||||
struct session* this_session = malloc(sizeof(struct session));
|
struct session* this_session = malloc(sizeof(struct session));
|
||||||
if (this_session == NULL) return 0;
|
if (this_session == NULL) return 0;
|
||||||
|
|
||||||
|
int arg_count;
|
||||||
|
char** args;
|
||||||
|
int parse_status = parse_exec_string(ctx.exec, &arg_count, &args);
|
||||||
|
if (parse_status != 0 || arg_count == 0 || !args[0]) {
|
||||||
|
log_printf("[E] parsing exec string '%s': %d\n", ctx.exec, parse_status);
|
||||||
|
goto err_parsing;
|
||||||
|
}
|
||||||
|
free(ctx.exec);
|
||||||
|
|
||||||
*this_session = (struct session){
|
*this_session = (struct session){
|
||||||
.name = ctx.name,
|
.name = ctx.name,
|
||||||
.exec = ctx.exec,
|
.exec = session_exec_desktop(arg_count, args),
|
||||||
.tryexec = ctx.tryexec,
|
|
||||||
.type = session_type,
|
.type = session_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,6 +132,12 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_close:
|
||||||
|
(void)fclose(fd);
|
||||||
|
err_parsing:
|
||||||
|
log_printf("[E] format error parsing %s", fpath);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code is designed to be run purely single threaded
|
// This code is designed to be run purely single threaded
|
||||||
@@ -127,7 +147,7 @@ struct Vector get_avaliable_sessions() {
|
|||||||
vec_reserve(&sessions, LIKELY_BOUND_SESSIONS);
|
vec_reserve(&sessions, LIKELY_BOUND_SESSIONS);
|
||||||
|
|
||||||
cb_sessions = &sessions;
|
cb_sessions = &sessions;
|
||||||
for (size_t i = 0; i < (sizeof(SOURCES) / sizeof(SOURCES[0])); i++) {
|
for (size_t i = 0; i < LEN(SOURCES); i++) {
|
||||||
log_printf("[I] parsing into %s\n", SOURCES[i].dir);
|
log_printf("[I] parsing into %s\n", SOURCES[i].dir);
|
||||||
session_type = SOURCES[i].type;
|
session_type = SOURCES[i].type;
|
||||||
ftw(SOURCES[i].dir, &fn, 1);
|
ftw(SOURCES[i].dir, &fn, 1);
|
||||||
|
25
src/ui.c
25
src/ui.c
@@ -25,6 +25,7 @@
|
|||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "launch_state.h"
|
#include "launch_state.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "ofield.h"
|
#include "ofield.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
@@ -61,6 +62,7 @@ struct config* g_config = NULL;
|
|||||||
static volatile sig_atomic_t need_resize = 0;
|
static volatile sig_atomic_t need_resize = 0;
|
||||||
|
|
||||||
static void process_sigwinch(int signal) {
|
static void process_sigwinch(int signal) {
|
||||||
|
UNUSED(signal);
|
||||||
need_resize = 1;
|
need_resize = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,28 +282,29 @@ int load(struct Vector* users, struct Vector* sessions) {
|
|||||||
(void)fflush(stdout);
|
(void)fflush(stdout);
|
||||||
if (!read_press_nb(&len, seq, &tv)) continue;
|
if (!read_press_nb(&len, seq, &tv)) continue;
|
||||||
if (*seq == '\x1b') {
|
if (*seq == '\x1b') {
|
||||||
enum Keys ansi_code = find_ansi(seq);
|
struct option_keys ansi_code = find_ansi(seq);
|
||||||
if (ansi_code != -1) {
|
if (ansi_code.is_some) {
|
||||||
if (ansi_code == ESC) {
|
enum Keys ansi_key = ansi_code.key;
|
||||||
|
if (ansi_key == ESC) {
|
||||||
esc = 2;
|
esc = 2;
|
||||||
} else if (ansi_code == g_config->functions.refresh) {
|
} else if (ansi_key == g_config->functions.refresh) {
|
||||||
restore_all();
|
restore_all();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ansi_code == g_config->functions.reboot) {
|
} else if (ansi_key == g_config->functions.reboot) {
|
||||||
restore_all();
|
restore_all();
|
||||||
reboot(RB_AUTOBOOT);
|
reboot(RB_AUTOBOOT);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (ansi_code == g_config->functions.poweroff) {
|
} else if (ansi_key == g_config->functions.poweroff) {
|
||||||
restore_all();
|
restore_all();
|
||||||
reboot(RB_POWER_OFF);
|
reboot(RB_POWER_OFF);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (ansi_code == A_UP || ansi_code == A_DOWN) {
|
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
|
||||||
st_ch_focus(ansi_code == A_DOWN ? 1 : -1);
|
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
|
||||||
} else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) {
|
} else if (ansi_key == A_RIGHT || ansi_key == A_LEFT) {
|
||||||
if (esc)
|
if (esc)
|
||||||
st_ch_of_opts(ansi_code == A_RIGHT ? 1 : -1);
|
st_ch_of_opts(ansi_key == A_RIGHT ? 1 : -1);
|
||||||
else
|
else
|
||||||
st_ch_ef_col(ansi_code == A_RIGHT ? 1 : -1);
|
st_ch_ef_col(ansi_key == A_RIGHT ? 1 : -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -40,7 +40,8 @@ struct session st_session(bool include_defshell) {
|
|||||||
if (include_defshell && of_session.current_opt == gsessions->length + 1) {
|
if (include_defshell && of_session.current_opt == gsessions->length + 1) {
|
||||||
struct session shell_session;
|
struct session shell_session;
|
||||||
shell_session.type = SHELL;
|
shell_session.type = SHELL;
|
||||||
shell_session.exec = shell_session.name = st_user().shell;
|
shell_session.exec =
|
||||||
|
session_exec_shell(shell_session.name = st_user().shell);
|
||||||
return shell_session;
|
return shell_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +50,8 @@ struct session st_session(bool include_defshell) {
|
|||||||
|
|
||||||
struct session custom_session;
|
struct session custom_session;
|
||||||
custom_session.type = SHELL;
|
custom_session.type = SHELL;
|
||||||
custom_session.name = custom_session.exec = of_session.efield.content;
|
custom_session.exec =
|
||||||
|
session_exec_shell(custom_session.name = of_session.efield.content);
|
||||||
return custom_session;
|
return custom_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ void st_kbd_type(char* text, bool cfg_include_defshell) {
|
|||||||
start = st_user().username;
|
start = st_user().username;
|
||||||
if (focused_input == SESSION && of_session.current_opt != 0 &&
|
if (focused_input == SESSION && of_session.current_opt != 0 &&
|
||||||
st_session(cfg_include_defshell).type == SHELL)
|
st_session(cfg_include_defshell).type == SHELL)
|
||||||
start = st_session(cfg_include_defshell).exec;
|
start = st_session(cfg_include_defshell).exec.shell;
|
||||||
|
|
||||||
ofield_kbd_type(field, text, start);
|
ofield_kbd_type(field, text, start);
|
||||||
ui_update_ffield();
|
ui_update_ffield();
|
||||||
|
@@ -24,16 +24,19 @@ int find_keyname(enum Keys* at, const char* name) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Keys find_ansi(const char* seq) {
|
struct option_keys find_ansi(const char* seq) {
|
||||||
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
||||||
struct key_mapping mapping = KEY_MAPPINGS[i];
|
struct key_mapping mapping = KEY_MAPPINGS[i];
|
||||||
for (size_t j = 0; mapping.sequences[j] != NULL; j++) {
|
for (size_t j = 0; mapping.sequences[j] != NULL; j++) {
|
||||||
if (strcmp(mapping.sequences[j], seq) == 0) {
|
if (strcmp(mapping.sequences[j], seq) == 0) {
|
||||||
return (enum Keys)i;
|
return (struct option_keys){
|
||||||
|
.is_some = true,
|
||||||
|
.key = (enum Keys)i,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return (struct option_keys){.is_some = false};
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_press(u_char* length, char* out) {
|
void read_press(u_char* length, char* out) {
|
||||||
|
Reference in New Issue
Block a user