IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Administration système Discussion :

Comment recevoir en directe le résultat d'une commande systeme en C++/C?


Sujet :

Administration système

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2008
    Messages : 69
    Par défaut Comment recevoir en directe le résultat d'une commande systeme en C++/C?
    Bnojour, je suis nouveau. J'ai une question. Je veux faire une application en C++ qui émet des commandes system et intéragit avec le retour, une sorte de terminal plus pret de hotwire que de xterm. Idéalement, j'aimerais que mon programme émet et recois lui même les output. À date, cela ma causé beaucoup de mots de tête. J'ai étudier 2 première possibilitées:

    Utiliser fopen pour recevoir le résultat:
    +facile
    +fonctionne sans trop se préocuper du système
    -ne commence à utiliser les output que quand la commande est terminé
    -demmande un buffer de plusieurs millions de char pour ne pas risqué de -faire un overflow

    Utiliser la redirection ">>" directement sur la ligne de commande dans un fichier temporaire:
    +il peut analyser en temps presquer réel les outputs dans une boucle infini
    -C'est une boucle infini, elle n'est pas capable de s'arrêter saud si j'ajoute && echo killme ou quelque chose du genre à la fin de la commande (très peu professionel)
    -C'est vraiment très insécure, trop insécure.


    Maintenant, après avoir lut quelque centaine de pages sur le fonctionement de bas niveau des systèmes POSIX, je commence à voir aparaitre la bonne solution:
    -forker mon prosessus
    -créer un pipe entre les 2 prosessus
    -executer la commande et redirectionné la sortie dans le pipe
    -attendre (ou provoquer) sa mort depuis le prosessus père en affichant/parsant les résultats à mesure.

    Le problème, c'est que à par forker le prosessus, je ne sais pas comment faire cela, les exemples sont très rare. Comment est-ce que je redirige la sortie de la commande dans le pipe et comment je le recois dans le prosessus père en directe?

    Merci de m'aider!

  2. #2
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Serait-tu québécois ? J'ai l'impression de lire ton accent.

    Je ne sais pas si le C++ propose des mécanismes de plus haut niveau, mais en C, ta dernière solution est la bonne.

    Ton programme doit ressembler à quelque chose du genre
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    /* Plein d'includes */
     
     
    /* Cette fonction finit par un exit() pour ne pas retourner dans le main() après */
    void exec_cmd(int *to_me, int *from_me) {
     
        /* Les dup donnent juste un "nouveau numéro" d'accès aux fichiers, cf man dup */
        dup2(to_me[0], STDIN_FILENO); /* Err */
        dup2(from_me[1], STDOUT_FILENO); /* Err */
     
        /* Fermer les descripteurs de fichier inutiles. Très important ! */
        /* Note : On peut fermer les 4 parce qu'on vient de dupliquer ceux dont on avait besoin */
        close(to_me[0]); /* Err */
        close(to_me[1]); /* Err */
        close(from_me[0]); /* Err */
        close(from_me[1]); /* Err */
     
        /* On exécute enfin la commande */
        execlp(/* blah */);
     
        /* Err */
        exit(EXIT_FAILLURE);
    }
     
     
    int main (void) {
        pid_t pid;
        int to_cmd[2], from_cmd[2];
     
        pipe(to_cmd); /* Err */
        pipe(from_cmd); /* Err */
     
        pid = fork(); /* Err */
        if (pid == 0)
            exec_cmd(to_cmd, from_cmd);
     
        /* Important ! Fermer les descripteurs de fichiers inutiles. */
        close(to_cmd[0]); /* Err */
        close(from_cmd[1]); /* Err */
     
     
        /* Envoyer les données en écrivant sur to_cmd[0]
         * Ces données seront reçues sur l'entrée standard du programme */
        write(/* blah */); /* Err */
     
        /* Lire le résultat sur from_cmd[1]
         * Ces données sont celles que la commande a envoyé sur la sortie standard */
        read(/* blah */); /* Err */
     
        /* On ferme les derniers descripteurs de fichier */
        close(to_cmd[0]); /* Err */
        close(from_cmd[1]); /* Err */
     
        /* On attend que le fils ait fini */
        wait(NULL);
     
        return EXIT_SUCCESS;
    }
    Les commentaires /* Err */ indiquent que tu dois tester la valeur de retour pour vérifier si il y a une erreur. En cas d'erreur, la fonction perror ou strerror devrait être appelée pour afficher un message d'erreur.

    Le programme globalement est assez simple, on crée deux pipes, un pour envoyer les données vers la commande, un pour lire les données renvoyées par la commande.
    Puis on fork. Lors d'un fork les descripteurs de fichier sont copiés, donc on se retrouve avec 4 descripteurs de fichier (2 par pipe) dans chaque processus.
    Le processus père, ferme les descripteurs de fichiers inutiles, envoie des données puis lit le résultat de la commande. Enfin il attend que le fils ait terminé avant de se terminer lui-même.

    Le fils, lui, avant d'exécuter la commande, commence par "brancher" les pipes sur ses entrée/sortie standard.
    En fait, pour chaque fichier ou pipe ouvert, le noyau crée une structure et y stocke tout plein d'information (entre autre la position de la "tête de lecture", celle qu'on modifie avec lseek/fseek), les descripteurs de fichiers (qui ne sont que des entiers) ne servent qu'à désigner une de ces structures.
    Les fonctions dup et dup2 ne servent qu'à donner un autre numéro à la structure qui est maintenant référencé par deux descripteurs (numéros) différents.
    Avec dup2 on choisit "numéro" de destination, et c'est cool, parce que comme ça, on peut remplacer l'entrée et la sortie standard par le descripteur de fichier qu'on veut. Comme ça, quand on va lancer la commande, elle pourra lire et écrire ses données comme elle le fait d'habitude sur ses entrées/sorties standard qui seront en fait branchés sur nos pipes.
    Ensuite, le fils ferme les descripteurs de fichiers inutiles. Les descritpeurs utiles ont été dupliqués, donc pour ceux-là, ça ne fait que décrémenter le "compteur d'ouverture" de la structure.
    Enfin exécuter la commande. Regarde le man, il existe plusieurs variantes de la commande execlp. Et puis on a bien de la chance parce que les descripteurs de fichiers ouverts sont conservés lors d'un exec.
    Les commandes exec se terminent toujours par une erreur. En effet, tu es censé remplacer ton processus actuel par un autre, donc si la suite de ton code s'exécute, c'est que l'exec a échoué.


    Ce genre de code est plein de subtilités, notamment le fait qu'il ne faut pas oublier de fermer tous les descripteurs de fichier inutiles.
    Et cela pour une raison simple.
    La fonction read est bloquante tant qu'il y a encore des données qui peuvent arriver. Si tous les descripteurs de fichiers en écriture sur ce pipe sont fermés, la fonction read renvoie 0 sans attendre.
    Donc oublier de fermer un descripteur de fichier peut conduire un read à être bloquant alors qu'il n'y a normalement plus aucune donnée qui puisse arriver.
    De même pour write, si tous les descripteurs en lecture sur ce pipe sont fermés, write doit échouer.
    Attention aussi au fait que write peut être bloquant si le buffer interne du pipe est plein.
    Donc le code que j'ai donné ci-dessus est potentiellement FAUX. En effet, si il y a beaucoup de données à écrire, la commande va en lire une partie, traiter puis renvoyer le résultat sur sa sortie standard.
    Mais toi, tu n'as pas fini d'écrire tes données, donc tu ne vas pas pouvoir lire le résultat. La commande va finir par se bloquer sur le write, et toi tu sera aussi bloqué sur ton write.
    Pouf, deadlock, y'a plus qu'à killer.

    C'est pour ça qu'en général on fait plutôt les read et les write dans deux processus ou threads séparés. Ou bien qu'on les gère avec un select. Mais pour ça je te laisse faire.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2008
    Messages : 69
    Par défaut
    Oui, tu as bien lut mon accent

    Merci de m'aider, je ne suis vraiment pas habitué à faire de la programation d'aussi bas niveau. J'ai essayé dede complèter ton code mais je n'ais pas réussi (oui, je suis vraiment un noob en prog système)

    Le code que j'utilise actuelement ressemble à :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    #include  <unistd.h>
    #include  <stdio.h>
    #include  <stdlib.h>
    #include  <errno.h>
    #include  <sys/wait.h>
    #include  <sys/types.h>
     
    void exec_cmd(int *to_me, int *from_me)
    {
     
        // Les dup donnent juste un "nouveau numéro" d'accès aux fichiers, cf man dup
        dup2(to_me[0], STDIN_FILENO); // Err
        dup2(from_me[1], STDOUT_FILENO); // Err
     
        // Fermer les descripteurs de fichier inutiles. Très important !
        // Note : On peut fermer les 4 parce qu'on vient de dupliquer ceux dont on avait besoin
        close(to_me[0]); // Err
        close(to_me[1]); // Err
        close(from_me[0]); // Err
        close(from_me[1]); // Err
     
        // On exécute enfin la commande
        execlp("ls", "ls", "-l", "/", 0);
     
        // Err
        sleep(15) ;
        exit(0);
    }
     
    int main(void)
    {
     pid_t  pid,pidfils ;
     int  status ;
     int to_cmd[2], from_cmd[2];
     
     pipe(to_cmd); // Err
     pipe(from_cmd); // Err
     
     
     
     printf("Processus pere de PID %d\n ",getpid()) ;
     
     switch(pid = fork())
     {
         case (pid_t)-1 :
            perror("naufrage... ") ;
            exit(2) ;
         case (pid_t)0 :
            printf(" Debut du processus fils PID=%d \n ",getpid()) ;
            system("echo commande executee par fils > /tmp/testprogsys.txt");
            exec_cmd(to_cmd, from_cmd);
         default:
            char bufferW[10000];
            write(to_cmd[0], bufferW, sizeof bufferW); // Err
     
            // Lire le résultat sur from_cmd[1]
            //* Ces données sont celles que la commande a envoyé sur la sortie standard
            char bufferR[10000];
            read(from_cmd[1], bufferR, sizeof bufferR); // Err
            printf("%s", bufferR);
     
            close(to_cmd[0]); // Err
            close(from_cmd[1]); // Err
     
            pidfils = wait(NULL) ; /* attention adresse ! ! ! */
            printf(" Mort du processus fils PID=%d\n ",pidfils) ;
      }
    return 0;
    }

    L'erreur est probablement stupide, je n'ai jmais fait sa et jamais vraiment travaillé en C pour autre chose que des petite fonctions.

    Ce que je remarque est que le sleep() ne s'éxécute jamais allors que avec le code du liens suivant ( http://drocourt.iut-amiens.fr/cours/...rog_sys3.xhtml ) il fonctionne. ce que je remarque aussi c'est que avec execlp("dmesg, "dmesg", "", "", 0) il affiche la ligne d'usage (-h) du prosessus sur mon terminal. Que manque t'il pour que ça fonctionne?

  4. #4
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Quelques remarques à propos de ton code.
    En C, les commentaires // ne sont pas standard, mais ils le sont en C++. Donc après, à toi de voir si tu veux faire du pure C ou du C++ à la C.

    J'espère que dans le programme final, tu testera le retour de toutes ces fonction. Généralement -1 indique une erreur, cf le man.
    Tous les arguments de execlp sont censés être des char*, y compris le dernier, donc tu devrais mettre NULL. D'ailleurs je suppose que si tu compile avec -W il va te dire un truc du genre "Warning: passing parameter makes pointer from integer without a cast".
    Le sleep ne s'exécute pas parce que le execlp a fonctionné. Je rappel que les fonction exec* en cas de succès remplacent le code de ton processus en mémoire par celui de l'exécutable donné.
    Au lieu de mettre exit(0), c'est plus propre de mettre exit(EXIT_SUCCESS). Cette macro a toujours la bonne valeur suivant le système, elle est définie dans stdlib.h.

    Dans la fonction main.
    Généralement on évite de faire appel à la fonction system(), c'est assez lent, et peut rapidement causer des soucis de sécurité. Mais tu as peut-être fait ça juste pour les tests.
    Tu n'est pas obligé de mettre tout le code du père dans le default du switch, puisque de toutes façons la fonction exec_cmd ne retournera jamais.
    Tu n'as pas fermé to_cmd[0] ni from_cmd[1] avant de commencer à envoyer/recevoir des données.
    Désolé hier j'ai inversé les bouts du pipe, pour lire/écrire des données vers la commande. Bien entendu on lit sur from_cmd[0] et écrit sur to_cmd[1]. Comme indiqué dans le man pipe, à l'extrémité 0 du pipe on ne peut que lire, et à l'extrémité 1 on ne peut que écrire.
    Ensuite, tu envoie à la commande, le contenu de bufferW alors que celui-ci n'est pas initialisé. (Et en C, les déclarations de variables se font toujours au début d'un bloc {}, mais cf la remarque du début.)
    À propos du read dans bufferR (tu lis sur le mauvais bout du pipe, mais c'est de ma faute). Tu ne lis que au maximum 10000 caractères, il faudrait peut-être mettre une boucle autour, mais là peut-être que tu voulais simplifier.
    La fonction printf, pour un format "%s", attend une chaîne de caractère qui se termine par un octet nul '\0'. Or quand tu fais un read, tu n'as aucune garantie que la chaîne se termine par octet nul, et d'ailleurs dans 99% des cas ce n'est pas le cas. Donc le printf risque de t'afficher ce que tu as lu avec des trucs en plus à la fin, ou alors il ne t'affichera pas le tout si un \0 se trouve en plein milieu de tes données.
    Et dernière chose le return 0 / return EXIT_SUCCESS comme dit précédemment.


    Et enfin, remarque plus générale : relire ce que j'ai dit précédemment à propos du deadlock.
    Ici le fait de faire des write sur le pipe avant de faire des read risque de marcher parce que sous linux les pipes ont un buffer de 4096 ou 65536 octets selon les versions, mais il se pourrait que quelqu'un sur un petit système ait mis seulement 16 octets de buffer.

    Et puis si le dmesg ne marche pas c'est parce que tu lui donne deux paramètres qui sont des chaînes vides.
    La fonction execlp prend un nombre d'arguments variable, tu peux très bien faire execlp("dmesg", "dmesg", NULL); ou bien execlp("ls", "ls", "/", "/home", "/home/toto", "/home/toto/video", "/home/toto/audio", NULL);.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2008
    Messages : 69
    Par défaut
    En effet, juste désinversé les io à règler le fait que sa ne fonctionnait pas. Escuse moi l'état purement dépriment du code qui suit. Je vais mettre la gestion d'erreur de l'ordre dans ce fouilli pur (et plein de raccouris pour sauver du tmeps dans mes testes). Je n'ai pas vraiment corrigé ce dont tu m'a parlé dans ton dernier post, mais je vais le faire.

    Pour l'instant, j'essai d'atteindre l'étape "just work" pour cette petite partie de code (qui est en C++ en passant, c'est juste que pour les pipe, sa doit être écrit en C, POSIX est comme sa). Actuelement, j'aimerais avoir un peut plus d'information sur le buffer, comment est-ce que je fais pour envoiyé seulement la limite de charactère et ensuite attendre avant la suivante? Je me sert du pipe du prosessus père pour lui envoyer un signal? Si oui, lequel?

    Et j'ai essailer de complèter mon semblan de terminal, mais très étrangement, certaine commde ne fonctionnent pas et d'autre parfaitement. Par exemple "ls -l /" ne fonctionne pas mais "ls -l" oui tout comme "ls /". Même chose pour "echo salut". Je l'ai passée avec atention dans GNU DDD, mais tout semble corecte! (en passant, oui je sais que j'ai une fuite de mémoire). Voici le code en question:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    #include <iostream>
    #include  <unistd.h>
    #include  <stdio.h>
    #include  <stdlib.h>
    #include  <errno.h>
    #include  <sys/wait.h>
    #include  <sys/types.h>
     
    using namespace std;
     
    void exec_cmd(int *to_me, int *from_me, char* paramArray[])
    {
     
        dup2(to_me[0], STDIN_FILENO); // Err
        dup2(from_me[1], STDOUT_FILENO); // Err
     
        close(to_me[0]); // Err
        close(to_me[1]); // Err
        close(from_me[0]); // Err
        close(from_me[1]); // Err
     
        execvp(paramArray[0], paramArray);
     
        sleep(15) ;
        exit(0);
    }
     
    int main()
    {
        while (1)
        {
            cout << ">";
           string command;
            string tmp;
            int counter;
     
     
                counter = 0;
     
     
                getline(cin, command);
     
                tmp =command;
                while (tmp.find(" ") != -1)
                {
                    counter++;
                    tmp = tmp.substr((tmp.find(" ") +1), (tmp.length() - tmp.find(" ") - 1));
                    //cout << tmp << endl;
                }
                counter++;
     
                char** paramArray = new char*[counter+1];
                int i =0;
     
                while (command.find(" ") != -1)
                {
                    int paramLenght = command.find(" ");
                    char* param = new char[paramLenght+1];
                    strcpy(param, command.substr(0, paramLenght).c_str());
                    paramArray[i] = param;
                    command = command.substr((paramLenght +1), (command.length() - paramLenght - 1));
                    i++;
                }
                int paramLenght = command.length();
                char* param = new char[paramLenght+1];
                strcpy(param, command.c_str());
                paramArray[i] = param;
     
                pid_t  pid,pidchild ;
                 int  status ;
                 int to_cmd[2], from_cmd[2];
                 int find0A =0;
                 int findStart;
     
                 pipe(to_cmd); // Err
                 pipe(from_cmd); // Err
     
     
     
                 printf("I am parent PID %d\n ",getpid()) ;
     
                 switch(pid = fork())
                 {
                     case (pid_t)-1 :
                        perror("fatal error... ") ;
                        exit(2) ;
                     case (pid_t)0 :
     
                        printf(" I am child PID=%d \n ",getpid()) ;
                        system("echo commande executed by child > /tmp/test/testprogsys.txt");
                        exec_cmd(to_cmd, from_cmd, paramArray);
                     default:
                        char bufferW[10000];
                        close(from_cmd[1]);
                        close(to_cmd[0]);
                        write(to_cmd[1], bufferW, sizeof bufferW); // Err
     
                        // Lire le résultat sur from_cmd[1]
                        //* Ces données sont celles que la commande a envoyé sur la sortie standard
                        char bufferR[10000];
                        read(from_cmd[0], bufferR, sizeof bufferR); // Err
     
                        string output = bufferR;
                        int j= 0;
                        while (j < output.length())
                        {
                            findStart = j;
                            while ((bufferR[j] != 0x0A) && (j != output.length())) j++;
                            cout << "    >>" << output.substr(findStart, (j-findStart)) << endl;
                            j++;
                        }
                        //printf("%s", bufferR);
     
                        close(to_cmd[0]); // Err
                        close(from_cmd[1]); // Err
     
                        pidchild = wait(NULL) ; /* attention adresse ! ! ! */
                        printf(" Death of child PID=%d\n ",pidchild) ;
     
                }
              }
     
     
        return 0;
    }

    En passant, je voudrait ajouté que je suis encore loin de l'université, je fait actuelement un cours pré universitaire en programation (qui équivaut probablement à une formation professionel en france, mais je ne connais pas vraiment votre système scolaire). Donc ce genre de code me dépasse un peut, désoler d'être aussi perdu, je ne suis même pas suposé être capable de faire sa à mon niveau. Donc merci de ton indulgence

    EDIT: À oui, et j'oubliais, cette solution ne semble pas renvoyer les code serial pour les couleurs, est-ce possible de les récupérer eux aussi?

  6. #6
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Ce n'est pas vraiment un terminal que tu cherches à faire, mais un shell.
    Mais bon, en vrai, les shells ne récupèrent pas la sortie des programme pour l'afficher dans le terminal, ce sont les programmes qui affichent directement dans le terminal.

    Pour arriver à ce que ça marche, les messages d'erreur sont d'une grande utilité tu peux me croire. Donc tu devrais commencer par ça. Par exemple quand la lecture/écriture des pipes était inversé, tu aurait eut un message d'erreur un peu explicite.


    Il semblerait que ce soit ta boucle qui foire, en effet la première commande marche toujours, pas la deuxième.
    Les fonctions read et write renvoient le nombre d'octet lu/écrits dans le buffer et -1 en cas d'erreur, cf le man. D'ailleurs je te conseille très fortement de lire le man de chacun des appels système utilisé dans ton code, tu y apprendra des tas de choses.
    Pour la gestion de ton bufferW, je pense que (vu ton code) tu veux stocker le résultat complet en mémoire avant de le parcourir.
    Une méthode en C consiste à avoir un buffer qu'on alloue avec malloc, plus un petit buffer. Le read se fait dans le petit buffer, et on rajoute ce morceau de données lues à la fin du grand buffer avec memcpy. Ce grand buffer on l'agrandit si besoin avec realloc. Bien entendu ça sous-endend de connaître à tout moment la taille du buffer, et combien de données il contient.
    Et on continue tant que read n'a pas renvoyé 0. Parce que je le rappel, read renvoie 0 en fin de fichier (si c'est un fichier normal), ou si l'autre bout du pipe a été fermé (donc plus aucune donnée ne peut arriver).
    Il est possible de se passer du petit buffer intermédiaire, mais ça nécessite de jouer un peu plus avec les pointeurs.

    Mais c'est quand même un gros gâchis de stocker l'intégralité des données en mémoire alors qu'on peut les traiter au fur et à mesure qu'elles arrivent.
    Dans ton cas tu n'as qu'à lire un bloc de données, et le réafficher tel quel caractère par caractère, sauf si c'est un "\n", auquel cas tu affiche en plus un ">>".

    Mais bon, je sais qu'en C++ on fait pas trop de malloc, et il existe peut-être des mécanismes de plus haut niveau pour gérer ça. Mais comme déjà dit, je ne connais pas le C++.

    Sinon, je ne connais pas trop le C++ donc j'aurais du mal à te dire ce qui ne va pas dans ton programme.

    Pour une gestion simple et claire des erreurs je te propose la fonction suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void system_error(const char *msg)
    {
    	perror(msg);
    	exit(EXIT_FAILURE);
    }
    Et tu t'en sert comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		err = pipe(to_cmd);	// Err
    		if (err == -1)
    			system_error("pipe");

    Et pour finir, remarque générale, un code propre c'est 50% de bugs en moins. Tu devrais essayer.


    À propos des couleurs, la commande ls se comporte différemment si sa sortie standard est connectée directement sur un terminal ou non. Il y a entre autre les couleurs qui ne sont plus envoyées. D'autres commandes se comportent ainsi. Tu peux la forcer à envoyer toujours les codes de couleur avec --color=always. Cf le man ls.
    Ce comportement permet d'avoir directement des données utilisables par d'autres commandes, comme grep.

Discussions similaires

  1. [Batch] Comment passer le résultat d'une commande en variable
    Par Ohemeg dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 30/11/2009, 23h51
  2. Réponses: 4
    Dernier message: 22/08/2008, 09h43
  3. Comment afficher le rang des résultats d'une requête sous Access 2002
    Par painpepper dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 15/08/2007, 01h19
  4. [SQL] Comment je peux mettre les résultat d'une requete dans un fichier
    Par Maria1505 dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 10/12/2006, 21h44
  5. Réponses: 2
    Dernier message: 04/10/2006, 14h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo