1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| /*******************************************************************************
Système d'exploitation : Ubuntu Intrepid Ibex
*******************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <termio.h>
#define FILEDES_IN 0
#define FILEDES_OUT 1
#define FILEDES_ERR 2
/*******************************************************************************
Point d'entrée de la fonction
*******************************************************************************/
int main (int argc, char **argv, char **env)
{ struct termio Termio;
FILE *fd_maitre ; // pour pouvoir utiliser fgets et fputs
int pt_maitre ; // descripteur de fichier pseudo-terminal maître
int pt_esclave ; // descripteur de fichier pseudo-terminal esclave
int pid ; // id du processus forkpty
int pid_fils ; // id du processus-fils
int grpid ; // group-id courant
unsigned char buffer[2048], ligne[512], auxligne[512] ;
int i, ier, ip, necho ;
/*** Reset du contrôle tty. On fait cela maintenant pour qu'à l'ouverture
de l'esclave et du maitre, la pty sélectée devienne la tty de contrôle : */
if ((i = open("/dev/tty", O_RDWR)) > 0) {
ioctl(i, TIOCNOTTY, 0);
close(i);
}
//******************************************************************************
pid = forkpty(&pt_maitre, &pt_esclave, NULL, NULL);
printf ("exec forkpty\n") ; // clonage du processus
//******************************************************************************
switch(pid)
{ case -1 :
goto ERR_01 ;
//******************************************************************************
//*************************** processus-fils ***********************************
//******************************************************************************
//*** Pour le moment, nous sommes dans le processus-fils 'pt_esclave' qui est
// un clone du processus-père et qui a hérité de tout son contexte en
// particulier :
// - le stdin qu'il faut connecter au stdout du processus-père,
// - le stdout qu'il faut connecter au stdin du processus-père,
// - le stderr qu'il faut connecter au stdin du processus-père.
case 0 :
close(pt_maitre); // pour avoir les mains libres dans les manipulations
pid_fils = getpid() ; // récupération du pid de notre processus (fils)
printf ("pid du fils = %d\n", pid_fils) ;
//*** On modifie le mode local et output du pty esclave :
ioctl(pt_esclave, TCGETA, &Termio);
Termio.c_lflag &= ~ECHO ; // mode No echo
Termio.c_oflag &= ~ONLCR ; // on ne transcrit pas NL to CR-NL en sortie
ioctl(pt_esclave, TCSETA, &Termio);
dup2(pt_esclave, FILEDES_IN) ; // pt_esclave devient stdin
dup2(pt_esclave, FILEDES_OUT) ; // pt_esclave devient stdout
dup2(pt_esclave, FILEDES_ERR) ; // pt_esclave devient stderr
//*** Il faut que les nouvelles affectations appartiennent au groupe courant et
// au pid courant :
ioctl(FILEDES_IN, TIOCGPGRP, &grpid) ;
setpgid(0,grpid) ;
ioctl(FILEDES_IN, TIOCSPGRP, &pid_fils) ;
setpgid(0,pid_fils);
//*** Maintenant, on peut REMPLACER le processus courant par le programme à
// encapsuler :
execl("mon_programme", "mon_programme", NULL);
goto ERR_02 ;
//******************************************************************************
//*************************** processus-père ***********************************
//******************************************************************************
default :
//*** Le programme encapsulé envoie des lignes de compte-rendu et
// un prompt pour aquérir une commande. Mais toutes les lignes sont
// bufferisées :
close(pt_esclave);
fcntl(pt_maitre, F_SETFL, FNDELAY);
fd_maitre = fdopen(pt_maitre, "r+");
setlinebuf(fd_maitre);
sleep(1) ; //================ !!!!!!!....... ==================
while(1) //****** protocole de dialogue avec le programme encapsulé ******
{
//*** Le programme encapsulé envoie des lignes de compte-rendu et
// un prompt pour aquérir une commande :
if((fgets(ligne, sizeof(ligne), fd_maitre)) == NULL) goto ERR_03 ;
printf ("=R=> %s",ligne) ;
// - A-t-on reçu un prompt du programme encapsulé ?
if (strncmp(ligne , "mpgm=>" , 6) == 0)
{ fprintf ( stdout , "???? :" ) ; // affichage du prompt-maitre
fscanf ( stdin , "%s" , ligne) ; // récuperation de la commande
printf ("=L=> %s\n",ligne) ;
// - L'utilisateur a-t-il entré une commande de sortie du programme ?
// On teste aprés conversion en minuscule :
if (ligne[0] == 'q') return (0) ;
if((fputs(ligne, fd_maitre)) == EOF) goto ERR_04 ;
fflush(fd_maitre) ;
}
}
}
return 0 ;
//==============================================================================
ERR_01 : printf ("ERR_01 forkpty() : création processus-esclave\n") ;
return (1) ;
ERR_02 : printf ("ERR_02 execl() : lancement du programme encapsulé\n") ;
return (2) ;
ERR_03 : printf ("ERR_03 fgets() : peut pas recevoir de l'esclave\n") ;
return (3) ;
ERR_04 : printf ("ERR_04 fputs() : peut pas envoyer vers l'esclave\n") ;
return (4) ;
} |
Partager