diff options
author | Phil Jones <philj56@gmail.com> | 2021-11-06 18:44:27 +0000 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2021-11-06 19:02:29 +0000 |
commit | ae23e86114f559ce6d01a3e2499fc5417dc90d37 (patch) | |
tree | c55d7f3c3b131efd50ec2a6f884b48f9ce250c63 /src/compgen.c | |
parent | c28c5249c4d3ba7076e2c6ea598e3ad93a168301 (diff) |
Start conversion to tofi.
Diffstat (limited to 'src/compgen.c')
-rw-r--r-- | src/compgen.c | 50 |
1 files changed, 50 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; +} |