From ae23e86114f559ce6d01a3e2499fc5417dc90d37 Mon Sep 17 00:00:00 2001 From: Phil Jones Date: Sat, 6 Nov 2021 18:44:27 +0000 Subject: Start conversion to tofi. --- src/compgen.c | 50 +++++++++++++++++++++++++++++++++ src/compgen.h | 8 ++++++ src/main.c | 2 ++ src/string_vec.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/string_vec.h | 28 +++++++++++++++++++ 5 files changed, 172 insertions(+) create mode 100644 src/compgen.c create mode 100644 src/compgen.h create mode 100644 src/string_vec.c create mode 100644 src/string_vec.h (limited to 'src') diff --git a/src/compgen.c b/src/compgen.c new file mode 100644 index 0000000..e04e0a5 --- /dev/null +++ b/src/compgen.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include "log.h" +#include "string_vec.h" + +struct string_vec compgen() +{ + log_debug("Retrieving PATH.\n"); + const char *env_path = getenv("PATH"); + if (env_path == NULL) { + log_error("Couldn't retrieve PATH from environment."); + exit(EXIT_FAILURE); + } + struct string_vec programs = string_vec_create(); + char *path = strdup(env_path); + char *saveptr = NULL; + char *path_entry = strtok_r(path, ":", &saveptr); + log_debug("Scanning PATH for binaries.\n"); + while (path_entry != NULL) { + DIR *dir = opendir(path_entry); + if (dir != NULL) { + int fd = dirfd(dir); + struct dirent *d; + while ((d = readdir(dir)) != NULL) { + struct stat sb; + if (fstatat(fd, d->d_name, &sb, 0) == -1) { + continue; + } + if (!(sb.st_mode & S_IXUSR)) { + continue; + } + if (!S_ISREG(sb.st_mode)) { + continue; + } + string_vec_add(&programs, d->d_name); + } + closedir(dir); + } + path_entry = strtok_r(NULL, ":", &saveptr); + } + free(path); + log_debug("Sorting results.\n"); + string_vec_sort(&programs); + log_debug("Making unique.\n"); + string_vec_uniq(&programs); + log_debug("Done.\n"); + return programs; +} diff --git a/src/compgen.h b/src/compgen.h new file mode 100644 index 0000000..b3b54b5 --- /dev/null +++ b/src/compgen.h @@ -0,0 +1,8 @@ +#ifndef COMPGEN_H +#define COMPGEN_H + +#include "string_vec.h" + +struct string_vec compgen(); + +#endif /* COMPGEN_H */ diff --git a/src/main.c b/src/main.c index 5a3c894..a1c873c 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include #include #include "client.h" +#include "compgen.h" #include "egl.h" #include "entry.h" #include "image.h" @@ -23,6 +24,7 @@ #include "greetd.h" #include "log.h" #include "nelem.h" +#include "string_vec.h" #undef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) diff --git a/src/string_vec.c b/src/string_vec.c new file mode 100644 index 0000000..94f41fa --- /dev/null +++ b/src/string_vec.c @@ -0,0 +1,84 @@ +#include +#include +#include "string_vec.h" + +static int cmpstringp(const void *a, const void *b) +{ + /* + * We receive pointers to the array elements (which are pointers to + * char), so convert and dereference them for comparison. + */ + const char *str1 = *(const char **)a; + const char *str2 = *(const char **)b; + + /* + * Ensure any NULL strings are shoved to the end. + */ + if (str1 == NULL) { + return 1; + } + if (str2 == NULL) { + return -1; + } + return strcmp(str1, str2); +} + +struct string_vec string_vec_create() +{ + struct string_vec vec = { + .count = 0, + .size = 128, + .buf = calloc(128, sizeof(char *)) + }; + return vec; +} + +void string_vec_destroy(struct string_vec *restrict vec) +{ + for (size_t i = 0; i < vec->count; i++) { + free(vec->buf[i]); + } + free(vec->buf); +} + +void string_vec_add(struct string_vec *restrict vec, const char *restrict str) +{ + if (vec->count == vec->size) { + vec->size *= 2; + vec->buf = realloc(vec->buf, vec->size * sizeof(vec->buf[0])); + } + vec->buf[vec->count] = strdup(str); + vec->count++; +} + +void string_vec_sort(struct string_vec *restrict vec) +{ + qsort(vec->buf, vec->count, sizeof(vec->buf[0]), cmpstringp); +} + +void string_vec_uniq(struct string_vec *restrict vec) +{ + size_t count = vec->count; + for (size_t i = 1; i < vec->count; i++) { + if (!strcmp(vec->buf[i], vec->buf[i-1])) { + free(vec->buf[i-1]); + vec->buf[i-1] = NULL; + count--; + } + } + string_vec_sort(vec); + vec->count = count; +} + +struct string_vec string_vec_filter( + struct string_vec *restrict vec, + const char *restrict substr) +{ + struct string_vec filt = string_vec_create(); + for (size_t i = 0; i < vec->count; i++) { + if (strstr(vec->buf[i], substr) != NULL) { + string_vec_add(&filt, vec->buf[i]); + } + } + return filt; +} diff --git a/src/string_vec.h b/src/string_vec.h new file mode 100644 index 0000000..0054c09 --- /dev/null +++ b/src/string_vec.h @@ -0,0 +1,28 @@ +#ifndef STRING_VEC_H +#define STRING_VEC_H + +#include + +struct string_vec { + size_t count; + size_t size; + char **buf; +}; + +[[nodiscard]] +struct string_vec string_vec_create(); + +void string_vec_destroy(struct string_vec *restrict vec); + +void string_vec_add(struct string_vec *restrict vec, const char *restrict str); + +void string_vec_sort(struct string_vec *restrict vec); + +void string_vec_uniq(struct string_vec *restrict vec); + +[[nodiscard]] [[gnu::nonnull]] +struct string_vec string_vec_filter( + struct string_vec *restrict vec, + const char *restrict substr); + +#endif /* STRING_VEC_H */ -- cgit v1.2.3