/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E M U L A T I O N   D ' U N E   C O N S O L E  :                                                                           */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Utilisation :                                                                                                              */
/*                                                                                                                                   */
/*                    Cette commande, formellement identique a ce                                                                    */
/*                  qui se passe dans '$xiidP/fonct$vv$FON' doit                                                                     */
/*                  etre precedee, si necessaire de l'operation                                                                      */
/*                  suivante :                                                                                                       */
/*                                                                                                                                   */
/*                                      sleep     1000000000                              < LIGNE_D_ACCES_A_LA_CONSOLE            &  */
/*                                                                                                                                   */
/*                  afin de permettre l'utilisation de la                                                                            */
/*                  ligne. Ainsi, on pourra emuler la console                                                                        */
/*                  de '$LACT28' (qui n'existe physiquement                                                                          */
/*                  pas) dans une fenetre de '$LACT27'...                                                                            */
/*                                                                                                                                   */
/*                    Pour envoyer des caracteres de controle                                                                        */
/*                  on pourra utiliser une sequence d'echappement                                                                    */
/*                  introduite par la touche <ESC>. Ainsi, pour                                                                      */
/*                  envoyer un <CTRL-D> on pourra faire :                                                                            */
/*                                                                                                                                   */
/*                                      <ESC>0x04                                                                                    */
/*                                                                                                                                   */
/*                  ou :                                                                                                             */
/*                                                                                                                                   */
/*                                      <ESC>4                                                                                       */
/*                                                                                                                                   */
/*                  ou encore tout autre forme licite de la                                                                          */
/*                  constante 4. Au passage, pour emettre un                                                                         */
/*                  <ESC>, il suffit de faire :                                                                                      */
/*                                                                                                                                   */
/*                                      <ESC>0x1b                                                                                    */
/*                                                                                                                                   */
/*                  bien evidemment...                                                                                               */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Nota :                                                                                                                     */
/*                                                                                                                                   */
/*                    Avec '$xcg/console.01$X', il est apparemment                                                                   */
/*                  impossible de passer a l'etat "System Maintenance"                                                               */
/*                  en utilisant <ESC>. La solution semble etre d'arreter                                                            */
/*                  le systeme par :                                                                                                 */
/*                                                                                                                                   */
/*                                      /etc/shutdown       -g0 -i0                                                                  */
/*                                                                                                                                   */
/*                  qui met a l'etat "firmware monitor". Ensuite, il faudra                                                          */
/*                  passer sous le "Enter Command Monitor" pour faire ce qui                                                         */
/*                  doit y etre fait...                                                                                              */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xcg/console.01$K' :                                                                                            */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 1995??????????).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        I N T E R F A C E   ' listG '  :                                                                                           */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        :Debut_listG:                                                                                                              */
/*        :Fin_listG:                                                                                                                */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D I R E C T I V E S   S P E C I F I Q U E S   D E   C O M P I L A T I O N  :                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F I C H I E R S   D ' I N C L U D E S  :                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#include  INCLUDES_MINI

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        P A R A M E T R E S  :                                                                                                     */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

#if       (         (defined(LACT27))                                                                                                   \
           )
#    define    LIGNE_D_ACCES_A_LA_CONSOLE                                                                                               \
                         Gvar("Console_LACT29")
                                        /* Definition de la ligne utile (on notera que c'est utilise aussi pour 'Console_LACT28').   */
#Aif      (         (defined(LACT27))                                                                                                   \
           )
#Eif      (         (defined(LACT27))                                                                                                   \
           )

#if       (         (defined(LACT28))                                                                                                   \
           )
#    define    LIGNE_D_ACCES_A_LA_CONSOLE                                                                                               \
                         Gvar("Console_LACT31")                                                                                         \
                                        /* Definition de la ligne utile...                                                           */
#Aif      (         (defined(LACT28))                                                                                                   \
           )
#Eif      (         (defined(LACT28))                                                                                                   \
           )

#TestADef LIGNE_D_ACCES_A_LA_CONSOLE                                                                                                    \
                    CHAINE_UNDEF                                                                                                        \
                                        /* Definition de la ligne utile...                                                           */

