mem.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * mem.c -- handles:
  3. * memory allocation and deallocation
  4. * keeping track of what memory is being used by whom
  5. *
  6. */
  7. #define MEMTBLSIZE 25000 /* yikes! */
  8. #define COMPILING_MEM
  9. #include "main.h"
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include "mod/modvals.h"
  15. #define STR(x) x
  16. extern module_entry *module_list;
  17. #ifdef DEBUG_MEM
  18. unsigned long memused = 0;
  19. static int lastused = 0;
  20. struct {
  21. void *ptr;
  22. int size;
  23. short line;
  24. char file[20];
  25. } memtbl[MEMTBLSIZE];
  26. #endif
  27. /* Prototypes */
  28. int expected_memory();
  29. int expmem_chanprog();
  30. int expmem_misc();
  31. int expmem_fileq();
  32. int expmem_users();
  33. int expmem_dccutil();
  34. int expmem_botnet();
  35. int expmem_tcl();
  36. int expmem_tclhash();
  37. int expmem_tclmisc();
  38. int expmem_net();
  39. int expmem_modules();
  40. int expmem_language()
  41. {
  42. return 0;
  43. }
  44. int expmem_tcldcc();
  45. int expmem_dns();
  46. /* Initialize the memory structure
  47. */
  48. void init_mem()
  49. {
  50. #ifdef DEBUG_MEM
  51. int i;
  52. for (i = 0; i < MEMTBLSIZE; i++)
  53. memtbl[i].ptr = NULL;
  54. #endif
  55. }
  56. /* Tell someone the gory memory details
  57. */
  58. void tell_mem_status(char *nick)
  59. {
  60. #ifdef DEBUG_MEM
  61. float per;
  62. per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
  63. dprintf(DP_HELP, "NOTICE %s :Memory table usage: %d/%d (%.1f%% full)\n",
  64. nick, lastused, MEMTBLSIZE, per);
  65. #endif
  66. dprintf(DP_HELP, "NOTICE %s :Think I'm using about %dk.\n", nick,
  67. (int) (expected_memory() / 1024));
  68. }
  69. void tell_mem_status_dcc(int idx)
  70. {
  71. #ifdef DEBUG_MEM
  72. int exp;
  73. float per;
  74. exp = expected_memory(); /* in main.c ? */
  75. per = ((lastused * 1.0) / (MEMTBLSIZE * 1.0)) * 100.0;
  76. dprintf(idx, STR("Memory table: %d/%d (%.1f%% full)\n"), lastused, MEMTBLSIZE,
  77. per);
  78. per = ((exp * 1.0) / (memused * 1.0)) * 100.0;
  79. if (per != 100.0)
  80. dprintf(idx, STR("Memory fault: only accounting for %d/%ld (%.1f%%)\n"),
  81. exp, memused, per);
  82. dprintf(idx, STR("Memory table itself occupies an additional %dk static\n"),
  83. (int) (sizeof(memtbl) / 1024));
  84. #endif
  85. }
  86. void debug_mem_to_dcc(int idx)
  87. {
  88. #ifdef DEBUG_MEM
  89. #define MAX_MEM 13
  90. unsigned long exp[MAX_MEM], use[MAX_MEM], l;
  91. int i, j;
  92. char fn[20], sofar[81];
  93. module_entry *me;
  94. char *p;
  95. exp[0] = expmem_language();
  96. exp[1] = expmem_chanprog();
  97. exp[2] = expmem_misc();
  98. exp[3] = expmem_users();
  99. exp[4] = expmem_net();
  100. exp[5] = expmem_dccutil();
  101. exp[6] = expmem_botnet();
  102. exp[7] = expmem_tcl();
  103. exp[8] = expmem_tclhash();
  104. exp[9] = expmem_tclmisc();
  105. exp[10] = expmem_modules(1);
  106. exp[11] = expmem_tcldcc();
  107. exp[12] = expmem_dns();
  108. for (me = module_list; me; me = me->next)
  109. me->mem_work = 0;
  110. for (i = 0; i < MAX_MEM; i++)
  111. use[i] = 0;
  112. for (i = 0; i < lastused; i++) {
  113. strcpy(fn, memtbl[i].file);
  114. p = strchr(fn, ':');
  115. if (p)
  116. *p = 0;
  117. l = memtbl[i].size;
  118. if (!strcmp(fn, "xlanguage.c"))
  119. use[0] += l;
  120. else if (!strcmp(fn, "xchanprog.c"))
  121. use[1] += l;
  122. else if (!strcmp(fn, "xmisc.c"))
  123. use[2] += l;
  124. else if (!strcmp(fn, "xuserrec.c"))
  125. use[3] += l;
  126. else if (!strcmp(fn, "xnet.c"))
  127. use[4] += l;
  128. else if (!strcmp(fn, "xdccutil.c"))
  129. use[5] += l;
  130. else if (!strcmp(fn, "xbotnet.c"))
  131. use[6] += l;
  132. else if (!strcmp(fn, "xtcl.c"))
  133. use[7] += l;
  134. else if (!strcmp(fn, "xtclhash.c"))
  135. use[8] += l;
  136. else if (!strcmp(fn, "xtclmisc.c"))
  137. use[9] += l;
  138. else if (!strcmp(fn, "xmodules.c"))
  139. use[10] += l;
  140. else if (!strcmp(fn, "xtcldcc.c"))
  141. use[11] += l;
  142. else if (!strcmp(fn, "xdns.c"))
  143. use[12] += l;
  144. else if (p) {
  145. for (me = module_list; me; me = me->next)
  146. if (!strcmp(fn, me->name))
  147. me->mem_work += l;
  148. } else
  149. dprintf(idx, STR("Not logging file %s!\n"), fn);
  150. }
  151. for (i = 0; i < MAX_MEM; i++) {
  152. switch (i) {
  153. case 0:
  154. strcpy(fn, "xlanguage.c");
  155. break;
  156. case 1:
  157. strcpy(fn, "xchanprog.c");
  158. break;
  159. case 2:
  160. strcpy(fn, "xmisc.c");
  161. break;
  162. case 3:
  163. strcpy(fn, "xuserrec.c");
  164. break;
  165. case 4:
  166. strcpy(fn, "xnet.c");
  167. break;
  168. case 5:
  169. strcpy(fn, "xdccutil.c");
  170. break;
  171. case 6:
  172. strcpy(fn, "xbotnet.c");
  173. break;
  174. case 7:
  175. strcpy(fn, "xtcl.c");
  176. break;
  177. case 8:
  178. strcpy(fn, "xtclhash.c");
  179. break;
  180. case 9:
  181. strcpy(fn, "xtclmisc.c");
  182. break;
  183. case 10:
  184. strcpy(fn, "xmodules.c");
  185. break;
  186. case 11:
  187. strcpy(fn, "xtcldcc.c");
  188. break;
  189. case 12:
  190. strcpy(fn, "xdns.c");
  191. break;
  192. }
  193. if (use[i] == exp[i]) {
  194. dprintf(idx, STR("File '%-10s' accounted for %lu/%lu (ok)\n"), fn, exp[i],
  195. use[i]);
  196. } else {
  197. dprintf(idx, STR("File '%-10s' accounted for %lu/%lu (debug follows:)\n"),
  198. fn, exp[i], use[i]);
  199. strcpy(sofar, " ");
  200. for (j = 0; j < lastused; j++) {
  201. if ((p = strchr(memtbl[j].file, ':')))
  202. *p = 0;
  203. if (!egg_strcasecmp(memtbl[j].file, fn)) {
  204. if (p)
  205. sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04d) ",
  206. p + 1, memtbl[j].line, memtbl[j].size);
  207. else
  208. sprintf(&sofar[strlen(sofar)], "%-4d:(%04d) ",
  209. memtbl[j].line, memtbl[j].size);
  210. if (strlen(sofar) > 60) {
  211. sofar[strlen(sofar) - 1] = 0;
  212. dprintf(idx, "%s\n", sofar);
  213. strcpy(sofar, " ");
  214. }
  215. }
  216. if (p)
  217. *p = ':';
  218. }
  219. if (sofar[0]) {
  220. sofar[strlen(sofar) - 1] = 0;
  221. dprintf(idx, "%s\n", sofar);
  222. }
  223. }
  224. }
  225. for (me = module_list; me; me = me->next) {
  226. Function *f = me->funcs;
  227. int expt = 0;
  228. if ((f != NULL) && (f[MODCALL_EXPMEM] != NULL))
  229. expt = f[MODCALL_EXPMEM] ();
  230. if (me->mem_work == expt) {
  231. dprintf(idx, STR("Module '%-10s' accounted for %lu/%lu (ok)\n"), me->name,
  232. expt, me->mem_work);
  233. } else {
  234. dprintf(idx, STR("Module '%-10s' accounted for %lu/%lu (debug follows:)\n"),
  235. me->name, expt, me->mem_work);
  236. strcpy(sofar, " ");
  237. for (j = 0; j < lastused; j++) {
  238. strcpy(fn, memtbl[j].file);
  239. if ((p = strchr(fn, ':')) != NULL) {
  240. *p = 0;
  241. if (!egg_strcasecmp(fn, me->name)) {
  242. sprintf(&sofar[strlen(sofar)], "%-10s/%-4d:(%04X) ", p + 1,
  243. memtbl[j].line, memtbl[j].size);
  244. if (strlen(sofar) > 60) {
  245. sofar[strlen(sofar) - 1] = 0;
  246. dprintf(idx, "%s\n", sofar);
  247. strcpy(sofar, " ");
  248. }
  249. *p = ':';
  250. }
  251. }
  252. }
  253. if (sofar[0]) {
  254. sofar[strlen(sofar) - 1] = 0;
  255. dprintf(idx, "%s\n", sofar);
  256. }
  257. }
  258. }
  259. dprintf(idx, STR("--- End of debug memory list.\n"));
  260. #else
  261. dprintf(idx, STR("Compiled without extensive memory debugging (sorry).\n"));
  262. #endif
  263. tell_netdebug(idx);
  264. }
  265. void *n_malloc(int size, const char *file, int line)
  266. {
  267. void *x;
  268. #ifdef DEBUG_MEM
  269. int i = 0;
  270. char *p;
  271. #endif
  272. x = (void *) malloc(size);
  273. if (x == NULL) {
  274. putlog(LOG_MISC, "*", "*** FAILED MALLOC %s (%d) (%d): %s", file, line,
  275. size, strerror(errno));
  276. fatal("Memory allocation failed", 0);
  277. }
  278. #ifdef DEBUG_MEM
  279. if (lastused == MEMTBLSIZE) {
  280. putlog(LOG_MISC, "*", "*** MEMORY TABLE FULL: %s (%d)", file, line);
  281. fatal("Memory table full", 0);
  282. }
  283. i = lastused;
  284. memtbl[i].ptr = x;
  285. memtbl[i].line = line;
  286. memtbl[i].size = size;
  287. p = strrchr(file, '/');
  288. strncpy(memtbl[i].file, p ? p + 1 : file, 19);
  289. memtbl[i].file[19] = 0;
  290. memused += size;
  291. lastused++;
  292. #endif
  293. return x;
  294. }
  295. void *n_realloc(void *ptr, int size, const char *file, int line)
  296. {
  297. void *x;
  298. int i = 0;
  299. #ifdef DEBUG_MEM
  300. char *p;
  301. #endif
  302. /* ptr == NULL is valid. Avoiding duplicate code further down */
  303. if (!ptr)
  304. return n_malloc(size, file, line);
  305. x = (void *) realloc(ptr, size);
  306. if (x == NULL && size > 0) {
  307. i = i;
  308. putlog(LOG_MISC, "*", "*** FAILED REALLOC %s (%d)", file, line);
  309. return NULL;
  310. }
  311. #ifdef DEBUG_MEM
  312. for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
  313. if (i == lastused) {
  314. putlog(LOG_MISC, "*", "*** ATTEMPTING TO REALLOC NON-MALLOC'D PTR: %s (%d)",
  315. file, line);
  316. return NULL;
  317. }
  318. memused -= memtbl[i].size;
  319. memtbl[i].ptr = x;
  320. memtbl[i].line = line;
  321. memtbl[i].size = size;
  322. p = strrchr(file, '/');
  323. strncpy(memtbl[i].file, p ? p + 1 : file, 19);
  324. memtbl[i].file[19] = 0;
  325. memused += size;
  326. #endif
  327. return x;
  328. }
  329. void n_free(void *ptr, const char *file, int line)
  330. {
  331. int i = 0;
  332. if (ptr == NULL) {
  333. putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NULL PTR: %s (%d)",
  334. file, line);
  335. i = i;
  336. return;
  337. }
  338. #ifdef DEBUG_MEM
  339. /* Give tcl builtins an escape mechanism */
  340. if (line) {
  341. for (i = 0; (i < lastused) && (memtbl[i].ptr != ptr); i++);
  342. if (i == lastused) {
  343. putlog(LOG_MISC, "*", "*** ATTEMPTING TO FREE NON-MALLOC'D PTR: %s (%d)",
  344. file, line);
  345. return;
  346. }
  347. memused -= memtbl[i].size;
  348. lastused--;
  349. memtbl[i].ptr = memtbl[lastused].ptr;
  350. memtbl[i].size = memtbl[lastused].size;
  351. memtbl[i].line = memtbl[lastused].line;
  352. strcpy(memtbl[i].file, memtbl[lastused].file);
  353. }
  354. #endif
  355. free(ptr);
  356. }
  357. #ifdef S_GARBLESTRINGS
  358. #define GARBLE_BUFFERS 40
  359. unsigned char *garble_buffer[GARBLE_BUFFERS] = {
  360. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  361. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  362. };
  363. int garble_ptr = (-1);
  364. char *degarble(int len, char *g)
  365. {
  366. int i;
  367. unsigned char x;
  368. garble_ptr++;
  369. if (garble_ptr == GARBLE_BUFFERS)
  370. garble_ptr = 0;
  371. if (garble_buffer[garble_ptr])
  372. free(garble_buffer[garble_ptr]);
  373. garble_buffer[garble_ptr] = malloc(len + 1);
  374. x = 0xFF;
  375. for (i = 0; i < len; i++) {
  376. garble_buffer[garble_ptr][i] = g[i] ^ x;
  377. x = garble_buffer[garble_ptr][i];
  378. }
  379. garble_buffer[garble_ptr][len] = 0;
  380. return (char *) garble_buffer[garble_ptr];
  381. }
  382. #endif /* S_GARBLESTRINGS */