Thread: Communication pipe

  1. #1
    Registered User
    Join Date
    Apr 2020
    Posts
    24

    Communication pipe

    Hello everyone,

    I am working on a program that allows the transmission of a message typed on the terminal of a parent process, to a child process which is responsible for displaying this message on the terminated. (it's stupid but it's an exercise to train )

    To do this, I want to use redirection in the parent process as well as in the child process.

    For now, the code I wrote contains several errors, but I don't really see how to solve them.

    Here is the program code:
    Code:
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #define TABSIZE 512
    
    int main(){
      int pid;
      int pipe(int filedes[2]); /* create a communication pipe */
      char tab[TABSIZE], *s;
    
      pid = fork(); /* create son process */
      
      switch(pid){
      
        case -1:
          break;
    
        case 0: /* son process */
          
          /* REDIRECTION */
          close(STDIN_FILENO); /* close standard input file */
          dup(filedes[0]); /* duplicate the new input file desired*/
          close(filedes[0]); /* the communication pipe is now the standard input file */
          
          /* listening in the the pipe and printing the received message in the terminal*/
          for (;;) {
            s = fgets(tab, TABSIZE, stdin); /* getting the text contained in the input file (that corresponds to the pipe) and putting it in the tab */
            printf(tab); /* print the message */
          }
    
        default: /* father process */
          
          /* REDIRECTION */
          close(STDOUT_FILENO);
          dup(filedes[1]); 
          close(filedes[1]);
    
          /* listening in the the pipe and printing the received message in the new output file (which is the communication pipe) */
          for (;;) {
            fputs("say_something_to_my_son...> ", stdout); /* prompt displaying */
            s = fgets(tab, TABSIZE, stdin); /* getting the text written in the terminal and putting it in a tab */
            printf(tab); /* writing in the new output file (communication pipe input) */
          }
      }  
      exit(EXIT_SUCCESS);
    }
    Can someone help me please ? I don't understand where the errors are coming from !

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You mean these errors?
    Code:
    $ gcc -Wall -Wextra foo.c
    foo.c: In function ‘main’:
    foo.c:23:11: error: ‘filedes’ undeclared (first use in this function)
           dup(filedes[0]); /* duplicate the new input file desired*/
               ^
    foo.c:23:11: note: each undeclared identifier is reported only once for each function it appears in
    foo.c:29:16: warning: format not a string literal and no format arguments [-Wformat-security]
             printf(tab); /* print the message */
                    ^
    foo.c:43:16: warning: format not a string literal and no format arguments [-Wformat-security]
             printf(tab); /* writing in the new output file (communication pipe input) */
                    ^
    foo.c:10:23: warning: variable ‘s’ set but not used [-Wunused-but-set-variable]
       char tab[TABSIZE], *s;
    Let's start with this.
    > int pipe(int filedes[2]); /* create a communication pipe */
    You just made another prototype for pipe.
    You didn't declare an array called filedes, and you didn't call pipe either.

    int filedes[2];
    pipe(filedes);

    > printf(tab);
    All someone has to do is type in a % character, and you've lost.
    Never pass user input as the format string for printf.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Quote Originally Posted by Salem View Post
    You mean these errors?
    Code:
    $ gcc -Wall -Wextra foo.c
    foo.c: In function ‘main’:
    foo.c:23:11: error: ‘filedes’ undeclared (first use in this function)
           dup(filedes[0]); /* duplicate the new input file desired*/
               ^
    foo.c:23:11: note: each undeclared identifier is reported only once for each function it appears in
    foo.c:29:16: warning: format not a string literal and no format arguments [-Wformat-security]
             printf(tab); /* print the message */
                    ^
    foo.c:43:16: warning: format not a string literal and no format arguments [-Wformat-security]
             printf(tab); /* writing in the new output file (communication pipe input) */
                    ^
    foo.c:10:23: warning: variable ‘s’ set but not used [-Wunused-but-set-variable]
       char tab[TABSIZE], *s;
    Let's start with this.
    > int pipe(int filedes[2]); /* create a communication pipe */
    You just made another prototype for pipe.
    You didn't declare an array called filedes, and you didn't call pipe either.

    int filedes[2];
    pipe(filedes);

    > printf(tab);
    All someone has to do is type in a % character, and you've lost.
    Never pass user input as the format string for printf.
    First, thank you for your remarks.
    I declared the communication pipe properly now, and I used printf correctly.
    Here is the new program:
    Code:
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
     
    #define TABSIZE 512
     
    int main(){
      int pid;
      int filedes[2];
      pipe(filedes); /* create a communication pipe */
      char tab[TABSIZE];
     
      pid = fork(); /* create son process */
       
      switch(pid){
       
        case -1:
          break;
     
        case 0: /* son process */
           
          /* REDIRECTION */
          close(STDIN_FILENO); /* close standard input file */
          dup(filedes[0]); /* duplicate the new input file desired*/
          close(filedes[0]); /* the communication pipe is now the standard input file */
           
          /* listening in the the pipe and printing the received message in the terminal*/
          for (;;) {
            fgets(tab, TABSIZE, stdin); /* getting the text contained in the input file (that corresponds to the pipe) and putting it in the tab */
            printf("%s", tab); /* print the message */
          }
     
        default: /* father process */
           
          /* REDIRECTION */
          close(STDOUT_FILENO);
          dup(filedes[1]); 
          close(filedes[1]);
     
          /* listening in the the pipe and printing the received message in the new output file (which is the communication pipe) */
          for (;;) {
            fgets(tab, TABSIZE, stdin); /* getting the text written in the terminal and putting it in a tab */
            printf("%s", tab); /* writing in the new output file (communication pipe input) */
          }
      }  
      exit(EXIT_SUCCESS);
    }
    I also deleted the prompt displaying in the father's code because I think that doesn't have sense since the output file of the father is no longer the screen.
    the program runs now with errors now. But it doesn't work as expected, the son does not printf the messages he receives from the father on the screen (if he receives something of course)
    Last edited by Ramsis94; 04-25-2020 at 01:31 PM. Reason: added something

  4. #4
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Hello guys ! I still need help here please

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    An example.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <sys/select.h>
    
    const int ReadEnd = 0, WriteEnd = 1;
    
    void die(const char *msg) {
      fprintf(stderr,"Grrr:%s:%d:%s\n",strerror(errno),errno,msg);
      exit(1);
    }
    
    void childScreenWriter(int readfd) {
      fprintf(stderr,"childScreenWriter enter\n");
      char buff[BUFSIZ] = { 0 };
      FILE *fp = fdopen(readfd,"r");
      setvbuf(fp,NULL,_IOLBF,0); // make it line buffered, pipe ends start fully buffered
      while ( fgets(buff,BUFSIZ,fp) ) {
        printf("C:%s",buff); // tag as being received by child
      }
      fprintf(stderr,"childScreenWriter exiting\n");
      fclose(fp);  // also closes associated descriptor
    }
    
    void parentInputReader(int writefd) {
      fprintf(stderr,"parentInputReader enter\n");
      char buff[BUFSIZ];
      FILE *fp = fdopen(writefd,"w");
      setvbuf(fp,NULL,_IOLBF,0); // make it line buffered, pipe ends start fully buffered
      while ( fgets(buff,BUFSIZ,stdin) ) {
        fprintf(fp,"P:%s",buff); // tag as being sent from parent to child
      }
      fprintf(stderr,"parentInputReader exiting\n");
      fclose(fp);  // also closes associated descriptor
    }
    
    #define CHECK(op,expected,msg) \
      if ( op != expected ) die(msg)
    
    int main ()
    {
      int parent2child[2];
      CHECK(pipe(parent2child),0,"pipe1");
      pid_t p = fork();
      if ( p == 0 ) {
        printf("Child=%d\n",getpid());
        CHECK(close(parent2child[WriteEnd]),0,"close1");
        childScreenWriter(parent2child[ReadEnd]);
      } else {
        printf("Parent=%d\n",getpid());
        CHECK(close(parent2child[ReadEnd]),0,"close3");
        parentInputReader(parent2child[WriteEnd]);
    
        int status;
        fprintf(stderr,"Waiting...\n");
        CHECK(waitpid(p,&status,0),p,"wait");
        fprintf(stderr,"Exit status=%d\n",status);
      }
      return 0;
    }
    
    $ ./a.out 
    Parent=5186
    parentInputReader enter
    Child=5187
    childScreenWriter enter
    hello
    C:P:hello
    world
    C:P:world
    bye
    C:P:bye
    parentInputReader exiting
    Waiting...
    childScreenWriter exiting
    Exit status=0
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Here's an example that redirects the standard streams like you were trying to do.
    Note that you can use stderr to print the parent's prompt since stderr is still going to the terminal.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
     
    #define TABSIZE 512
    enum {INPUT_END, OUTPUT_END};
     
    int main() {
        char tab[TABSIZE];
     
        int fd[2];
        if (pipe(fd) == -1) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
     
        pid_t pid = fork();
     
        switch (pid) {
        case -1:
            perror("fork");
            exit(EXIT_FAILURE);
            break;
     
        case 0: // child
            dup2(fd[INPUT_END], STDIN_FILENO);
            close(fd[INPUT_END]);
            close(fd[OUTPUT_END]);
     
            while (fgets(tab, TABSIZE, stdin))
                printf("child: %s", tab);
     
            close(STDIN_FILENO);
            break;
     
        default: // parent
            dup2(fd[OUTPUT_END], STDOUT_FILENO);
            close(fd[INPUT_END]);
            close(fd[OUTPUT_END]);
     
            while (fputs(">>> ", stderr), fgets(tab, TABSIZE, stdin)) {
                printf("%s", tab);
                fflush(stdout);
            }
            fputs("\n", stderr);
     
            close(STDOUT_FILENO);
            wait(NULL);
        }
     
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    thank you

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pipe multiple programs using pipe() and c
    By HaitiBoy in forum C Programming
    Replies: 1
    Last Post: 12-07-2010, 05:19 PM
  2. pipe
    By vapanchamukhi in forum C Programming
    Replies: 2
    Last Post: 09-23-2008, 01:35 AM
  3. Pipe problem, popen(), pipe().
    By apacz in forum C Programming
    Replies: 7
    Last Post: 06-08-2006, 12:55 AM
  4. pipe()
    By bojan in forum C Programming
    Replies: 2
    Last Post: 04-13-2006, 07:47 AM
  5. How to Pipe?
    By crazykilla726 in forum C++ Programming
    Replies: 4
    Last Post: 02-09-2006, 07:49 AM

Tags for this Thread