1

There is a shell script

#!/bin/bash

while :
do
    echo "++stdout..";
    echo "++stderr.." >> /dev/stderr;
    sleep 1
done

and c prog

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
 
 
int main(int argc, char *argv[])
{
  pid_t pid; 
 
  int pipefd[2];
  int pipe_stderr[2];
 
  char parametr[32]; 
 
 
   if(argc != 2)
   {
        fprintf(stderr,"Niepoprawna liczba argumetnow procesu P \n");
        exit(EXIT_FAILURE);
   }
 
  /* pipe  
      pipe0 - write
      pipe1 - read
  */
  if(pipe(pipefd) == -1)
   {
    perror("pipe");
    exit(EXIT_FAILURE);
   }
 
  if(pipe(pipe_stderr) == -1)
   {
    perror("pipe");
    exit(EXIT_FAILURE);
   }
 
  sprintf(parametr,"%d",pipefd[0]); //convert - we want to use exec 
 
   pid = fork() ;
   if(pid < 0)
   {
    perror("fork!"); 
   }  
   else if(pid == 0)
   {
        puts("child");
        dup2(pipefd[1],STDOUT_FILENO); // write
        dup2(pipe_stderr[1],STDERR_FILENO); // write
        
        close(pipefd[0]);
        close(pipe_stderr[0]);
        execv(argv[1],&argv[1]); 
   }
   else{
        puts("parent");
        fd_set set;
        struct timeval timeout;
        int sel; 
        char buf;   

        close(pipefd[1]) ;  
        close(pipe_stderr[1]) ;  


        fcntl(pipefd[0],F_SETFL,O_NONBLOCK);
        fcntl(pipe_stderr[0],F_SETFL,O_NONBLOCK);

        FD_ZERO(&set); 
        FD_SET(pipefd[0], &set); // READ
        FD_SET(pipe_stderr[0], &set); // READ


        timeout.tv_sec = 17; 
        timeout.tv_usec = 0; 

        while(1){
            puts("Select");  
            sel = select(FD_SETSIZE,&set,NULL,NULL,&timeout);
            if(sel < 0 )
            {
                perror("Select");  
            }
            else if(sel == 0)
            {
                printf("No communicate \n");
            }
            else{
                if(FD_ISSET(pipefd[0], &set)){
                    puts("PARENT_READ_STDOUT:");
                    while(1){
                        ssize_t ret = read(pipefd[0], &buf,1);
                        if(ret > 0){
                            write(STDOUT_FILENO, &buf,1);  
                        }else{
                            break;
                        }
                    }
                }

                if(FD_ISSET(pipe_stderr[0], &set)){
                    puts("PARENT_READ_STDERR:");
                    while(1){
                        ssize_t ret = read(pipe_stderr[0], &buf,1);
                        if(ret > 0){
                            write(STDERR_FILENO, &buf,1);  
                        }else{
                            break;
                        }
                    }
                }
            }
        }
   } 
}

the output of

./main ./test.sh

is

parent
Select
child
PARENT_READ_STDOUT:
++stdout..
Select
PARENT_READ_STDOUT:
++stdout..
Select
PARENT_READ_STDOUT:
++stdout..
Select
PARENT_READ_STDOUT:
++stdout..
Select
PARENT_READ_STDOUT:
++stdout..
Select
PARENT_READ_STDOUT:
++stdout..
Select

where did the stderr output go??

Thomas
  • 174,939
  • 50
  • 355
  • 478

1 Answers1

0
    timeout.tv_sec = 17; 
    timeout.tv_usec = 0; 

    while(1){

    FD_ZERO(&set); 
    FD_SET(pipefd[0], &set); // READ
    FD_SET(pipe_stderr[0], &set); // READ
  • Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Zaboj Campula Feb 16 '21 at 13:19