/***************************************
**  SRead  Secure Read from a stream (stdin)
**  directly in a char array.
**
** Copyright 2005 Stefano Di Paola
** stefano.dipaola@wisec.it
**
** Released under GPL 2.0
**  
** Compile with 
**  gcc -o saferead saferead.c 
** 
****************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


/** Maximum number of chars to read every epoch */
#define MAX_CHAR_IN 4096

static size_t getsafe(char *buffer, int count,FILE *fh) {  
     int bytes=0;
fflush(fh);
     if ((buffer == NULL) || (count < 1))
	bytes = 0;
     else if (count == 1)
	*buffer = '\0';
     else if ((bytes = fread(buffer,sizeof(char), count, fh)) < 0)
	return -1;

     buffer[bytes]='\0';

     return bytes;
}

char *getfile_byhandler(FILE *fh, int maxsize) {
    char *in ;
    int bytes=1;
    int i=0;

    in=(char *)malloc(MAX_CHAR_IN*sizeof(char));
    if (in==NULL)
 	  return NULL;

    while (!feof(fh)) {
	  i++;
          
	 // Going to read a file block of MAX_CHAR_IN bytes	
	 if((bytes = getsafe(in+(MAX_CHAR_IN*(i-1)),MAX_CHAR_IN,fh)) == MAX_CHAR_IN) {
                if((MAX_CHAR_IN*sizeof(char)*i) >= (maxsize-1))
                  return in;
             
             // realloc 'in' array to fit next read
	      if((in = (char *)realloc(in, MAX_CHAR_IN*(i+1)*sizeof(char))) == NULL)
	         return NULL;
		 
              // zeroing the new alloc'ed  space (realloc doesn't do it)
	       bzero(in+(MAX_CHAR_IN*sizeof(char)*(i)), MAX_CHAR_IN); 
	}else if(bytes<0) {
	    // a problem occurred
               free(in);
               return NULL;
	}
    }
    fprintf(stderr,"read %d bytes\n",(i-1)*MAX_CHAR_IN+bytes);
    return in;
}

/* This will work if file is a textfile.
   For binary file you have to write( stdout)
*/
int main(int argc, char **argv) {
    char *in;
    int maxsize =  1024*1024;  // 1M
    
    FILE *fh=fopen(argv[1],"r");
    
    in = getfile_byhandler(fh, maxsize);
    if(in==NULL)
    {
     perror("Error in reading file:");
     fclose(fh);
     
    }
    printf("%s", in);
    
    fclose(fh);
    return 1;
}
