2017-10-20 60 views
0

J'exécution d'un simple programme shell à partir du répertoire:exec (...) n'exécute pas le programme, malgré le passage dans la variable PATH

/home/user/shell.exe

En utilisant le code ci-dessous , Je suis capable d'exécuter des fichiers qui sont dans le même dossier que mon exécutable shell, mais je suis incapable d'exécuter des programmes tels que ls.exe. Le conteneur de jetons inclut le nom de fichier comme premier élément et tous les jetons suivants (tels que "-l" dans l'entrée "ls.exe -l") dans les éléments suivants.

if (fork()) 
{ 
    int status; 
    wait(&status); 
} 
else 
{ 
std::vector<const char*> exeArgs; 
std::vector<const char*> envArgs; 

std::for_each(tokens.begin(), tokens.end(), 
[&exeArgs](const string& elem){ exeArgs.push_back(elem.c_str()); } 
      ); 

exeArgs.push_back(nullptr); 

string path = "PATH="; 
path.append(getenv("PATH")); 

envArgs.push_back(path.c_str()); 
envArgs.push_back(nullptr); 

if (execve(exeArgs[0], const_cast<char *const *>(&exeArgs[0]), 
         const_cast<char *const *>(&envArgs[0]))) 
{ 
    std::cout << word << ": command not found" << std::endl; 
    exit(0); 
} 
} 

J'ai passé d'innombrables heures juste googler et en lisant les pages de l'homme à plusieurs reprises mais ne peut pas sembler obtenir un indice pourquoi ce code ne fonctionne pas. L'idée est que mon programme shell devrait permettre aux utilisateurs de définir la variable PATH, puis d'exécuter des programmes avec cette variable PATH, c'est pourquoi je dois faire fonctionner execve() au lieu d'utiliser simplement execvp(). J'ai une carte de variables de shell dans une partie séparée du fichier mais comme je n'arrive même pas à faire fonctionner cela, j'ai pensé qu'il serait inutile d'inclure cela.

Répondre

2

Vous ne savent que la famille exec des fonctions remplace le processus en cours avec l'image du nouveau programme? C'est pourquoi il est si commun d'utiliser fork avant exec.

Armé de cette connaissance, il est facile de trouver une solution pour vous, et comment vous pouvez utiliser execvp (que vous devez utiliser, execve ne pas vraiment utiliser l'environnement que vous passez, il passe juste le long de le nouveau programme): Vous fork et utilisez setenv pour définir le PATH du processus nouveau, avant d'appeler execvp.

+0

J'ai modifié le post pour inclure le reste de ma fonction. Je voudrais juste clarifier, si execve() n'utilise pas les variables d'environnement qui sont passées pour définir les variables d'environnement du processus après le chargement du nouveau programme, alors à quoi sert le paramètre array de la variable d'environnement? – ozma

+1

@ozma Comme je l'ai dit, il passe l'environnement au programme * new *, celui que exec exécute. Si vous ne savez pas, dans les systèmes POSIX (comme Linux ou macOS, où 'exec' est standardisé), la fonction' main' peut avoir un * troisième * argument, généralement nommé 'env' et est déclaré et fonctionne comme le' argv' tableau. C'est l'environnement passé par 'execve' (et qui sera disponible via' getenv' dans le nouveau programme). –

+0

Oh, c'est vrai! Pendant tout ce temps j'ai supposé que puisque je passais dans les variables d'environnement, ils joueraient aussi un rôle dans l'exécution du programme. C'est aussi la première fois que j'ai entendu parler du troisième argument de main. Merci beaucoup. – ozma