/*
**
** Copyright (C) 1994 Swedish University Network (SUNET)
**
**
** This program is developed by UDAC, Uppsala University by commission
** of the Swedish University Network (SUNET). 
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITTNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**
**                                        Martin.Wendel@udac.uu.se
**                                        Torbjorn.Wictorin@udac.uu.se
**
**                                        UDAC	
**                                        P.O. Box 174
**                                        S-751 04 Uppsala
**                                        Sweden
**
*/


#include	<signal.h>
#include	<stdlib.h>
#include 	"emil.h"

#define	MAXSZ	16*1024	/* Maximum amount to allocate */
#define	MULTF	2		/* Increase factor */

#ifdef	SIGDANGER
extern	int	psdanger(int);
#endif

long     memall = 0;
extern	int	in_fd;

static	void * Zalloc(void * old, off_t prevsize, off_t newsize)
{
	/* Allocate memory */


        void	* Z;
	memall = memall + newsize - prevsize;

#ifdef DEBUG

   alloc_total += newsize - prevsize;
	if (edebug)
	  {
	    fprintf(stderr, "* Allocated %lu, new total: %lu\n", newsize - prevsize, alloc_total);
	    fflush(stderr);
	  }

#endif
	if (old == NULL)
	  {
		assert (prevsize == 0);
		Z 	= malloc((size_t)newsize);
	  }
	else {
		assert (prevsize != 0);

		assert (prevsize < newsize);
		Z	= realloc(old,(size_t)newsize);
	}

	if (Z == NULL) {
		logger(LOG_ERR,"load_data cannot allocate memory");
		closelog();
		fprintf(stderr, "Emil: load_data: cannot allocate memory (using %lu bytes)\n", memall);
		fflush(stderr);
		exit(EX_OSERR);
	}
	memset(((char *) Z) + prevsize, 0, newsize - prevsize);
	return	Z;
}

struct data *
load_data()
{
	struct data *out;
	long chunk;
#ifdef	SIGDANGER
	long border;
#endif
	char	* tmp;
	int	l;
	int     left;

#ifdef DEBUG
	if (edebug)
	  fprintf(stderr, "* Load data\n");
#endif

	/* Allocate an output struct */

	out	= (struct data *) Yalloc(sizeof(struct data));

	/* And an initial output buffer */

	chunk		= pz;
	left            = chunk;
	out->contents	= (char *) Zalloc(NULL,0,chunk);
	out->size	= chunk;

	/* Read all on standard input and reallocate buffer if required */

	while ((l=read(in_fd, (out->contents + out->end), chunk - 1)) > 0) {
		out->end	+= l;
		left            -= l;
		if (left < chunk)
		  {
		    chunk		*= MULTF;
		    if (chunk > MAXSZ) chunk = MAXSZ;
#ifdef	SIGDANGER
		    border = (psdanger(SIGDANGER) * pz) / 2; 
		    if (chunk > border)	chunk = border;
#endif
#ifdef DEBUG
		    if (edebug)
		      fprintf(stderr, "read %d characters\n", l);
		    if (edebug)
		      fprintf(stderr,"load_data: realloc %lud to %lud\n",
			      out->size,chunk + out->size);
#endif
		    out->contents	=  
		      (char *)Zalloc(out->contents,out->size,out->size+chunk);
		    out->size	+= chunk;
		    left        += chunk;
		  }
	      }

	out->contents[out->end] = 0;

	/* Count number of lines */

	for (	tmp = out->contents, out->lend = 0;
		(tmp= index(tmp,'\n')) != NULL;
		tmp++)	out->lend++;

	return(out);
}

int
append_data(struct data *d, char *c, int len, int busize)
{
  if (d->size == 0)
    {
      if ((d->contents = Zalloc(NULL, 0, busize)) == NULL)
	return(NOK);
      d->size = busize;
    }
  while ((len + d->end + 2) > d->size)	/* TW 941220 */
    {
      if ((d->contents = Zalloc(d->contents,d->size,d->size+busize)) == NULL)
	return(NOK);
      d->size += busize;
    }
  /* bcopy(c, (d->contents + d->end), len); */
  memcpy((d->contents + d->end), c, (off_t) len);
  
  d->end += len;
  d->bodyend += len;
  *(d->contents + d->end) = '\0';
  return(OK);
}

int
append_char(struct data *d, char c, int busize)
{


  if (d->size == 0)
    {
      if ((d->contents = Zalloc(NULL, 0, busize)) == NULL)
	return(NOK);
      d->size = busize;
    }
  while ((3 + d->end) > d->size)
    {
      if ((d->contents = Zalloc(d->contents,d->size,d->size+busize)) == NULL)
	return(NOK);
      d->size += busize;
    }
  *(d->contents + d->end) = c;
  d->end += 1;
  d->bodyend += 1;
  *(d->contents + d->end) = '\0';
  return(OK);
}

