From 2dcdba77045a5e86d6e9906c81623cb8ef250ca8 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Tue, 10 Jan 2023 22:07:30 -0500 Subject: [PATCH] which - once a match is found in $PATH, test that it is a regular file and can be accessed as executable --- world/usr.bin/which/Makefile | 6 ++-- world/usr.bin/which/src/which.c | 57 ++++++++++++++++++++++++++++++++ world/usr.bin/which/src/which.sh | 2 -- 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 world/usr.bin/which/src/which.c delete mode 100644 world/usr.bin/which/src/which.sh diff --git a/world/usr.bin/which/Makefile b/world/usr.bin/which/Makefile index eb0926b..d0bb342 100644 --- a/world/usr.bin/which/Makefile +++ b/world/usr.bin/which/Makefile @@ -1,5 +1,7 @@ -# Makefile - hhl - /src/world/bin/which +# Makefile - hhl - /src/world/usr.bin/which # Copyright 2020 Nathan Fisher # progname = which -include hhl.script.mk +hhl_source = 1 +onestage = true +include hhl.cprog.mk diff --git a/world/usr.bin/which/src/which.c b/world/usr.bin/which/src/which.c new file mode 100644 index 0000000..4a7543a --- /dev/null +++ b/world/usr.bin/which/src/which.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include + +char *__progname; + +void usage() { + printf("Usage: %s [COMMAND]\n", __progname); + exit(1); +} + +int main(int argc, char **argv) { + char *path, *seg, *__path; + const char sep[2] = ":"; + + __progname = basename(argv[0]); + if (argc < 2) { + fprintf(stderr, "%s: Error: missing argument\n", __progname); + usage(); + } else if (argc > 2) { + fprintf(stderr, "%s: Error: missing argument\n", __progname); + usage(); + } + path = getenv("PATH"); + if (path == NULL) { + path = "/usr/bin:/bin"; + } + // Save a copy for later use, since strtok will modify the original + __path = strndup(path, strlen(path) + 1); + seg = strtok(path, sep); + while (seg != NULL) { + struct dirent *dp; + DIR *dir = opendir(seg); + if (dir) { + while ((dp = readdir(dir)) != NULL) { + if (strcmp(argv[1], dp->d_name) == 0) { + char *p = malloc(strlen(argv[1] + strlen(seg) + 2)); + (void)strncpy(p, seg, strlen(seg) + 1); + (void)strncat(p, "/", 2); + (void)strncat(p, argv[1], strlen(argv[1]) + 1); + struct stat path_stat; + stat(p, &path_stat); + if (access(p, X_OK) == 0 && S_ISREG(path_stat.st_mode)) { + printf("%s\n", p); + exit(0); + } + } + } + } + seg = strtok(NULL, sep); + } + printf("%s: no %s in (%s)\n", __progname, argv[1], __path); +} diff --git a/world/usr.bin/which/src/which.sh b/world/usr.bin/which/src/which.sh deleted file mode 100644 index 3a6a255..0000000 --- a/world/usr.bin/which/src/which.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/zsh -which $@