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 :

Exécuter des commandes shell


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 17
    Par défaut Exécuter des commandes shell
    Bonjour, j'ai shell à rendre et je butte sur quelques erreurs.

    je ne comprends pas pourquoi lorsque je rentre une commande comprenant un chemin, le code se déroule correctement, et lorsque'il n'y en a pas j'ai une erreur de segmentation.

    le deuxième blocage se trouve dans la fonction Execution : la commande y arrive mais rien ne se passe.

    any idea ?

    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
    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
     
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
     
    typedef struct command
    {
        char chemin[256];
        char instruction[128];
        char argument[128];
     
    }command;
     
    void Execution(command cmde, int path)
    {
    	pid_t fils;
        printf("\nentrée fonction Execution :\n");
        printf("cmde.instruction : %s\n",cmde.instruction);
        printf("cmde.chemin : %s\n",cmde.chemin);
        printf("cmde.argument : %s\n",cmde.argument);
     
        fils=fork();
        if (fils==0)
        {
        	if (path>0)
    	    {
    	        printf("execl\n");
    	        execl (cmde.instruction, cmde.chemin, cmde.argument, NULL);
    	    }
     
    	    else
    	    {
    	        printf("execlp\n");
    	        execlp (cmde.instruction, cmde.argument, NULL);
    	    }
    	    exit(0);
        }
     
     
     
    }
     
    void Interpretation (char* saisie)
    {
        int i=0,j,path=0,cmpt,args=0;
        command cmde;
        cmde.argument[0]='\0';
        char* temp=strtok(saisie," ");
     
        j=i;
     
        strcpy(cmde.instruction,temp);
        printf("cmde.instruction : %s\n",cmde.instruction);
     
        for (cmpt=0;cmpt<=j;cmpt++)
        {
        	i+=strlen(temp);
            temp = strtok(0," ");
            printf("saisie[%d] = %c\n",i, saisie[i]);
     
            if (saisie[i]=='/')
            {
                path=1;
                strcpy(cmde.chemin,temp);
                printf("cmde.chemin : %s\n",cmde.chemin);
                i+=strlen(temp);
            }
     
            else
            {
                if (args>0)
                {
                    strcat(cmde.argument," ");
                    strcat(cmde.argument,temp);
                }
     
                else
                {
                    strcpy(cmde.argument,temp);
                }
     
                printf("cmde.argument : %s\n",cmde.argument);
                args++;
                i+=strlen(temp);
            }
     
            i+=strlen(temp);
        }
     
        if (saisie[i-1]=='&')
        {
            printf("PID = %d\n",getpid());
        }
     
        Execution(cmde,path);
    }
     
    int main ()
    {
        char saisie[1500]={'\0'};
        command cmde;
     
        puts("Saisir une commande :");
        fgets(saisie, 300, stdin);
     
        strncpy(cmde.chemin, saisie, sizeof(cmde.chemin));
     
        Interpretation(saisie);
     
        return 0;
    }

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Ca provient du fait que le pointeur "temp" est à NULL quand tu le copies dans "cmde.argument". Et il est à NULL quand on tape une commande sans argument style "ls" ou "/bin/ls" si on y met un chemin.
    Sinon concernant ton second blocage chez-moi il n'y est pas. J'ai exécuté ton code en y mettant une commande avec argument (style "ls -l") et il l'a exécutée (bon sans activer l'option "-l" mais je pense que c'est juste un réglage).

    PS: inclure les termes "urgence" dans un titre ou le texe est très mal vu. Déjà d'une part tes urgences ne sont pas les notres et d'autres part on part du principe que les profs donnent les TP avec assez de temps pour les faire et donc que s'ils ne sont pas faits dans les temps ce n'est ni la faute du prof ni la notre...

    PS2: tu devrais rajouter char *pt; if ((pt=strchr(saisie, '\n')) != NULL) *pt='\0'; sous ton fgets(saisie, 300, stdin)...
    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]

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 17
    Par défaut
    Merci, et désolé si j'ai traumatisé mes lecteurs, je n'avais jamais posté avant et j'essayais de faire tout bien tout bien

    Je ne comprends pas à quoi sert le pointeur pt, vu qu'il n'est utilisé nulle part ailleurs dans le code

    Accessoirement, d'autres étudiants qui ont vu mon code le jugent trop compliqué, un avis ?

    P.S. : je cherche un moyen de debugger mon code (tout seul), mais ce que j'ai trouvé jusqu'à maintenant me paraît assez abscons, existe-t-il des outils un peu futés ?

    Merci encore !

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par M3lm4n Voir le message
    Je ne comprends pas à quoi sert le pointeur pt, vu qu'il n'est utilisé nulle part ailleurs dans le code
    Sisi, il est utilisé dans le if qui suit sa définition. Généralement on met ça sur 2 lignes mais j'avais pas envie que mon post soit coupé.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char *pt;
    if ((pt=strchr(saisie, '\n')) != NULL)
    	*pt='\0';
    Utilisé une seule fois peut-être mais ça oblige quand-même à le définir...

    Citation Envoyé par M3lm4n Voir le message
    Accessoirement, d'autres étudiants qui ont vu mon code le jugent trop compliqué, un avis ?
    Non, moi je le trouve "construit". Bien/pas bien c'est à étudier mais au-moins tu tentes de consacrer une fonction à une action et une action à une fonction et ça c'est bien.
    Question ergonomie c'est un peu brouillon. Par exemple ici
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        	if (path>0)
    	    {
    	        printf("execl\n");
    	        execl (cmde.instruction, cmde.chemin, cmde.argument, NULL);
    	    }
     
    	    else
    	    {
    	        printf("execlp\n");
    	        execlp (cmde.instruction, cmde.argument, NULL);
    	    }
    	    exit(0);
    ton indentation des accolades est "intermédiaire" (moitié tabulation/moitié espaces). Et cette ligne vide au dessus du else !!!
    Un code bien tabulé et bien aéré se lit bien plus facilement...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	if (path > 0)
    	{
    		printf("execl\n");
    		execl(cmde.instruction, cmde.chemin, cmde.argument, NULL);
    	}
    	else
    	{
    		printf("execlp\n");
    		execlp(cmde.instruction, cmde.argument, NULL);
    	}

    Ou bien
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	if (path > 0) {
    		printf("execl\n");
    		execl(cmde.instruction, cmde.chemin, cmde.argument, NULL);
    	}
    	else {
    		printf("execlp\n");
    		execlp(cmde.instruction, cmde.argument, NULL);
    	}
    (moi avant j'écrivais comme la première version et maintenant je préfère la seconde ?!?).

    Et pour les aérations, moi je fais comme ceci
    • pas d'espace pour les affectations
    • pas d'espace entre le nom de la fonction et sa parenthèse ouvrante
    • un espace après un mot clef if/for/while et la parenthèse
    • un espace avant et après l'opérateur de comparaison
    • un espace après la virgule (dans les paramètres de la fonction)

    Ca a l'air compliqué à lire comme ça mais le plus compliqué a été surtout de l'expliquer dans ce post parce qu'au naturel ça vient facilement et ça donne if ((pt=strchr(saisie, '\n')) != NULL) *pt='\0';. Et question "affectation dans la comparaison" (style if ((x=fct(...)) != y)) généralement j'évite sauf si la fonction est vraiment petite à écrire (peu de paramètres) et donc à relire.

    Par ailleurs on ne quitte jamais une fonction via exit(). Si une fonction échoue et qu'on veut le signaler alors on renvoie une valeur spéciale à l'appelant qui la gèrera en conséquence (peut-être que lui-aussi considèrera que c'est majeur et alors lui-aussi renverra une valeur spéciale à son appelant et ainsi de suite jusqu'au main).


    Citation Envoyé par M3lm4n Voir le message
    P.S. : je cherche un moyen de debugger mon code (tout seul), mais ce que j'ai trouvé jusqu'à maintenant me paraît assez abscons, existe-t-il des outils un peu futés ?
    printf(). C'est comme ça que j'ai vu ton souci. J'en ai mis de partout jusqu'à isoler la ligne en erreur puis en affichant les valeurs de cette ligne...
    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]

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Pour rebondir sur ce qu'écrit Svear, le choix du style reste subjectif. Ce qui est important est surtout de rester homogène, constant dans l'écriture.

    Des outils comme indent et clang-format peuvent t'aider. J'utilise principalement le second, plus souple qu'indent mais plus complexe à configurer également.

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 17
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Sisi, il est utilisé dans le if qui suit sa définition. Généralement on met ça sur 2 lignes mais j'avais pas envie que mon post soit coupé.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char *pt;
    if ((pt=strchr(saisie, '\n')) != NULL)
    	*pt='\0';
    Utilisé une seule fois peut-être mais ça oblige quand-même à le définir...
    heuuuu... oui mais ça sert a quoi ?

    c'est comme si j'ajoutais une variable x que j'incrémente jusqu'a un certain point sans m'en servir ailleurs

    sinon j'ai modifié mon code et je n'ai plus d'erreur (à part l'absence de prise en compte des paramètres) :

    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
    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
     
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
     
    typedef struct command
    {
        char chemin[256];
        char instruction[128];
        char argument[128];
     
    }command;
     
    void Execution(command cmde, int path)
    {
        pid_t fils;
        printf("\nentrée fonction Execution :\n");
        printf("cmde.instruction : %s\n", cmde.instruction);
        printf("cmde.chemin : %s\n", cmde.chemin);
        printf("cmde.argument : %s\n", cmde.argument);
     
        fils = fork();
        if (fils == 0)
        {
            if (path > 0)
            {
                printf("execl\n");
                execl(cmde.instruction, cmde.chemin, cmde.argument, NULL);
            }
     
            else
            {
                printf("execlp\n");
                execlp(cmde.instruction, cmde.argument, NULL);
            }
        }
    }
     
    void Interpretation(char* saisie)
    {
        int i = strlen(saisie) - 1, path=0, args=0;
        command cmde;
        cmde.argument[0] = '\0';
        char* temp = strtok(saisie, " ");
     
     
     
        strcpy(cmde.instruction, temp);
        printf("temp = %s\n", temp);
        printf("cmde.instruction : %s\n\n", cmde.instruction);
     
        while (i > 0)
        {
            if ((temp = strtok(0, " ")) == NULL)
            {
                i = 0;
            }
     
     
            else
            {
                printf("temp = %s\n", temp);
     
                if ((strchr(temp, '/') != NULL) || (strchr(temp, '.') != NULL))
                {
                    path = 1;
                    strcpy(cmde.chemin, temp);
                    printf("cmde.chemin : %s\n\n", cmde.chemin);
                }
                else
                {
                    if (args > 0)
                    {
                        strcat(cmde.argument, " ");
                    }
     
                    strcat(cmde.argument, temp);
                    args++;
                    printf("cmde.argument : %s\n\n", cmde.argument);
                }
     
                i -= strlen(temp);
            }
        }
     
        Execution(cmde, path);
    }
     
    int main()
    {
        char saisie[1500] = {'\0'};
        command cmde;
        char *pt;
     
        puts("Saisir une commande :");
        fgets(saisie, 300, stdin);
     
        if ((pt = strchr(saisie, '\n')) != NULL)
        {
            *pt = '\0';
        }
     
        strncpy(cmde.chemin, saisie, sizeof(cmde.chemin));
     
        Interpretation(saisie);
     
        return 0;
    }
    Je vais m'atteler à la présentation, par contre les tabulations et les espaces mélangés sont dûs à sublime text, je n'utilise que les tabulations.

    Citation Envoyé par Matt_Houston Voir le message
    Pour rebondir sur ce qu'écrit Svear, le choix du style reste subjectif. Ce qui est important est surtout de rester homogène, constant dans l'écriture.

    Des outils comme indent et clang-format peuvent t'aider. J'utilise principalement le second, plus souple qu'indent mais plus complexe à configurer également.
    Merci, je vais regarder le premier, le deuxième à l'air tendu...

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par M3lm4n Voir le message
    heuuuu... oui mais ça sert a quoi ?

    c'est comme si j'ajoutais une variable x que j'incrémente jusqu'a un certain point sans m'en servir ailleurs
    Tu n'as pas détaillé l'instruction
    1) je positionne un pointeur à un certain endroit
    2) je modifie l'élément pointé !!!
    J'ai donc bien incrémenté une variable et je m'en suis servie...

    Et pour répondre à ta première question, ça sert à supprimer le '\n' (représentant la touche <return> sur laquelle tu tapes pour valider ta saisie) récupéré et stocké par fgets(). C'est très bien d'utiliser fgets(), ça offre un verrouillage concret et efficace de la zone saisie. Mais ça a le petit inconvénient de tout stocker absolument tout ce qui est tapé...
    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]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Développement] besoin d'aide en shell
    Par kissakissa dans le forum AppleScript
    Réponses: 1
    Dernier message: 14/04/2016, 06h53
  2. Besoin d'aide commandes shell administration serveur linux
    Par SEIYA. dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 10/03/2015, 17h17
  3. Besoin d'aide : commande shell
    Par HDI103 dans le forum Shell et commandes GNU
    Réponses: 32
    Dernier message: 30/05/2013, 20h06
  4. Besoin d'aide au niveau de Shell
    Par Argael dans le forum Shell et commandes GNU
    Réponses: 1
    Dernier message: 01/08/2006, 11h04
  5. Besoin d'aide pour un script shell
    Par lecharcutierdelinux dans le forum Linux
    Réponses: 5
    Dernier message: 20/05/2006, 10h36

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