mirror of
https://github.com/javalsai/lidm.git
synced 2025-07-03 14:25:03 +02:00
feat|perf: generic&efficient desktop&config parser
This commit is contained in:
parent
d13ebfff4e
commit
22c3f7c896
4
Makefile
4
Makefile
@ -12,10 +12,10 @@ ALLFLAGS=$(CFLAGS) -I$(IDIR)
|
|||||||
|
|
||||||
LIBS=-lpam
|
LIBS=-lpam
|
||||||
|
|
||||||
_DEPS = util.h ui.h config.h auth.h efield.h keys.h users.h sessions.h chvt.h
|
_DEPS = util.h ui.h config.h desktop.h auth.h efield.h keys.h users.h sessions.h chvt.h macros.h
|
||||||
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
||||||
|
|
||||||
_OBJ = main.o util.o ui.o config.o auth.o efield.o users.o sessions.o chvt.o
|
_OBJ = main.o util.o ui.o config.o desktop.o auth.o efield.o users.o sessions.o chvt.o
|
||||||
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
||||||
|
|
||||||
$(ODIR)/%.o: $(CDIR)/%.c $(DEPS)
|
$(ODIR)/%.o: $(CDIR)/%.c $(DEPS)
|
||||||
|
17
include/desktop.h
Normal file
17
include/desktop.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef DESKTOPH_
|
||||||
|
#define DESKTOPH_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "macros.h"
|
||||||
|
|
||||||
|
struct status {
|
||||||
|
bool finish;
|
||||||
|
int ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
int read_desktop(FILE* fd, void* ctx, struct status (*cb)(void* ctx, char* NULLABLE table,
|
||||||
|
char* key, char* value));
|
||||||
|
|
||||||
|
#endif
|
12
include/macros.h
Normal file
12
include/macros.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Do we just replace the compiler with clang??
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define NULLABLE _Nullable
|
||||||
|
#else
|
||||||
|
#define NULLABLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define NNULLABLE _Nonnull
|
||||||
|
#else
|
||||||
|
#define NNULLABLE
|
||||||
|
#endif
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "macros.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
enum session_type {
|
enum session_type {
|
||||||
@ -12,9 +13,9 @@ enum session_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
char* name;
|
char* NNULLABLE name;
|
||||||
char* exec;
|
char* NNULLABLE exec;
|
||||||
char* tryexec;
|
char* NULLABLE tryexec;
|
||||||
enum session_type type;
|
enum session_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,7 +132,8 @@ void moarEnv(char* user,
|
|||||||
if (newbuf == NULL) continue; // can't bother
|
if (newbuf == NULL) continue; // can't bother
|
||||||
strlcpy(newbuf, pw->pw_dir, newbuf_len);
|
strlcpy(newbuf, pw->pw_dir, newbuf_len);
|
||||||
newbuf[home_len] = '/'; // assume pw_dir doesn't start with '/' :P
|
newbuf[home_len] = '/'; // assume pw_dir doesn't start with '/' :P
|
||||||
strlcpy(&newbuf[home_len + 1], file2sourcepath, newbuf_len - home_len - 1);
|
strlcpy(&newbuf[home_len + 1], file2sourcepath,
|
||||||
|
newbuf_len - home_len - 1);
|
||||||
|
|
||||||
/* printf("DEBUG(user_source)!!!! %d %s\n", i, newbuf); */
|
/* printf("DEBUG(user_source)!!!! %d %s\n", i, newbuf); */
|
||||||
sourceFileTry(newbuf);
|
sourceFileTry(newbuf);
|
||||||
@ -250,8 +251,7 @@ bool launch(char* user,
|
|||||||
pam_close_session(pamh, 0);
|
pam_close_session(pamh, 0);
|
||||||
pam_end(pamh, PAM_SUCCESS);
|
pam_end(pamh, PAM_SUCCESS);
|
||||||
|
|
||||||
if (*reach_session == false)
|
if (*reach_session == false) return false;
|
||||||
return false;
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ int chvt(int n) {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)fputs("Couldn't get a file descriptor referring to the console.\n", stderr);
|
(void)fputs("Couldn't get a file descriptor referring to the console.\n",
|
||||||
|
stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
74
src/desktop.c
Normal file
74
src/desktop.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "desktop.h"
|
||||||
|
#include "macros.h"
|
||||||
|
|
||||||
|
#define NOK \
|
||||||
|
{ \
|
||||||
|
ret = -1; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
#define NOKFKEY \
|
||||||
|
{ \
|
||||||
|
free(key); \
|
||||||
|
NOK \
|
||||||
|
}
|
||||||
|
int read_desktop(FILE* fd, void* ctx,
|
||||||
|
struct status (*cb)(void* ctx, char* NULLABLE table, char* key,
|
||||||
|
char* value)) {
|
||||||
|
char* table_name = NULL;
|
||||||
|
|
||||||
|
bool ret = -1;
|
||||||
|
char* buf = NULL;
|
||||||
|
size_t alloc_size = 0;
|
||||||
|
size_t read_size;
|
||||||
|
while ((read_size = getline(&buf, &alloc_size, fd)) > 0) {
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if (read_size <= 1) continue;
|
||||||
|
|
||||||
|
if (buf[0] == '[' && buf[read_size - 2] == ']') {
|
||||||
|
if (table_name != NULL) free(table_name);
|
||||||
|
table_name = realloc(buf, read_size);
|
||||||
|
table_name[read_size - 1] = '\0'; // newline
|
||||||
|
buf = NULL;
|
||||||
|
alloc_size = 0;
|
||||||
|
} else {
|
||||||
|
// Find '='
|
||||||
|
size_t eq_idx = 0;
|
||||||
|
while (buf[eq_idx] != '\0') {
|
||||||
|
if (buf[eq_idx] == '=') break;
|
||||||
|
eq_idx++;
|
||||||
|
}
|
||||||
|
// impossible with a min len of 1 (empty line)
|
||||||
|
if (eq_idx == 0) continue;
|
||||||
|
// Check its not end
|
||||||
|
if (buf[eq_idx] != '=') NOK;
|
||||||
|
|
||||||
|
// Key & Value
|
||||||
|
char* key = buf;
|
||||||
|
buf[eq_idx] = '\0'; // the equal
|
||||||
|
char* value = &buf[eq_idx+1];
|
||||||
|
buf[read_size-1] = '\0'; // the newline
|
||||||
|
|
||||||
|
// Callback
|
||||||
|
struct status cb_ret = cb(ctx, table_name, key, value);
|
||||||
|
if (cb_ret.finish) {
|
||||||
|
ret = cb_ret.ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(table_name);
|
||||||
|
|
||||||
|
if (buf != NULL) free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#undef NOK
|
||||||
|
#undef NOKFKEY
|
||||||
|
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
@ -50,8 +50,8 @@ void field_update(struct editable_field* self, char* update) {
|
|||||||
}
|
}
|
||||||
if (self->pos < self->length) {
|
if (self->pos < self->length) {
|
||||||
// move with immediate buffer
|
// move with immediate buffer
|
||||||
memmove(&self->content[self->pos + insert_len],
|
memmove(&self->content[self->pos + insert_len], &self->content[self->pos],
|
||||||
&self->content[self->pos], self->length - self->pos);
|
self->length - self->pos);
|
||||||
}
|
}
|
||||||
memcpy(&self->content[self->pos], update, insert_len);
|
memcpy(&self->content[self->pos], update, insert_len);
|
||||||
|
|
||||||
|
135
src/sessions.c
135
src/sessions.c
@ -7,6 +7,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "desktop.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -19,105 +20,89 @@ static const struct source_dir sources[] = {
|
|||||||
{WAYLAND, "/usr/share/wayland-sessions"},
|
{WAYLAND, "/usr/share/wayland-sessions"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct session new_session(enum session_type type,
|
// static struct session new_session(enum session_type type, char* name,
|
||||||
char* name,
|
// const char* exec, const char* tryexec) {
|
||||||
const char* exec,
|
// struct session session;
|
||||||
const char* tryexec) {
|
// session.type = type;
|
||||||
struct session session;
|
// strcln(&session.name, name);
|
||||||
session.type = type;
|
// strcln(&session.exec, exec);
|
||||||
strcln(&session.name, name);
|
// strcln(&session.tryexec, tryexec);
|
||||||
strcln(&session.exec, exec);
|
|
||||||
strcln(&session.tryexec, tryexec);
|
|
||||||
|
|
||||||
return session;
|
// return session;
|
||||||
}
|
// }
|
||||||
|
|
||||||
static struct Vector* cb_sessions = NULL;
|
static struct Vector* cb_sessions = NULL;
|
||||||
|
|
||||||
// NOTE: commented printf's here would be nice to have debug logs if I ever
|
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||||
// implement it
|
struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) {
|
||||||
#define LN_NAME 0b0001
|
struct session* ctx = (struct session*)_ctx;
|
||||||
#define LN_EXEC 0b0010
|
struct status ret;
|
||||||
#define LN_TEXEC 0b0100
|
ret.finish = false;
|
||||||
#define LN_ALL (LN_NAME | LN_EXEC | LN_TEXEC)
|
|
||||||
|
if (table == NULL) return ret;
|
||||||
|
if (strcmp(table, "[Desktop Entry]") != 0) return ret;
|
||||||
|
|
||||||
|
char** NULLABLE copy_at = NULL;
|
||||||
|
if (strcmp(key, "Name") == 0) {
|
||||||
|
if (ctx->name == NULL) copy_at = &ctx->name;
|
||||||
|
} else if (strcmp(key, "Exec") == 0) {
|
||||||
|
if (ctx->exec == NULL) copy_at = &ctx->exec;
|
||||||
|
} else if (strcmp(key, "TryExec") == 0) {
|
||||||
|
if (ctx->tryexec == NULL) copy_at = &ctx->tryexec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_at != NULL) {
|
||||||
|
*copy_at = malloc((strlen(value) + 1) * sizeof(char));
|
||||||
|
if (*copy_at == NULL) {
|
||||||
|
ret.finish = true;
|
||||||
|
ret.ret = -1; // malloc error
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(*copy_at, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->name != NULL && ctx->exec != NULL && ctx->tryexec != NULL) {
|
||||||
|
ret.finish = true;
|
||||||
|
ret.ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static enum session_type session_type;
|
static enum session_type 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) {
|
||||||
if (!S_ISREG(sb->st_mode)) return 0;
|
if (!S_ISREG(sb->st_mode)) return 0;
|
||||||
|
|
||||||
// printf("gonna open %s\n", fpath);
|
struct session* ctx = malloc(sizeof(struct session));
|
||||||
|
if (ctx == NULL) return 0;
|
||||||
|
ctx->name = NULL;
|
||||||
|
ctx->exec = NULL;
|
||||||
|
ctx->tryexec = NULL;
|
||||||
|
|
||||||
FILE* fd = fopen(fpath, "r");
|
FILE* fd = fopen(fpath, "r");
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
|
free(ctx);
|
||||||
perror("fopen");
|
perror("fopen");
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
||||||
(void)fprintf(stderr, "error opening file (r) '%s'\n", fpath);
|
(void)fprintf(stderr, "error opening file (r) '%s'\n", fpath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_char found = 0;
|
int ret = read_desktop(fd, ctx, &cb);
|
||||||
|
if (ret < 0) { // any error
|
||||||
char* name_buf = NULL;
|
free(ctx);
|
||||||
char* exec_buf = NULL;
|
return 0;
|
||||||
char* tryexec_buf = NULL;
|
|
||||||
// This should be made a specific function
|
|
||||||
// Emm, if anything goes wrong just free the inner loop and `break;` fd and
|
|
||||||
// the rest is handled after
|
|
||||||
char* buf = NULL;
|
|
||||||
size_t alloc_size = 0;
|
|
||||||
size_t read_size;
|
|
||||||
while ((read_size = getline(&buf, &alloc_size, fd)) != -1) {
|
|
||||||
char* key = malloc(read_size + sizeof(char));
|
|
||||||
if (key == NULL) {
|
|
||||||
free(buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char* value = malloc(read_size + sizeof(char));
|
|
||||||
if (value == NULL) {
|
|
||||||
free(buf);
|
|
||||||
free(key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value[0] = '\0'; // I'm not sure if sscanf would null this string out
|
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
if (sscanf(buf, "%[^=]=%[^\n]\n", key, value) == 2) {
|
|
||||||
if (strcmp(key, "Name") == 0) {
|
|
||||||
found &= LN_EXEC;
|
|
||||||
if(name_buf != NULL) free(name_buf);
|
|
||||||
name_buf = realloc(value, strlen(value) + sizeof(char));
|
|
||||||
} else if (strcmp(key, "Exec") == 0) {
|
|
||||||
found &= LN_EXEC;
|
|
||||||
if(exec_buf != NULL) free(exec_buf);
|
|
||||||
exec_buf = realloc(value, strlen(value) + sizeof(char));
|
|
||||||
} else if (strcmp(key, "TryExec") == 0) {
|
|
||||||
found &= LN_TEXEC;
|
|
||||||
if(tryexec_buf != NULL) free(tryexec_buf);
|
|
||||||
tryexec_buf = realloc(value, strlen(value) + sizeof(char));
|
|
||||||
} else {
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
free(key);
|
|
||||||
// if (found == LN_ALL) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buf != NULL) free(buf);
|
|
||||||
(void)fclose(fd);
|
(void)fclose(fd);
|
||||||
// printf("\nend parsing...\n");
|
|
||||||
|
|
||||||
// just add this to the list
|
// just add this to the list
|
||||||
if (name_buf != NULL && exec_buf != NULL) {
|
if (ctx->name != NULL && ctx->exec != NULL) {
|
||||||
struct session* session_i = malloc(sizeof(struct session));
|
ctx->type = session_type;
|
||||||
*session_i = new_session(session_type, name_buf, exec_buf,
|
vec_push(cb_sessions, ctx);
|
||||||
tryexec_buf == NULL ? "" : tryexec_buf);
|
|
||||||
vec_push(cb_sessions, session_i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name_buf != NULL) free(name_buf);
|
|
||||||
if (exec_buf != NULL) free(exec_buf);
|
|
||||||
if (tryexec_buf != NULL) free(tryexec_buf);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user