00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define MEMTBLSIZE 25000
00028 #define COMPILING_MEM
00029
00030 #include "main.h"
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <errno.h>
00035
00036 #include "mod/modvals.h"
00037
00038
00039 extern module_entry *module_list;
00040
00041 #ifdef DEBUG_MEM
00042 unsigned long memused = 0;
00043 static int lastused = 0;
00044
00045 struct {
00046 void *ptr;
00047 int size;
00048 short line;
00049 char file[20];
00050 } memtbl[MEMTBLSIZE];
00051 #endif
00052
00053
00054 int expected_memory();
00055 int expmem_chanprog();
00056 int expmem_misc();
00057 int expmem_fileq();
00058 int expmem_users();
00059 int expmem_dccutil();
00060 int expmem_botnet();
00061 int expmem_tcl();
00062 int expmem_tclhash();
00063 int expmem_tclmisc();
00064 int expmem_net();
00065 int expmem_modules();
00066 int expmem_language();
00067 int expmem_tcldcc();
00068 int expmem_dns();
00069
00070
00071
00072
00073 void init_mem()
00074 {
00075 #ifdef DEBUG_MEM
00076 int i;
00077
00078 for (i = 0; i < MEMTBLSIZE; i++)
00079 memtbl[i].ptr = NULL;
00080 #endif
00081 }
00082
00083
00084
00085 void tell_mem_status(char *nick)
00086 {
00087 #ifdef DEBUG_MEM
00088 float per;
00089
00090 per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
00091 dprintf(DP_HELP, "NOTICE %s :Memory table usage: %d/%d (%.1f%% full)\n",
00092 nick, lastused, MEMTBLSIZE, per);
00093 #endif
00094 dprintf(DP_HELP, "NOTICE %s :Think I'm using about %dk.\n", nick,
00095 (int) (expected_memory() / 1024));
00096 }
00097
00098 void tell_mem_status_dcc(int idx)
00099 {
00100 #ifdef DEBUG_MEM
00101 int exp;
00102 float per;
00103
00104 exp = expected_memory();
00105 per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
00106 dprintf(idx, "Memory table: %d/%d (%.1f%% full)\n", lastused, MEMTBLSIZE,
00107 per);
00108 per = ((exp * 1.0) / (memused * 1.0)) * 100.0;
00109 if (per != 100.0)
00110 dprintf(idx, "Memory fault: only accounting for %d/%ld (%.1f%%)\n",
00111 exp, memused, per);
00112 dprintf(idx, "Memory table itself occupies an additional %dk static\n",
00113 (int) (sizeof(memtbl) / 1024));
00114 #endif
00115 }
00116
00117 void debug_mem_to_dcc(int idx)
00118 {
00119 #ifdef DEBUG_MEM
00120 # define MAX_MEM 13
00121 unsigned long exp[MAX_MEM], use[MAX_MEM], l;
00122 int i, j;
00123 char fn[20], sofar[81];
00124 module_entry *me;
00125 char *p;
00126
00127 exp[0] = expmem_language();
00128 exp[1] = expmem_chanprog();
00129 exp[2] = expmem_misc();
00130 exp[3] = expmem_users();
00131 exp[4] = expmem_net();
00132 exp[5] = expmem_dccutil();
00133 exp[6] = expmem_botnet();
00134 exp[7] = expmem_tcl();
00135 exp[8] = expmem_tclhash();
00136 exp[9] = expmem_tclmisc();
00137 exp[10] = expmem_modules(1);
00138 exp[11] = expmem_tcldcc();
00139 exp[12] = expmem_dns();
00140
00141 for (me = module_list; me; me = me->next)
00142 me->mem_work = 0;
00143
00144 for (i = 0; i < MAX_MEM; i++)
00145 use[i] = 0;
00146
00147 for (i = 0; i < lastused; i++) {
00148 strcpy(fn, memtbl[i].file);
00149 p = strchr(fn, ':');
00150 if (p)
00151 *p = 0;
00152 l = memtbl[i].size;
00153 if (!strcmp(fn, "language.c"))
00154 use[0] += l;
00155 else if (!strcmp(fn, "chanprog.c"))
00156 use[1] += l;
00157 else if (!strcmp(fn, "misc.c"))
00158 use[2] += l;
00159 else if (!strcmp(fn, "userrec.c"))
00160 use[3] += l;
00161 else if (!strcmp(fn, "net.c"))
00162 use[4] += l;
00163 else if (!strcmp(fn, "dccutil.c"))
00164 use[5] += l;
00165 else if (!strcmp(fn, "botnet.c"))
00166 use[6] += l;
00167 else if (!strcmp(fn, "tcl.c"))
00168 use[7] += l;
00169 else if (!strcmp(fn, "tclhash.c"))
00170 use[8] += l;
00171 else if (!strcmp(fn, "tclmisc.c"))
00172 use[9] += l;
00173 else if (!strcmp(fn, "modules.c"))
00174 use[10] += l;
00175 else if (!strcmp(fn, "tcldcc.c"))
00176 use[11] += l;
00177 else if (!strcmp(fn, "dns.c"))
00178 use[12] += l;
00179 else if (p) {
00180 for (me = module_list; me; me = me->next)
00181 if (!strcmp(fn, me->name))
00182 me->mem_work += l;
00183 } else
00184 dprintf(idx, "Not logging file %s!\n", fn);
00185 }
00186
00187 for (i = 0; i < MAX_MEM; i++) {
00188 switch (i) {
00189 case 0:
00190 strcpy(fn, "language.c");
00191 break;
00192 case 1:
00193 strcpy(fn, "chanprog.c");
00194 break;
00195 case 2:
00196 strcpy(fn, "misc.c");
00197 break;
00198 case 3:
00199 strcpy(fn, "userrec.c");
00200 break;
00201 case 4:
00202 strcpy(fn, "net.c");
00203 break;
00204 case 5:
00205 strcpy(fn, "dccutil.c");
00206 break;
00207 case 6:
00208 strcpy(fn, "botnet.c");
00209 break;
00210 case 7:
00211 strcpy(fn, "tcl.c");
00212 break;
00213 case 8:
00214 strcpy(fn, "tclhash.c");
00215 break;
00216 case 9:
00217 strcpy(fn, "tclmisc.c");
00218 break;
00219 case 10:
00220 strcpy(fn, "modules.c");
00221 break;
00222 case 11:
00223 strcpy(fn, "tcldcc.c");
00224 break;
00225 case 12:
00226 strcpy(fn, "dns.c");
00227 break;
00228 }
00229
00230 if (use[i] == exp[i])
00231 dprintf(idx, "File '%-10s' accounted for %lu/%lu (ok)\n", fn, exp[i],
00232 use[i]);
00233 else {
00234 dprintf(idx, "File '%-10s' accounted for %lu/%lu (debug follows:)\n",
00235 fn, exp[i], use[i]);
00236 strcpy(sofar, " ");
00237 for (j = 0; j < lastused; j++) {
00238 if ((p = strchr(memtbl[j].file, ':')))
00239 *p = 0;
00240 if (!egg_strcasecmp(memtbl[j].file, fn)) {
00241 if (p)
00242 sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04d) ",
00243 p + 1, memtbl[j].line, memtbl[j].size);
00244 else
00245 sprintf(&sofar[strlen(sofar)], "%-4d:(%04d) ",
00246 memtbl[j].line, memtbl[j].size);
00247
00248 if (strlen(sofar) > 60) {
00249 sofar[strlen(sofar) - 1] = 0;
00250 dprintf(idx, "%s\n", sofar);
00251 strcpy(sofar, " ");
00252 }
00253 }
00254 if (p)
00255 *p = ':';
00256 }
00257 if (sofar[0]) {
00258 sofar[strlen(sofar) - 1] = 0;
00259 dprintf(idx, "%s\n", sofar);
00260 }
00261 }
00262 }
00263
00264 for (me = module_list; me; me = me->next) {
00265 Function *f = me->funcs;
00266 int expt = 0;
00267
00268 if ((f != NULL) && (f[MODCALL_EXPMEM] != NULL))
00269 expt = f[MODCALL_EXPMEM] ();
00270 if (me->mem_work == expt)
00271 dprintf(idx, "Module '%-10s' accounted for %lu/%lu (ok)\n", me->name,
00272 expt, me->mem_work);
00273 else {
00274 dprintf(idx, "Module '%-10s' accounted for %lu/%lu (debug follows:)\n",
00275 me->name, expt, me->mem_work);
00276 strcpy(sofar, " ");
00277 for (j = 0; j < lastused; j++) {
00278 strcpy(fn, memtbl[j].file);
00279 if ((p = strchr(fn, ':')) != NULL) {
00280 *p = 0;
00281 if (!egg_strcasecmp(fn, me->name)) {
00282 sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04X) ", p + 1,
00283 memtbl[j].line, memtbl[j].size);
00284 if (strlen(sofar) > 60) {
00285 sofar[strlen(sofar) - 1] = 0;
00286 dprintf(idx, "%s\n", sofar);
00287 strcpy(sofar, " ");
00288 }
00289 *p = ':';
00290 }
00291 }
00292 }
00293 if (sofar[0]) {
00294 sofar[strlen(sofar) - 1] = 0;
00295 dprintf(idx, "%s\n", sofar);
00296 }
00297 }
00298 }
00299
00300 dprintf(idx, "--- End of debug memory list.\n");
00301 #else
00302 dprintf(idx, "Compiled without extensive memory debugging (sorry).\n");
00303 #endif
00304 tell_netdebug(idx);
00305 }
00306
00307 #ifdef DEBUG_MEM
00308 static inline void addtomemtbl(void *x, int size, const char *file, int line)
00309 {
00310 int i = 0;
00311 char *p;
00312
00313 if (lastused == MEMTBLSIZE) {
00314 putlog(LOG_MISC, "*", "*** MEMORY TABLE FULL: %s (%d)", file, line);
00315 fatal("Memory table full", 0);
00316 }
00317 i = lastused;
00318 memtbl[i].ptr = x;
00319 memtbl[i].line = line;
00320 memtbl[i].size = size;
00321 p = strrchr(file, '/');
00322 strncpy(memtbl[i].file, p ? p + 1 : file, 19);
00323 memtbl[i].file[19] = 0;
00324 memused += size;
00325 lastused++;
00326 }
00327 #endif
00328
00329 char *n_strdup(const char *s, const char *file, int line)
00330 {
00331 char *x;
00332
00333 x = egg_strdup(s);
00334
00335 #if defined(DEBUG_MEM) && defined(HAVE_STRDUP)
00336 addtomemtbl(x, strlen(s)+1, file, line);
00337 #endif
00338 return x;
00339 }
00340
00341 void *n_malloc(int size, const char *file, int line)
00342 {
00343 void *x;
00344
00345 x = (void *) malloc(size);
00346 if (x == NULL) {
00347 putlog(LOG_MISC, "*", "*** FAILED MALLOC %s (%d) (%d): %s", file, line,
00348 size, strerror(errno));
00349 fatal("Memory allocation failed", 0);
00350 }
00351 #ifdef DEBUG_MEM
00352 addtomemtbl(x, size, file, line);
00353 #endif
00354 return x;
00355 }
00356
00357 void *n_realloc(void *ptr, int size, const char *file, int line)
00358 {
00359 void *x;
00360 int i = 0;
00361
00362 #ifdef DEBUG_MEM
00363 char *p;
00364 #endif
00365
00366
00367 if (!ptr)
00368 return n_malloc(size, file, line);
00369
00370 x = (void *) realloc(ptr, size);
00371 if (x == NULL && size > 0) {
00372 i = i;
00373 putlog(LOG_MISC, "*", "*** FAILED REALLOC %s (%d)", file, line);
00374 return NULL;
00375 }
00376 #ifdef DEBUG_MEM
00377 for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
00378 if (i == lastused) {
00379 putlog(LOG_MISC, "*", "*** ATTEMPTING TO REALLOC NON-MALLOC'D PTR: %s (%d)",
00380 file, line);
00381 return NULL;
00382 }
00383 memused -= memtbl[i].size;
00384 memtbl[i].ptr = x;
00385 memtbl[i].line = line;
00386 memtbl[i].size = size;
00387 p = strrchr(file, '/');
00388 strncpy(memtbl[i].file, p ? p + 1 : file, 19);
00389 memtbl[i].file[19] = 0;
00390 memused += size;
00391 #endif
00392 return x;
00393 }
00394
00395 void n_free(void *ptr, const char *file, int line)
00396 {
00397 int i = 0;
00398
00399 if (ptr == NULL) {
00400 putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NULL PTR: %s (%d)",
00401 file, line);
00402 i = i;
00403 return;
00404 }
00405 #ifdef DEBUG_MEM
00406
00407 if (line) {
00408 for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
00409 if (i == lastused) {
00410 putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NON-MALLOC'D PTR: %s (%d)",
00411 file, line);
00412 return;
00413 }
00414 memused -= memtbl[i].size;
00415 lastused--;
00416
00417 if (i != lastused) {
00418 memtbl[i].ptr = memtbl[lastused].ptr;
00419 memtbl[i].size = memtbl[lastused].size;
00420 memtbl[i].line = memtbl[lastused].line;
00421 strcpy(memtbl[i].file, memtbl[lastused].file);
00422 }
00423 }
00424 #endif
00425 free(ptr);
00426 }