检查文件是否存在,包括PATH

给定一个C文件名,我想确定这个文件是否存在并且对它有执行权限。 我目前所拥有的是:

if( access( filename, X_OK) != 0 ) { 

但是这不会searchPATH的文件,也将匹配目录(我不想)。 任何人都可以请帮忙?

编辑:

作为替代方法,看到我在subprocess中运行execvp(),是否有办法检查execvp()的返回值,并用父错误消息告诉父进程?

这段代码并不是你想要的,因为它只是盲目执行第一件事情。 但是,您可以修改搜索代码,以便不调用execve而是调用access ,然后查找它是否不是目录。 我想只有最后一个函数execvepath必须被替换。

在最好的Unix传统中,代码是“自我记录”(即无证)。

 #include <string.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include "shellpath.h" static void *malloc_check(const char *what, size_t n) { void *p = malloc(n); if (p == NULL) { fprintf(stderr, "Cannot allocate %zu bytes to %s\n", n, what); exit(2); } return p; } static char *strsave(const char *s, const char *lim) { if (lim == NULL) lim = s + strlen(s); char *p = malloc_check("save string", lim - s + 1); strncpy(p, s, lim-s); p[lim-s] = '\0'; return p; } char ** shellpath(void) { const char *path = getenv("PATH"); if (!path) path = "/bin:/usr/bin:/usr/local/bin"; char **vector = // size is overkill malloc_check("hold path elements", strlen(path) * sizeof(*vector)); const char *p = path; int next = 0; while (p) { char *q = strchr(p, ':'); vector[next++] = strsave(p, q); p = q ? q + 1 : NULL; } vector[next] = NULL; return vector; } void freeshellpath (char *shellpath[]) { for (int i = 0; shellpath[i]; i++) free(shellpath[i]); free(shellpath); } unsigned maxpathlen(char *path[], const char *base) { unsigned blen = strlen(base); unsigned n = 0; for (int i = 0; path[i]; i++) { unsigned pn = strlen(path[i]); if (pn > n) n = pn; } return blen+n+1; } void execvepath(char *path[], const char *base, char *const argv[], char *const envp[]) { if (strchr(base, '/')) execve(base, argv, envp); else { size_t maxlen = maxpathlen(path, base)+1; char *buf = malloc_check("hold path", maxlen); for (int i = 0; path[i]; i++) { snprintf(buf, maxlen, "%s/%s", path[i], base); execve(buf, argv, envp); } } } 

您可以使用以下功能。 像下面的代码包含一些伪代码,但应该很容易实现

 if the given path contains the current directory path, like /root/a or ./abc, then return access( filename, X_OK) == 0; Else - if the given path only contains the filename, { getenv( "PATH" ); while( iterate the directories in PATH ) { if( search( PATH_directory, filename ) ) { // create the full path string with strcat, strcpy, and/or etc. full_path = blabla if( !is_directory( full_path ) && access( filename, X_OK ) == 0 ) return 1; // Yeah~~ We got it!!! } } return 0; // Nah, I don't think there is any of such a file. } int is_directory( const char* path ) { struct stat file_info; return ( stat( path, &file_info ) == 0 ) ? S_ISDIR( file_info.st_mode ) : 0; } int search( const char* file_name, const char* path ) { struct dirent* dptr; DIR* dirp; if( (dirp = opendir( path )) == NULL ) return 0; while( dptr = readdir( dirp ) ) { if( strcmp( file_name, dptr->d_name ) == 0 ) { closedir( dirp ); return 1; } } closedir( dirp ); return 0; } 

最后必须在新管道上设置FD_CLOEXEC标志,并在exec之后通过它写入一个错误消息,如果失败的话。 然后,我可以从父级读取错误消息,并确定exec是否成功。

感谢您的努力,虽然家伙,upvoted的帮助