Check if file exists, including on PATH


Check if file exists, including on PATH



Given a filename in C, I want to determine whether this file exists and has execute permission on it. All I've got currently is:

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

But this wont search the PATH for files and will also match directories (which I don't want). Could anyone please help?

Edit:

As an alternative, seeing as I'm running execvp() in a child process, is there a way to check the return value of execvp() and signal the parent process to die with an error message?


Displaying an image from the tmp directory

1:

How do they read clusters/cylinders/sectors from the disk?
This code's not quite what you want, as it simply blindly executes the first thing it comes to. Use OpenBSD's malloc, realloc and free in my program But you must modify the search code so this instead of calling execve you call access and then stat to find out if it's not a directory. Strange results while measuring delta time on Linux I think only the last function, execvepath, has to be replaced.. Java OutOfMemoryError due to Linux RAM disk cache not freed In the best Unix tradition, the code is "self-documenting" (i.e., undocumented).. Spring ResourceServlet throws too many open files exception in jetty and tomcat under linux
#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 = receive env("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);     }   } } 
compile with -ansi -pedantic -Wall switches automatically with gccbluetooth application devlopment

2:

You must use the following functions. like.. the following codes contains any pseudid codes, although should be easy to implement.
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, {         receive env( "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; } 

3:

Ended up having to set the FD_CLOEXEC flag on a new pipe and writing an error message through it after the exec if it had failed. I could then read the error message from the parent and determine whether exec was successful or not.. Thanks for your effort though guys, upvoted for the help.


80 out of 100 based on 35 user ratings 790 reviews