Gregorek
Gregorek

Reputation: 263

fopen() stream to popen() for progress bar/controll - but how to get stdout of popen()?

I'm trying to write simple c function which would give me possibility to see progress of data transfer from one stream to other stream and display it on my char LCD.

I manage to transfer the data and indicate the progress but how to get result of the piping?

So basically i want to do in c corresponds to shell command:

/home/image.img | md5sum > result

The problem i have i with the stdout. I would like to get it to a char * result.

In other words the md5sum returns a string on the screen like this "5193fd9ebfa30bcb914e7af4760deb15" but i would like to get it to my char * result for further usage in the function.

FILE *in_stream, *out_stream;
#define TRANSFER_BLOCK_SIZE 1048576 //one MB
int n=0;
int i=0;
long int input_size=0; 
unsigned char buffer[TRANSFER_BLOCK_SIZE];

if((out_stream=popen("md5sum","w"))==NULL)
   {
   perror(output_pipe_name);
   return 1;
   }
if((in_stream=fopen("/home/gregorek/image.img","r"))==NULL)
   {
   perror(input_file_name);
   return 1;    
   }
//check total size of the input file
fseek(in_stream,0,SEEK_END);
input_size=(ftell(in_stream)/TRANSFER_BLOCK_SIZE)+1;
fseek(in_stream,0,SEEK_SET);
//
do
    {
    i++;
    memset(buffer,'\0',TRANSFER_BLOCK_SIZE);
    n=fread(buffer,sizeof(unsigned char),TRANSFER_BLOCK_SIZE,in_stream);
    lcd_display(i); //this is my progress indicator
    fwrite(buffer,sizeof(unsigned char),n,out_stream);
    }
while(!feof(in_stream));

fclose(in_stream);
pclose(out_stream);

return 0;
}

thanks

Upvotes: 0

Views: 1155

Answers (2)

Gregorek
Gregorek

Reputation: 263

Thanks Henrik, Here is the code for all of you who wonder how to do it:

int     fd_pipe[2], nbytes, status;
char    pipe_buffer[1000];
memset(pipe_buffer,'\0',1000);

        if(pipe(fd_pipe)!=0)
            {
            perror("fd_pipe:");
            exit(EXIT_FAILURE);
            }
        pid = fork();
        if (pid == -1) 
            {
            perror("Fork failed");
            exit(EXIT_FAILURE);
            }
        else
            {
            if(pid>0) //The parent's part
                {
                // Parent process closes output side of the pipe 
                close(fd_pipe[1]);
                //Parent wait's untill the child is done
                wait(&status);
                // Read in a string from the pipe's input side 
                nbytes = read(fd_pipe[0], pipe_buffer, sizeof(pipe_buffer)); 

                printf("Received %d chars, string: %s \n", nbytes, pipe_buffer);
                                    //on the end close the other side of pipe                   
                                    close(fd_pipe[0]);
                }
            else
                {   // The child's part
                /* Child process closes input side of the pipe */
                close(fd_pipe[0]);
                //redirect the stdout(1) to the fd_pipe and then close the sdtout
                dup2(fd_pipe[1],1); 
                //Do the thing which creates the result message 
                system("/image/"IMAGE_NAME | md5sum");

                //on the end close the other side of pipe 
                close(fd_pipe[1]); 
                exit(0);
                }
            }

Upvotes: 1

Henrik
Henrik

Reputation: 4314

popen doesn't really give you what you want here, as it's a specialized library function. Use the system calls fork and pipe directly instead.

You use fork to create a child process and pipe to redirect stdout back to the parent process.

See this example for details.

This is incidentally exactly what the shell does when you command it to do this:

cat /home/image.img | md5sum > result

Upvotes: 2

Related Questions