/** * * @File : exo_06.cxx * * @Authors : A. B. Dragut * * @Date : 2012 * * @Synopsis : emulation de la fonction systeme * * **/ #include #include #include #include // atoi() #include // strcpy(), strtok(), strlen() #include // system() #include #include #include "CExc.h" #include "nsSysteme.h" // Fork(), Signal() using namespace std; using namespace nsSysteme; // Fork(), Signal() namespace{ void System (const char * const LigneCommande){ if(!strlen(LigneCommande)) { throw CExc("System()","Pas de ligne de commande..."); } if (::pid_t PidFils = Fork ()) //pere Waitpid (PidFils); else //fils { // enlever les commentaires de chaque sleep() et autres cerr // pour l'analyse avec strace et maps du /proc/ // /*pour l'analyse*/ cerr << "My pid is " << (getpid()) << "\n"; // /*pour l'analyse*/ sleep(1); // on s'apprete a balayer LigneCommande caractere par caractere const int nTotChar(strlen (LigneCommande)); // combien au total // /*pour l'analyse*/ sleep(2); // qInsideArg est une variable d'etat, nous disant si on est sur des // separateurs ou bien dans un des arguments (ou la commande-meme) int qInsideArg (-1); // c'est-a-dire qu'on ne sait pas encore // /*pour l'analyse*/ sleep(3); vector > argPos; // pour le (debut,fin) de chaque // element ainsi decouvert dans LigneCommande suite au balayage qui // commence maintenant dans la boucle for() // /*pour l'analyse*/ sleep(4); for(int kChar(0); kChar < nTotChar; kChar++) { if(LigneCommande[kChar] == ' ') { // ceci est un separateur switch(qInsideArg) { // voyons dans quel etat nous sommes case -1: // on vient de commencer, c'est donc qu'il // y a des espaces au debut, donc on les ignore qInsideArg = 0;break; // et on passe en etat 'sep' case 0 : break; // on reste en etat 'sep' et on passe case 1 : // nous sommes a la fin d'un des elements argPos . back() . second = (kChar-1); // on marque // la vraie fin de sa portion dans LigneCommande qInsideArg = 0; break;// et on passe en etat 'sep' default: // on ne devrait jamais arriver ici throw CExc("System()","Should never happen, fixme"); } } else { // donc un (ou le premier) caractere d'un element // on le saura plus precisement en fonction de l'etat courant if(qInsideArg <= 0) { // en effet, le premier // on doit donc creer une nouvelle entree dans argPos if(qInsideArg < 0) { // /*pour l'analyse*/ sleep(1); } argPos . push_back(pair(kChar,kChar)); // pour // l'instant on ne connait que le debut, pour la fin on // verra plus tard, pour l'instant on la met au meme // endroit elle aussi (donc kChar) if(qInsideArg < 0) { // /*pour l'analyse*/ sleep(1); } qInsideArg = 1; // et nous passons dans l'etat 'arg' } } } // fin de la boucle for() pour le balayage de LigneCommande // on a donc tout fini, sauf la fin du dernier element, qui // pourrait ne pas etre la bonne (car le push_back() met la // meme position pour (debut,fin), // on doit donc juste prendre soin du 'second' du '.back()', // pour le cas ou on n'a pas eu d'espace a la fin de LigneCommande // (car autrement ce serait deja fait avec le 'case plus haut) if(qInsideArg > 0) { // alors pas d'espace(s) a la fin argPos . back() . second = nTotChar - 1; // on peut bien faire // .back() ici, car on est forcement passe par un .push_back() // (pourquoi cela ? car qInsideArg commence a -1 et le seul // endroit ou qInsideArg est mis a >0 (donc 1) est celui-la) } const int nTotArgs(argPos . size()); char * NewArgv [nTotArgs + 1]; // pour mettre aussi le pointeur nul // maintenant on depose un par un la commande et les arguments dans // NewArgv, pour le donner ensuite a execvp() // /*pour l'analyse*/ sleep(5); for(unsigned int kArg(0); kArg < argPos . size(); kArg++) { const int argSize(argPos[kArg] . second - argPos[kArg] . first + 1); NewArgv[kArg] = new char[argSize+1]; // (char*)malloc((argSize+1)*sizeof(char)); memcpy(NewArgv[kArg], LigneCommande+argPos[kArg] . first,argSize); NewArgv[kArg][argSize] = '\0'; } NewArgv[nTotArgs] = 0; // /*pour l'analyse*/ cerr << "Ok, here we go\n"; // /*pour l'analyse*/ sleep(20); // /*pour l'analyse*/ cerr << "Ok, here we go now\n"; ::execvp (NewArgv [0], NewArgv); // si on est la, c'est qu'il y a eu un probleme avec execvp() // on libere alors d'abord la memoire allouee avec 'new' for(unsigned int kArg(0); kArg < argPos . size(); kArg++) { // free(NewArgv[kArg]); delete [] NewArgv[kArg]; } // et on leve l'exception necessaire pour le signaler throw CExc("execv ()",NewArgv [0]); } } // System() } // namespace anonyme int main(int argc, char * argv []) { try { if (2!= argc) throw CExc("main()",string ("Usage : ") + argv [0] + " "); System(argv [1]); return 0; } catch (const CExc & Exc) { cerr <