Thread: sending CTRL-D to pipe

  1. #1
    Registered User
    Join Date
    Nov 2008
    Location
    Mt Umunum, CA
    Posts
    16

    sending CTRL-D to pipe

    Hi group,
    I have a simple test program that opens a pipe to a sh command. I want to be able to send a CTRL-D to the child. I have tried reading from the parent's keyboard and using a write but this does not product the correct results.

    Any suggestions?

    Thanks for your time.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    If by "send a Ctrl-D" you mean you want to close the pipe, just call close on the other end of the pipe. "Ctrl-D" is just an arbitrary way of telling the OS to send the eof signal to a process that is reading from the keyboard.

    Depending on your code, it's likely that the write end of the pipe (presumably your sh command) automatically closes and sends the eof signal back to the parent.

    Post your code if you want more detailed help.

  3. #3
    Registered User
    Join Date
    Nov 2008
    Location
    Mt Umunum, CA
    Posts
    16
    Quote Originally Posted by algorism View Post
    If by "send a Ctrl-D" you mean you want to close the pipe, just call close on the other end of the pipe. "Ctrl-D" is just an arbitrary way of telling the OS to send the eof signal to a process that is reading from the keyboard.

    Depending on your code, it's likely that the write end of the pipe (presumably your sh command) automatically closes and sends the eof signal back to the parent.

    Post your code if you want more detailed help.
    The problem is if the sh hangs waiting for more input. I need a way of sending EOF to the shell. right now, I am looking at termios and catching CTRL-D signal. Nether one has provided a solution. Here is the code:
    Code:
    #define _GNU_SOURCE
    #include <fcntl.h>  
    #include <stdlib.h>
    #include <ctype.h>
    #include <ncurses.h>
    #include <string.h>
    #include <linux/input.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <poll.h>
    #include <termios.h>
    #include <unistd.h>
    
    
    #define BS       7
    #define TAB      9
    #define ESC     27
    #define NEWLINE 10
    
    #define LEFT    4
    #define UP      3
    #define RIGHT   5
    #define DOWN    2
    
    #define INSERT  75
    
    #define HEADER  5
    
    #define streql( str1, str2 ) !strcmp( str1, str2 )
    
    #define OFF               "\x1B[0;0;0m"
    #define DEFAULT           "\x1B[0;0;0m"
    #define RED               "\x1B[1;31;40m"
    #define BLUE              "\x1B[1;34;40m"
    #define GREEN             "\x1B[1;32;40m"
    #define YELLOW            "\x1B[1;33;40m"
    #define PURPLE            "\x1B[1;35;40m"
    #define CLEAR_EOL         "\x1B[K"
    
       int   Fork = 0;
       FILE *Parent_Out;
       FILE *Parent_In;
       FILE *Child_Out;
       FILE *Child_In;
    
       FILE *Log;
    
       int Parent[2];
       int Child[ 2];
    
       int  X_Size, Y_Size, CMD_Line, PRT_Line, X, Y, RC, EOD;
    
       char Message[500];
    
       int  C;
       int  EOL;
       int  old    = 0;
       int  mode   = 3;
       int  Home   = 5;
       int  Index  = 0;
       int  Debug  = 0;
       int  Insert = 0;
       int  Length = 0;
       int  Cursor = 5;
    
       fd_set  FD_Table;
    
    int  Quit();
    
    void
    CTRL_Z( int Signal )  {
      kill( Fork, SIGTSTP );
      signal( SIGTSTP, CTRL_Z );  }
    
    void
    CTRL_C( int Signal )  {
      kill( Fork, SIGINT );
      signal( SIGINT,  CTRL_C );  }  
    
    
    void
    CTRL_D( int Signal )  {
      kill( Fork, SIGINT );
      signal( SIGINT,  CTRL_C );  }  
    
    
      
    int
    main( int argc, char *argv[] )  {  //  Main
    
       signal( SIGTSTP, CTRL_Z );
       signal( SIGINT,  CTRL_C );
       
       Log = fopen( "Log", "w" );
    
       int x, y, I;
       for( I = 0; I < argc; I++ )  {
         if( !strcmp( argv[I], "d" )) Debug = 1;  }
    
       unsigned char msg_buf[80];
       unsigned char net_buf[80];
       unsigned char cmd_buf[80];
    
       bzero (msg_buf, 80);
       bzero (net_buf, 80);
       bzero (cmd_buf, 80);
    
       char *Current;
    
       char  Buf[256];
    
       char  Con[256];
    
       int P, R, F, errno, Wheel = 0, Cnt;
       int Display;
    
       Current = cmd_buf;
    
       if( Fork == 0 )  {  // Create child process
    
          if( ( pipe2( Parent, O_CLOEXEC ) ) == -1 )  {
    	 perror( "Parent pipe failed" );
    	 exit(1);  }
          if( ( pipe2( Child,  O_CLOEXEC ) ) == -1 )  {
    	 perror( "Child pipe failed" );
    	 exit(1);  }
    
          if( ( Fork = fork() ) == -1 )  {
    	 perror("Fork failed");
    	 return 1;  }
    
          if( Fork == 0 )  {
    	 /* Child process closes up input side of pipe */
    
    	 dup2( Child[0], 0 );
    	 Child_In = fdopen( 0, "r" );
    	 close( Child[0] );
    
    	 dup2( Parent[1], 1 );
    	 dup2( Parent[1], 2 );
    	 
    	 Parent_In = fdopen( 1, "w" );
    	 close( Parent[1] );
    	 
    	 char  Fork[] = "sh";
    	 char *Argv[] = { "sh", "-", NULL };
    
    	 if(( Display = execvp( Fork, Argv )) != 0 ) {
    	    fputs( "Fork Command failed.\n", Log );
    	    return 1;  }
    	 fputs( "env\n", Child_In );
    	 while( 1 )  {
    	    RC = read( Child[0], Buf, 256 );
    	    fputs( Buf, Log );
    	    system( Buf );  }  }
    
          else  {
    	 /* Parent process closes up output side of pipe */
    	 Child_In  = fdopen( Child[1], "w" );
    	 Parent_In = fdopen( Parent[1], "w" );  } 
    
          struct termios new, old;
          tcgetattr( 0, &old );
    
          signal( SIGINT, CTRL_D );
    
          new = old;
       //   term.c_iflag |= IGNBRK;
       //   term.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF);
       //   term.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN);
       //   term.c_cc[VMIN] = 1;
          //   new.c_cc[VINTR] = 4;
       tcsetattr( fileno( stdin ), TCSANOW, &new );
       
       unsigned char Spiner[] = "/-\\|";
       struct timeval Timer;
       Timer.tv_sec  = 0;
       Timer.tv_usec = 250000;
    
       P = Parent[0];
    
       while( 1 )  {  // While
    
             Cnt = 0;
             R   = 1;
    
    	 while( R )  {  // While
    
    	    FD_ZERO(   &FD_Table );
    	    FD_SET( 0, &FD_Table );
    	    FD_SET( 4, &FD_Table );
    	    FD_SET( 6, &FD_Table );
    	    /*
    	    if( ++Cnt > 10 )  {
    	       R = 0;
    	       printf( RED "\nTimeout" OFF "\n" );
    	       fflush( NULL );
    	       break;  }
    	    */
    	    int Count = select( P +1, &FD_Table, NULL, NULL, NULL );
    
    	    if( Count < 0 )  {
    	       printf( "Select Error %s\n", strerror(errno) );
    	       return 0;  }
    	    /*
    	    for( I = 0; I < 8; I++ )  {
    	       if( FD_ISSET( I, &FD_Table ) )  {
    		 printf( PURPLE  "Is set: %d, Cnt: %d" OFF "\n", I, Cnt ); }  }
    	    */
    	    if( FD_ISSET( 0, &FD_Table ))  {
    		bzero( Con, 256 );
    		printf( PURPLE "Enter: " OFF ); fflush( stdout );
    		if( ( RC = read( 0, Con, 256 ) ) > 0 )  {
    		   printf( "%d ", RC );
    		   for( I = 0; I < RC; I++ )  {
    		      printf( "%02x", Con[I] );  }
    		   printf( "\n" );
    		   if( streql( Con, "q\n" ) )  Quit();
    		   write( Child[1], Con, RC );  }
    		// fflush( Child[1] );
    	       continue;  }
    	    
    	    if( FD_ISSET( 4, &FD_Table ))  {  //  ISSET
    
                   printf( BLUE "Child_Out:\n" );
    	       
    	       while(1)  {
    		  struct pollfd UFDS[1];
    		  UFDS[0].fd = 4;
    		  UFDS[0].events = POLLIN | POLLPRI;
    		  RC = poll( UFDS, 1, 1 );
    		  if( RC < 1 )  {
    		     R = 0;
    		     break;  }
    		  RC = read( 4, Buf, 256 );
    		  if( streql( Buf, "\n" ) )  {
    		     printf( "%s", Buf );
    		     break;  }
    		  if( RC < 0 ) {
    		     if( errno == EAGAIN ) break;
    		     perror( "Read failed" );
    		     break;  }
    		  if( RC == 0 ) break;
    		  else  {
    		     sprintf( Message, "RC: %d, Buf: '%s'\n", RC, Buf );
    		     fputs( Message, Log );
    		     printf( Buf );
    		     bzero( Buf, 256 );
    		     continue;  }  }
    		printf( OFF );
    		fflush( stdout );
    		break;  }
    	    /*
    	    if( Count == 0 )  {
    
    	       if( ++Wheel > 3 ) Wheel = 0;
    	       printf( CLEAR_EOL  "%c  %5.2f secs.\r", Spiner[ Wheel ],
    		       (float) Cnt*.25 );
    	       fflush( NULL );  }
    	    */
    	    }
    	 bzero( Current, 80 );  }
          }
    
    
       Quit();  }
    
    
    /* --------------------------------------------------------- */
    /*  Clean up after ourselves  */
    int Quit()  {
    
       printf( RED "Terminated" OFF "\n" );
       //   kill( Child, 9 );
       fclose( Log );
       exit(0);  }
    
    /* --------------------------------------------------------- */
    Thanks for your time.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    35,869
    - too many global variables
    - too many variables with meaningless names
    - too badly formatted
    - main is way too long (nearly 200 lines) for it's own good.

    Oh, and your local errno variable masks the global errno variable that all the system calls set, so even that is broken.
    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.

  5. #5
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    Your code is extremely difficult to understand (although I sense it's trying to do something fairly simple). I don't feel like spending the time to sort it out. If you told me what it's supposed to do I bet I could write a program to do it in far less time than it would take me to disentangle your code. That's not a good sign.

    EDIT: Writing a quick example of what I think you're trying to do gave me a little insight into what I think is your problem. Have you considered sending the command followed by the shell "exit" command so that the shell will exit. E.g., "ls\nexit\n".
    Last edited by algorism; 04-20-2017 at 11:50 AM.

  6. #6
    Registered User
    Join Date
    Nov 2008
    Location
    Mt Umunum, CA
    Posts
    16
    Quote Originally Posted by Salem View Post
    - too many global variables
    - too many variables with meaningless names
    - too badly formatted
    - main is way too long (nearly 200 lines) for it's own good.

    Oh, and your local errno variable masks the global errno variable that all the system calls set, so even that is broken.
    IT IS A TEST PROGRAM!!!!!!!! The only comment worth while is about errno! Thanks for that.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    35,869
    It's purpose is irrelevant if it's too long and unwieldy for you to debug effectively or for anyone else to invest time and effort in picking apart your program to find out what you did wrong.

    Separate the code out into smaller functions you can test.

    Nobody is going to look or care about your big ball of mud.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Detect Ctrl+anykey (e.g. Ctrl+A)
    By Tiago in forum C Programming
    Replies: 3
    Last Post: 10-29-2009, 09:46 AM
  2. Replies: 1
    Last Post: 03-19-2009, 02:15 AM
  3. Sending a byte down serial pipe
    By blackcell in forum C Programming
    Replies: 3
    Last Post: 05-16-2008, 02:20 AM
  4. Replacing (Ctrl-C) signal with (Ctrl-D)
    By Lord CyKill in forum Linux Programming
    Replies: 2
    Last Post: 10-31-2003, 01:47 AM
  5. How I can trap Ctrl+C and Ctrl+Break?
    By Visu A in forum C Programming
    Replies: 4
    Last Post: 03-03-2002, 07:06 AM

Tags for this Thread