/*************************************************************************************************************************************/ /* */ /* 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