Totoro a écrit 6 commentaires

  • [^] # Re: Impossible

    Posté par  . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.

    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 -1
    
    
    int main(int ac, char *av[]){
    
        int fd_master, fd_slave, pid, rc, i, nb_read;
        FILE *f = NULL;
        char *buffer;
        char* const basharg[]={"/bin/bash",NULL};
        fd_set readfd_slave;
        struct timeval timeout;
    
        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){
    
          struct termios slave_orig_term_settings; // Saved terminal settings
          struct termios new_term_settings; // Current terminal settings
          // Close the master side of the PTY
          close(fd_master);
          // Save the default parameters of the slave side of the PTY
          rc = tcgetattr(fd_slave, &slave_orig_term_settings);
          // Set raw mode on the slave side of the PTY
          new_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 process
          close(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 useless
          close(fd_slave);
    
          // Make the current process a new session leader
          setsid();
    
          // 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);
    }
  • [^] # Re: Impossible

    Posté par  . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.

    Pour execve si j'utilise :

    basharg[0] = "-i";
    basharg[1] = NULL;
    

    Le prompt ne s'affiche pas.

    Je pense avoir corrigé le reste .

    #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 2
    
    int main(int argc, char **argv){
      char buff[BUFF_SIZE];             /* Déclaration des variables */
      char* basharg[3];
      int fd[NB_PIPE][2];
      FILE *f = NULL;
      fd_set readfds;
      struct timeval timeout;
      int pid,i,nb_read;
    
      memset(buff,0,sizeof buff);
      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");
           return 1;
        }
      }
    
      if((pid = fork()) == -1){             /* Création du processus fils */
         perror("fork failed\n");
         return 2;
      }
    
      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 */
                }
            }
        }
      }
      return 0;
    }
  • [^] # Re: Impossible

    Posté par  . 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  . 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 :

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    #define NB_PIPE 2
    
    int main(int argc, char **argv){
      int pid;
      /* Création du processus fils */
      if((pid = fork()) == -1){
         perror("fork failed\n");
         return 2;
      }
      /* Processus fils */
      if(pid == 0){
        execve("/bin/bash",NULL,NULL);
      }
      /* Processus père */
      else{
        wait(0);
      }
      return 0;
    }

    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 2
    
    int main(int argc, char **argv){
      char *buff;                           /* Déclaration des variables */
      int pid,i,fd_stdin,fd_stdout,ret,nb_read;
      int fd[NB_PIPE][2];
      FILE *f = NULL;
      fd_set readfds;
      struct timeval timeout;
    
      for(i=0;i<NB_PIPE;i++){               /* Création des pipes */
        if(pipe(fd[i]) == -1){
           perror("pipe failed\n");
           return 1;
        }
      }
    
      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");
         return 2;
      }
    
      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 */
                }
            }
        }
      }
      return 0;
    }

    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.

  • [^] # Re: Impossible

    Posté par  . En réponse au message Communication entre processus avec pipe() et dup2().. Évalué à 1.

    Source :

    argv[0] = "-li";
    argv[1] = NULL;
    execve("/bin/bash",argv,NULL);

    Résultat :

    toto@ThinkPad:~/lab$ ./main 
    ls
    Makefile
    main
    main.c
    main.o
    tmp_log
    toto
    toto.c
    toto.o
    ls
    Makefile
    main
    main.c
    main.o
    tmp_log
    toto
    toto.c
    toto.o
    
    
  • [^] # Re: Impossible

    Posté par  . 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 :

    #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 2
    
    int main(int argc, char **argv){
      char *buff;                           /* Déclaration des variables */
      int pid,i,fd_stdin,fd_stdout,ret,nb_read;
      int fd[NB_PIPE][2];
      FILE *f = NULL;
      fd_set readfds;
      struct timeval timeout;
    
      for(i=0;i<NB_PIPE;i++){               /* Création des pipes */
        if(pipe(fd[i]) == -1){
           perror("pipe failed\n");
           return 1;
        }
      }
    
      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");
         return 2;
      }
    
      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 */
                }
            }
        }
      }
      return 0;
    }

    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 2
    
    int main(int argc, char **argv){
      int pid;
      /* Création du processus fils */
      if((pid = fork()) == -1){
         perror("fork failed\n");
         return 2;
      }
      /* Processus fils */
      if(pid == 0){
        execve("/bin/bash",NULL,NULL);
      }
      /* Processus père */
      else{
        wait(0);
      }
      return 0;
    }

    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.