logo

utils-std

Collection of commonly available Unix tools
commit: d176c8781a093f5e300689dbe75e7fa4172584bd
parent 0c5c782733c7ac1cf4bd19177d2e5ec7ef269846
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 29 May 2024 08:46:21 +0200

cmd/which: new

Diffstat:

Acmd/which.142++++++++++++++++++++++++++++++++++++++++++
Acmd/which.c85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmakeless.sh1+
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