Bonjour, ça fonctionne avec un PTY.
Merci pour votre aide.
#define _XOPEN_SOURCE 600#include<stdlib.h>#include<fcntl.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#define __USE_BSD#include<termios.h>#include<sys/select.h>#include<sys/ioctl.h>#include<string.h>#define BUFF_SIZE 4096#define OPERATION_FAIL -1intmain(intac,char*av[]){intfd_master,fd_slave,pid,rc,i,nb_read;FILE*f=NULL;char*buffer;char*constbasharg[]={"/bin/bash",NULL};fd_setreadfd_slave;structtimevaltimeout;buffer=malloc(BUFF_SIZE*sizeof(char));f=fopen("tmp_log","wba+");memset(buffer,0,BUFF_SIZE);/* Open PTY in read and write mode */fd_master=posix_openpt(O_RDWR);if(fd_master==OPERATION_FAIL){fprintf(stderr,"Error %d on posix_openpt()\n",errno);exit(EXIT_FAILURE);}/* Change acces rigth of slave side and set group */rc=grantpt(fd_master);if(rc==OPERATION_FAIL){fprintf(stderr,"Error %d on grantpt()\n",errno);exit(EXIT_FAILURE);}/* Unlock slave side */rc=unlockpt(fd_master);if(rc==OPERATION_FAIL){fprintf(stderr,"Error %d on unlockpt()\n",errno);exit(EXIT_FAILURE);}/* Get file descriptor of slave */fd_slave=open(ptsname(fd_master),O_RDWR);if(rc==OPERATION_FAIL){fprintf(stderr,"Error %d on open()\n",errno);exit(EXIT_FAILURE);}/* Create son process */if((pid=fork())==OPERATION_FAIL){fprintf(stderr,"Error %d on fork()\n",errno);exit(EXIT_FAILURE);}/* Soon process */if(pid==0){structtermiosslave_orig_term_settings;// Saved terminal settingsstructtermiosnew_term_settings;// Current terminal settings// Close the master side of the PTYclose(fd_master);// Save the default parameters of the slave side of the PTYrc=tcgetattr(fd_slave,&slave_orig_term_settings);// Set raw mode on the slave side of the PTYnew_term_settings=slave_orig_term_settings;cfmakeraw(&new_term_settings);tcsetattr(fd_slave,TCSANOW,&new_term_settings);// The slave side of the PTY becomes the standard input and outputs of the child processclose(0);// Close standard input (current terminal)close(1);// Close standard output (current terminal)close(2);// Close standard error (current terminal)dup(fd_slave);// PTY becomes standard input (0)dup(fd_slave);// PTY becomes standard output (1)dup(fd_slave);// PTY becomes standard error (2)// Now the original file descriptor is uselessclose(fd_slave);// Make the current process a new session leadersetsid();// As the child is a session leader, set the controlling terminal to be the slave side of the PTY// (Mandatory for programs like the shell to make them manage correctly their outputs)ioctl(0,TIOCSCTTY,1);// Execution of the program{execve("/bin/bash",basharg,NULL);}}/* Father process */else{/* Close the slave side of the PTY */close(fd_slave);/* While soon process is not terminated */while(waitpid(pid,NULL,WNOHANG)!=pid){/* Set timeout for select() */timeout.tv_sec=5;timeout.tv_usec=0;/* Set on wich file descriptor listen*/FD_ZERO(&readfd_slave);FD_SET(STDIN_FILENO,&readfd_slave);FD_SET(fd_master,&readfd_slave);/* Listen file descriptor */rc=select(FD_SETSIZE,&readfd_slave,NULL,NULL,&timeout);if(rc==OPERATION_FAIL){fprintf(stderr,"Error %d on select()\n",errno);exit(EXIT_FAILURE);}/* Data on STDIN */if(FD_ISSET(STDIN_FILENO,&readfd_slave)){nb_read=read(STDIN_FILENO,buffer,BUFF_SIZE);if(nb_read==OPERATION_FAIL){fprintf(stderr,"Error %d on read standard input\n",errno);exit(EXIT_FAILURE);}else{write(fd_master,buffer,nb_read);for(i=0;i<nb_read;i++){fputc(buffer[i],f);}}}/* Data on fd_slave */if(FD_ISSET(fd_master,&readfd_slave)){nb_read=read(fd_master,buffer,BUFF_SIZE);if(nb_read==OPERATION_FAIL){fprintf(stderr,"Error %d on read master PTY\n",errno);exit(EXIT_FAILURE);}else{write(STDOUT_FILENO,buffer,nb_read);for(i=0;i<nb_read;i++){fputc(buffer[i],f);}}}}close(f);free(buffer);}exit(EXIT_SUCCESS);}
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/wait.h>#include<sys/select.h>#include<sys/time.h>#include<sys/types.h>#include<errno.h>#include<string.h>#define BUFF_SIZE 4096 /* the capacity of a pipe is 4096 bytes */#define NB_PIPE 2intmain(intargc,char**argv){charbuff[BUFF_SIZE];/* Déclaration des variables */char*basharg[3];intfd[NB_PIPE][2];FILE*f=NULL;fd_setreadfds;structtimevaltimeout;intpid,i,nb_read;memset(buff,0,sizeofbuff);f=fopen("tmp_log","wba+");for(i=0;i<NB_PIPE;i++){/* Création des pipes */if(pipe(fd[i])==-1){perror("pipe failed\n");return1;}}if((pid=fork())==-1){/* Création du processus fils */perror("fork failed\n");return2;}if(pid==0){/* Processus fils */close(fd[0][1]);/* Ferme l'entrée de pipe 1 */close(fd[1][0]);/* Ferme la sortie de pipe 2 */dup2(fd[0][0],0);/* Duplique la sortie de pipe 1 sur STDIN */dup2(fd[1][1],1);/* Duplique l'entrée de pipe 2 sur STDOUT */basharg[0]="/bin/bash";basharg[1]="-li";basharg[2]=NULL;execve("/bin/bash",basharg,NULL);perror("Execve failed\n");exit(EXIT_FAILURE);}else{/* Processus père */close(fd[0][0]);/* Ferme la sortie de pipe 1 */close(fd[1][1]);/* Ferme l'entrée de pipe 2 */while(waitpid(pid,NULL,WNOHANG)!=pid){timeout.tv_sec=5;/* Initialisation timeout et des file descriptor a écouter */timeout.tv_usec=0;FD_ZERO(&readfds);FD_SET(STDIN_FILENO,&readfds);FD_SET(fd[1][0],&readfds);select(FD_SETSIZE,&readfds,NULL,NULL,&timeout);/* On ecoute les descripteurs de fichier contenu dans readfds *//* Activité detectée */if(FD_ISSET(STDIN_FILENO,&readfds)){/* Sur STDIN */nb_read=read(STDIN_FILENO,buff,BUFF_SIZE);/* Lecture sur STDIN* */write(fd[0][1],buff,nb_read);/* Ecriture sur l'entrée de pipe 1 */fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}if(FD_ISSET(fd[1][0],&readfds)){/* Sur la sortie du pipe 2 */nb_read=read(fd[1][0],buff,BUFF_SIZE);/* Lecture sur la sortie de pipe 2 */write(STDOUT_FILENO,buff,nb_read);/* Ecriture sur STDOUT*/fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}}}return0;}
Alors quand je fait sans pipe() et dup2() ça marche avec le prompt :
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#define NB_PIPE 2intmain(intargc,char**argv){intpid;/* Création du processus fils */if((pid=fork())==-1){perror("fork failed\n");return2;}/* Processus fils */if(pid==0){execve("/bin/bash",NULL,NULL);}/* Processus père */else{wait(0);}return0;}
Quand je fait :
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/wait.h>#include<sys/select.h>#include<sys/time.h>#include<sys/types.h>#include<errno.h>#define BUFF_SIZE 4096 /* the capacity of a pipe is 4096 bytes */#define NB_PIPE 2intmain(intargc,char**argv){char*buff;/* Déclaration des variables */intpid,i,fd_stdin,fd_stdout,ret,nb_read;intfd[NB_PIPE][2];FILE*f=NULL;fd_setreadfds;structtimevaltimeout;for(i=0;i<NB_PIPE;i++){/* Création des pipes */if(pipe(fd[i])==-1){perror("pipe failed\n");return1;}}fd_stdin=0;/* Initialisation des variables */fd_stdout=1;f=fopen("tmp_log","wba+");if((pid=fork())==-1){/* Création du processus fils */perror("fork failed\n");return2;}if(pid==0){/* Processus fils */close(fd[0][1]);/* Ferme l'entrée de pipe 1 */close(fd[1][0]);/* Ferme la sortie de pipe 2 */dup2(fd[0][0],0);/* Duplique la sortie de pipe 1 sur STDIN */dup2(fd[1][1],1);/* Duplique l'entrée de pipe 2 sur STDOUT */argv[0]="/bin/bash";argv[1]="-li";argv[2]=NULL;execve("/bin/bash",argv,NULL);/* Lance l'execution d'un bash */}else{/* Processus père */close(fd[0][0]);/* Ferme la sortie de pipe 1 */close(fd[1][1]);/* Ferme l'entrée de pipe 2 */while(1){timeout.tv_sec=5;/* Initialisation timeout et des file descriptor a écouter */timeout.tv_usec=0;FD_ZERO(&readfds);FD_SET(fd_stdin,&readfds);FD_SET(fd[1][0],&readfds);select(FD_SETSIZE,&readfds,NULL,NULL,&timeout);/* On ecoute les descripteurs de fichier contenu dans readfds *//* Activité detectée */if(FD_ISSET(fd_stdin,&readfds)){/* Sur STDIN */printf("toto\n");nb_read=read(fd_stdin,buff,BUFF_SIZE);/* Lecture sur STDIN* */printf("toto\n");write(fd[0][1],buff,nb_read);/* Ecriture sur l'entrée de pipe 1 */fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}if(FD_ISSET(fd[1][0],&readfds)){/* Sur la sortie du pipe 2 */nb_read=read(fd[1][0],buff,BUFF_SIZE);/* Lecture sur la sortie de pipe 2 */write(fd_stdout,buff,nb_read);/* Ecriture sur STDOUT*/fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}}}return0;}
L'exécution donne :
toto@ThinkPad:~/lab$ ./main
toto@ThinkPad:/home/toto/lab$ ls
toto
[1]+ Arrêté ./main
toto@ThinkPad:~/lab$ ls
main main.c main.o Makefile tmp_log toto toto.c toto.o
toto@ThinkPad:~/lab$
Le prompt s'affiche mais quand j'exécute "ls" le bash se ferme
et exécute "ls" dans le bash qui appelle main.
L'erreur semble venir du read de STDIN dans le père.
Merci pour ta réponse, j'ai corrigé.
Voila ou j'en suis :
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/wait.h>#include<sys/select.h>#include<sys/time.h>#include<sys/types.h>#define BUFF_SIZE 256#define NB_PIPE 2intmain(intargc,char**argv){char*buff;/* Déclaration des variables */intpid,i,fd_stdin,fd_stdout,ret,nb_read;intfd[NB_PIPE][2];FILE*f=NULL;fd_setreadfds;structtimevaltimeout;for(i=0;i<NB_PIPE;i++){/* Création des pipes */if(pipe(fd[i])==-1){perror("pipe failed\n");return1;}}fd_stdin=0;/* Initialisation des variables */fd_stdout=1;buff=malloc(BUFF_SIZE*sizeof(char));f=fopen("tmp_log","wba+");if((pid=fork())==-1){/* Création du processus fils */perror("fork failed\n");return2;}if(pid==0){/* Processus fils */close(fd[0][1]);/* Ferme l'entrée de pipe 1 */close(fd[1][0]);/* Ferme la sortie de pipe 2 */dup2(fd[0][0],0);/* Duplique la sortie de pipe 1 sur STDIN */dup2(fd[1][1],1);/* Duplique l'entrée de pipe 2 sur STDOUT */execve("/bin/bash",NULL,NULL);/* Lance l'execution d'un bash */}else{/* Processus père */close(fd[0][0]);/* Ferme la sortie de pipe 1 */close(fd[1][1]);/* Ferme l'entrée de pipe 2 */while(1){timeout.tv_sec=5;/* Initialisation timeout et des file descriptor a écouter */timeout.tv_usec=0;FD_ZERO(&readfds);FD_SET(fd_stdin,&readfds);FD_SET(fd[1][0],&readfds);select(FD_SETSIZE,&readfds,NULL,NULL,&timeout);/* On ecoute les descripteurs de fichier contenu dans readfds *//* Activité detecté */if(FD_ISSET(fd_stdin,&readfds)){/* Sur STDIN */nb_read=read(fd_stdin,buff,BUFF_SIZE);/* Lecture sur STDIN* */write(fd[0][1],buff,nb_read);/* Ecriture sur l'entrée de pipe 1 */fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}if(FD_ISSET(fd[1][0],&readfds)){/* Sur la sortie du pipe 2 */nb_read=read(fd[1][0],buff,BUFF_SIZE);/* Lecture sur la sortie de pipe 2 */write(fd_stdout,buff,nb_read);/* Ecriture sur STDOUT*/fseek(f,0,SEEK_END);/* Se déplace a la fin du fichier */for(i=0;i<nb_read;i++){fputc(buff[i],f);/* Ecrit un caractère a la fin du fichier */}}}}return0;}
Exemple :
toto@ThinkPad:~/lab$ ./main
ls
Makefile
main
main.c
main.o
tmp_log
toto
toto.c
toto.o
env
PWD=/home/toto/lab
SHLVL=1
_=/usr/bin/env
^C
Le programme fonctionne quasiment.
Le soucis maintenant c'est l'affichage, et toujours pas de prompt.
J'ai essayé les options de bash sans succès.
Je pense que l'erreur vient d'ailleurs car quand j'exécute ce programme :
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#define NB_PIPE 2intmain(intargc,char**argv){intpid;/* Création du processus fils */if((pid=fork())==-1){perror("fork failed\n");return2;}/* Processus fils */if(pid==0){execve("/bin/bash",NULL,NULL);}/* Processus père */else{wait(0);}return0;}
J'ai ça :
toto@ThinkPad:~/lab$ ./toto
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
toto@ThinkPad:/home/toto/lab$ ls
Makefile main main.c main.o tmp_log toto toto.c toto.o
toto@ThinkPad:/home/toto/lab$ env
LS_COLORS=
M2_HOME=/opt/maven
LESSCLOSE=/usr/bin/lesspipe %s %s
PWD=/home/toto/lab
SHLVL=1
PATH=/opt/maven/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/var/lib/snapd/snap/bin
LESSOPEN=| /usr/bin/lesspipe %s
_=/usr/bin/env
Aussi je ne comprend pas pourquoi le résultat de la commande env est différent.
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.
Bonjour, ça fonctionne avec un PTY.
Merci pour votre aide.
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.
Pour execve si j'utilise :
Le prompt ne s'affiche pas.
Je pense avoir corrigé le reste .
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1. Dernière modification le 01 mars 2020 à 17:23.
Je suis entrain de regarder pselect et le paramètre sigmask.
Je vais regarder ton lien.
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1. Dernière modification le 01 mars 2020 à 11:09.
Alors quand je fait sans pipe() et dup2() ça marche avec le prompt :
Quand je fait :
L'exécution donne :
Le prompt s'affiche mais quand j'exécute "ls" le bash se ferme
et exécute "ls" dans le bash qui appelle main.
L'erreur semble venir du read de STDIN dans le père.
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.
Source :
Résultat :
[^] # Re: Impossible
Posté par Totoro . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.
Merci pour ta réponse, j'ai corrigé.
Voila ou j'en suis :
Exemple :
Le programme fonctionne quasiment.
Le soucis maintenant c'est l'affichage, et toujours pas de prompt.
J'ai essayé les options de bash sans succès.
Je pense que l'erreur vient d'ailleurs car quand j'exécute ce programme :
J'ai ça :
Aussi je ne comprend pas pourquoi le résultat de la commande env est différent.