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 :

Redirection de la sortie standard


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Points : 41
    Points
    41
    Par défaut Redirection de la sortie standard
    J'ai récupéré le code d'un mini-shell que quelqu'un a fait et je me pose des questions sur la façon d'avoir programmé la redirection de la sortie standard :
    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
     
    else if(strcmp(arg2,">")==0 && arg3 != '\0')
    {
         int fichier = open(arg3,O_RDWR|O_CREAT, 0600);
         pid = fork();
     
         if(pid==0)
         {
             close(1);
             dup(fichier);
             close(fichier);
             execlp(arg1,arg1,NULL);
             printf("Commande inexistante : %s\n",arg1);
             exit(-1);
         }
    Tout d'abord je ne suis pas sûr que ce code soit juste, donc n'hésitez pas à le corriger.
    Je ne comprend pas bien pourquoi il y a close(fichier). Pour moi, si l'on ferme ce descripteur, c'est un peu comme si l'on faisait un free c'est à dire que l'on ne pourra plus accéder à ce descripteur. Et si l'on ne peut plus y accéder, je vois mal comment on peut y écrire des données!

    Et sinon, j'ai changé les permission dans la primitive open et j'ai constaté que ça ne changeait rien que je mettre 0777 ou 0000! A quoi est-ce dû?

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    dup() tout court sur un descripteur, ça me parait bizarre : Normalement, on garde le résultat de dup(), ou on utilise dup2()...

    En l'occurence, je pense qu'il aurait fallu utiliser dup2() avec 1 (ou plutôt STDOUT_FILENO) dans l'un des paramètres.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Si j'ai bonne memoire, dup reutilise le plus petit descripteur libre. L'auteur suppose que donc 0 est toujours ouvert (ou bien il l'a ouvert avant).

    L'utilisation de dup2 serait plus claire (mais si j'ai bonne memoire, dup2 est nettement posterieur a dup).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  4. #4
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Hello,

    Citation Envoyé par Dud225
    J'ai récupéré le code d'un mini-shell que quelqu'un a fait et je me pose des questions sur la façon d'avoir programmé la redirection de la sortie standard :
    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
     
    else if(strcmp(arg2,">")==0 && arg3 != '\0')
    {
         int fichier = open(arg3,O_RDWR|O_CREAT, 0600);
         pid = fork();
     
         if(pid==0)
         {
             close(1);
             dup(fichier);
             close(fichier);
             execlp(arg1,arg1,NULL);
             printf("Commande inexistante : %s\n",arg1);
             exit(-1);
         }
    Tout d'abord je ne suis pas sûr que ce code soit juste, donc n'hésitez pas à le corriger.
    Je ne comprend pas bien pourquoi il y a close(fichier). Pour moi, si l'on ferme ce descripteur, c'est un peu comme si l'on faisait un free c'est à dire que l'on ne pourra plus accéder à ce descripteur. Et si l'on ne peut plus y accéder, je vois mal comment on peut y écrire des données!

    Et sinon, j'ai changé les permission dans la primitive open et j'ai constaté que ça ne changeait rien que je mettre 0777 ou 0000! A quoi est-ce dû?
    Tout d'abord, ce qui me gêne, la variable arg3 : elle est comparée à un entier dans l'expression conditionnelle puis passée en argument à open() qui attend char *. On peut supposer qu'il s'agit de *arg3 != '\0'.

    Sinon le code est correct. fork() créé un processus fils, le close(1) ferme le stdout de ce processus nouvellement créé, le dup(fichier) redirige la sortie standard vers le fichier 'fichier' (ou plutôt, créé un nouveau stdout en utilisant 'fichier'). N'ayant plus besoin du fichier 'fichier', normal, on a obtenu notre stdout, on peut fermer 'fichier'. execlp() execute la commande identifiée par arg1 dans le processus fils. Si la commande est inconnue, on peut légitimement écrire sur le stdout (qu'on a redirigé) du processus fils avec printf(). Donc aucun problème.

    Ton pb de compréhension vient de dup(). Pour cela, il faut aller chercher la réponse dans la documentation de la fonction fcntl() après avoir lu tout aussi attentivement celle de dup().

    http://www.opengroup.org/onlinepubs/...tions/dup.html
    http://www.opengroup.org/onlinepubs/...ons/fcntl.html

    A+

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Correct, mais sale. Très sale.
    Utiliser dup2() est plus propre. Utiliser les defines STD*_FILENO est plus propre également.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Hello,

    Citation Envoyé par Médinoc
    Correct, mais sale. Très sale.
    Utiliser dup2() est plus propre. Utiliser les defines STD*_FILENO est plus propre également.
    Ah, mais je n'ai pas dit qu'il ne fallait pas utiliser dup2() . Le lecteur qui lit attentivement la doc indiquée par les liens de mon msg précédent devrait même utiliser dup2() en toute logique.

    A+

  7. #7
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Médinoc
    Correct, mais sale. Très sale.
    Utiliser dup2() est plus propre. Utiliser les defines STD*_FILENO est plus propre également.
    Je ne vois pas pourquoi c'est sale.

    L'utilisation de dup est correcte et ne nécessite pas l'utilisation de dup2 dans ce cas précis. Dans un cas général, il va sans dire qu'on est d'accord...

    Par contre, je suis d'accord sur l'utilisation des STD*_FILENO.

    Jc

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ben si, fermer un descripteur pour réouvrir autre chose magiquement par-dessus, c'est sale.

    D'ailleurs, si le descripteur 0 était fermé avant, ça échouerait.


    D'ailleurs, je ne sais pas du tout si la norme POSIX garantit que le descripteur nouvellement ouvert sera forcément le plus petit disponible (bien que c'est possible, chez POSIX)...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Citation Envoyé par Médinoc
    Ben si, fermer un descripteur pour réouvrir autre chose magiquement par-dessus, c'est sale.
    Je pensais que tu estimais que dup() était "sale" pour le seul manque de lisibilité. Que crois-tu que fait dup2() ? Il fait la même chose que dup(), il ferme un descripteur pour en ouvrir un autre par dessus, sans magie .

    Citation Envoyé par Médinoc
    D'ailleurs, si le descripteur 0 était fermé avant, ça échouerait.
    Oui, mais un dup2( <my file descriptor>, 1) ou dup2( <my file descriptor>, STDOUT_FILENO) ne changerait rien.

    Citation Envoyé par Médinoc
    D'ailleurs, je ne sais pas du tout si la norme POSIX garantit que le descripteur nouvellement ouvert sera forcément le plus petit disponible (bien que c'est possible, chez POSIX)...
    C'est garanti.

    A+

  10. #10
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    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
     
    int fichier=0;
    pid_t pid=0;
     
    ...
     
    else if(strcmp(arg2,">")==0 && *arg3 != '\0')
    {
         fichier = open(arg3,O_RDWR|O_CREAT,S_IRWXU);
         pid = fork();
     
         if (pid==0)
         {
             close(STDOUT_FILENO);
             dup2(fichier,STDOUT_FILENO);
             close(fichier);
             execlp(arg1,arg1,NULL);
             printf("Commande inexistante : %s\n",arg1);
             exit(-1);
         }
    Voilà pour les puristes...
    Je suis sincèrement très d'accord avec vous sur le fait qu'il est important de coder proprement et de prendre tout de suite de bonnes habitudes, mais je pense que le fond est au préalable plus important que la forme. Dans mon école, des mecs écrivent des programmes sans même finir le main par un "return 0" et notre prof de C ne dit rien, donc bon je me dit par là qu'il veut que prioritairement on comprenne les choses.

    Donc merci Foobar1329, j'ai une réponse à ma question sur l'intérêt de dup(fichier). Mais bon, quand on compile (et quand on débute encore), on a du mal à voir l'importance de tels et tels fonctions lorsque l'on voit que quand on les enlève ça marche tout aussi bien (en apparence).

    Mais je repose ma question en ce qui concerne les droits : ça ne change rien si je mets S_IRWXU (0777), S_IWUSR (0200) ou S_IXOTH (0001), le fichier est toujours créé avec les même droits : 0775! Comment cela se fait-il?

  11. #11
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Re,

    Citation Envoyé par Dud225
    Mais je repose ma question en ce qui concerne les droits : ça ne change rien si je mets S_IRWXU (0777), S_IWUSR (0200) ou S_IXOTH (0001), le fichier est toujours créé avec les même droits : 0775! Comment cela se fait-il?
    Question bête, le fichier existe t-il déjà ? Si oui, tu peux changer ce que tu veux pour le mode_t, ça ne changera rien, vu qu'il s'agit de modes de création du fichier, c'est à dire quand le fichier est créé et seulement créé (quand O_CREAT sert à quelque chose quoi, sinon il ne fait rien non plus). Il faut supprimer le fichier si il existe déjà puis rééxecuter le programme afin de vérifier si le mode de création est bien pris en compte.

    A+

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Foobar1329
    Je pensais que tu estimais que dup() était "sale" pour le seul manque de lisibilité. Que crois-tu que fait dup2() ? Il fait la même chose que dup(), il ferme un descripteur pour en ouvrir un autre par dessus, sans magie .
    Perdu, dup2() permet de toujours forcer le descripteur destinataire, qu'il soit déjà ouvert ou non. Pas de manipulation hasardeuse.

    Oui, mais un dup2( <my file descriptor>, 1) ou dup2( <my file descriptor>, STDOUT_FILENO) ne changerait rien.
    Ben si, ça marcherait que le descripteur 0 soit ouvert ou non...

    C'est garanti.
    C'est toujours ça.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Points : 41
    Points
    41
    Par défaut
    Citation Envoyé par Foobar1329
    Question bête, le fichier existe t-il déjà ?
    NON!! Je supprime le fichier à chaque test et j'ai toujours les même droits : 0774. Je peux mettre n'importe quoi entre 0 et 7777, ça ne change rien!!!!!

Discussions similaires

  1. Redirection de la sortie standard d'une console
    Par LsMarx dans le forum C++/CLI
    Réponses: 5
    Dernier message: 25/07/2012, 14h33
  2. redirection de la sortie standard
    Par mauroyb0 dans le forum Langage
    Réponses: 6
    Dernier message: 27/12/2006, 19h18
  3. Redirection de la sortie standard
    Par ankou82 dans le forum SDL
    Réponses: 20
    Dernier message: 29/05/2006, 13h54
  4. [Débutant(e)] Redirection de la sortie standard
    Par salber dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 17/06/2005, 15h34
  5. redirection de la sortie standard
    Par sorari dans le forum C++
    Réponses: 8
    Dernier message: 19/05/2005, 11h47

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