src/world/usr.bin/which/src/which.c

86 lines
2.7 KiB
C

/*
*----------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <jeang3nie@HitchHiker-Linux.org> wrote this file. As long as you
* retain this notice you can do whatever you want with this stuff. If
* we meet some day, and you think this stuff is worth it, you can buy
* me a beer in return.
* ---------------------------------------------------------------------
* ______ _______ _ _________
* ( __ \ ( ___ )( ( /|( )\__ __/
* | ( \ )| ( ) || \ ( ||/ ) (
* | | ) || | | || \ | | | |
* | | | || | | || (\ \) | | |
* | | ) || | | || | \ | | |
* | (__/ )| (___) || ) \ | | |
* (______/ (_______)|/ )_) )_(
*
* _______ _______ _ _________ _______
* ( ____ )( ___ )( \ /|\__ __/( ____ \
* | ( )|| ( ) || \ ( | ) ( | ( |/
* | (____)|| (___) || \ | | | | | |
* | _____)| ___ || (\ \) | | | | |
* | ( | ( ) || | \ | | | | |
* | ) | ) ( || ) \ |___) (___| (____|\
* |/ |/ \||/ \_)\_______/(_______/
*
*/
#include <dirent.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
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);
}