blob: bf96c8828957d7dff1b8ddbe3b5791c1be3b6fcb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002, 2010 QNX Software Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* QNX Software Systems - initial API and implementation
* Wind River Systems, Inc.
* Mikhail Sennikovsky - bug 145737
* Everton Rufino Constantino (IBM) - bug 237611
*******************************************************************************/
/*
* pfind.c - Search for a binary in $PATH.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define PATH_DEF "PATH="
const int path_def_len = 5; /* strlen(PATH_DEF); */
char *path_val(char *const envp[]) {
if (!envp || !envp[0]) {
return getenv("PATH");
}
for (int i = 0; envp[i]; i++) {
char *p = envp[i];
if (!strncmp(PATH_DEF, p, path_def_len)) {
return p + path_def_len;
}
}
return NULL;
}
char *pfind(const char *name, char *const envp[]) {
char *tok;
char *sp;
char *path;
char fullpath[PATH_MAX + 1];
struct stat sb;
/* Sanity check. */
if (!name) {
fprintf(stderr, "pfind(): Null argument.\n");
return NULL;
}
/* For absolute name or name with a path, check if it is an executable. */
if (name[0] == '/' || name[0] == '.') {
if (access(name, X_OK) == 0) {
return strdup(name);
}
return NULL;
}
/* Search in the PATH environment. */
path = path_val(envp);
if (!path || strlen(path) <= 0) {
fprintf(stderr, "Unable to get $PATH.\n");
return NULL;
}
/* The value return by getenv() is read-only */
path = strdup(path);
tok = strtok_r(path, ":", &sp);
while (tok) {
snprintf(fullpath, sizeof(fullpath) - 1, "%s/%s", tok, name);
if (stat(fullpath, &sb) == 0 && S_ISREG(sb.st_mode)) { /* fullpath is a file */
if (access(fullpath, X_OK) == 0) { /* fullpath is executable */
free(path);
return strdup(fullpath);
}
}
tok = strtok_r(NULL, ":", &sp);
}
free(path);
return NULL;
}
#ifdef BUILD_WITH_MAIN
int main(int argc, char **argv) {
for (int i = 1; i < argc; i++) {
char *fullpath = pfind(argv[i], NULL);
if (fullpath) {
printf("Found %s @ %s.\n", argv[i], fullpath);
} else {
printf("Unable to find %s in $PATH.\n", argv[i]);
}
}
}
#endif