The which program probably does a search for the file in any of the directories specified in the PATH environment variable.
There are many ways to do this, this is one such ways
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <sys/stat.h>
int
main(int argc, char *argv[])
{
const char *head;
const char *command;
size_t length;
if (argc < 2) {
fprintf(stderr, "insufficient number of arguments\n");
return -1;
}
command = argv[1];
length = strlen(command);
// Get the PATH environment variable
head = getenv("PATH");
if (head == NULL) {
fprintf(stderr, "the PATH variable was not set, what?\n");
return -1;
}
// Find the first separator
while (*head != '\0') {
struct stat st;
ptrdiff_t dirlen;
const char *tail;
char *path;
// Check for the next ':' if it's not found
// then get a pointer to the null terminator
tail = strchr(head, ':');
if (tail == NULL)
tail = strchr(head, '\0');
// Get the length of the string between the head
// and the ':'
dirlen = tail - head;
// Allocate space for the new string
path = malloc(length + dirlen + 2);
if (path == NULL)
return -1;
// Copy the directory path into the newly
// allocated space
memcpy(path, head, dirlen);
// Append the directory separator
path[dirlen] = '/';
// Copy the name of the command
memcpy(path + dirlen + 1, command, length);
// `null' terminate please
path[dirlen + length + 1] = '\0';
// Check if the file exists and whether it's
// executable
if ((stat(path, &st) != -1) && (S_ISREG(st.st_mode) != 0)) {
if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
fprintf(stdout, "found `%s' but it's not executable\n", path);
} else {
fprintf(stdout, "found at: %s\n", path);
}
}
// Don't forget to free!
free(path);
// Point to the next directory
head = tail + 1;
}
return 0;
}
in general the same algorithm
- Get the
PATH environment variable, which consists of a sequence of directory paths separated by a : character.
- Obtain each directory path in this sequence by iterating over it, this is where you can do it many ways.
Check if,
- The file exists.
- Has execution permissions for the caller.
popento runwhich Rscriptand capture the output.