Forum Programmation.c++ Lancer un programme, comment ?

Posté par .
Tags : aucun
0
16
oct.
2004
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 (page perso) . Évalué à 3.

    J'ai pas compris ta question, mais bon...

    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 (page perso) . Évalué à 2.

      Maintenant, tu souhaites lancer ton programme sans passer par un shell, et pourtant, ... tu lances un /bin/sh ! Mais pourquoi donc ?
      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 . Évalué à 3.

        Quelle difficulté y a-t-il à séparer les arguments ? Si tu ne veux pas utiliser strtok(), un sscanf() devrait suffire pour les cas les plus compliqués (ou un stringstream si tu tiens à utiliser la STL).

        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 . Évalué à 1.

          Laisse moi t'expliquer.
          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 . Évalué à 2.

            int my_system (std::string commande[]) (j'ai réussi, mais le pb c'est que mon tableau passé en argument ne convient pas :(

            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 . Évalué à 1.

              j'ai pas réussi avec ton truc, mais j'ai réussi à faire quelque chose qui marche à peu près
              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 . Évalué à 1.

                J'ai  amélioré  :  
                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 . Évalué à 1.

                  Pour utiliser un malloc dans du code c++ tu ferais mieux de coder en C :/
                  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 . Évalué à 1.

                    Peux tu détailler ?
                    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 à ceux qui les ont postés. Nous n'en sommes pas responsables.