2010-04-27 7 views
2

Étant donné un nom de fichier dans C, je veux déterminer si ce fichier existe et a l'autorisation d'exécution sur ce fichier. Tout ce que j'ai est actuellement:Vérifiez si le fichier existe, y compris sur PATH

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

Mais cette recherche wont le chemin des fichiers et des répertoires correspondra également (que je ne veux pas). Quelqu'un pourrait-il m'aider?

Edit:

Comme alternative, car je suis en execvp() dans un processus enfant, est-il un moyen de vérifier la valeur de retour de execvp() et signaler le processus parent mourir avec un Message d'erreur?

+0

@diciu je sais que. C'est pourquoi je cherche un moyen d'amener C à chercher le nom de fichier dans ces chemins de la même manière que bash fait – Gary

Répondre

0

Nous avons fini d'avoir à mettre le drapeau FD_CLOEXEC sur une nouvelle conduite et à écrire un message d'erreur par après l'exec si elle avait échoué. Je pourrais alors lire le message d'erreur du parent et déterminer si exec a réussi ou non.

Merci pour vos efforts si les gars, upvoted pour l'aide

2

Ce code n'est pas tout à fait ce que vous voulez, car il exécute simplement aveuglément la première chose à laquelle il arrive. Mais vous pouvez modifier le code de recherche afin qu'au lieu d'appeler execve, vous appelez access puis stat pour savoir si ce n'est pas un répertoire. Je pense que seule la dernière fonction, , doit être remplacée.

Dans la meilleure tradition Unix, le code est "auto-documenté" (c'est-à-dire non documenté).

#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); 
    } 
    } 
} 
+0

Hey - merci pour votre aide. Cela semble beaucoup plus complexe que ce que je pensais que ce serait. N'existe-t-il aucun moyen d'exécuter une fonction exec et de la renvoyer si le fichier n'existe pas? – Gary

1

Vous pouvez utiliser les fonctions suivantes. comme .. les codes suivants contiennent des codes pseudo, mais doivent être faciles à mettre en œuvre

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; 
}