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