PROBLEMES:

* pstream : bidirectionnel
   
   float result;
   pstream bc("bc -l");
   bc << "2+2" << endl;
   bc >> result;

   qui marche au niveau C sur HP-UX,mais pas Linux, et pas en C++
   => implementer en 1 stream ou 2 ?

   en C il faut attendre le resultat, sinon bc -l n'a pas le temps...
    => sleep(n); ou 'n' serait en parametre de la classe pstream (delay).

   en C++ rien encore...

  ==> voir avec les ex. de X-window...

* irheostream : doit
	- ouvrir un fstream en normal
	- ouvrir un pstream en decompresses'
  
  => class irheostream : public ipstream, public ifstream {
   
   mais istream n'est pas classe virtuelle...

  ==> pour l'instant, ouvre
	ipstream ("cat toto.hb")
      au lieu de 
	ifstream ("toto.hb");

- ipstream est ok

   ipstream zin ("zcat tutu.geo.gz");
   zin >> a;

- reste les opstream,
  pour les sorties (compresse'es, ...)

   opstream zout("gzip -c9 > toto.hb.gz");
   zout << a;


LIEN entre filebuf et istream ==> lien entre procbuf et ipstream
----------------------------------------------------------------
  class pstream : istream { 
    ...
    private:
      filbuf pbuf;
  };

1. construction de pbuf 

  GNU: pbuf = filebuf(int fileno);
  KAI: pbuf = filebuf(FILE* filedesc);

2. activation de istream

   istream.rdbuf (pbuf);

VERSION GNU:
------------

class filebuf : streambuf {
    filebuf (int fileno);
};
class ios : public _ios_fields {

    streambuf* rdbuf() const 
	{ return _strbuf; }
    streambuf* rdbuf(streambuf *_s) 
	{ streambuf *_old = _strbuf; _strbuf = _s; clear (); return _old; }
};
class istream : virtual public ios 
{   
    istream(streambuf* sb, ostream*tied=NULL);
};

SYNCHRONISATION e/s
-------------------
exemple: cin, cout
  1. creation de cin, cout
     ostream cout;
     istream cin;
  2. synchronisation de cout avec la sequence d'entree
     controlee par le streambuf de cin:

     cin.tie(&cout);

     effet: (cin.tie() == &cout)
     avant chaque entree formatee, on apelle 
	     cin.tee()-> flush()
     cad:    cout.flush()

ostream* ios::tee(ostream* tie_stream) { _tie_stream = tie_stream; }
ostream* ios::tee() const { return _tie_stream; }

ostream& endl(ostream& os) { os << "\n"; return os.flush(); }
ostream& fflush(ostream& os) { return os.flush(); }
ostream& ostream::flush() { if (rdbuf() != 0) rdbuf()->pubsync(); return *this; }

	if os.ios::unitbuf => call flush() after each output operation

	prefix aux entrees formattees:
	bool istream::ipfx() { if (tie()) tie()->flush(); et saute les blancs; return good(); } 
	bool istream::opfx() { if (tie()) tie()->flush(); if (flags()&unitbuf) flush(); return good(); } 

streambuf::rdbuf() { sync(); }
virtual streambuf::sync()  { VIDE LE TAMPON D'E/S }

Ouf

** Dand le cas des procbuf, il faut non seulement vider
** le tampon du ostream (etre sur que "2+2" est expedie a` "bc -l"),
** mais attendre que "bc -l" ait fini de bosser... La`, c'est plus dur;
** on peut attendre qu'un caractere arrive en entree, par ex., avec un
** temps limite d'attente.

Peut-etre en utilisant des signaux.

* SIGUP=18: lorsqu'on se delogue (le pere (tcsh) s'arrete), si on ignore
         c,a permet de continuer le calcul.

* kill: emission
	int kill(int pid, int sig);
 renvoie 0 si sig est envoye, -1 sinon
 pour sig=0 aucun signal n'est envoye : 
   permet de savoir si pid est un process (retour == 0)

* alarm: emission de SIGALRM=14
    emis quand l'horloge d'un processus s'arrete;
    l'horloge est mise en marche par:
	
	unsigned int alarm(unsigned int secs);

    le retour est le temps restant dans l'horloge
    apres l'appel, l'horloge est initialisee a` secs,
    est sera decr jusqu'a 0; le traitement du SIGARM 
    doit etre prevu.
    Application: forcer la lecture dans un delai donne';
    autrement, continuer.
    
      alarm(10); // arme un signal SIGARM pour dans 10 sec 

* la fct

      pause();

  est de l'attente pure; sera interrompue par un signal,
  et si intercepte', reprend apres cette instruction.
  => on attend un signal ici.

* pour attraper un signal:

  int ma_fct_attrappe () { hehe..; }
  
  int signal (int sig, int (ma_fct_attrappe*)());

 ex. un calcul long envoie un bilan ou` il en est a` la
     reception d'un signal ; 
     plante la solution a` la fin de l'iteration courante dans un fichier
     mais continue ensuite les calculs.
     les variables a` editer doivent etre globales.

     long somme = 0;
     void bilan() {
       signal (SIGUSR1, bilan); // re-active le signal
       long t_date; time(&t_date);
       cerr << "somme = " << somme << " a` t = " << ctime(&t_date) << endl;
     }
     main() {
       signal(SIGUSR1, bilan);
       cerr << "pour un bilan, faire: \"kill " << SIGUSR1 << " " << getpid() << "\"\n";
       while (1) somme++;
     }

* pipe(int p_desc[2]): 
     read():  si le conduit est vide, read() se bloque;
     write(): si le conduit est plein, write() se bloque;
	      on peut eviter cela en positionnant le
	      drapeau O_NDELAY : les fcts read() et write() retournent
	      alors 0.
     close():  lorsqu'on ferme le descripteur d'ecriture p_decs[1],
	      alors elle agit comme EOF pour la lecture p_decs[0].
              dans le cas de "bc -l", c'est alors la fin du processus fils.

* fifo: 
