/* mem.c -- handles: memory allocation and deallocation keeping track of what memory is being used by whom dprintf'ized, 15nov95 */ /* This file is part of the eggdrop source code copyright (c) 1997 Robey Pointer and is distributed according to the GNU general public license. For full details, read the top of 'main.c' or the file called COPYING that was distributed with this code. */ #define LOG_MISC 32 #define MEMTBLSIZE 25000 /* yikes! */ #ifdef EBUG_MEM #define DEBUG #endif #if HAVE_CONFIG_H #include #endif #include #include #include #ifdef MODULES #include "mod/modvals.h" typedef struct _module_entry { char * name; /* name of the module (without .so) */ int major; /* major version number MUST match */ int minor; /* minor version number MUST be >= */ void * hand; /* module handle */ void * needed; void * needing; struct _module_entry * next; #ifdef EBUG_MEM int mem_work; #endif module_function * funcs; } module_entry; extern module_entry * module_list; #endif extern int serv; #ifdef DEBUG unsigned long memused=0; static int lastused=0; struct { void *ptr; short size; char file[15]; short line; } memtbl[MEMTBLSIZE]; #endif #ifdef STDC_HEADERS #define PROTO(x) x #define PROTO1(a,b) (a b) #define PROTO2(a1,b1,a2,b2) (a1 b1, a2 b2) #define PROTO3(a1,b1,a2,b2,a3,b3) (a1 b1, a2 b2, a3 b3) #define PROTO4(a1,b1,a2,b2,a3,b3,a4,b4) \ (a1 b1, a2 b2, a3 b3, a4 b4) #define PROTO5(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5) \ (a1 b1, a2 b2, a3 b3, a4 b4, a5 b5) #define PROTO6(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6) \ (a1 b1, a2 b2, a3 b3, a4 b4, a5 b5, a6 b6) #else #define PROTO(x) () #define PROTO1(a,b) (b) a b; #define PROTO2(a1,b1,a2,b2) (b1, b2) a1 b1; a2 b2; #define PROTO3(a1,b1,a2,b2,a3,b3) (b1, b2, b3) a1 b1; a2 b2; a3 b3; #define PROTO4(a1,b1,a2,b2,a3,b3,a4,b4) (b1, b2, b3, b4) \ a1 b1; a2 b2; a3 b3; a4 b4; #define PROTO5(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5) \ (b1, b2, b3, b4, b5) \ a1 b1; a2 b2; a3 b3; a4 b4; a5 b5; #define PROTO6(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6) \ (b1, b2, b3, b4, b5, b6) \ a1 b1; a2 b2; a3 b3; a4 b4; a5 b5; a6 b6; #endif #ifdef HAVE_DPRINTF #define dprintf dprintf_eggdrop #endif /* prototypes */ void mprintf(); void tprintf(); void dprintf(); void putlog(); int expected_memory(); int expmem_chan(); int expmem_chanprog(); int expmem_misc(); int expmem_fileq(); int expmem_users(); int expmem_dccutil(); int expmem_botnet(); int expmem_tcl(); int expmem_tclhash(); int expmem_net(); int expmem_blowfish(); int expmem_modules(); int expmem_assoc(); void tell_netdebug(); void debug_blowfish(); void do_module_report(); /* initialize the memory structure */ void init_mem() { #ifdef DEBUG int i; for (i=0; inext) me->mem_work = 0; #endif for (i=0; inext) if (strcmp(fn,me->name)==0) me->mem_work +=l; *p = ':'; } #endif else { if (idx<0) tprintf(-idx,"Not logging file %s!\n",fn); else dprintf(idx,"Not logging file %s!\n",fn); } } for (i=0; i60) { sofar[strlen(sofar)-1]=0; if (idx<0) tprintf(-idx,"%s\n",sofar); else dprintf(idx,"%s\n",sofar); strcpy(sofar," "); } } if (sofar[0]) { sofar[strlen(sofar)-1]=0; if (idx<0) tprintf(-idx,"%s\n",sofar); else dprintf(idx,"%s\n",sofar); } } } #ifdef MODULES for (me=module_list;me;me=me->next) { module_function * f = me->funcs; int expt = 0; if ((f != NULL) && (f[MODCALL_EXPMEM] != NULL)) expt = f[MODCALL_EXPMEM](); if (me->mem_work==expt) { dprintf(idx,"Module '%-10s' accounted for %lu/%lu (ok)\n",me->name, expt,me->mem_work); } else { dprintf(idx,"Module '%-10s' accounted for %lu/%lu (debug follows:)\n", me->name,expt,me->mem_work); strcpy(sofar," "); for (j=0; jname)==0) { sprintf(&sofar[strlen(sofar)],"%-10s/%-3d:(%03X) ", p+1, memtbl[j].line, memtbl[j].size); if (strlen(sofar)>60) { sofar[strlen(sofar)-1]=0; dprintf(idx,"%s\n",sofar); strcpy(sofar," "); } *p = ':'; } } } if (sofar[0]) { sofar[strlen(sofar)-1]=0; dprintf(idx,"%s\n",sofar); } } } #endif if (idx<0) tprintf(-idx,"--- End of debug memory list.\n"); else dprintf(idx,"--- End of debug memory list.\n"); #else if (idx<0) tprintf(-idx,"Compiled without debug info.\n"); else dprintf(idx,"Compiled without extensive memory debugging (sorry).\n"); #endif tell_netdebug(idx); #ifdef MODULES do_module_report(idx); #else debug_blowfish(idx); #endif } void *n_malloc PROTO3(int,size,char *,file,int,line) { void *x; int i=0; x=(void *)malloc(size); if (x==NULL) { i=i; putlog(LOG_MISC,"*","*** FAILED MALLOC %s (%d)",file,line); return NULL; } #ifdef DEBUG if (lastused==MEMTBLSIZE) { putlog(LOG_MISC,"*","*** MEMORY TABLE FULL: %s (%d)",file,line); return x; } i=lastused; memtbl[i].ptr=x; memtbl[i].line=line; memtbl[i].size=size; strcpy(memtbl[i].file,file); memused+=size; lastused++; #endif return x; } void *n_realloc PROTO4(void *,ptr,int,size,char *,file,int,line) { void *x; int i=0; x=(void *)realloc(ptr,size); if (x==NULL) { i=i; putlog(LOG_MISC,"*","*** FAILED REALLOC %s (%d)",file,line); return NULL; } #ifdef DEBUG for (i=0; (i