/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST
const char *
libsimple_which(const char *file, int cwdfd, const char *path, char **free_this_out)
{
const char *p, *q;
char *buf = NULL;
size_t bufsize, len, filelen;
int got_eacces = 0, saved_errno = errno;
free_this_out = NULL;
if (!file || !free_this_out) {
errno = EINVAL;
return NULL;
}
if (strchr(file, '/'))
return file;
if (!path) {
path = getenv("PATH");
if (!path)
path = "";
}
if (!*path) {
errno = ENOENT;
return NULL;
}
bufsize = 0;
for (p = path; p; p = q) {
q = strchr(p, ':');
if (q)
len = (size_t)(q++ - p);
else
len = strlen(p);
if (len > bufsize)
bufsize = len;
}
if (bufsize) {
filelen = strlen(file) + 1U;
bufsize += 1U + filelen;
buf = malloc(bufsize);
if (!buf)
return NULL;
}
for (p = path; p; p = q) {
q = strchr(p, ':');
if (q)
len = (size_t)(q++ - p);
else
len = strlen(p);
if (len) {
memcpy(buf, p, len);
buf[len] = '/';
memcpy(&buf[len + 1], file, filelen);
if (!faccessat(cwdfd, buf, X_OK, AT_EACCESS)) {
*free_this_out = buf;
errno = saved_errno;
return buf;
}
} else {
if (!faccessat(cwdfd, file, X_OK, AT_EACCESS)) {
errno = saved_errno;
return file;
}
}
if (errno == EACCES)
got_eacces = 1;
}
free(buf);
errno = got_eacces ? EACCES : ENOENT;
return NULL;
}
#else
#include "test.h"
int
main(void)
{
return 0;
}
#endif