-const char actions_rcs[] = "$Id: actions.c,v 1.22 2002/01/21 00:27:02 jongfoster Exp $";
+const char actions_rcs[] = "$Id: actions.c,v 1.23 2002/03/07 03:46:16 oes Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/actions.c,v $
  *
  * Revisions   :
  *    $Log: actions.c,v $
+ *    Revision 1.23  2002/03/07 03:46:16  oes
+ *    Fixed compiler warnings
+ *
  *    Revision 1.22  2002/01/21 00:27:02  jongfoster
  *    Allowing free_action(NULL).
  *    Moving the functions that #include actionlist.h to the end of the file,
 }
 
 
+static struct file_list *current_actions_file  = NULL;
+
+
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function    :  unload_current_actions_file
+ *
+ * Description :  Unloads current actions file - reset to state at
+ *                beginning of program.
+ *
+ * Parameters  :  None
+ *
+ * Returns     :  N/A
+ *
+ *********************************************************************/
+void unload_current_actions_file(void)
+{
+   if (current_actions_file)
+   {
+      current_actions_file->unloader = unload_actions_file;
+      current_actions_file = NULL;
+   }
+}
+#endif /* FEATURE_GRACEFUL_TERMINATION */
+
+
 /*********************************************************************
  *
  * Function    :  unload_actions_file
  *********************************************************************/
 int load_actions_file(struct client_state *csp)
 {
-   static struct file_list *current_actions_file  = NULL;
 
    /*
     * Parser mode.
 
 #ifndef ACTIONS_H_INCLUDED
 #define ACTIONS_H_INCLUDED
-#define ACTIONS_H_VERSION "$Id: actions.h,v 1.5 2001/10/14 21:58:22 jongfoster Exp $"
+#define ACTIONS_H_VERSION "$Id: actions.h,v 1.6 2001/10/23 21:30:30 jongfoster Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/actions.h,v $
  *
  * Revisions   :
  *    $Log: actions.h,v $
+ *    Revision 1.6  2001/10/23 21:30:30  jongfoster
+ *    Adding error-checking to selected functions.
+ *
  *    Revision 1.5  2001/10/14 21:58:22  jongfoster
  *    Adding support for the CGI-based editor:
  *    - Exported get_actions()
 extern void unload_actions_file(void *file_data);
 extern int load_actions_file(struct client_state *csp);
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+void unload_current_actions_file(void);
+#endif
 
 
 /* Revision control strings from this header and associated .c file */
 
-const char cgi_rcs[] = "$Id: cgi.c,v 1.48 2002/03/08 17:47:07 jongfoster Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.49 2002/03/13 00:27:04 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgi.c,v $
  *
  * Revisions   :
  *    $Log: cgi.c,v $
+ *    Revision 1.49  2002/03/13 00:27:04  jongfoster
+ *    Killing warnings
+ *
  *    Revision 1.48  2002/03/08 17:47:07  jongfoster
  *    Adding comments
  *
    { "",
          cgi_default,
          "Junkbuster main page" },
+#ifdef FEATURE_GRACEFUL_TERMINATION
+   { "die", 
+         cgi_die,  
+         "<b>Shut down</b> - <font color=red size='+1'>Do not deploy this build in a production environment, this is a one click Denial Of Service attack!!!</font>" }, 
+#endif
    { "show-status", 
          cgi_show_status,  
          "Show information about the current configuration" }, 
 
-const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.17 2002/03/08 16:43:18 oes Exp $";
+const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.18 2002/03/12 01:44:49 oes Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
  *
  * Revisions   :
  *    $Log: cgisimple.c,v $
+ *    Revision 1.18  2002/03/12 01:44:49  oes
+ *    Changed default for "blocked" image from jb logo to checkboard pattern
+ *
  *    Revision 1.17  2002/03/08 16:43:18  oes
  *    Added choice beween GIF and PNG built-in images
  *
 }
 
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function    :  cgi_die
+ *
+ * Description :  CGI function to shut down JunkBuster.
+ *                NOTE: Turning this on in a production build
+ *                would be a BAD idea.  An EXTREMELY BAD idea.
+ *                In short, don't do it.
+ *               
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  rsp = http_response data structure for output
+ *          3  :  parameters = map of cgi parameters
+ *
+ * CGI Parameters : none
+ *
+ * Returns     :  JB_ERR_OK on success
+ *                JB_ERR_MEMORY on out-of-memory error.  
+ *
+ *********************************************************************/
+jb_err cgi_die (struct client_state *csp,
+                struct http_response *rsp,
+                const struct map *parameters)
+{
+   assert(csp);
+   assert(rsp);
+   assert(parameters);
+
+   /* quit */
+   g_terminate = 1;
+
+   /*
+    * I don't really care what gets sent back to the browser.
+    * Take the easy option - "out of memory" page.
+    */
+
+   return JB_ERR_MEMORY;
+}
+#endif /* def FEATURE_GRACEFUL_TERMINATION */
+
+
 /*********************************************************************
  *
  * Function    :  cgi_show_request
 
 #ifndef CGISIMPLE_H_INCLUDED
 #define CGISIMPLE_H_INCLUDED
-#define CGISIMPLE_H_VERSION "$Id: cgisimple.h,v 1.6 2002/03/07 03:48:59 oes Exp $"
+#define CGISIMPLE_H_VERSION "$Id: cgisimple.h,v 1.7 2002/03/08 16:43:59 oes Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgisimple.h,v $
  *
  * Revisions   :
  *    $Log: cgisimple.h,v $
+ *    Revision 1.7  2002/03/08 16:43:59  oes
+ *    Renamed cgi_transparent_png to cgi_transparent_image
+ *
  *    Revision 1.6  2002/03/07 03:48:59  oes
  *     - Changed built-in images from GIF to PNG
  *       (with regard to Unisys patent issue)
                                    struct http_response *rsp,
                                    const struct map *parameters);
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+extern jb_err cgi_die (struct client_state *csp,
+                       struct http_response *rsp,
+                       const struct map *parameters);
+#endif
+
 /* Revision control strings from this header and associated .c file */
 extern const char cgisimple_rcs[];
 extern const char cgisimple_h_rcs[];
 
