httpd: fix CGI handling bug (we were closing wrong fd).
[oweals/busybox.git] / libbb / error_msg_and_die.c
index 29a260bdee8fc0b28008c265d640084c68a5caf7..0e99a03cfa96ce204a751f35fdf4cdd096f71669 100644 (file)
@@ -7,13 +7,34 @@
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
 #include "libbb.h"
 
 int die_sleep;
+#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH
+jmp_buf die_jmp;
+#endif
+
+void xfunc_die(void)
+{
+       if (die_sleep) {
+               if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH)
+                && die_sleep < 0
+               ) {
+                       /* Special case. We arrive here if NOFORK applet
+                        * calls xfunc, which then decides to die.
+                        * We don't die, but jump instead back to caller.
+                        * NOFORK applets still cannot carelessly call xfuncs:
+                        * p = xmalloc(10);
+                        * q = xmalloc(10); // BUG! if this dies, we leak p!
+                        */
+                       /* -2222 means "zero" (longjmp can't pass 0)
+                        * run_nofork_applet() catches -2222. */
+                       longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222);
+               }
+               sleep(die_sleep);
+       }
+       exit(xfunc_error_retval);
+}
 
 void bb_error_msg_and_die(const char *s, ...)
 {
@@ -22,7 +43,5 @@ void bb_error_msg_and_die(const char *s, ...)
        va_start(p, s);
        bb_verror_msg(s, p, NULL);
        va_end(p);
-       if (die_sleep)
-               sleep(die_sleep);
-       exit(bb_default_error_retval);
+       xfunc_die();
 }