/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E X E C U T I O N   A   D I S T A N C E   D E   C O M M A N D E S  :                                                       */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xtc/remote.12$c' :                                                                                             */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, AAAAMMJJhhmmss).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

#include  <stdio.h>
#include  <netdb.h>
#include  <sys/signal.h>
#include  <sys/types.h>

#define   STANDARD_IN                                                                                                                   \
                    0
#define   STANDARD_OUT                                                                                                                  \
                    (STANDARD_IN+1)
#define   STANDARD_ERREUR                                                                                                               \
                    (STANDARD_OUT+1)

#define   BUFFER                                                                                                                        \
                    10                                                                                                                  \
                                        /* Taille des buffers d'ecriture et de lecture de la commande distante.                      */
#define   LWRITE                                                                                                                        \
                    BUFFER                                                                                                              \
                                        /* Nombre d'octets a ecrire par 'write(...)'.                                                */
#define   LREAD                                                                                                                         \
                    BUFFER                                                                                                              \
                                        /* Nombre d'octets a lire par 'read(...)'.                                                   */

#define   CLOSE(stream,message)                                                                                                         \
                    {                                                                                                                   \
                    if        (close(stream) == 0)                                                                                      \
                              {                                                                                                         \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              printf("\n ERREUR lors de la fermeture d'un stream (%s)",message);                                        \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Fermeture d'un stream.                                                                    */

extern    int       rexec();
extern    pid_t     fork();
extern    pid_t     getpid();

char                *host="lactB.polytechnique.fr";
                                        /* Identite de la machine distante (ici '$LACT29').                                          */
char                *user="colonna";
char                *passwd=0;
                                        /* Definition de l'utilisateur. ATTENTION, sur 'SYSTEME_SGIND4GA_IRIX_CC', la valeur nulle   */
                                        /* de '*passwd' provoque un :                                                                */
                                        /*                                                                                           */
                                        /*                  Segmentation fault                                                       */
                                        /*                                                                                           */
                                        /* que je n'ai pas pu faire disparaitre. Cela semble vrai aussi pour '*user'...              */
char                *cmd="cat | cat";
                                        /* Commande a executer a distance. ATTENTION, ecrire seulement :                             */
                                        /*                                                                                           */
                                        /*                  cmd[]="cat";                                                             */
                                        /*                                                                                           */
                                        /* conduit au message :                                                                      */
                                        /*                                                                                           */
                                        /*                  UX:cat: ERROR: Input/output files '-' identical                          */
                                        /*                                                                                           */
                                        /* (ce que l'on voit en remplacant '&signalisation' par '0' dans 'rexec(...)') ce qui peut   */
                                        /* se comprendre car alors, le 'cat' voit un 'STANDARD_IN' et un 'STANDARD_OUT' identiques   */
                                        /* (le "stream"...).                                                                         */

main()
          {
          pid_t     process_pere=getpid();
          pid_t     process_fils;
                                        /* Identificateurs du process pere et du process fils.                                       */

          struct    servent   *Pserveur;
                                        /* Identite de la machine distante (ici '$LACT29').                                          */

          int                 signalisation=-1;
                                        /* "Stream" de signalisation pour la commande distante.                                      */
          int                 stream=-1;
                                        /* "Stream" pour 'stdin' et 'stdout' de la commande distante.                                */

          char                signal=0;
                                        /* Buffer de signalisation. Il permet de faire par exemple :                                 */
                                        /*                                                                                           */
                                        /*                  signal=SIGKILL;                                                          */
                                        /*                  write(signalisation,signal,sizeof(signal));                              */
                                        /*                                                                                           */
                                        /* pour tuer la commande distante...                                                         */

          char                buffer_du_write[LWRITE];
          int                 longueur_du_write;
                                        /* Buffer destine aux arguments de la commande distante.                                     */
          int                 iterer_le_write=0;
                                        /* =0 : iterer le 'write(...)', #1 : ne plus iterer.                                         */

          char                buffer_du_read[LREAD];
          int                 longueur_du_read;
                                        /* Buffer destine aux resultats de la commande distante.                                     */
          int                 iterer_le_read=0;
                                        /* =0 : iterer le 'read(...)', #1 : ne plus iterer.                                          */

          if        ((Pserveur=getservbyname("exec","tcp")) != NULL)
                                        /* ATTENTION, sur 'SYSTEME_APC_LinuxRedHat_GCC', il y a permutation 2 a 2 des octets         */
                                        /* donnant le numero de port. Dans le cas de {exec,tcp} on recupere donc 2 a la place        */
                                        /* de 512...                                                                                 */
                    {
                    if        ((stream=rexec(&host,Pserveur->s_port,user,passwd,cmd,&signalisation)) > 0)
                              {
                                        /* Recuperation du "stream" pour 'stdin' et 'stdout' de la commande distante.                */

                              process_fils=fork();
                                        /* Creation d'un processus "fils".                                                           */

                              if        (process_fils == 0)
                                        {
                                        /* Cas du processus "fils".                                                                  */

                                        while     (iterer_le_write == 0)
                                                  {
                                                  longueur_du_write=read(STANDARD_IN
                                                                        ,buffer_du_write
                                                                        ,LREAD
                                                                         );

                                                  if        (longueur_du_write > 0)
                                                            {
                                                            write(stream
                                                                 ,buffer_du_write
                                                                 ,longueur_du_write
                                                                  );
                                        /* Transfert du 'STANDARD_IN' a distance. Malheureusement, je n'arrive pas (19971020092441)  */
                                        /* a transmettre la fin de fichier ; donc, la commande distante se trouve bloquee croyant    */
                                        /* qu'il reste des octets a transmettre. J'ai essaye en remplacant "cat | cat" par le        */
                                        /* programme simple 'v $xtc/inout.01$c', mais cela ne change rien. Le 19971020115021, j'ai   */
                                        /* trouve, il faut ajouter plus loin un 'shutdown(stream,1)'...                              */
                                                            }
                                                  else
                                                            {
                                                            iterer_le_write++;
                                                            }
                                                  }

                                        shutdown(stream,1);
                                        }
                              else
                                        {
                                        /* Cas du processus "pere".                                                                  */

                                        while     (iterer_le_read == 0)
                                                  {
                                                  longueur_du_read=read(stream
                                                                       ,buffer_du_read
                                                                       ,LREAD
                                                                        );
                                        /* Recuperation du 'STANDARD_OUT' a distance.                                                */

                                                  if        (longueur_du_read > 0)
                                                            {
                                                            write(STANDARD_OUT
                                                                 ,buffer_du_read
                                                                 ,longueur_du_read
                                                                  );
                                        /* Et sortie des resultats...                                                                */
                                                            }
                                                  else
                                                            {
                                                            iterer_le_read++;
                                                            }
                                                  }

                                        shutdown(stream,0);
                                        CLOSE(stream,"STREAM");
                                        CLOSE(signalisation,"SIGNALISATION");
                                        }
                              }
                    else
                              {
                              printf("\n\n erreur dans 'rexec(...)'\n\n");
                              }
                    }
          else
                    {
                    printf("\n\n erreur dans 'getservbyname(...)'\n\n");
                    }
          }



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