commit: d176c8781a093f5e300689dbe75e7fa4172584bd
parent 0c5c782733c7ac1cf4bd19177d2e5ec7ef269846
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Wed, 29 May 2024 08:46:21 +0200
cmd/which: new
Diffstat:
A | cmd/which.1 | 42 | ++++++++++++++++++++++++++++++++++++++++++ |
A | cmd/which.c | 85 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | makeless.sh | 1 | + |
3 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/cmd/which.1 b/cmd/which.1
@@ -0,0 +1,42 @@
+.\" utils-std: Collection of commonly available Unix tools
+.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+.\" SPDX-License-Identifier: MPL-2.0
+.Dd 2024-05-29
+.Dt WHICH 1
+.Os
+.Sh NAME
+.Nm which
+.Nd locate executable within PATH
+.Sh SYNOPSIS
+.Nm
+.Op Fl as
+.Ar name...
+.Sh DESCRIPTION
+The
+.Nm
+utility scans
+.Ev PATH
+for each given executable
+.Ar name .
+.Pp
+.Nm
+shall not be used when the standard
+.Xr sh 1
+builtin
+.Cm command
+.Fl v
+.Ar name
+can be used instead.
+.Sh OPTIONS
+.Bl -tag -width _a
+.It Fl a
+List all matching executables.
+.It Fl s
+Do not print executable names.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh STANDARDS
+None.
+.Sh AUTHORS
+.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me
diff --git a/cmd/which.c b/cmd/which.c
@@ -0,0 +1,85 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _POSIX_C_SOURCE 200809L
+
+#include <limits.h> // PATH_MAX
+#include <stdbool.h>
+#include <stdio.h> // fprintf
+#include <stdlib.h> // getenv
+#include <string.h> // strtok
+#include <unistd.h> // access, getopt
+
+int
+main(int argc, char *argv[])
+{
+ bool opt_a = false, opt_s = false;
+ int missing = 0;
+
+ char *path = getenv("PATH");
+ if(path == NULL)
+ {
+ fputs("which: Error: $PATH environment unset", stderr);
+ return 1;
+ }
+
+ int c = -1;
+ while((c = getopt(argc, argv, "as")) != -1)
+ {
+ switch(c)
+ {
+ case 'a':
+ opt_a = true;
+ break;
+ case 's':
+ opt_s = true;
+ break;
+ case '?':
+ fprintf(stderr, "which: Error: Unrecognised option: '-%c'\n", optopt);
+ return 1;
+ default:
+ abort();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if(argc <= 0) return 1;
+
+ for(int i = 0; i < argc; i++)
+ {
+ char *cmd = argv[i];
+ bool found = false;
+ char *state = NULL;
+
+ char *hay = strdup(path);
+ if(hay == NULL)
+ {
+ perror("which: Failed duplicating $PATH");
+ return 1;
+ }
+
+ for(char *tok = strtok_r(hay, ":", &state); tok != NULL; tok = strtok_r(NULL, ":", &state))
+ {
+ char buf[PATH_MAX] = "";
+ snprintf(buf, PATH_MAX, "%s/%s", tok, cmd);
+
+ if(access(buf, X_OK) == 0)
+ {
+ if(!opt_s) puts(buf);
+
+ found = true;
+
+ if(!opt_a) break;
+ }
+ }
+
+ if(!found) missing++;
+
+ free(hay);
+ }
+
+ return missing;
+}
diff --git a/makeless.sh b/makeless.sh
@@ -60,6 +60,7 @@ $CC -std=c99 $CFLAGS -o cmd/uname cmd/uname.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/uniq cmd/uniq.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/unlink cmd/unlink.c $LDFLAGS $LDSTATIC
$CC -std=c99 $CFLAGS -o cmd/wc cmd/wc.c $LDFLAGS $LDSTATIC
+$CC -std=c99 $CFLAGS -o cmd/which cmd/which.c $LDFLAGS $LDSTATIC
$YACC -b cmd/expr cmd/expr.y
$CC -std=c99 $CFLAGS -o cmd/expr cmd/expr.tab.c $LDFLAGS $LDSTATIC
$M4 cmd/date.1.in > build/cmd/date.1