Bonsoir
Pour mon programme en C++, j'ai besoin d'exécuter des programmes externes sans passer par l'appel system qui lance /bin/sh.
On m'a donné une fonction utilisant fork et wait4, mais le problème c'est qu'il faut lui donner un tableau.
J'aimerais soit savoir comment la transformer pour lui donner un nombre d'arguments variable, soit savoir quelle fonction (C++ si possible, donc qui accepte des std::string) utiliser pour remplacer system. J'accepte toute autre idée off course :)
Merci d'avance
PS : voici le code de la fonction actuelle :
Elle se comporte EXACTEMENT comme un system, et lance donc /bin/sh, ce que je ne veux pas :(
int my_system(std::string commande) {
char *parms[4];
parms[0]="sh";
parms[1]="-c";
parms[2]=(char *)commande.data();
parms[3]=NULL;
int pid;
if((pid=fork())>0) {
execv("/bin/sh", parms);
} else if(pid==0) {
int ret;
wait4(pid, &ret, 0, NULL);
return ret;
} else if(pid<0) {
std::cerr << "Mechant fork! il veut pas marcher!" << std::endl;
}
return -1;
}
(Merci à phh pour cette fonction)
# execle(...);
Posté par G. R. (site web personnel) . Évalué à 3.
Dans la famille des fonctions exec*(), celles avec un « l » prennent une liste d'arguments (terminée par un NULL) et celles avec un « v » un tableau.
Donc, remplaces ton execv() par un execl(), voire un execle() ;
Maintenant, tu souhaites lancer ton programme sans passer par un shell, et pourtant, ... tu lances un /bin/sh ! Mais pourquoi donc ?
La famille exec*() prend en premier paramètre le nom d'un fichier à exécuter.
Pour les détails, voir man 3 exec
Mais c'est du C, du vrai, pas du C++. En C++, je ne sais pas, il y a peut-être des front-end disponibles à ces fonctions.
[^] # Re: execle(...);
Posté par Ph Husson (site web personnel) . Évalué à 2.
Ben justement c'est ca le probleme...
Pour l'instant c'est une copie conforme de system() mais la ce qu'on veut c'est se passer de ca
Donc faut séparer nous memes les arguments, et on y arrive pas
(J'avais fait avec strtok.. je recommencerais pas)
(Merci à phh pour cette fonction)
Au mais de rien
[^] # Re: execle(...);
Posté par Obsidian . Évalué à 3.
Dans un premier temps, pourquoi ne te contentes-tu pas de transmettre les arguments qui ont été passés au programme père ? Tu récupères argv,argc dans main() et tu les transmets au futur programme à l'aide de execve().
[^] # Re: execle(...);
Posté par Pinaraf . Évalué à 1.
Ce programme est un programme disons... "bas niveau" dans le sens où il doit pouvoir, s'il est en static, fonctionner sur n'importe quelle machine, dans un / vide, complètement vide !
Actuellement, il utilise des commandes comme tar, md5sum... J'aimerais que ces commandes soient :
- soit remplacées par des libs C (c'est faisable pour tar...)
- n'utilisent pas l'appel system qui a le défaut de lancer /bin/sh, qui n'est pas disponible lors de l'utilisation de mon programme...
En gros, je souhaite coder une fonction qui ressemble à ça :
int my_system (std::string commande)
int my_system (std::string commande1, ...) (nombre d'arguments variable, j'y arrive pas :(
int my_system (std::string commande[]) (j'ai réussi, mais le pb c'est que mon tableau passé en argument ne convient pas :(
J'ai essayé de l'appeler comme ça : my_system(["tar", "-zxvf","/test.tar.gz"]) et il refuse pour d'obscures raisons...
[^] # Re: execle(...);
Posté par eJah . Évalué à 2.
Je dis ptet une grosse betise, mais comme j'ai pas envie de verifier j'essaie qd meme:
essaye avec ce prototype de fonction:
int my_system (const std::string commande[]
Ca devrait passer tout seul apres lorsque tu appelles:
my_system(["tar", "-zxvf","/test.tar.gz"])
Voili voilou, tiens nous au courant ;)
[^] # Re: execle(...);
Posté par Pinaraf . Évalué à 1.
int my_system (std::string commande, std::string separator) {
std::vector<std::string> liste;
std::string cmd;
char **tableau;
int pid, position=0, last_find = 0,i, retour = -1;
cmd = commande + separator;
for (position = 0 ; position < cmd.size() ; position ++) {
if (cmd.substr(position, separator.size()) == separator) {
liste.push_back(cmd.substr(last_find, position-last_find));
last_find = position + separator.size();
}
}
tableau = (char **)malloc((liste.size()+1)*sizeof(char *));
for (i=0 ; i < liste.size() ; i++) {
std::cout << liste[i] << std::endl;
tableau[i] = (char *)liste[i].c_str();
}
tableau[i+1] = NULL;
if ((pid=fork()) > 0) {
execvp(liste[0].c_str(), tableau);
} else if (pid==0) {
wait4 (pid, &retour, 0, NULL);
if (tableau) free(tableau);
return retour;
} else if (pid<0) {
std::cerr << "Le fork n'a pas marché !" << std::endl;
}
if (tableau) free(tableau);
return -1;
}
Ce code est crade, je sais
La commande ifconfig eth0 se lance par :
my_system("ifconfig||eth0","||");
Si quelqu'un arrive à résoudre le besoin du séparateur.
C'est du au fait que si la commande contient un argument comme : nom fichier.tar.gz, en un argument, ça marchera pas avec " " comme séparateur.
[^] # Re: execle(...);
Posté par Pinaraf . Évalué à 1.
voici les changements (tout ce qui précède tableau = (char **)malloc(.....
int my_system (std::string commande) {
std::vector<std::string> liste;
std::string cmd, element;
char **tableau;
bool in_quotes = false;
int pid, last_find = 0,i, retour = -1;
cmd = commande + " ";
for (i=0 ; i < cmd.size() ; i++) {
if (cmd[i] == '"') {
in_quotes = !in_quotes;
}
if ((cmd[i] == ' ') and (!in_quotes)) {
element = cmd.substr(last_find, i-last_find);
if (element[0]=='"') {
element = element.substr(1);
}
if (element[element.size()-1]=='"') {
element = element.substr(0, element.size()-1);
}
liste.push_back(element);
last_find = i+1;
}
}
[^] # Re: execle(...);
Posté par eJah . Évalué à 1.
Sinon un bon bouquin ou un bon cour de C++ online s'impose la.
De plus tu utilises la classe string alors utilise les methodes qui vont bien, donc profites-en pour compulser la STL
Voila pour les conseils :)
[^] # Re: execle(...);
Posté par Pinaraf . Évalué à 1.
J'ai besoin du malloc car la fonction execvp a besoin d'un char **
J'ai oublié quelle méthode qui va bien dans la classe string ?
J'ai lu les docs, ne t'inquiète pas. J'ai un bouquin sur le C++ pas terrible, mais j'ai un bouquin.
Merci d'avance
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.