From 07d2842be066c2474ddc2fc6aa0ecdac55ac63b9 Mon Sep 17 00:00:00 2001 From: javalsai Date: Wed, 10 Jul 2024 23:24:51 +0200 Subject: [PATCH] feat: add users and sessions discovery - also add clangd multi-file intellisense --- .clangd | 3 ++ .gitignore | 2 + Makefile | 4 +- compile_commands.json | 50 ++++++++++++++++++++++ include/sessions.h | 13 ++++++ include/users.h | 13 ++++++ include/util.h | 1 + src/main.c | 22 +++++++++- src/sessions.c | 97 +++++++++++++++++++++++++++++++++++++++++++ src/users.c | 61 +++++++++++++++++++++++++++ src/util.c | 9 ++++ 11 files changed, 272 insertions(+), 3 deletions(-) create mode 100644 .clangd create mode 100644 compile_commands.json create mode 100644 include/sessions.h create mode 100644 include/users.h create mode 100644 include/util.h create mode 100644 src/sessions.c create mode 100644 src/users.c create mode 100644 src/util.c diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..1ed4fc2 --- /dev/null +++ b/.clangd @@ -0,0 +1,3 @@ +CompileFlags: + Add: + - "-Iinclude" diff --git a/.gitignore b/.gitignore index f834842..1fff046 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ li dist/ + +.cache/ diff --git a/Makefile b/Makefile index a7ea3ab..f2e90a4 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,10 @@ CFLAGS=-I$(IDIR) LIBS=-lm -_DEPS = +_DEPS = util.h users.h sessions.h DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) -_OBJ = main.o +_OBJ = main.o util.o users.o sessions.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: $(CDIR)/%.c $(DEPS) diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..0aae781 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,50 @@ +[ + { + "directory": "/home/javalsai/coding/li", + "arguments": [ + "gcc", + "-c", + "-o", + "dist/main.o", + "src/main.c", + "-Iinclude" + ], + "file": "src/main.c" + }, + { + "directory": "/home/javalsai/coding/li", + "arguments": [ + "gcc", + "-c", + "-o", + "dist/users.o", + "src/users.c", + "-Iinclude" + ], + "file": "src/users.c" + }, + { + "directory": "/home/javalsai/coding/li", + "arguments": [ + "gcc", + "-c", + "-o", + "dist/sessions.o", + "src/sessions.c", + "-Iinclude" + ], + "file": "src/sessions.c" + }, + { + "directory": "/home/javalsai/coding/li", + "arguments": [ + "gcc", + "-c", + "-o", + "dist/util.o", + "src/util.c", + "-Iinclude" + ], + "file": "src/util.c" + } +] diff --git a/include/sessions.h b/include/sessions.h new file mode 100644 index 0000000..7839e22 --- /dev/null +++ b/include/sessions.h @@ -0,0 +1,13 @@ +#include + +struct session { + char *name; + char *path; +}; + +struct sessions_list { + u_int16_t length; + struct session *sessions; +}; + +struct sessions_list *get_avaliable_sessions(); diff --git a/include/users.h b/include/users.h new file mode 100644 index 0000000..666a25e --- /dev/null +++ b/include/users.h @@ -0,0 +1,13 @@ +#include + +struct user { + char *username; + char *display_name; +}; + +struct users_list { + u_int16_t length; + struct user *users; +}; + +struct users_list *get_human_users(); diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..8e17069 --- /dev/null +++ b/include/util.h @@ -0,0 +1 @@ +void strcln(char **dest, const char *source); diff --git a/src/main.c b/src/main.c index 5cca8e2..07925aa 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,23 @@ +#include +#include +#include + +#include +#include + int main() { - return 2; + struct users_list *users = get_human_users(); + struct sessions_list *sessions = get_avaliable_sessions(); + + printf("users(%hu) sessions(%hu)\n", users->length, sessions->length); + + for (uint i = 0; i < users->length; i++) + printf("u[%d]: %s %s\n", i, users->users[i].username, + users->users[i].display_name); + + for (uint i = 0; i < sessions->length; i++) + printf("s[%d]: %s %s\n", i, sessions->sessions[i].name, + sessions->sessions[i].path); + + return 0; } diff --git a/src/sessions.c b/src/sessions.c new file mode 100644 index 0000000..ce7ba02 --- /dev/null +++ b/src/sessions.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static const char *sources[] = {"/usr/share/xsessions", + "/usr/share/wayland-sessions"}; +static const size_t sources_size = sizeof(sources) / sizeof(sources[0]); + +static struct session __new_session(char *name, const char *path) { + struct session __session; + strcln(&__session.name, name); + strcln(&__session.path, path); + + return __session; +} + +static const u_int8_t bs = 16; +static const u_int8_t unit_size = sizeof(struct session); + +static u_int16_t alloc_size = bs; +static u_int16_t used_size = 0; + +static struct session *sessions = NULL; +static struct sessions_list *__sessions_list = NULL; + +static int fn(const char *fpath, const struct stat *sb, int typeflag) { + // practically impossible to reach this + // but will prevent break + if (used_size == 0xffff) + return 0; + + if (!S_ISREG(sb->st_mode)) + return 0; + + FILE *fd = fopen(fpath, "r"); + if (fd == NULL) { + fprintf(stderr, "error opening file (r) %s", fpath); + return 0; + } + + bool found = false; + size_t alloc_size = sb->st_blksize; + char *buf = malloc(sb->st_blksize); + while (true) { + buf = realloc(buf, sb->st_blksize); + ssize_t read_size = getline(&buf, &alloc_size, fd); + if (read_size == -1) + break; + + uint read; + if ((read = sscanf(buf, "Name=%s\n", buf)) != 0) { + found = true; + buf = realloc(buf, read); + break; + } + } + + // just add this to the list + if (found) { + if (used_size >= alloc_size) { + alloc_size += bs; + sessions = realloc(sessions, alloc_size * unit_size); + } + + sessions[used_size] = __new_session(buf, fpath); + used_size++; + } + + free(buf); + return 0; +} + +static struct sessions_list __list; +// This code is designed to be run purely sinlge threaded +struct sessions_list *get_avaliable_sessions() { + if (sessions != NULL) + return __sessions_list; + else + sessions = malloc(alloc_size * unit_size); + + for (uint i = 0; i < sources_size; i++) { + ftw(sources[i], &fn, 1); + } + + sessions = realloc(sessions, used_size * unit_size); + + __list.length = used_size; + __list.sessions = sessions; + return __sessions_list = &__list; +} diff --git a/src/users.c b/src/users.c new file mode 100644 index 0000000..d073a2a --- /dev/null +++ b/src/users.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct user __new_user(struct passwd *p) { + struct user __user; + strcln(&__user.username, p->pw_name); + if (p->pw_gecos[0] == '\0') + __user.display_name = __user.username; + else + strcln(&__user.display_name, p->pw_gecos); + + return __user; +} + +static const u_int8_t bs = 16; +static const u_int8_t unit_size = sizeof(struct user); + +static u_int16_t alloc_size = bs; +static u_int16_t used_size = 0; + +static struct user *users = NULL; +static struct users_list *__users_list = NULL; + +struct users_list __list; +// This code is designed to be run purely sinlge threaded +struct users_list *get_human_users() { + if (users != NULL) + return __users_list; + else + users = malloc(alloc_size * unit_size); + + struct passwd *pwd; + while ((pwd = getpwent()) != NULL) { + // practically impossible to reach this (== 0xffff) + // but will prevent break + if (used_size == 0xffff || + !(pwd->pw_dir && strncmp(pwd->pw_dir, "/home/", 6) == 0)) + continue; + + if (used_size >= alloc_size) { + alloc_size += bs; + users = realloc(users, alloc_size * unit_size); + } + + users[used_size] = __new_user(pwd); + used_size++; + } + + users = realloc(users, used_size * unit_size); + + __list.length = used_size; + __list.users = users; + return __users_list = &__list; +} diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..b9231b7 --- /dev/null +++ b/src/util.c @@ -0,0 +1,9 @@ +#include +#include + +#include + +void strcln(char **dest, const char *source) { + *dest = malloc(strlen(source) + sizeof(char)); + strcpy(*dest, source); +}