#define   REINITIALISATION_DE_LA_LIGNE_D_ACCES_A_LA_CONSOLE                                                                             \
                    "stty sane < "                                                                                                      \
                                        /* Reinitialisation de la ligne physique d'acces a la console.                               */
#define   PARAMETRAGE_DE_LA_LIGNE_D_ACCES_A_LA_CONSOLE                                                                                  \
                    "stty 9600 -cstopb -parity raw -echo < "                                                                            \
                                        /* Parametrage de la ligne physique d'acces a la console.                                    */

#define   CARACTERE_D_ECHAPPEMENT                                                                                                       \
                    K_ESC                                                                                                               \
                                        /* Caractere destine a introduire les caracteres de controle dont le code est donne sous     */ \
                                        /* la forme numerique. ATTENTION, actuellement, ce n'est pas un argument d'appel...          */

#define   LONGUEUR_DES_BUFFERS                                                                                                          \
                    UN                                                                                                                  \
                                        /* Afin de lire caractere par caractere...                                                   */
#define   LONGUEUR_DES_BUFFERS_D_ECHAPPEMENT                                                                                            \
                    QUATRE                                                                                                              \
                                        /* Afin de lire des caracteres dont on se donne le code hexa-decimal...                      */

#define   RECEVOIR                                                                                                                      \
                    VRAI
#define   EMETTRE                                                                                                                       \
                    VRAI
                                        /* Afin de controler separemment la reception et l'emission...                               */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        M A C R O S   U T I L E S  :                                                                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E M U L A T I O N   D ' U N E   C O N S O L E  :                                                                           */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
