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 :

Programme C - Executer une commande shell


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 9
    Points : 6
    Points
    6
    Par défaut Programme C - Executer une commande shell
    Bonjour,

    je suis étudiant en licence pro informatique, mais n'y connais absolument rien en programmation. :s

    Pour un exercice, on doit créer un programme en C qui exécute une commande shell. J'avais trouvé la primitive system() mais bien sûr, restriction de l'exercice : c'est interdit de l'utiliser.

    Pouvez-vous me conseiller, orienter sur quoi je dois partir pour effectuer ce programme ?

    Merci d'avance.

  2. #2
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Les fonctions de la famille execv le font. N'oublie pas de lancer l'appel a l'une de ces fonctions dans un processus fils (cree avec fork) pour ne pas que ca quitte ton programme.

    En gros :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    fork();
     
    if (processus_fils) {
      execv();
    } else {
      wait(processus_fils);
    }

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Peux-tu nous éclairer en nous disant pourquoi il est interdit d'utiliser system() ? Est-ce que tu dois "recréer" une commande existante ou bien simplement en appeler une ? Parce que, dans ce dernier cas, system() est la plus indiquée.

    Certes, Imperio te donne execv qui n'est pas la seule car il y a une grande famille de fonctions de type "exec" (execl, execle, execv, execve, execp, execpe) qui s'appellent différemment selon qu'on a des arguments ou pas, besoin de leur envoyer un environnement ou pas, besoin d'utiliser le PATH ou pas, etc.
    Mais leurs utilisations est un peu plus pointues (nécessité de créer un second processus etc). Ce n'est pas pour embêter le programmeur mais pour lui donner la possibilité de récupérer et traiter les infos renvoyées par la commande shell (ce que ne permet pas system()). Sinon demander d'appeler un shell sans utiliser system() et sans nécessité de récupérer ce que la commande renvoie est un peu dommage (s'il n'y a pas une autre explication annexe)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Salut,

    Merci pour vos réponses. Alors en fait, je dois exécuter une commande shell existante, par exemple "ls -l", et créer un programme en C qui l’exécute. L'interdiction de system() fait partie de l'exercice, sans doute trop facile !

    Effectivement, quand j'ai tapé sur Google « langage C exécuter commande shell », je tombe que sur system() :s

    Personnellement je ne comprends pas trop l’intérêt de cet exercice, mais bon, vu que c'est noté…

  5. #5
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    C'est tout simplement pour que tu comprennes mieux comment fonctionne l'environnement linux. Pour executer "ls -l -a" par-exemple, il va falloir retracer toutes les etapes, a savoir :

    - trouver la commande
    - trouver les parametres a lui passer
    - trouver l'executable de la commande
    - le lancer dans un processus fils pour ne pas quitter le processus courant

    Donc pour les 2 premieres etapes, un peu de parsing. Pour la 3e, il va te falloir l'environnement (commande env dans ton shell) et plus precisement la variable PATH qui contient les chemins ou sont places les libs et les executables. Donc pour avoir l'environnement de ton executable, rien de bien mechant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main (int argc, char *argv[], char *envp[])
    C'est donc le 3e argument, dedans il te suffira donc de chercher la variable que tu souhaites. Pour chacune, concatene le nom de l'executable et le path. Par-exemple :

    executable : ls
    path : /usr

    Donnera /usr/ls. Apres teste l'existence du fichier ainsi que la possibilite de l'executer avec la fonction access. Enfin, il te suffit de creer un processus fils dans lequel tu vas appeler une fonction la famille exec (execvp est la plus simple d'utilisation si je me souviens bien) dans laquelle tu passeras le path complet de ton executable (/usr/ls dans le cas present) ainsi que les arguments (-l et -a) dans un char** et enfin l'environnement que tu souhaites lui envoyer.

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bilbon59 Voir le message
    merci pour vos réponses, alors en fait, je doit exécuter une commande shel existante, exemple "ls -l" et créer un programme en C qui l’exécute. L'interdiction de system() fait parti de l'exercice, sans doute trop facile !!
    Citation Envoyé par imperio Voir le message
    C'est tout simplement pour que tu comprennes mieux comment fonctionne l'environnement linux. Pour executer "ls -l -a" par-exemple, il va falloir retracer toutes les etapes...
    Mouais. Franchement entre sysem("ls -l -a") et execlp("ls", "ls", "-l", "-a", NULL) je vois pas trop bien où se situe la difficulté et ce que ça aidera à mieux comprendre. Surtout qu'on n'est même pas obligé de forker si on n'a pas besoin de conserver le processus initial...

    En, revanche, reproduire le comportement de ls en faisant du opendir/readdir/stat là ça devient tout de suite différent...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    J'insiste sur le fait que ca permet de mieux comprendre comment fonctionne l'environnement linux. Faire un opendir/readdir ca n'est pas tres complique et ca ne t'apprendra pas grand chose. stat te permettra de voir les droits et les liens mais a part ca...

    L'interet d'utiliser un exec (et execve me semble le plus indique dans ce cas) est de voir ou se situent les executables des commandes qu'on utilise. Avant ca, je n'avais aucune idee de comment fonctionnait un environnement shell et de ce qu'il se passait quand je faisais un "ls -l | wc" par exemple. A quoi servait la commande "env" et qu'est-ce qu'elle retournait, comment un programme avait-il acces a l'environnement du shell ? Sans parler du fait que ca m'a permis de decouvrir la fonction access qui est bien trop peu utilisee de mon point de vue.

    Pour moi, recoder un petit environnement shell est quelque chose a faire absolument pour tout developpeur C travaillant sous linux. Apres ca il ne reste plus qu'a leur demande de coder un petit gestionnaire de processus et la je pense qu'ils auront une bonne base.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par imperio Voir le message
    J'insiste sur le fait que ca permet de mieux comprendre comment fonctionne l'environnement linux. Faire un opendir/readdir ca n'est pas tres complique et ca ne t'apprendra pas grand chose. stat te permettra de voir les droits et les liens mais a part ca...
    Ben oui, stat pour afficher le rwxrwxrwx (et aussi les différentes dates du fichier)...

    Citation Envoyé par imperio Voir le message
    L'interet d'utiliser un exec (et execve me semble le plus indique dans ce cas) est de voir ou se situent les executables des commandes qu'on utilise. Avant ca, je n'avais aucune idee de comment fonctionnait un environnement shell et de ce qu'il se passait quand je faisais un "ls -l | wc" par exemple. A quoi servait la commande "env" et qu'est-ce qu'elle retournait, comment un programme avait-il acces a l'environnement du shell ?
    Dans ce cas, faut pas appeler ls. Faut appeler un autre programme (que tu as codé) qui affiche envp. Là oui ça devient plus parlant. Tu lui passes (avec execve effetivement) un environnement de ton choix et tu vois comment il le récupère.
    Pour le ls |wc là oui ça peut devenir intéressant (je l'ai fait une fois). Faut créer les pipe, dupliquer stdin sur le pipe[0], dupliquer stdout sur le pipe[1], etc. Effectivement on commence à s'amuser.
    Mais sinon je ne vois pas ce que ls apportera à execve (on ne verra même pas à quoi sert le "e"...). Mais t'as raison, peut-être que ce TP continuera sur un pipe...

    Citation Envoyé par imperio Voir le message
    Sans parler du fait que ca m'a permis de decouvrir la fonction access qui est bien trop peu utilisee de mon point de vue.
    Bah c'est un peu normal. Généralement on ne travaille sur un fichier que pour l'ouvrir et fopen() permet de détecter le minimum (ça s'ouvre/ça ne s'ouvre pas). Sans compter open() qui possède plus de flags pour affiner le comportement lors de l'ouverture. Moi non plus j'ai rarement eu l'occasion d'avoir besoin de access(). Ceci dit, dans mon cours j'en parlais. Peu utilisé oui, oublié non !
    Et puis (désolé c'est trop tentant) "access te permettra de voir si un fichier existe mais à part ça..."
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Dans ce cas, faut pas appeler ls. Faut appeler un autre programme (que tu as codé) qui affiche envp. Là oui ça devient plus parlant. Tu lui passes (avec execve effetivement) un environnement de ton choix et tu vois comment il le récupère.
    Pour le ls |wc là oui ça peut devenir intéressant (je l'ai fait une fois). Faut créer les pipe, dupliquer stdin sur le pipe[0], dupliquer stdout sur le pipe[1], etc. Effectivement on commence à s'amuser. Mais sinon je ne vois pas ce que ls apportera à execve (on ne verra même pas à quoi sert le "e"...). Mais t'as raison, peut-être que ce TP continuera sur un pipe...
    Les pipes infinis, un vrai cauchemar a comprendre au debut... Que ce soit avec ls ou une autre commande, il faut toujours aller chercher son executable en regardant dans tous les path de l'environnement.

    Citation Envoyé par Sve@r Voir le message
    Bah c'est un peu normal. Généralement on ne travaille sur un fichier que pour l'ouvrir et fopen() permet de détecter le minimum (ça s'ouvre/ça ne s'ouvre pas). Sans compter open() qui possède plus de flags pour affiner le comportement lors de l'ouverture. Moi non plus j'ai rarement eu l'occasion d'avoir besoin de access(). Ceci dit, dans mon cours j'en parlais. Peu utilisé oui, oublié non !
    Et puis (désolé c'est trop tentant) "access te permettra de voir si un fichier existe mais à part ça..."
    Pas que, loin de la ! Il permet de verifier si le fichier existe, si tu peux l'executer, le lire, ou le modifier. En gros tous les trucs de bases quoi... Ca a l'avantage d'eviter d'ouvrir le fichier inutilement si on en a pas besoin, ce qui est utile pour trouver l'executable d'une commande par exemple.

Discussions similaires

  1. iptable peut il executer une commande shell ?
    Par htristra dans le forum Sécurité
    Réponses: 2
    Dernier message: 02/01/2011, 14h18
  2. Réponses: 8
    Dernier message: 25/09/2008, 20h22
  3. executer une commande shell en c++
    Par robux dans le forum Linux
    Réponses: 4
    Dernier message: 25/09/2007, 18h01
  4. [C] code pour executer une commande shell
    Par waldoun dans le forum Linux
    Réponses: 3
    Dernier message: 05/05/2007, 22h41
  5. execute une commande shell en java
    Par freakfm dans le forum API standards et tierces
    Réponses: 8
    Dernier message: 07/10/2006, 17h03

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