#include	<stdio.h>
#include	<malloc.h>
#include	<string.h>
#include	<errno.h>
#include	<dlfcn.h>

#define	MEMTBLSIZE	10000
#define	LOGFILENAME	"/tmp/malloc.log"

typedef struct malloc_s {
	void	*ptr;
	size_t	len;
	short	inUse;
} malloc_t, *malloc_p;

malloc_t	poolTbl[MEMTBLSIZE];
void	*mark = NULL;
FILE	*logFilePtr = NULL;
int	poolIndex = NULL;

void
setMark( void *ptr ) {
	mark = ptr;
}

int
myinit() {
	int	i;

	if( ( logFilePtr = fopen( LOGFILENAME, "w" ) ) == NULL ) {
		fprintf( stderr, "myinit: fopen(%s): %s\n", LOGFILENAME,
		  strerror( errno ) );
		abort();
	}
	setbuf( logFilePtr, NULL );
	for( i = 0; i < MEMTBLSIZE; i++ ) {
		poolTbl[i].ptr = NULL;
		poolTbl[i].len = 0;
		poolTbl[i].inUse = 0;
	}
}

void *
malloc( size_t size ) {
	void	*(*functionPtr)( size_t );
	void	*returned;
	int	index;
	int	i;

	if( logFilePtr == NULL )
		myinit();

	functionPtr = ( void *(*)( size_t ) ) dlsym( RTLD_NEXT, "malloc" );
	returned = (*functionPtr)( size );
	if( returned == NULL )
		return( returned );

	index = -1;
	for( i = 0; i < MEMTBLSIZE; i++ ) {
		if( ( index < 0 ) && ( poolTbl[i].inUse == 0 ) )
			index = i;
		if( poolTbl[i].inUse == 0 )
			continue;
		if( returned == poolTbl[i].ptr ) {
			fprintf( stderr, "mymalloc: dup: 0x%08x\n", returned );
			abort();
		}
	}
	if( index < 0 ) {
		fprintf( stderr, "mymalloc: table full\n" );
		abort();
	}
	poolTbl[index].ptr = returned;
	poolTbl[index].len = size;
	poolTbl[index].inUse++;
	fprintf( logFilePtr, "malloc: 0x%08x\n", returned );

	return( returned );
}

void *
calloc( size_t count, size_t size ) {
	void	*(*functionPtr)( size_t, size_t );
	void	*returned;
	int	index;
	int	i;

	if( logFilePtr == NULL )
		myinit();

	functionPtr = ( void *(*)( size_t, size_t ) ) dlsym( RTLD_NEXT, "calloc" );
	returned = (*functionPtr)( count, size );
	if( returned == NULL )
		return( returned );

	fprintf( logFilePtr, "calloc: 0x%08x\n", returned );
	return( returned );
}

void *
realloc( void *ptr, size_t size ) {
	void	*(*functionPtr)( void *, size_t );
	void	*returned;
	int	index;
	int	i;

	if( logFilePtr == NULL )
		myinit();

	functionPtr = ( void *(*)( void *, size_t ) ) dlsym( RTLD_NEXT, "realloc" );
	returned = (*functionPtr)( ptr, size );
	if( returned == NULL )
		return( returned );

	index = -1;
	for( i = 0; i < MEMTBLSIZE; i++ ) {
		if( poolTbl[i].ptr == ptr )
			index = i;
		if( poolTbl[i].inUse == 0 )
			continue;
	}
	if( index < 0 ) {
		fprintf( stderr, "myrealloc: not found: 0x%08x\n", ptr );
		abort();
	}
	poolTbl[index].ptr = returned;
	poolTbl[index].len = size;
	poolTbl[index].inUse++;
	fprintf( logFilePtr, "realloc: 0x%08x\n", returned );

	return( returned );
}

void
free( void *ptr ) {
	void	(*functionPtr)( void * );
	int	index;
	int	i;

	if( logFilePtr == NULL )
		myinit();

	if( ptr == mark ) {
		fprintf( stderr, "trying to free marked block\n" );
		abort();
	}

	index = -1;
	for( i = 0; i < MEMTBLSIZE; i++ ) {
		if( poolTbl[i].ptr == ptr )
			index = i;
	}
	if( index < 0 ) {
		fprintf( stderr, "myfree: not found: 0x%08x\n", ptr );
		abort();
	}
	poolTbl[index].ptr = NULL;
	poolTbl[index].len = 0;
	poolTbl[index].inUse = 0;

	fprintf( logFilePtr, "free: 0x%08x\n", ptr );
	functionPtr = ( void (*)( void * ) ) dlsym( RTLD_NEXT, "free" );
	(*functionPtr)( ptr );
}