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

Bibliothèques, systèmes et outils C Discussion :

Probleme fonction readline et pipe


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2019
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2019
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Probleme fonction readline et pipe
    Bonjour a tous !

    Je suis actuellement entrain de commencer a recoder un minishell, j ai actuellement un gros probleme avec l implantation de la fonction readline avec mon simple pipe, en effet bizarrement le pipe yes | head fonctionne parfaitement, par contre ls | wc -l ne m affiche absolument rien sur la sortie standard, par contre la commande pwd | grep "test" fonctionne mais m affiche le resultat directement apres mon prompt ce qui est plutot bizzare car j attends la fin de tout mes processus fils avant de reappeller readline et donc d afficher le prompt

    J ai l impression que readline modifie mon fd stdin car si je n utilise pas la fonction et que je remplace les in_put de readline par la commande direct par exemple in_put = "ls | wc -l", le pipe m affiche bien le bon resultat, j ai pense reset stdin avec l appel a readline mais cela ne fonctionne pas non plus, auriez vous donc une idee de ce qui cloche svp ?

    Voici la partie du code qui nous interesse:

    main.c:
    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
    int	main(int argc, char **argv, char **envp)
    {
    	char	*prompt;
    	char	*in_put;
    	int	is_alive;
    	int status;
    int oldstdin;
    	int oldstdout;
     
    	argc = (int) argc;
    	argv = (char **)argv;
    	envp = (char **) envp;
    	prompt = ">$";
    	is_alive = 1;
    	while (is_alive)
    	{
    		in_put = readline(prompt);
    		add_history(in_put);
                   dup2(oldstdin, STDIN_FILENO);
    		dup2(oldstdout, STDOUT_FILENO);
    		if (!run_pipe(in_put, envp))
    			return (1);
    		waitpid(-1, &status, 0);
    	}
    return (0);
    }
    pipex.c:

    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
    char	**make_cmd(char *one_string_cmd, char **envp)
    {
    	char	**cmd;
    	char	*tempo_cmd;
    	size_t	i;
     
    	cmd = ft_split(one_string_cmd, ' ');
    	if (!cmd)
    		return (NULL);
    	tempo_cmd = format_string(cmd);
    	if (!tempo_cmd)
    		return (NULL);
    	cmd[0] = tempo_cmd;
    	i = 0;
    	while (envp[i] && ft_strncmp(envp[i], "PATH=", 5) != 0)
    		++i;
    	tempo_cmd = find_path(envp, cmd, i);
    	if (!tempo_cmd)
    		return (NULL);
    	cmd[0] = tempo_cmd;
    	return (cmd);
    }
    void	receiver(char *input_cmd, char **envp, int *pipe_fd, size_t num_proc, size_t pipes_nb)
    {
    	char	**cmd;
     
    	//verif make cmd
    	cmd = make_cmd(input_cmd, envp);
    	pipes_nb = (size_t) pipes_nb;
    	num_proc = (size_t) num_proc;
     
    		close(pipe_fd[1]);
    		dup2(pipe_fd[0], 0);
    		close(pipe_fd[0]);
    	execve(cmd[0], cmd, envp);
    	//verif execve
    }
    void	sender(char *input_cmd, char **envp, int *pipe_fd, size_t num_proc, size_t pipes_nb)
    {
    	char	**cmd;
     
    	//verif make cmd
    	cmd = make_cmd(input_cmd, envp);
    	pipes_nb = (size_t) pipes_nb;
    	num_proc = (size_t) num_proc;
     
    		close(pipe_fd[0]);
    		dup2(pipe_fd[1], 1);
    		close(pipe_fd[1]);
    	execve(cmd[0], cmd, envp);
    	//verif execve
    }
     
    int	run_pipe(char *in_put, char **envp)
    {
    	size_t	i;
    	size_t	pipes_nb;
    	pid_t	pid;
    	char	**cmds;
    	int	pipes_fd[2];
     
    	i = 0;
    	pipes_nb = 0;
    	while (*(in_put + i))
    	{
    		if (*(in_put + i) == '|')
    			++pipes_nb;
    		++i;
    	}
    	cmds = ft_split(in_put, '|');
    	envp = (char **) envp;
     
    	if (pipe(pipes_fd) == -1)
    	{
    		printf("Erreur init pipe\n");
    		return (0);
    	}
     
    	i = 0;
    	while (i < pipes_nb + 1)
    	{
    		pid = fork();
    		if (pid < 0)
    		{
    			perror("Probleme fork");
    			return(0);
    		}
    		else if (pid == 0)
    		{
    			if (i == 0)
    				sender(cmds[i], envp, pipes_fd, i, pipes_nb);
    			else
    				receiver(cmds[i], envp, pipes_fd, i, pipes_nb);
    		}
    		++i;
    	}
    	return (1);
    }
    Je tiens a preciser que j ai teste le formattage des commandes envoye a execve et que je n ai trouve aucuns soucis par rapport a ca

    Voila a toute !

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par RickSanchez Voir le message
    auriez-vous donc une idée de ce qui cloche SVP ?
    Bonjour ! Là, comme ça, malheureusement non. Si vous pouviez poster le projet complet, en précisant comment vous le compilez, et quelles manipulations vous faites ensuite, il serait plus facile de vous aider (pour moi en tout cas).

    Bon courage pour la suite.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2019
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2019
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Bonjour !

    Tout d abord merci Roland Chastain pour avoir pris le temps de t interesser a mon probleme

    Voici le code complet qui est sur github: https://github.com/UhtredTheDane/min...he/tree/master

    J ai tente de resoudre le probleme par moi meme aujourd hui mais sa a ete infructueux mais j ai pu effectuer certains tests.

    Quand j indique EOF a la fonction readline le resultat de mon simple pipe s affiche, pareil si je supprime ma boucle infinie avec la variable is_alive le resultat s affiche bien.

    J ai l impression readline ne me rend pas correctement stdin pourtant j ai tente d enregistrer l etat de mon stdin avec un dup avant d executer readline puis de restaurer avec dup2 mais cela ne change rien

    Cordialement.

  4. #4
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    J'ai téléchargé le projet et j'ai pu le compiler.

    Pourriez-vous donner un ou plusieurs exemples de commandes qui ne donnent pas le résultat attendu ?

    Pour le moment j'ai essayé ls et exit. Ni l'un ni l'autre n'ont fonctionné.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2019
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2019
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Oui j'ai simplifié au maximun, on ne peut rentrer que un pipe, par exemple yes | head qui fonctionne mais par exemple ls | wc -l ne fonctionne pas.

    Modif: Avec les commandes pwd | grep mini ou cat Makefile | grep S sa fonctionne mais le prompt est affiché avant les resultats j'ai l'impression que le processus pere n 'attend pas la terminaison de tout ces fils avec waitpid(-1, &status, 0);

  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 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par RickSanchez Voir le message
    Je suis actuellement entrain de commencer a recoder un minishell
    Déjà avant de voir le pourquoi des erreurs, on peut commencer à voir ce qui ne va pas dans ton code...
    Citation Envoyé par RickSanchez Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    argc = (int) argc;
    argv = (char **)argv;
    envp = (char **) envp;
    Jusque là, rien que de très normal. Tu aurais dû rajouter aussi status=(int) status et is_alive=(int) is_alive pour plus de sûreté...

    Citation Envoyé par RickSanchez Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    is_alive = 1;
    while (is_alive)
    C'est voulu (utile) cette variable qui ne varie jamais???

    Citation Envoyé par RickSanchez Voir le message
    return (cmd)
    Pas de parenthèses ni au return (ce n'est pas une fonction), ni à la variable (ce n'est pas non plus une expression faisant intervenir des opérateurs de priorités différentes et nécessitant de modifier explicitement ces priorités). C'est peut-être pinailler mais quand on en est à vouloir recoder un minishell, on est en droit d'attendre de toi un code professionnel.

    Citation Envoyé par RickSanchez Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while (*(in_put + i))
    	{
    		if (*(in_put + i) == '|')
    Manifestement tu aimes bien indenter pour rien mais ce n'est pas le plus important. Ce qui est important, c'est qu'écrire *(in_put + i) n'est absolument pas plus efficace qu'écrire in_put[i], et bien moins lisible. Or écrire du code lisible aide à sa relecture.
    Oui passer par un pointeur est plus rapide que passer par la notation indicée, mais uniquement quand le pointeur est déjà positionné sur la bonne case. S'il faut lui appliquer un calcul, cela perd alors tout l'avantage d'utiliser un pointeur et ça devient alors exactement la même chose qu'un indice (qui n'est qu'un décalage dans un tableau). Et ça peut même être pire car avec la notation indicée, le compilateur peut arriver à trouver des optimisations (en remplaçant par exemple de lui-même l'indice par un pointeur), ce qu'il ne fera pas dans le cas de ce pointeur que tu décales. Donc *(in_put + i) c'est soit pareil que in_put[i], soit pire...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (char* pt=in_put; *pt != '\0'; pt++) {
    	if (*pt == '|') ++pipes_nb;
    }

    Citation Envoyé par RickSanchez Voir le message
    Code c : 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
    i = 0;
    	while (i < pipes_nb + 1)
    	{
    		pid = fork();
    		if (pid < 0)
    		{
    			perror("Probleme fork");
    			return(0);
    		}
    		else if (pid == 0)
    		{
    			if (i == 0)
    				sender(cmds[i], envp, pipes_fd, i, pipes_nb);
    			else
    				receiver(cmds[i], envp, pipes_fd, i, pipes_nb);
    		}
    		++i;
    }
    Là aussi indentation pareillement inutile de ce qui aurait pu être une simple boucle for(). Mais ce qui me préoccupe vraiment (en dehors aussi de ces parenthèses là encore inutiles ainsi que ce "else" qui l'est tout autant), c'est le fait que le fils, une fois créé, se mette lui-aussi à continuer la boucle (ben oui, je ne vois pas d'instruction pour l'arrêter). Ca ressemble assez à une fork-bomb. Ok sender et receiver font du execve ce qui substitue le fils par le programme exécuté mais (là j'ai un flou) je me demande si c'est suffisant. A voir si rajouter un exit() qui, pour l'occasion, serait vraiment sécuritaire.
    Et while (i < pipes_nb + 1) sérieux??? => while (i <= pipes_nb) !!!

    Citation Envoyé par RickSanchez Voir le message
    Code c : 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
    void	receiver(char *input_cmd, char **envp, int *pipe_fd, size_t num_proc, size_t pipes_nb)
    {
    	char	**cmd;
     
    	//verif make cmd
    	cmd = make_cmd(input_cmd, envp);
    	pipes_nb = (size_t) pipes_nb;
    	num_proc = (size_t) num_proc;
     
    		close(pipe_fd[1]);
    		dup2(pipe_fd[0], 0);
    		close(pipe_fd[0]);
    	execve(cmd[0], cmd, envp);
    	//verif execve
    }
    void	sender(char *input_cmd, char **envp, int *pipe_fd, size_t num_proc, size_t pipes_nb)
    {
    	char	**cmd;
     
    	//verif make cmd
    	cmd = make_cmd(input_cmd, envp);
    	pipes_nb = (size_t) pipes_nb;
    	num_proc = (size_t) num_proc;
     
    		close(pipe_fd[0]);
    		dup2(pipe_fd[1], 1);
    		close(pipe_fd[1]);
    	execve(cmd[0], cmd, envp);
    	//verif execve
    }
    Ah, on retrouve avec plaisir ces pipes_nb = (size_t) pipes_nb et num_proc = (size_t) num_proc tellement utiles (sait-on jamais, si les valeurs changeaient par magie entre temps... ). Mis à part, tu ne trouves pas que ces fonctions sont redoutablement similaires et pourraient être mutualisées selon le num_proc. Cela éviterait ainsi de tester i==0 dans la boucle précédente...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void action(char *input_cmd, char **envp, int *pipe_fd, size_t num_proc, size_t pipes_nb) {
    	char	**cmd;
     
    	//verif make cmd
     
    	cmd = make_cmd(input_cmd, envp);
    	int sens=num_proc > 0 ?0 :1;
     
    	close(pipe_fd[1-sens]);
    	dup2(pipe_fd[sens], sens);
    	close(pipe_fd[sens]);
    	execve(cmd[0], cmd, envp);
    	//verif execve
    }

    Et la boucle précédente
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    for (i=0; i <= nb_pipes; i++) {
    	pid = fork();
    	if (pid < 0) {
    		// Erreur de fork
    		perror("Probleme fork");
    		return -1;		// Conventionnellement, un code d'erreur système doit être de valeur inférieure à 0...
    	}
    	if (pid == 0) {
    		// Fils
    		action(cmds[i], envp, pipes_fd, i, pipes_nb);
    		exit(0);
    	}
    }
    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]

Discussions similaires

  1. [XSL]Probleme fonction recursive
    Par Le-Cortex dans le forum XSL/XSLT/XPATH
    Réponses: 9
    Dernier message: 12/12/2005, 15h10
  2. [Mail] Probleme fonction mail()
    Par tissot dans le forum Langage
    Réponses: 1
    Dernier message: 14/11/2005, 12h55
  3. problème fonctions callback
    Par youp_db dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 02/10/2005, 14h47
  4. probleme fonction gethostbyname
    Par oclone dans le forum Développement
    Réponses: 6
    Dernier message: 14/04/2005, 10h31
  5. probleme fonction syntaxe
    Par gIch dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 28/02/2005, 09h52

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