Mini Shell, erreur de segmentation

Résolu/Fermé
shelly - 26 mai 2011 à 00:32
 shelly - 26 mai 2011 à 22:21
Bonjour,
je suis en train de réaliser un mini shell, mais voilà quand je compile, j'ai le message erreur de segmentation qui s'affiche (je l'aime vraiment pas celui là). Et je m'embrouille avec tous ces pointeurs, quelqu'un verrait-il d'où cela peut-il provenir?
voici mon programme, je l'ai commenté pour qu'il effraie moins :

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <ctype.h>
#include <fcntl.h>

#define MAXMOTS 12

void
invitation_commande ()
{
printf ("> "); /*on affiche l'invitation pour rentrer une commande */
fflush (stdout); /*on vide la sortie standard */
}

void
lecture_commande (char *commande)
{
/*on lit la commande entrée sur l'entrée standard */
if (!fgets (commande, sizeof (commande) - 1, stdin))
{
/* si ^D ou fin de fichier, on quitte */
printf ("\n");
exit (0);
}
}

/* verifie si c'est une redirection et retourne le nb char correspondants (0 si pas de redirection) */
int get_redirection(char* pt)
{
int len=0;
while (*pt && !isspace (*pt) && (*pt == '<' || *pt == '>') )
{
pt++;
++len;
}
return len;
}


void
analyse_commande (char * commande, char* mot[])
{
char *debut; /* debut de mot */
char *pt; /* pointeur de parcours de la commande */
int len=0; /* longueur de mot */

/* on supprime le \n final */
if ( (pt=strchr (commande, '\n')) != NULL)
*pt = 0;
pt = commande;
int i;
for (i = 0; i < MAXMOTS - 1; i++)
{

/* on saute les espaces contenus dans la commande */
while (*pt && isspace (*pt))
pt++;

/* fin de commande ? */
if (!*pt)
break;

/* on se souvient du début de ce mot */
debut = pt;

if ( (len=get_redirection(pt)) == 0 )
{
/* cherche la fin du mot */
while (*pt && !isspace (*pt) && *pt != '<' && *pt != '>' )
pt++;

len = &pt-&debut; //XXXX ADDRESSE???
}
/* on duplique le mot ; pour cela on alloue de la mémoire*/
mot[i] = malloc (len+1);
strncpy(mot[i], debut, len);
mot[i][len]=0;
}

mot[i] = NULL;
}

/* attend la fin du processus pid */
void
attend_fin_processus (pid_t pid)
{
while (1)
{
int status;
waitpid (pid, &status, 0);

/* on vérifie si le programme s'est terminé normalement */
if (WIFEXITED (status))
printf ("terminaison normale, status %i\n", WEXITSTATUS (status));
if (WIFSIGNALED (status))
printf ("terminaison par signal %i\n", WTERMSIG (status));
break;
}
}

/* on execute la commande saisie */
void
execute_commande (char *commande, char* mot[])
{
pid_t pid;


/* on saute les commandes vides */
if ( mot[0] == NULL)
return;

pid = fork ();
if (pid == -1)
{
fprintf (stderr, "fork a échoué\n");
return;
}

if (pid == 0)
{
/* fils */
int i;
int fin_cmd = 0;
/* on cherche si la commande comporte des redirections */
for (i = 0; mot[i] != NULL ; i++)
{

if ( get_redirection(mot[i]) > 0 )
{
/* on traite la redirection */
if ( fin_cmd == 0 ) fin_cmd = i;
if (mot[i][0] == '>')
{

/* on ouvre ou on crée le fichier destination */
int fichier = open (&mot[i][1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fichier == -1)
{
fprintf (stderr,
"la création du fichier résultat a échoué \"%s\"\n",
&mot[i][1]);
exit (1);
}

/* on redirige la sortie standard sur le fichier */
close (1);
dup2 (fichier, 1);
}

if (mot[i][0] == '2' && mot[i][1] == '>')
{

/* on ouvre ou on crée le fichier destination */
int fichier = open (&mot[i][2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fichier == -1)
{
fprintf (stderr,
"la création du fichier erreur a échoué \"%s\"\n",
&mot[i][2]);
exit (1);
}

/* on redirige les erreurs sur le fichier */
close (1);
dup2 (fichier, 2);

}

if (mot[i][0] == '<')
{

/* on ouvre le fichier source */
int fichier = open (&mot[i][1], O_RDONLY, 0644);
if (fichier == -1)
{
fprintf (stderr,
"la lecture du fichier d'entrée a échoué \"%s\"\n",
&mot[i][1]);
exit (1);
}

/* on redirige l'entrée standard sur le fichier */
close (1);
dup2 (fichier, STDIN_FILENO);

}
/* on efface les redirections */
free(mot[i]);
mot[i]=NULL;

}

}
/*on execute la commande entrée par l'utilisateur*/
execvp (mot[0], mot);

/* le exec a échoué */
fprintf (stderr, "impossible d'executer \"%s\"\n", commande);
exit (1);
}
else
{
/* père */
attend_fin_processus (pid);
}
}

/*désalloue la mémoire occupée par les mots*/
void desalloue(char* mot[])
{
int i;
for ( i=0; i < MAXMOTS && mot[i] != NULL; ++i )
{
free(mot[i]);
mot[i]=NULL;
}
}


int main()
{
char *commande; /*commande entrée */
char *mot[MAXMOTS];

/* boucle d'interaction */
while (1)
{
invitation_commande ();
lecture_commande (commande);
analyse_commande (commande, mot);
execute_commande (commande, mot);
desalloue(mot);
}
return 0;
}

Merci d'avance !

A voir également:

2 réponses

Merci beaucoup, magique cette commande :)
3
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
26 mai 2011 à 08:52
Salut.
C'est très bien de commenter, mais il faut aussi indenté (et utiliser les balises de code).
le code est un peu long pour voir ça en lisant.
Je te conseil de te mettre au debuger, comme ça tu pourras résoudre tes problème tout seul (et comprendree aussi mieux les choses).
Je vois que tu es sous Linux, ça devrais bien le faire alors.
Il faut que tu compiles avec l'option -g, ensuite, "gdb nom_du_prog"
gdb charge ton programme en mémoire, tu le lances avec "run" il ira jusqu'à l'erreur de segmentation, et devrais te dire d'où elle vient.
un petit message qui peut t'être utile : https://forums.commentcamarche.net/forum/affich-6655669-debogger-avec-gdb#q=gdb&cur=1&url=%2F
0