/*************************************************************************************************************************************/ /* */ /* 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"); } }