BCommande(nombre_d_arguments,arguments)
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(processus,identificateur);
                                        /* Identificateur du processus fils dit de "reception", le processus pere etant le           */
                                        /* processus d'"emission".                                                                   */
     DEFV(CHAR,INIC(POINTERc(ligne_d_acces_a_la_console),LIGNE_D_ACCES_A_LA_CONSOLE));
                                        /* Identite de la ligne d'acces a la console...                                              */
     DEFV(Int,INIT(descripteur_de_la_ligne_de_la_console,CANNOT_OPEN));
                                        /* Descripteur d'acces a la ligne de la console.                                             */
     DEFV(Int,INIT(compte_rendu,UNDEF));
                                        /* Compte_rendu des fonctions "stty"...                                                      */
     DEFV(CHAR,INIT(POINTERc(commande_STTY),COMMANDE_UNDEF));
                                        /* Afin d'envoyer une commande fixant les parametres de la ligne d'acces a la console.       */
     DEFV(CHAR,INIT(caractere_d_echappement,CARACTERE_D_ECHAPPEMENT));
                                        /* Caractere destine a introduire les caracteres de controle dont le code est donne sous     */
                                        /* la forme numerique. ATTENTION, actuellement, ce n'est pas un argument d'appel...          */
     DEFV(Logical,INIT(recevoir,RECEVOIR));
     DEFV(Logical,INIT(emettre,EMETTRE));
                                        /* Afin de controler separemment la reception et l'emission...                               */
     DEFV(Logical,INIT(iterer,VRAI));
                                        /* Afin de boucler eternellement...                                                          */
     DEFV(CHAR,INIT(POINTERc(buffer_de_reception),kMalo(LONGUEUR_DES_BUFFERS)));
     DEFV(CHAR,INIT(POINTERc(buffer_d_emission),kMalo(LONGUEUR_DES_BUFFERS)));
                                        /* Reservation des buffers 'in' et 'out'...                                                  */
     /*..............................................................................................................................*/
     GET_ARGUMENTS_(nombre_d_arguments
                   ,BLOC(GET_ARGUMENT_C("ligne=",ligne_d_acces_a_la_console);
                         GET_ARGUMENT_L("recevoir=",recevoir);
                         GET_ARGUMENT_L("emettre=",emettre);
                         )
                    );

     EGAL(descripteur_de_la_ligne_de_la_console,Open(ligne_d_acces_a_la_console,OPEN_READ_AND_WRITE));
                                        /* Tentative d'ouverture de la ligne de la console.                                          */

     Test(IFNE(descripteur_de_la_ligne_de_la_console,CANNOT_OPEN))
          Bblock
          EGAL(commande_STTY,chain_Aconcaten2(REINITIALISATION_DE_LA_LIGNE_D_ACCES_A_LA_CONSOLE,ligne_d_acces_a_la_console));
          EGAL(compte_rendu,SYSTEM(commande_STTY));
          CALZ_FreCC(commande_STTY);
                                        /* Au prealable, on reinitialise la ligne d'acces a la console,                              */
          Test(PAS_D_ERREUR(compte_rendu))
               Bblock
               EGAL(commande_STTY,chain_Aconcaten2(PARAMETRAGE_DE_LA_LIGNE_D_ACCES_A_LA_CONSOLE,ligne_d_acces_a_la_console));
               EGAL(compte_rendu,SYSTEM(commande_STTY));
               CALZ_FreCC(commande_STTY);
                                        /* Puis, on la programme comme il convient...                                                */
               Test(PAS_D_ERREUR(compte_rendu))
                    Bblock
                    Test(IL_FAUT(recevoir))
                         Bblock
                         iPARALLELE(BLOC(Tant(IL_FAUT(iterer))
                                              Bblock
                                        /* Envoi des messages :                                                                      */
                                        /*                                                                                           */
                                        /*                  console(ordinateur) --> utilisateur                                      */
                                        /*                                                                                           */
                                        /* c'est-a-dire processus dit de "reception".                                                */
                                              DEFV(Int,INIT(longueur_recue
                                                           ,Read(descripteur_de_la_ligne_de_la_console
                                                                ,buffer_de_reception
                                                                ,LONGUEUR_DES_BUFFERS
                                                                 )
                                                            )
                                                   );
                                        /* Lecture d'un message a recevoir.                                                          */

                                              Test(IFNE(longueur_recue,FICHIER_VIDE))
                                                   Bblock
                                                   CAL2(Prin2("%.*s",longueur_recue,buffer_de_reception));
                                        /* Envoi des messages destines a l'utilisateur...                                            */
                                                   Eblock
                                              ATes
                                                   Bblock
                                                   PRINT_ERREUR("la lecture de la ligne ne fonctionne pas");
                                                   DODO(UNITE);
                                        /* En cas de probleme, on ne boucle pas comme une "bete"...                                  */
                                                   Eblock
                                              ETes
                                              Eblock
                                         ETan
                                         )
                                   ,identificateur
                                    );
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                    Test(IL_FAUT(emettre))
                         Bblock
                                        /* Envoi des messages :                                                                      */
                                        /*                                                                                           */
                                        /*                   utilisateur--> console(ordinateur)                                      */
                                        /*                                                                                           */
                                        /* c'est-a-dire processus dit d'"emission".                                                  */
                         Tant(IL_FAUT(iterer))
                              Bblock
                              DEFV(Int,INIT(longueur_a_emettre
                                           ,Read(STANDARD_IN,buffer_d_emission,LONGUEUR_DES_BUFFERS)
                                            )
                                   );
                                        /* Lecture d'un message a emettre. ATTENTION, il n'est pas facile de gerer a ce niveau       */
                                        /* l'echo ou son absence sur 'STANDARD_IN' car, en effet, on sort pratiquement toujours      */
                                        /* du programme '$xcg/console.01$X' par un <CTRL-C>. Donc si ce programme supprimait l'echo  */
                                        /* en option, il faudrait qu'il le retablisse systematiquement en sortant, ce qui donc       */
                                        /* compliquerait les choses. Il est donc decide d'implementer cette facilite dans l'alias    */
                                        /* 'console' qui permet d'acceder a '$xcg/console.01$X'.                                     */

                              Test(IFNE(longueur_a_emettre,FICHIER_VIDE))
                                   Bblock
                                   DEFV(Int,INIT(emettre_un_message,VRAI));
                                        /* Afin de pouvoir bloquer l'emission en cas de probleme avec les caracteres dits            */
                                        /* d'"echappement"...                                                                        */

                                   Test(IFEQ(PREMIER_CARACTERE_ITb1(buffer_d_emission),caractere_d_echappement))
                                        Bblock
                                        /* Cas des messages d'"echappement" :                                                        */
                                        DEFV(CHAR,INIT(POINTERc(buffer_d_echappement)
                                                      ,kMalo(ADD2(LONGUEUR_DES_BUFFERS_D_ECHAPPEMENT,chain_taille(C_VIDE)))
                                                       )
                                             );
                                        /* Reservation du buffer d'echappement...                                                    */
                                        DEFV(Int,INIT(longueur_d_echappement
                                                     ,Read(STANDARD_IN,buffer_d_echappement,LONGUEUR_DES_BUFFERS_D_ECHAPPEMENT)
                                                      )
                                             );
                                        /* Lecture d'un message a emettre.                                                           */
                                        DEFV(CHAR,INIT(caractere_d_echappement,K_NULL));
                                        /* Caractere d'echappement a emettre initialise a 'K_NULL' au cas ou un probleme surgirait   */
                                        /* ci-apres...                                                                               */

                                        Test(IFNE(longueur_d_echappement,FICHIER_VIDE))
                                             Bblock
                                             DEFV(Int,INIT(code_desire,UNDEF));
                                        /* Afin de mettre le code d'echappement desire avant sa conversion 'CARA(...)'.              */
                                             EGAL(ITb1(buffer_d_echappement
                                                      ,INDX(SUCC(TRMU(longueur_d_echappement)),PREMIER_CARACTERE)
                                                       )
                                                 ,END_OF_CHAIN
                                                  );
                                        /* Mise en place d'une fin de chaine en bout de message d'echappement.                       */
                                             EGAL(code_desire
                                                 ,FconversionI(buffer_d_echappement
                                                              ,C_VIDE
                                                              ,INTE(K_NULL)
                                                              ,NE_PAS_EDITER_LES_VALEURS_APRES_Fconversion
                                                              ,C_VIDE
                                                              ,C_VIDE
                                                               )
                                                  );
                                        /* Recuperation du code numerique du caractere d'echappement a emettre.                      */
                                        /*                                                                                           */
                                        /* Le deuxieme 'C_VIDE' a ete introduit le 20060310135742...                                 */

                                             Test(IFOU(IZLT(code_desire),IFGT(code_desire,MOCD)))
                                                  Bblock
                                                  PRINT_ERREUR("le code d'echappement n'est pas un caractere, rien n'est emis");
                                                  EGAL(emettre_un_message,FAUX);
                                                  Eblock
                                             ATes
                                                  Bblock
                                                  Eblock
                                             ETes

                                             EGAL(caractere_d_echappement,CARA(code_desire));
                                        /* Conversion du caractere d'echappement a emettre.                                          */
                                             Eblock
                                        ATes
                                             Bblock
                                             PRINT_ERREUR("la lecture d'echappement ne fonctionne pas");
                                             Eblock
                                        ETes

                                        EGAL(PREMIER_CARACTERE_ITb1(buffer_d_emission),caractere_d_echappement);
                                        /* Mise en place du caractere d'echappement...                                               */
                                        Eblock
                                   ATes
                                        Bblock
                                        /* Cas des messages "normaux" : rien a faire...                                              */
                                        Eblock
                                   ETes

                                   Test(IL_FAUT(emettre_un_message))
                                        Bblock
                                        CALS(Writ(descripteur_de_la_ligne_de_la_console,buffer_d_emission,longueur_a_emettre));
                                        /* Envoi des messages destines a l'ordinateur via la console...                              */
                                        Eblock
                                   ATes
                                        Bblock
                                        Eblock
                                   ETes
                                   Eblock
                              ATes
                                   Bblock
                                   PRINT_ERREUR("la lecture standard ne fonctionne pas");
                                   DODO(UNITE);
                                        /* En cas de probleme, on ne boucle pas comme une "bete"...                                  */
                                   Eblock
                              ETes
                              Eblock
                         ETan
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ATes
                    Bblock
                    PRINT_ERREUR("la programmation de la ligne d'acces s'est mal passee");
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               PRINT_ERREUR("l'initialisation de la ligne d'acces s'est mal passee");
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          PRINT_ERREUR("impossible d'ouvrir la console");
          Eblock
     ETes

     RETU_Commande;
     Eblock
ECommande



Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.