-const char jcc_rcs[] = "$Id: jcc.c,v 1.81 2002/03/12 01:42:50 oes Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.82 2002/03/13 00:27:05 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.82  2002/03/13 00:27:05  jongfoster
+ *    Killing warnings
+ *
  *    Revision 1.81  2002/03/12 01:42:50  oes
  *    Introduced modular filters
  *
 int urls_rejected = 0;     /* total nr of urls rejected */
 #endif /* def FEATURE_STATISTICS */
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+int g_terminate = 0;
+#endif
 
 static void listen_loop(void);
 static void chat(struct client_state *csp);
 
    bfd = bind_port_helper(config);
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+   while (!g_terminate)
+#else
    for (;;)
+#endif
    {
 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
       while (waitpid(-1, NULL, WNOHANG) > 0)
          serve(csp);
       }
    }
-   /* NOTREACHED */
+
+   /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
+
+   /* Clean up.  Aim: free all memory (no leaks) */
+#ifdef FEATURE_GRACEFUL_TERMINATION
+
+   log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
+
+   unload_current_config_file();
+   unload_current_actions_file();
+   unload_current_re_filterfile();
+#ifdef FEATURE_TRUST
+   unload_current_trust_file();
+#endif
+
+   if (config->multi_threaded)
+   {
+      int i = 60;
+      do
+      {
+         sleep(1);
+         sweep();
+      } while ((clients->next != NULL) && (--i > 0));
+
+      if (i <= 0)
+      {
+         log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
+      }
+   }
+   sweep();
+   sweep();
+
+#if defined(_WIN32) && !defined(_WIN_CONSOLE)
+   /* Cleanup - remove taskbar icon etc. */
+   TermLogWindow();
+#endif
+
+   exit(0);
+#endif /* FEATURE_GRACEFUL_TERMINATION */
 
 }
 
 
 #ifndef JCC_H_INCLUDED
 #define JCC_H_INCLUDED
-#define JCC_H_VERSION "$Id: jcc.h,v 1.8 2002/03/04 18:19:49 oes Exp $"
+#define JCC_H_VERSION "$Id: jcc.h,v 1.9 2002/03/07 03:52:44 oes Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.h,v $
  *
  * Revisions   :
  *    $Log: jcc.h,v $
+ *    Revision 1.9  2002/03/07 03:52:44  oes
+ *    Set logging to tty for --no-daemon mode
+ *
  *    Revision 1.8  2002/03/04 18:19:49  oes
  *    Added extern const char *pidfile
  *
 #endif
 extern int no_daemon;
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+extern int g_terminate;
+#endif
+
 /* Functions */
 
 #ifdef __MINGW32__
 
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.35 2002/03/07 03:52:44 oes Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.36 2002/03/13 00:27:05 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
  *
  * Revisions   :
  *    $Log: loadcfg.c,v $
