j'essaye de realiser un programme tout bete ...
je dois realiser l'interface entre 1 programme, et plusieurs autres aux moyens de pipes.

le premier programme apelle le mien;
mon programme se charge de lancer plusieurs autres programmes et attend des requetes sur son stdin (reçu via une pipe dans le premier programme). ensuite mon programme vas interroger tour a tour d'autres applications et recuperer les resultats (via plusieurs pipes) pour ensuite envoyer un resultat final (stdout :: pipe) a ce fameux premier programme. (vous m'avez suivi? :X)
pas de critique sur la conception, j'ai pas trop le choix ... (malgres que tout les programmes soit open source)

voila mon probleme (on y viens): les programmes appelés se comportent comme ce programme de test:

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int
main ()
{
  char inbuff[10000];
  char *ptr;
  while (fgets (inbuff, 10000, stdin) != NULL)
    {
		if((ptr = strchr(inbuff,'\n')) != NULL)
			*ptr = 0;
      printf ("bien recu %s\n", inbuff);
	  fprintf(stderr,"debug: %s\n",inbuff);
		if(inbuff[0] == 'q')
			break;
    }
  return 0;
}
(le stderr n'est pas pipé)
le fait est que je ne reçoi strictement rien ... SAUF si je met un fflush(stdout) dans la boucle de mon programme de test (celui ci dessus)

je met le programme appelant entierement (fin, c'est la version test pipe, tout le reste n'y est pas), etant encore debutant il se peux que l'erreur soit ailleurs (si vous voyez d'autres choses ... meme qui ne soit pas relatives au sujet, n'hesitez surtout pas !)

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
/*
PARENT_READ		pfd_c2p[2*i]
CHILD_WRITE		pfd_c2p[1+2*i]
CHILD_READ		pfd_p2c[2*i]
PARENT_WRITE	pfd_p2c[1+2*i]
*/
static int
readcfg_file (char ***cmd, char ***parms)
{
/* mode debug */
  return 3;
}
 
static int
my_read (int fd, char *outbuff, int maxlen)
{
  int i,ret=1;
  for (i = 0; i < maxlen && outbuff[i - 1] != '\n' && ret > 0; i++)
    {
      //ici rien n'est lut. (test avec printf)
      ret = read (fd, &outbuff[i], 1);
    }
  return i;
}
 
int
main (int argc, char **argv)
{
  int *pfd_c2p = NULL;
  int *pfd_p2c = NULL;
  pid_t *pid = NULL;
  char **parms = NULL, **cmd = NULL;
  int n, i, nbytes, ret;
  char inbuff[10000];
  char outbuff[10000];
//read the config file  
  fprintf (stdout, "reading cfg_file !\n");
  n = readcfg_file (&cmd, &parms);
  if (n > 0)
    {
      //allocate
      pfd_c2p = malloc (2 * n * sizeof (int));
      pfd_p2c = malloc (2 * n * sizeof (int));
      pid = malloc (n * sizeof (pid_t));
      if ((pid == NULL) || (pfd_c2p == NULL) || (pfd_p2c == NULL))
	{
	  perror ("malloc");
	  return EXIT_FAILURE;
	}
    }
//create the pipes
  for (i = 0; i < n; i++)
    {
      ret = pipe (&pfd_c2p[2 * i]);
      if (ret == -1)
	{
	  perror ("pipe c2p");
	  return EXIT_FAILURE;
	}
      ret = pipe (&pfd_p2c[2 * i]);
      if (ret == -1)
	{
	  perror ("pipe p2c");
	  return EXIT_FAILURE;
	}
    }
//spawn the processes !
  fprintf (stdout, "spawning processes\n");
  for (i = 0; i < n; i++)
    {
      pid[i] = fork ();
      if (pid[i] == 0)		//fils
	{
	  close (pfd_p2c[1 + 2 * i]);
	  close (pfd_c2p[2 * i]);
 
	  dup2 (pfd_p2c[2 * i], STDIN_FILENO);
	  close (pfd_p2c[2 * i]);
	  dup2 (pfd_c2p[1 + 2 * i], STDOUT_FILENO);
	  close (pfd_c2p[1 + 2 * i]);
	  //execv (cmd[i],parms[i]);
	  fprintf (stderr, "launching command !\n");
	  //execlp ("ls", "ls", (char *) 0);
	  execv ("test-chain-red", NULL);
	  fprintf (stderr, "erreur execv pour le processus %d:%s %s\n", i,
		   parms[i], cmd[i]);
	  return EXIT_FAILURE;
	}
      else if (pid[i] > 0)	//pere
	{
	  close (pfd_p2c[2 * i]);
	  close (pfd_c2p[1 + 2 * i]);
	}
      else
	{
	  perror ("fork");
	}
    }				//for
 
  //process the requets
  fprintf (stdout, "processing requests\n");
  fprintf (stdout, "input now!\n");
  while (fgets (inbuff, 10000, stdin) != NULL)
    {
      for (i = 0; i < n; i++)
	{
	  fprintf (stdout, "writing pipe:%d\n", i);
	  nbytes = write (pfd_p2c[1 + 2 * i], inbuff, strlen (inbuff));
	  if (nbytes > 0)
	    {
	      fprintf (stdout, "reading pipe:%d\n", i);
//------!!!!---le prog reste "coincé" dans la fonction my_read-------!!!!!!---
	      nbytes = my_read (pfd_c2p[2 * i], outbuff, sizeof (outbuff)-1);
	      if (nbytes > 0)
		{
	          fprintf (stdout, "out: <%s>\n", outbuff);
		}
	      else
		{
		  perror ("read");
		  return EXIT_FAILURE;
		}
	    }
	  else
	    {
	      perror ("write");
	      return EXIT_FAILURE;
	    }
	}			//for
    }				//while fgets
  return EXIT_SUCCESS;
}
en lisant le man, ils deconseillent de "mix" read//write et les fonctions basé sur des streams.
j'ai transformé mes read//write en fgets//fputs en utilisant fdopen (j'ai fait deux tableaux de FILE*) et en mettant mes streams en non buffered avec setvbuf; cela n'as rien changé (je n'ai pas cette version du code sous la main par contre). j'ai essayé le mode raw sur mes file descriptors aussi ... pas mieux !

pour resumer: ca marche quand le programmé appelé (via fork -> execv) fait un fflush(stdout). mais rien s'il n'en fait pas (pourtant il envoie des \n ?)
et je ne peux pas modifier le comportement des programmes appelés (c'est justement pour eviter d'avoir a le faire que je fait tout ce *merdier*)
bref, si vous avez une idée ... n'importe laquelle ... hesitez pas

edit: haben forcement, quand je tire a pile ou face pour choisir le forum sur lequel poster, ca tombe sur le mauvais

maintenant que c'est tombé dans le forum linux, je peux le dire ...
ce truc devrais servir a communiquer entre squid (programme appelant) et plusieurs redirecteurs (notemment squidguard et squidclam).
les solutions comme Willowbark ne me convenant pas ... codage de ce truc .