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

C Discussion :

Passage de commandes à un autre programme


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Par défaut Passage de commandes à un autre programme
    Bonjour.

    J'essaye de réaliser une interface graphique pour un programme qui s'utilise au départ en lignes de commande.
    Je voudrais utiliser directement l'exécutable de ce programme, je pense que ce serait plus simple que de modifier les sources et tout recompiler avec mon interface graphique.

    Mon programme "interface" doit exécuter le programme d'origine, lui envoyer une commande, lire la réponse, envoyer une autre commande, et ainsi de suite...

    Le programme d'origine n'est pas sensé "savoir" qu'il communique avec un autre programme, il croit que c'est l'utilisateur qui entre des commandes dans le terminal.

    Mais je ne sais pas quelles fonctions C il faut utiliser...
    J'ai vu pas mal de choses (popen(), select(), poll(), ...), mais je suis un peu perdu avec toutes ces fonctions.
    Faut-il utiliser un "tube", un socket ?

  2. #2
    Membre émérite Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Par défaut
    Renseignes toi sur la fonction system.

    Ce que je ferais pour récupérer le résultat c'est le rediriger vers un fichier puis aller lire ce fichier tout simplement.

  3. #3
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Salut,

    Si la solution de ssmario2 ne te convient pas tu peux (dois?) faire comme ceci:
    - creer 2 tubes (un dans le sens interface -> prog, et un pour l'autre sens)
    - fork
    - dans le fils, connecter une extremite du premier tube a stdin et une extremite du second a stdout
    - dans le fils toujours, exec(programme).
    - dans le pere, ecrire dans le tube connecte a stdin du fils et lire dans le tube connecte a stdout du fils

    Il te faudra fermer les extremites non utilisees dans le pere et le fils, jouer du select ou poll dans le pere pour ne pas bloquer.

    Chercher sur google ou ce forum avec les mots clefs pipe, fork, dup2, exec et les pages de man associees devrait te donner des exemples pour commencer.
    Un bon debut ici pour un exemple dans un seul sens et sans utilisation de stdin / stdout.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Par défaut
    Merci tonton fred, j'ai essayé de programmer ce que tu m'a dit.

    Ça donne ça :

    Code : 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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
     
    int main (int argc, const char * argv[])
    {
    	int tube1[2];
    	int tube2[2];
    	pid_t pid;
     
    	// Ouverture du premier tube
    	if (0 != pipe(tube1))
    	{
    		perror("Problème pour ouvrir le premier tube.\n");
    		exit(1);
    	}
     
    	// Ouverture du deuxième tube
    	if (0 != pipe(tube2))
    	{
    		perror("Problème pour ouvrir le deuxième tube.\n");
    		exit(1);
    	}
     
    	// Séparation du programme en deux
    	pid = fork();
     
    	if (pid == -1)
    	{
    		perror("Problème pour séparer le programme en deux.\n");
    		exit(0);
    	}
    	else if (pid == 0)
    	{
    		// FILS
     
    		// Fermeture du côté "écriture" du tube 1
    		close(tube1[1]);
    		// Fermeture du côté "lecture" du tube 2
    		close(tube2[0]);
     
    		// Connexion du côté "lecture" du tube 1 sur stdin
    		dup2(tube1[0], 0);
    		// Connexion du côté "écriture" du tube 2 sur stdout
    		dup2(tube2[1], 1);
     
    		// Exécution du programme en ligne de commande
    		execl("/Users/nicolas/Documents/programme", NULL);
    	}
    	else
    	{
    		// PÈRE
     
    		// Fermeture du côté "lecture" du tube 1
    		close(tube1[0]);
    		// Fermeture du côté "écriture" du tube 2
    		close(tube2[1]);
     
    		// Envoi des commandes et lecture des réponses
    		char *commande;
    		char buffer[100];
     
    		commande = "5\n";
    		write(tube1[1], commande, strlen(commande));
    		read(tube2[0], buffer, sizeof(buffer));
    	}
     
        return 0;
    }
    Evidemment, ça marche pas du premier coup, mais je pense qu'il n'y a plus grand chose à changer pour que ça marche.

    Le seul truc que j'ai pas fait, c'est "jouer du select ou poll dans le pere pour ne pas bloquer", tu pourrais expliquer un peu plus ?

  5. #5
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Citation Envoyé par hpccpp Voir le message
    Le seul truc que j'ai pas fait, c'est "jouer du select ou poll dans le pere pour ne pas bloquer", tu pourrais expliquer un peu plus ?
    Une explication tres claire du pourquoi ici.
    Dans ton cas tu sembles ecrire une fois puis lire une fois, donc ca ne devrait pas etre necessaire. Cependant, si tes programmes doivent communiquer plusieurs fois dans les deux sens alors tu devras utiliser select ou poll.
    Exemple avec select:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    fd_set ecriture, lecture;
    FD_ZERO(ecriture);
    FD_ZERO(lecture);
    FD_SET(tube1[1], &ecriture);
    FD_SET(tube2[0], &lecture);
     
    while (jai-des-trucs-a-faire) {
        if (select(MAX(tube1[1], tube2[0]) + 1, &lecture, &ecriture, NULL, NULL) > 0) 
            if (FD_ISSET(tube1[1], &ecriture)
                write(tube1[1], .....);
            if (FD_ISSET(tube2[0], &lecture)
                read(tube2[0], ......);
    }
    Une petite remarque: apres dup2 tu peux fermer l'extremite du tube.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    dup2(tube1[0], 0);
    close(tube1[0]);
    dup2(tube2[1], 1);
    close(tube2[1]);

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    ça c'est monter une usine à gaz pour faire un truc simple


    Citation Envoyé par hpccpp Voir le message
    Bonjour.

    J'essaye de réaliser une interface graphique pour un programme qui s'utilise au départ en lignes de commande.
    Je voudrais utiliser directement l'exécutable de ce programme, je pense que ce serait plus simple que de modifier les sources et tout recompiler avec mon interface graphique.

    Mon programme "interface" doit exécuter le programme d'origine, lui envoyer une commande, lire la réponse, envoyer une autre commande, et ainsi de suite...

    Le programme d'origine n'est pas sensé "savoir" qu'il communique avec un autre programme, il croit que c'est l'utilisateur qui entre des commandes dans le terminal.
    En dehors de la solution de ssmario2 (qui est déjà nettement plus simple que les tubes), en voici une autre :

    Il suffit de simuler un tube (pipe) :

    rediriger la sortie du premier programme vers le second, dans lequel on lit stdin...

    on peut aussi rediriger la sortie du premier programme vers un fichier et se servir de ce fichier comme stdin.

  7. #7
    Membre émérite
    Inscrit en
    Avril 2007
    Messages
    667
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Avril 2007
    Messages : 667
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    En dehors de la solution de ssmario2 (qui est déjà nettement plus simple que les tubes), en voici une autre :

    Il suffit de simuler un tube (pipe) :
    Juste pour etre sur, qQu'entends-tu par "simuler un tube" ? La redirection?
    Citation Envoyé par souviron34 Voir le message
    rediriger la sortie du premier programme vers le second, dans lequel on lit stdin...

    on peut aussi rediriger la sortie du premier programme vers un fichier et se servir de ce fichier comme stdin.
    Et un deuxieme fichier pour lire la reponse du programme ?
    Je rappelle la question:
    Citation Envoyé par hpccpp Voir le message
    Mon programme "interface" doit exécuter le programme d'origine, lui envoyer une commande, lire la réponse, envoyer une autre commande, et ainsi de suite...
    Et le "ainsi de suite" de la question me fait penser que cela devra tourner dans une boucle, donc il faut gerer les acces concurrents a deux fichiers, le fifo (les fichiers sont plutot des piles) etc. Donc "l'usine a gaz" devient nettement plus interressante a mon avis
    Mais si tu as plus simple, ca m'interresse aussi

  8. #8
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    reprenons alors simplement :

    • le premier programme (langage de commande) a ses entrées et sorties automatiquement redirigeables instantanément (stdin et stdout). (que ce soit à la main, dans un fichier "pipé" en ligne, etc etc.)


    • reste le second.

      Il suffit :

      • en entrée : re-diriger le stdin, ou lire le fichier de sortie du premier
      • en sortie : rediriger le stdout sur le stdin du premier, ou écrire dans le fichier stdin du premier.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Par défaut
    Merci pour vos réponses.

    Mais j'ai un petit problème :
    Quand mon programme en ligne de commande démarre, il envoie une ligne pour dire qu'il a démarré.
    Et j'arrive même pas à récupérer cette ligne.

    Code : 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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
     
    int main (int argc, const char * argv[])
    {
    	int tube1[2];
    	int tube2[2];
    	pid_t pid;
     
    	// Ouverture du premier tube
    	if (0 != pipe(tube1))
    	{
    		perror("Problème pour ouvrir le premier tube.\n");
    		exit(1);
    	}
     
    	// Ouverture du deuxième tube
    	if (0 != pipe(tube2))
    	{
    		perror("Problème pour ouvrir le deuxième tube.\n");
    		exit(1);
    	}
     
    	// Séparation du programme en deux
    	pid = fork();
     
    	if (pid == -1)
    	{
    		perror("Problème pour séparer le programme en deux.\n");
    		exit(0);
    	}
    	else if (pid == 0)
    	{
    		// FILS
     
    		// Fermeture du côté "écriture" du tube 1
    		close(tube1[1]);
    		// Fermeture du côté "lecture" du tube 2
    		close(tube2[0]);
     
    		// Connexion du côté "lecture" du tube 1 sur stdin
    		dup2(tube1[0], 0);
    		close(tube1[0]);
    		// Connexion du côté "écriture" du tube 2 sur stdout
    		dup2(tube2[1], 1);
    		close(tube2[1]);
     
    		// Exécution du programme en ligne de commande
    		execl("/Users/nicolas/Documents/programme", "programme", (char*)0);
    	}
    	else
    	{
    		// PÈRE
     
    		// Fermeture du côté "lecture" du tube 1
    		close(tube1[0]);
    		// Fermeture du côté "écriture" du tube 2
    		close(tube2[1]);
     
    		// Lecture du premier message
    		char buffer[128];
     
    		read(tube2[0], buffer, sizeof(buffer));
    		printf("Le programme a répondu : '%s'.\n", buffer);
    	}
     
        return 0;
    }
    Quand j'exécute ça, rien ne s'affiche, et le programme a l'air d'attendre indéfiniment que quelque chose arrive dans read();

    Pour lire juste cette ligne, je n'ai pas encore besoin de select().
    Il faudrait déjà que j'arrive à faire ça avant de faire des lectures/écritures multiples.

    Le programme en ligne de commande démarre bien, parce que si j'"oublie" de rediriger stdin et stdout, j'ai bien le message qui s'affiche.

    Dans cet exemple, je me contente d'écrire "Le programme a répondu : ...", c'est juste pour tester. Une fois que ça marchera, j'utiliserai la réponse pour autre chose.

    Est-ce que le fait que j'utilise Mac OS X (et pas Linux) peut justifier le fait que ça marche pas ? Je pense pas, mais bon...

Discussions similaires

  1. [delphi 2005]envoyer une commande a un autre programme
    Par shell13010 dans le forum Langage
    Réponses: 2
    Dernier message: 03/02/2010, 20h34
  2. Réponses: 9
    Dernier message: 19/08/2008, 16h15
  3. Passage de commande MSDOS
    Par costaud05 dans le forum Langage
    Réponses: 13
    Dernier message: 10/11/2004, 14h14
  4. Réponses: 9
    Dernier message: 19/08/2004, 11h03
  5. [TP]Insertion texte dans un autre programme
    Par FLB dans le forum Turbo Pascal
    Réponses: 53
    Dernier message: 14/06/2003, 20h11

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