home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d105 / pere-et-fils.lha / Pere-et-Fils / fils.c < prev    next >
C/C++ Source or Header  |  1987-10-25  |  7KB  |  209 lines

  1. /**********************************************************************
  2.  *
  3.  *       fichier: fils.c       Terminal sur une fenetre Amiga.
  4.  *                          le code est reentrant pour permettre le
  5.  *                          lancement de plusieurs process dessus.
  6.  *                             Pour cela, il doit etre linke avec
  7.  *                          'startproc.obj' qui est reentrant aussi
  8.  *                          et remplace 'astartup.obj'.
  9.  *                             StartProc.obj permet seulement d'avoir
  10.  *                          une fonction "exit()" et SysBase.
  11.  *
  12.  *       par Jean-Michel FORGEAS
  13.  *
  14.  *       creation: 09-Jun-87
  15.  *       revision: 18-Jun-87
  16.  *
  17.  **********************************************************************/
  18.  
  19.  
  20. /******* Included Files ***********************************************/
  21.  
  22. #include "proc.h"
  23.  
  24.  
  25. /******* Imported *****************************************************/
  26.  
  27. extern ULONG  SysBase;                 /* = AbsExecBase seule adresse
  28.                                             absolue dans Exec         */
  29. extern struct Pack       *GetMsg();
  30. extern struct FileHandle *Open();
  31.  
  32.  
  33. /******* Exported ******************************************************/
  34.  
  35. VOID main();
  36.  
  37.  
  38. /******* Program ******************************************************/
  39.  
  40. static VOID Quitte();
  41.  
  42.             /* ATTENTION!!! DOSBase est GLOBAL au 
  43.                programme, si un process ecris alors
  44.                qu'un autre lis, ca fait desordre !!!
  45.             */
  46. struct DosLibrary *DOSBase=0;
  47.  
  48.  
  49.             /* chaque fils a besoin de ses variables globales, mais
  50.                elles doivent leur etre propre. Donc chaque fils va
  51.                allouer de la memoire a l'image de cette structure
  52.                et va ranger ses variables dedans.
  53.             */
  54. struct Global {
  55.         int    id;              /* numero du process */
  56.         struct MsgPort *port;   /* port original du process */
  57.         struct Pack    *pack;   /* message recu du pere */
  58.         struct FileHandle *stdin, *stdout, *stderr; /* fichier d'e/s */
  59.         int  initialSP;         /* pointeur initial sur la pile du process */
  60. };                              /* il est passe par startproc.obj et doit  */
  61.                                 /* lui etre retourne avec exit(initialSP); */
  62.  
  63.  
  64. /**********************************************************************
  65.  *
  66.  *      Point d'entree
  67.  *
  68.  **********************************************************************/
  69.  
  70.  
  71. /*-------------------------------------------------------------
  72.  *      lancement de chaque fils
  73.  */
  74.  
  75. VOID main(initialSP)  /* chaque process a un pointeur sur sa pile. Ici il */
  76. int initialSP;        /* est passe au process par 'startproc.obj' pour le */
  77.                       /* memoriser et le rendre avec exit(initialSP) */
  78. {
  79.    struct Global  *G=0;  /* pointeur sur la zone des variables du process */
  80.    struct Process *proc; /* process de chaque fils pour trouver le port */
  81.    struct MsgPort *port; /* adresse du port original du process */
  82.    struct Pack    *pack; /* adresse du message venant du pere */
  83.    int rc;
  84.  
  85.    if (!DOSBase) {
  86.         Forbid(); /* bloque les autre process pendant que celui-ci ecrit */
  87.         DOSBase = (struct DosLibrary *) OpenLibrary( DOSNAME, 0 );
  88.         if (!DOSBase) exit(0);
  89.         Permit(); /* les autres peuvent maintenant lire */
  90.    }
  91.  
  92.    proc = (struct Process *) FindTask(0);  /* adresse de son descripteur...*/
  93.    port = &proc->pr_MsgPort;               /* ...pour adresse de son port */
  94.  
  95.    WaitPort( port );       /* attend le message du pere avec infos */
  96.    pack = GetMsg( port );  /* sur fichier a ouvrir */
  97.  
  98.  
  99.           /*--- allocation de memoire pour les variables globales ---*/
  100.    if (!(G = (struct Global *) AllocMem( sizeof(struct Global), MEMF_CLEAR )))
  101.     {
  102.       Quitte( G, NO_MEMORY );
  103.     }
  104.           /*--- initialisation des variables globales ---*/
  105.    if ((rc = InitGlobal( G, initialSP, pack )) != NO_ERROR)
  106.     {
  107.       Quitte( G, rc );
  108.     }
  109.  
  110.    pack->result = NO_ERROR;    /* le pere veut savoir si tout est OK */
  111.    pack->FilsPort = G->port;   /* le pere sait de qui vient le reply */
  112.    ReplyMsg( pack );
  113.                  /* Appel fonction principale */
  114.    rc = ProcessCode( G );
  115.  
  116.    Quitte( G, rc );
  117. }
  118.  
  119.  
  120. /*-------------------------------------------------------------
  121.  *      Initialisation de l'environement de chaque fils
  122.  */
  123.  
  124. static int InitGlobal( G, initialSP, pack )
  125. struct Global  *G;
  126. int    initialSP;
  127. struct Pack *pack;
  128. {
  129.  struct MsgPort *port;
  130.  
  131.    G->id   = pack->id;  /* numero */
  132.    G->initialSP = initialSP; /* pointeur de pile passe par startproc.obj */
  133.  
  134.                 /* chacun ouvre son fichier (console) */
  135.  
  136.    if (!(port = (struct MsgPort *) CreatePort( "fils", 0 ))) return( NO_MEMORY );
  137.    G->port = port;
  138.  
  139.    if (!(G->stdin = Open( pack->bufread, MODE_OLDFILE ))) return( NO_FILE );
  140.    G->stdout = G->stderr = G->stdin;
  141.  
  142.    Write( G->stdout, "stdout ok\n", 10 );
  143.  
  144.    return( NO_ERROR );
  145. }
  146.  
  147.  
  148. /*-------------------------------------------------------------
  149.  *      Nettoie et fin
  150.  */
  151.  
  152. static VOID Quitte( G, rc )
  153. struct Global *G;
  154. int rc;
  155. {
  156.    int  initialSP;
  157.    struct Pack *pack;
  158.  
  159.    initialSP = G->initialSP; /* rememoriser initialSP avant FreeMem() */
  160.    pack = G->pack;           /* l'adresse du message aussi */
  161.  
  162.    Write( G->stdout, "Quitte() ok\n", 12 );
  163.    if (G->stdin)  Close( G->stdin );
  164.    if (G->port)   DeletePort( G->port );
  165.    if (G)         FreeMem( G, sizeof(struct Global) );
  166.    if (DOSBase)   CloseLibrary( DOSBase );
  167.  
  168.    Forbid();          /* bloque le pere: il faut que le process se */
  169.                       /* termine avant que le pere fasse UnLoad du code */
  170.    pack->result = rc;
  171.    ReplyMsg( pack );  /* pour que le pere sache qu'il peut faire UnLoad */
  172.                       /* si c'est le dernier fils */
  173.    exit(initialSP);   /* retour a startproc.obj qui va remettre son */
  174.                       /* pointeur de pile a cette valeur avant RTS */
  175. }
  176.  
  177.  
  178.  
  179. /*-------------------------------------------------------------
  180.  *      code de fonctionnement de chaque process fils
  181.  */
  182.  
  183. static int ProcessCode(G)
  184. struct Global *G;
  185. {
  186.    Write( G->stdout, "Process Fils prêt\n", 18 ); /*accueil */
  187.  
  188.    while (TRUE)
  189.    {
  190.      WaitPort( G->port );          /* attend une requete du pere */
  191.      G->pack = GetMsg( G->port );
  192.  
  193.      if (G->pack->lenwrite)
  194.       {
  195.         Write( G->stdout, G->pack->bufwrite, G->pack->lenwrite );
  196.         G->pack->lenwrite = 0;
  197.       }
  198.  
  199.      if (G->pack->cmd == CMD_STOP) break;
  200.  
  201.      G->pack->lenread = Read( G->stdin, G->pack->bufread, G->pack->lenread );
  202.  
  203.         /* renvoit les caracteres lu au pere. Si c'est 'logoff', le */
  204.         /* pere renverra un CMD_STOP */
  205.      ReplyMsg( G->pack );
  206.    }
  207.    return( NO_ERROR );
  208. }
  209.