summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhil Jones <philj56@gmail.com>2021-11-06 18:44:27 +0000
committerPhil Jones <philj56@gmail.com>2021-11-06 19:02:29 +0000
commitae23e86114f559ce6d01a3e2499fc5417dc90d37 (patch)
treec55d7f3c3b131efd50ec2a6f884b48f9ce250c63 /src
parentc28c5249c4d3ba7076e2c6ea598e3ad93a168301 (diff)
Start conversion to tofi.
Diffstat (limited to 'src')
-rw-r--r--src/compgen.c50
-rw-r--r--src/compgen.h8
-rw-r--r--src/main.c2
-rw-r--r--src/string_vec.c84
-rw-r--r--src/string_vec.h28
5 files changed, 172 insertions, 0 deletions
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 <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#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 <xdg-shell.h>
#include <locale.h>
#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 <stdlib.h>
+#include <string.h>
+#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 <stddef.h>
+
+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 */