+ *    Revision 1.36  2002/03/13 00:27:05  jongfoster
+ *    Killing warnings
+ *
  *    Revision 1.35  2002/03/07 03:52:44  oes
  *    Set logging to tty for --no-daemon mode
  *
 }
 
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function    :  unload_current_config_file
+ *
+ * Description :  Unloads current config file - reset to state at
+ *                beginning of program.
+ *
+ * Parameters  :  None
+ *
+ * Returns     :  N/A
+ *
+ *********************************************************************/
+void unload_current_config_file(void)
+{
+   if (current_configfile)
+   {
+      current_configfile->unloader = unload_configfile;
+      current_configfile = NULL;
+   }
+}
+#endif
+
+
 /*********************************************************************
  *
  * Function    :  load_config
 
 #ifndef LOADCFG_H_INCLUDED
 #define LOADCFG_H_INCLUDED
-#define LOADCFG_H_VERSION "$Id: loadcfg.h,v 1.7 2001/07/30 22:08:36 jongfoster Exp $"
+#define LOADCFG_H_VERSION "$Id: loadcfg.h,v 1.8 2001/12/30 14:07:32 steudten Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.h,v $
  *
  * Revisions   :
  *    $Log: loadcfg.h,v $
+ *    Revision 1.8  2001/12/30 14:07:32  steudten
+ *    - Add signal handling (unix)
+ *    - Add SIGHUP handler (unix)
+ *    - Add creation of pidfile (unix)
+ *    - Add action 'top' in rc file (RH)
+ *    - Add entry 'SIGNALS' to manpage
+ *    - Add exit message to logfile (unix)
+ *
  *    Revision 1.7  2001/07/30 22:08:36  jongfoster
  *    Tidying up #defines:
  *    - All feature #defines are now of the form FEATURE_xxx
 
 extern struct configuration_spec * load_config(void);
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+void unload_current_config_file(void);
+#endif
 
 /* Revision control strings from this header and associated .c file */
 extern const char loadcfg_rcs[];
 
-const char loaders_rcs[] = "$Id: loaders.c,v 1.43 2002/03/16 20:28:34 oes Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.44 2002/03/16 21:51:00 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.c,v $
  *
  * Revisions   :
  *    $Log: loaders.c,v $
+ *    Revision 1.44  2002/03/16 21:51:00  jongfoster
+ *    Fixing free(NULL).
+ *
  *    Revision 1.43  2002/03/16 20:28:34  oes
  *    Added descriptions to the filters so users will know what they select in the cgi editor
  *
  *********************************************************************/
 static void unload_trustfile(void *f)
 {
-   struct block_spec *b = (struct block_spec *)f;
-   if (b == NULL) return;
+   struct block_spec *cur = (struct block_spec *)f;
+   struct block_spec *next;
 
-   unload_trustfile(b->next); /* Stack is cheap, isn't it? */
+   while (cur != NULL)
+   {
+      next = cur->next;
 
-   free_url_spec(b->url);
+      free_url_spec(cur->url);
+      free(cur);
 
-   freez(b);
+      cur = next;
+   }
 
 }
 
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function    :  unload_current_trust_file
+ *
+ * Description :  Unloads current trust file - reset to state at
+ *                beginning of program.
+ *
+ * Parameters  :  None
+ *
+ * Returns     :  N/A
+ *
+ *********************************************************************/
+void unload_current_trust_file(void)
+{
+   if (current_trustfile)
+   {
+      current_trustfile->unloader = unload_trustfile;
+      current_trustfile = NULL;
+   }
+}
+#endif /* FEATURE_GRACEFUL_TERMINATION */
+
+
 /*********************************************************************
  *
  * Function    :  load_trustfile
 }
 
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function    :  unload_current_re_filterfile
+ *
+ * Description :  Unloads current re_filter file - reset to state at
+ *                beginning of program.
+ *
+ * Parameters  :  None
+ *
+ * Returns     :  N/A
+ *
+ *********************************************************************/
+void unload_current_re_filterfile(void)
+{
+   if (current_re_filterfile)
+   {
+      current_re_filterfile->unloader = unload_re_filterfile;
+      current_re_filterfile = NULL;
+   }
+}
+#endif
+
+
 /*********************************************************************
  *
  * Function    :  load_re_filterfile
 
 #ifndef LOADERS_H_INCLUDED
 #define LOADERS_H_INCLUDED
-#define LOADERS_H_VERSION "$Id: loaders.h,v 1.15 2002/01/22 23:46:18 jongfoster Exp $"
+#define LOADERS_H_VERSION "$Id: loaders.h,v 1.16 2002/03/07 03:46:17 oes Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.h,v $
  *
  * Revisions   :
  *    $Log: loaders.h,v $
+ *    Revision 1.16  2002/03/07 03:46:17  oes
+ *    Fixed compiler warnings
+ *
  *    Revision 1.15  2002/01/22 23:46:18  jongfoster
  *    Moving edit_read_line() and simple_read_line() to loaders.c, and
  *    extending them to support reading MS-DOS, Mac and UNIX style files
 extern int load_trustfile(struct client_state *csp);
 #endif /* def FEATURE_TRUST */
 
+#ifdef FEATURE_GRACEFUL_TERMINATION
+#ifdef FEATURE_TRUST
+void unload_current_trust_file(void);
+#endif
+void unload_current_re_filterfile(void);
+#endif /* FEATURE_GRACEFUL_TERMINATION */
 
 
 extern void add_loader(int (*loader)(struct client_state *),