Bryan Drewery před 23 roky
rodič
revize
41cc99bd17

+ 0 - 1
CREDITS

@@ -4,7 +4,6 @@ Wraith botpack by bryan, with credits to the following:
 Eggdrop team for developing such a great bot to code off of.
 Einride and ievil for taking eggdrop1.4.3 and making their very effecient botpack Ghost.
 SFC for providing compile shells, continuous input, feature suggestions, and testing.
-xmage for proving shells and beta testing
 #c on EFnet.
 
 The following botpacks gave me inspiration and ideas (no code):

+ 29 - 0
Changelog

@@ -18,3 +18,32 @@
  Fixed FreeBSD compile errors 
  Improved last checker functions
  
+1.0.04
+ Rewrote most of the update system... the first bot installed on shells will set their uplink to the +u bot now.
+
+1.0.05
+ Added cmd_botdie
+ Added text for HOSTS entry on leaf bots..
+ Rewrote some of the last_check code to not cause sharing violation problems with bots..
+ Added .secpass .chsecpass (to be used at a later time)
+ Users are given a random secpass when added
+ Disabled share system host/user/flag related logging on leaf bots
+ Added cookieops checking and flag stripping..
+ Added roles
+ Fixed various seg fault bugs..
+ Rewrote update system once again, seems to be working flawlessly now.
+	-Binaries are no longer compressed on send, use upx for linux binaries.
+	-Hubs must be manually updated in most cases (unless your hublevel 1 hub is the update bot ;])
+          -Just ftp the new binary, and use .botupdate
+ Added cmds: botupdate, botkill, net/botcrontab
+ Removed cmd_rehash; cmd_restart does nothing for now.
+ Fixed +take
+ +bitch is enforced by every bot as of now, will be fixed to be like +take later..
+ Added ctcp cloaking
+ All kicks are cloaked correctly now 
+
+1.0.06
+ +closed now sends +i a lot quicker.
+ Fixed msg_op to use cookieops when a channel is specified
+ Fixed do_op to only send opline (+o-b) if nick is in channel ;)
+ Removed cmd_pls_bot

+ 1 - 1
README

@@ -17,7 +17,7 @@ edit src/settings.c
 Edit pack.conf (dont change anything in this actually.)
 Now, ./bldall pack
 Ignore any warnings, any errors report to bryan
-There are your binaries: leaf, hub
+There are your binaries for the OS you compiled on..: leaf, hub
 
 DONT LOSE: settings.c salt.h
 

+ 7 - 6
bldall

@@ -44,13 +44,14 @@ make distclean > /dev/null
 echo "Configuring..."
 #./configure > /dev/null 2>configure.temp
 ./configure --with-tcllib=${TCLDIR}/lib/libtcl8.4.a --with-tclinc=${TCLDIR}/include/tcl.h > /dev/null 2>configure.temp
-if test "`cat configure.temp`"
-then
-  echo "Configure error'd"
-  cat configure.temp
+#if test "`cat configure.temp`"
+#then
+#  echo "Configure error'd"
+#  cat configure.temp
+#
 #  exit 1
-fi
-rm -f configure.temp
+#fi
+#rm -f configure.temp
 
 
 

+ 1 - 0
conf

@@ -1,3 +1,4 @@
+#when you make the bot, remove these #lines :)
 #These lines MUST be correctly syntaxed or the bot will not work properly.
 #A conf can be only a hub conf or only a leaf conf. (see README for locations)
 #The first line must contain UID (use "id" in shell to get uid)

+ 0 - 0
configure.temp


+ 26 - 1
makesalt.c

@@ -1,8 +1,31 @@
+/************************************************************************
+ *   psybnc2.2.2, tools/makesalt.c
+ *   Copyright (C) 2001 the most psychoid  and
+ *                      the cool lam3rz IRC Group, IRCnet
+ *			http://www.psychoid.lam3rz.de
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 1, or (at your option)
+ *   any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
 #include <time.h>
+
 char rbuf[100];
+
 const char *
 randstring (int length)
 {
@@ -15,7 +38,8 @@ randstring (int length)
     {
       *po = (char) (0x61 + (rand () & 15));
       po++;
-    } *po = 0;
+    }
+  *po = 0;
   po = rbuf;
   return po;
 }
@@ -23,6 +47,7 @@ randstring (int length)
 int
 main (void)
 {
+
   FILE *salt;
   int saltlen1;
   int saltlen2;

+ 4 - 4
misc/modconfig

@@ -370,9 +370,9 @@ EOF
 	#  Create declarations for module _start functions
 	for mc_mod in ${mc_sel_modules}; do
 		echo ${mc_n} ".${mc_c}" 1>&6
-if test ${mc_mod} = "server" || test ${mc_mod} = "irc" || test ${mc_mod} = "ctcp";then echo "#ifdef LEAF" 1>> ${mc_fstatic_h};fi
+if test ${mc_mod} = "server" || test ${mc_mod} = "irc";then echo "#ifdef LEAF" 1>> ${mc_fstatic_h};fi
 		echo "char *${mc_mod}_start();" 1>> ${mc_fstatic_h}
-if test ${mc_mod} = "server" || test ${mc_mod} = "irc" || test ${mc_mod} = "ctcp";then echo "#endif" 1>> ${mc_fstatic_h};fi
+if test ${mc_mod} = "server" || test ${mc_mod} = "irc";then echo "#endif" 1>> ${mc_fstatic_h};fi
 
 	done
 	echo 1>> ${mc_fstatic_h}
@@ -381,9 +381,9 @@ if test ${mc_mod} = "server" || test ${mc_mod} = "irc" || test ${mc_mod} = "ctcp
 	echo "static void link_statics()" 1>> ${mc_fstatic_h}
 	echo "{" 1>> ${mc_fstatic_h}
 	for mc_mod in ${mc_sel_modules}; do
-if test ${mc_mod} = "server" || test ${mc_mod} = "irc" || test ${mc_mod} = "ctcp";then echo "#ifdef LEAF" 1>> ${mc_fstatic_h};fi
+if test ${mc_mod} = "server" || test ${mc_mod} = "irc";then echo "#ifdef LEAF" 1>> ${mc_fstatic_h};fi
 		echo "  check_static(\"${mc_mod}\", ${mc_mod}_start);" 1>> ${mc_fstatic_h}
-if test ${mc_mod} = "server" || test ${mc_mod} = "irc" || test ${mc_mod} = "ctcp";then echo "#endif" 1>> ${mc_fstatic_h};fi
+if test ${mc_mod} = "server" || test ${mc_mod} = "irc";then echo "#endif" 1>> ${mc_fstatic_h};fi
 
 	done
 	cat 1>> ${mc_fstatic_h} << EOF

+ 4 - 3
pack.conf

@@ -1,9 +1,10 @@
+#DONT DISABLE: IRCNET, PSCLOAK, RANDSERVERS
+#DONT ENABLE LASTCHECK YET.
 #ANTITRACE
-#OWNEREXCEPT
 NODELAY
-LASTCHECK
+#LASTCHECK
 DCCPASS
 IRCNET
 RANDSERVERS
-#AUTOHOSTADD
 PSCLOAK
+AUTOAWAY

+ 1 - 1
src/botcmd.c

@@ -859,7 +859,7 @@ bot_traced (int idx, char *par)
 void
 bot_timesync (int idx, char *par)
 {
-  putlog (LOG_BOTS, "*", "Got timesync from %s: %s\n", dcc[idx].nick, par);
+  putlog (LOG_DEBUG, "*", "Got timesync from %s: %s\n", dcc[idx].nick, par);
   timesync = atoi (par) - now;
 #ifdef HUB
   send_timesync (-1);

+ 37 - 0
src/botnet.c

@@ -1654,9 +1654,46 @@ restart_chons ()
 		      party[i].flag, party[i].sock, party[i].from);
     }
 }
+static int
+get_role (char *bot)
+{
+  int rl, i;
+  struct bot_addr *ba;
+  int r[5] = { 0, 0, 0, 0, 0 };
+  struct userrec *u, *u2;
+  u2 = get_user_by_handle (userlist, bot);
+  if (!u2)
+    return 1;
+  for (u = userlist; u; u = u->next)
+    {
+      if (u->flags & USER_BOT)
+	{
+	  if (strcmp (u->handle, bot))
+	    {
+	      ba = get_user (&USERENTRY_BOTADDR, u);
+	      if ((nextbot (u->handle) >= 0) && (ba) && (ba->roleid > 0)
+		  && (ba->roleid < 5))
+		r[(ba->roleid - 1)]++;
+	    }
+	}
+    }
+  rl = 0;
+  for (i = 1; i <= 4; i++)
+    if (r[i] < r[rl])
+      rl = i;
+  rl++;
+  ba = get_user (&USERENTRY_BOTADDR, u2);
+  if (ba)
+    ba->roleid = rl;
+  return rl;
+}
+
 void
 lower_bot_linked (int idx)
 {
+  char tmp[5];
+  sprintf (tmp, STR ("rl %d"), get_role (dcc[idx].nick));
+  botnet_send_zapf (nextbot (dcc[idx].nick), botnetnick, dcc[idx].nick, tmp);
 } void
 higher_bot_linked (int idx)
 {

+ 571 - 269
src/cmds.c

@@ -22,7 +22,7 @@ extern unsigned long otraffic_irc, otraffic_irc_today, itraffic_irc,
   itraffic_unknown, itraffic_unknown_today;
 extern Tcl_Interp *interp;
 extern char botnetnick[], origbotname[], ver[], network[], owner[],
-  quit_msg[], dcc_prefix[], netpass[], botname[];
+  quit_msg[], dcc_prefix[], netpass[], botname[], *binname;
 extern time_t now, online_since;
 extern module_entry *module_list;
 extern struct cfg_entry CFG_MOTD;
@@ -659,6 +659,39 @@ cmd_newpass (struct userrec *u, int idx, char *par)
   set_user (&USERENTRY_PASS, u, new);
   dprintf (idx, "Changed password to '%s'.\n", new);
 }
+static void
+cmd_secpass (struct userrec *u, int idx, char *par)
+{
+  char *new, pass[17];
+  putlog (LOG_CMDS, "*", "#%s# secpass...", dcc[idx].nick);
+  if (!par[0])
+    {
+      dprintf (idx,
+	       "Usage: secpass <newsecpass>\nIf you use \"rand\" as the secpass, a random pass will be chosen.\n");
+      return;
+    }
+  new = newsplit (&par);
+  if (!strcmp (new, "rand"))
+    {
+      make_rand_str (pass, 17);
+    }
+  else
+    {
+      if (strlen (new) < 6)
+	{
+	  dprintf (idx, "Please use at least 6 characters.\n");
+	  return;
+	}
+      else
+	{
+	  sprintf (pass, "%s", new);
+	}
+    }
+  if (strlen (pass) > 16)
+    pass[16] = 0;
+  set_user (&USERENTRY_SECPASS, u, pass);
+  dprintf (idx, "Changed secpass to '%s'.\n", pass);
+}
 
 #ifdef HUB
 static void
@@ -893,6 +926,35 @@ cmd_match (struct userrec *u, int idx, char *par)
   tell_users_match (idx, s, start, limit, u ? (u->flags & USER_MASTER) : 0,
 		    chname);
 }
+
+#ifdef HUB
+void
+cmd_botupdate (struct userrec *u, int idx, char *par)
+{
+  char *tbot, tmp[256];
+  putlog (LOG_CMDS, "*", STR ("#%s# botupdate %s"), dcc[idx].nick, par);
+  tbot = newsplit (&par);
+  if (!par[0])
+    {
+      dprintf (idx, STR ("Not enough parameters.\n"));
+      return;
+    }
+  if (nextbot (tbot) < 0)
+    {
+      dprintf (idx, STR ("No such bot linked\n"));
+      return;
+    }
+  sprintf (tmp, STR ("update %s"), par);
+  botnet_send_cmd (botnetnick, tbot, u->handle, idx, tmp);
+}
+#endif
+static void
+rcmd_update (char *fbot, char *fhand, char *fidx, char *par)
+{
+  if (!par[0])
+    return;
+  updatebin (0, par, 0);
+}
 static void
 cmd_update (struct userrec *u, int idx, char *par)
 {
@@ -911,6 +973,26 @@ cmd_userlist (struct userrec *u, int idx, char *par)
 {
   int cnt = 0;
   putlog (LOG_CMDS, "*", STR ("#%s# userlist"), dcc[idx].nick);
+  for (u = userlist; u; u = u->next)
+    {
+      if ((u->flags & USER_BOT) && (u->flags & USER_CHANHUB))
+	{
+	  if (cnt)
+	    dprintf (idx, ", ");
+	  else
+	    dprintf (idx, STR ("Chathubs  : "));
+	  dprintf (idx, u->handle);
+	  cnt++;
+	  if (cnt == 15)
+	    {
+	      dprintf (idx, "\n");
+	      cnt = 0;
+	    }
+	}
+    }
+  if (cnt)
+    dprintf (idx, "\n");
+  cnt = 0;
 #ifdef HUB
   for (u = userlist; u; u = u->next)
     {
@@ -1266,74 +1348,6 @@ cmd_console (struct userrec *u, int idx, char *par)
 
 #ifdef HUB
 static void
-cmd_pls_bot (struct userrec *u, int idx, char *par)
-{
-  char *handle, *addr, *p, *q, *host;
-  struct userrec *u1;
-  struct bot_addr *bi;
-  if (!par[0])
-    dprintf (idx,
-	     "Usage: +bot <handle> <address[:telnet-port[/relay-port]]> [host]\n");
-  else
-    {
-      handle = newsplit (&par);
-      addr = newsplit (&par);
-      if (strlen (handle) > HANDLEN)
-	handle[HANDLEN] = 0;
-      if (get_user_by_handle (userlist, handle))
-	dprintf (idx, "Someone already exists by that name.\n");
-      else if (strchr (BADHANDCHARS, handle[0]) != NULL)
-	dprintf (idx, "You can't start a botnick with '%c'.\n", handle[0]);
-      else
-	{
-	  if (strlen (addr) > 60)
-	    addr[60] = 0;
-	  putlog (LOG_CMDS, "*", "#%s# +bot %s %s", dcc[idx].nick, handle,
-		  addr);
-	  userlist = adduser (userlist, handle, "none", "-", USER_BOT);
-	  u1 = get_user_by_handle (userlist, handle);
-	  bi = user_malloc (sizeof (struct bot_addr));
-	  q = strchr (addr, ':');
-	  if (!q)
-	    {
-	      bi->address = user_malloc (strlen (addr) + 1);
-	      strcpy (bi->address, addr);
-	      bi->telnet_port = 3333;
-	      bi->relay_port = 3333;
-	    }
-	  else
-	    {
-	      bi->address = user_malloc (q - addr + 1);
-	      strncpy (bi->address, addr, q - addr);
-	      bi->address[q - addr] = 0;
-	      p = q + 1;
-	      bi->telnet_port = atoi (p);
-	      q = strchr (p, '/');
-	      if (!q)
-		{
-		  bi->relay_port = bi->telnet_port;
-		}
-	      else
-		{
-		  bi->relay_port = atoi (q + 1);
-		}
-	    }
-	  set_user (&USERENTRY_BOTADDR, u1, bi);
-	  dprintf (idx, "Added bot '%s' with address '%s' and no password.\n",
-		   handle, addr);
-	  host = newsplit (&par);
-	  if (host[0])
-	    {
-	      addhost_by_handle (handle, host);
-	    }
-	  else if (!add_bot_hostmask (idx, handle))
-	    dprintf (idx,
-		     "You'll want to add a hostmask if this bot will ever %s",
-		     "be on any channels that I'm on.\n");
-	}
-    }
-}
-static void
 cmd_chhandle (struct userrec *u, int idx, char *par)
 {
   char hand[HANDLEN + 1], newhand[HANDLEN + 1];
@@ -1494,6 +1508,72 @@ cmd_chpass (struct userrec *u, int idx, char *par)
     }
 }
 static void
+cmd_chsecpass (struct userrec *u, int idx, char *par)
+{
+  char *handle, *new;
+  int atr = u ? u->flags : 0, l;
+  int ucase, lcase, ocase, tc, faenda;
+  ucase = lcase = ocase = 0;
+  if (!par[0])
+    dprintf (idx, "Usage: chsecpass <handle> [secpass]\n");
+  else
+    {
+      handle = newsplit (&par);
+      u = get_user_by_handle (userlist, handle);
+      if (!u)
+	dprintf (idx, "No such user.\n");
+      else if (!(atr & USER_MASTER) && !(u->flags & USER_BOT))
+	dprintf (idx, "You can't change passwords for non-bots.\n");
+      else if ((bot_flags (u) & BOT_SHARE) && !(atr & USER_OWNER))
+	dprintf (idx, "You can't change a share bot's password.\n");
+      else if ((u->flags & USER_OWNER) && !(atr & USER_OWNER)
+	       && egg_strcasecmp (handle, dcc[idx].nick))
+	dprintf (idx, "You can't change a bot owner's password.\n");
+      else if (isowner (handle) && egg_strcasecmp (dcc[idx].nick, handle))
+	dprintf (idx, "You can't change a permanent bot owner's password.\n");
+      else if (!par[0])
+	{
+	  putlog (LOG_CMDS, "*", "#%s# chsecpass %s [nothing]", dcc[idx].nick,
+		  handle);
+	  set_user (&USERENTRY_PASS, u, NULL);
+	  dprintf (idx, "Removed secpass.\n");
+	}
+      else
+	{
+	  l = strlen (new = newsplit (&par));
+	  if (l > 16)
+	    new[16] = 0;
+	  if (l < 8)
+	    {
+	      dprintf (idx, "Use >= 8 chars, ucase, lcase and a number.\n");
+	      return;
+	    }
+	  for (faenda = 0; faenda < l; faenda++)
+	    {
+	      tc = (int) new[faenda];
+	      if (tc < 58 && tc > 47)
+		ocase = 1;
+	      if (tc < 91 && tc > 64)
+		ucase = 1;
+	      if (tc < 123 && tc > 96)
+		lcase = 1;
+	    }
+	  if ((lcase + ocase + ucase) == 3)
+	    {
+	      set_user (&USERENTRY_SECPASS, u, new);
+	      putlog (LOG_CMDS, "*", "#%s# chsecpass %s [something]",
+		      dcc[idx].nick, handle);
+	      dprintf (idx, "Changed secpass.\n");
+	    }
+	  else
+	    {
+	      dprintf (idx, "Use >= 8 chars, ucase, lcase and a number.\n");
+	      return;
+	    }
+	}
+    }
+}
+static void
 cmd_hublevel (struct userrec *u, int idx, char *par)
 {
   char *handle, *level;
@@ -1658,6 +1738,7 @@ cmd_comment (struct userrec *u, int idx, char *par)
 static void
 cmd_restart (struct userrec *u, int idx, char *par)
 {
+  return;
   putlog (LOG_CMDS, "*", "#%s# restart", dcc[idx].nick);
   if (!backgrd)
     {
@@ -1674,17 +1755,6 @@ cmd_restart (struct userrec *u, int idx, char *par)
   wipe_timers (interp, &timer);
   do_restart = idx;
 }
-static void
-cmd_rehash (struct userrec *u, int idx, char *par)
-{
-  putlog (LOG_CMDS, "*", "#%s# rehash", dcc[idx].nick);
-  dprintf (idx, "Rehashing.\n");
-#ifdef HUB
-  write_userfile (-1);
-#endif
-  putlog (LOG_MISC, "*", "Rehashing ...");
-  do_restart = -2;
-}
 
 #ifdef HUB
 static void
@@ -2699,6 +2769,8 @@ cmd_last (struct userrec *u, int idx, char *par)
   else
     {
       pw = getpwuid (geteuid ());
+      if (!pw)
+	return;
       strncpy0 (user, pw->pw_name, sizeof (user));
     }
   if (!user[0])
@@ -3356,7 +3428,7 @@ cmd_pls_user (struct userrec *u, int idx, char *par)
   else
     {
       struct userrec *u2;
-      char tmp[50], s[50];
+      char tmp[50], s[50], s2[50];
       userlist = adduser (userlist, handle, host, "-", USER_DEFAULT);
       u2 = get_user_by_handle (userlist, handle);
       sprintf (tmp, STR ("%lu %s"), time (NULL), u->handle);
@@ -3370,7 +3442,10 @@ cmd_pls_user (struct userrec *u, int idx, char *par)
 	}
       make_rand_str (s, 10);
       set_user (&USERENTRY_PASS, u2, s);
+      make_rand_str (s2, 17);
+      set_user (&USERENTRY_SECPASS, u2, s2);
       dprintf (idx, STR ("%s's password set to \002%s\002.\n"), handle, s);
+      dprintf (idx, STR ("%s's secpass set to \002%s\002.\n"), handle, s2);
 #ifdef HUB
       write_userfile (idx);
 #endif
@@ -3867,6 +3942,35 @@ cmd_netw (struct userrec *u, int idx, char *par)
   strcpy (tmp, STR ("exec w"));
   botnet_send_cmd_broad (-1, botnetnick, dcc[idx].nick, idx, tmp);
 } static void
+cmd_botkill (struct userrec *u, int idx, char *par)
+{
+  char *tbot, buf[1024];
+  putlog (LOG_CMDS, "*", STR ("#%s# botkill %s"), dcc[idx].nick, par);
+  tbot = newsplit (&par);
+  if (!tbot[0])
+    {
+      dprintf (idx, STR ("Usage: botkill <botname> [kill-parameters]\n"));
+      return;
+    }
+  if (strchr (par, '|') || strchr (par, '<') || strchr (par, ';')
+      || strchr (par, '>'))
+    {
+      putlog (LOG_WARN, "*",
+	      STR
+	      ("%s attempted 'botkill' with pipe/semicolon in parameters: %s"),
+	      dcc[idx].nick, par);
+      dprintf (idx, STR ("No."));
+      return;
+    }
+  if (nextbot (tbot) < 0)
+    {
+      dprintf (idx, STR ("No such linked bot\n"));
+      return;
+    }
+  sprintf (buf, STR ("exec kill %s"), par);
+  botnet_send_cmd (botnetnick, tbot, dcc[idx].nick, idx, buf);
+}
+static void
 cmd_botps (struct userrec *u, int idx, char *par)
 {
   char *tbot, buf[1024];
@@ -3961,6 +4065,137 @@ cmd_netlast (struct userrec *u, int idx, char *par)
   botnet_send_cmd_broad (-1, botnetnick, dcc[idx].nick, idx, buf);
 }
 
+void
+crontab_show (struct userrec *u, int idx)
+{
+  dprintf (idx, STR ("Showing current crontab:\n"));
+  if (!exec_str (u, idx, STR ("crontab -l | grep -v \"^#\"")))
+    dprintf (idx, STR ("Exec failed"));
+}
+
+void
+crontab_del ()
+{
+  char *tmpfile, *p, buf[2048];
+  tmpfile = nmalloc (strlen (binname) + 100);
+  strcpy (tmpfile, binname);
+  if (!(p = strrchr (tmpfile, '/')))
+    return;
+  p++;
+  strcpy (p, STR (".ctb"));
+  sprintf (buf,
+	   STR
+	   ("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\" > %s"),
+	   binname, tmpfile);
+  if (shell_exec (buf, NULL, NULL, NULL))
+    {
+      sprintf (buf, STR ("crontab %s"), tmpfile);
+      shell_exec (buf, NULL, NULL, NULL);
+    }
+  unlink (tmpfile);
+}
+
+void
+cmd_crontab (struct userrec *u, int idx, char *par)
+{
+  char *code;
+  int i;
+  putlog (LOG_CMDS, "*", STR ("#%s# crontab %s"), dcc[idx].nick, par);
+  if (!par[0])
+    {
+      dprintf (idx,
+	       STR ("Usage: crontab status|delete|show|new [interval]\n"));
+      return;
+    }
+  code = newsplit (&par);
+  if (!strcmp (code, STR ("status")))
+    {
+      i = crontab_exists ();
+      if (!i)
+	dprintf (idx, STR ("No crontab\n"));
+      else if (i == 1)
+	dprintf (idx, STR ("Crontabbed\n"));
+      else
+	dprintf (idx, STR ("Error checking crontab status\n"));
+    }
+  else if (!strcmp (code, STR ("show")))
+    {
+      crontab_show (u, idx);
+    }
+  else if (!strcmp (code, STR ("delete")))
+    {
+      crontab_del ();
+      i = crontab_exists ();
+      if (!i)
+	dprintf (idx, STR ("No crontab\n"));
+      else if (i == 1)
+	dprintf (idx, STR ("Crontabbed\n"));
+      else
+	dprintf (idx, STR ("Error checking crontab status\n"));
+    }
+  else if (!strcmp (code, STR ("new")))
+    {
+      i = atoi (par);
+      if ((i <= 0) || (i > 60))
+	i = 10;
+      crontab_create (i);
+      i = crontab_exists ();
+      if (!i)
+	dprintf (idx, STR ("No crontab\n"));
+      else if (i == 1)
+	dprintf (idx, STR ("Crontabbed\n"));
+      else
+	dprintf (idx, STR ("Error checking crontab status\n"));
+    }
+  else
+    {
+      dprintf (idx,
+	       STR ("Usage: crontab status|delete|show|new [interval]\n"));
+    }
+}
+
+#ifdef HUB
+static void
+cmd_botcrontab (struct userrec *u, int idx, char *par)
+{
+  char *tbot, buf[1024], *cmd;
+  putlog (LOG_CMDS, "*", STR ("#%s# botcrontab %s"), dcc[idx].nick, par);
+  tbot = newsplit (&par);
+  cmd = newsplit (&par);
+  if (!tbot[0]
+      || (strcmp (cmd, STR ("status")) && strcmp (cmd, STR ("show"))
+	  && strcmp (cmd, STR ("delete")) && strcmp (cmd, STR ("new"))))
+    {
+      dprintf (idx,
+	       STR
+	       ("Usage: botcrontab <botname> status|delete|show|new [interval]\n"));
+      return;
+    }
+  if (nextbot (tbot) < 0)
+    {
+      dprintf (idx, STR ("No such linked bot\n"));
+      return;
+    }
+  sprintf (buf, STR ("exec crontab %s %s"), cmd, par);
+  botnet_send_cmd (botnetnick, tbot, dcc[idx].nick, idx, buf);
+}
+static void
+cmd_netcrontab (struct userrec *u, int idx, char *par)
+{
+  char buf[1024], *cmd;
+  putlog (LOG_CMDS, "*", STR ("#%s# netcrontab %s"), dcc[idx].nick, par);
+  cmd = newsplit (&par);
+  if ((strcmp (cmd, STR ("status")) && strcmp (cmd, STR ("show"))
+       && strcmp (cmd, STR ("delete")) && strcmp (cmd, STR ("new"))))
+    {
+      dprintf (idx,
+	       STR ("Usage: netcrontab status|delete|show|new [interval]\n"));
+      return;
+    }
+  sprintf (buf, STR ("exec crontab %s %s"), cmd, par);
+  botnet_send_cmd_broad (-1, botnetnick, dcc[idx].nick, idx, buf);
+}
+#endif
 void
 rcmd_exec (char *frombot, char *fromhand, char *fromidx, char *par)
 {
@@ -3982,6 +4217,8 @@ rcmd_exec (char *frombot, char *fromhand, char *fromidx, char *par)
       else
 	{
 	  pw = getpwuid (geteuid ());
+	  if (!pw)
+	    return;
 	  strncpy0 (user, pw->pw_name, sizeof (user));
 	}
       if (!user[0])
@@ -3996,6 +4233,43 @@ rcmd_exec (char *frombot, char *fromhand, char *fromidx, char *par)
     {
       sprintf (scmd, STR ("ps %s"), par);
     }
+  else if (!strcmp (cmd, STR ("kill")))
+    {
+      sprintf (scmd, STR ("kill %s"), par);
+    }
+  else if (!strcmp (cmd, STR ("crontab")))
+    {
+      char *code = newsplit (&par);
+      scmd[0] = 0;
+      if (!strcmp (code, STR ("show")))
+	{
+	  strcpy (scmd, STR ("crontab -l | grep -v \"^#\""));
+	}
+      else if (!strcmp (code, STR ("delete")))
+	{
+	  crontab_del ();
+	}
+      else if (!strcmp (code, STR ("new")))
+	{
+	  int i = atoi (par);
+	  if ((i <= 0) || (i > 60))
+	    i = 10;
+	  crontab_create (i);
+	}
+      if (!scmd[0])
+	{
+	  char s[200];
+	  int i;
+	  i = crontab_exists ();
+	  if (!i)
+	    sprintf (s, STR ("No crontab"));
+	  else if (i == 1)
+	    sprintf (s, STR ("Crontabbed"));
+	  else
+	    sprintf (s, STR ("Error checking crontab status"));
+	  botnet_send_cmdreply (botnetnick, frombot, fromhand, fromidx, s);
+	}
+    }
   if (!scmd[0])
     return;
   if (shell_exec (scmd, NULL, &out, &err))
@@ -4041,6 +4315,28 @@ rcmd_exec (char *frombot, char *fromhand, char *fromidx, char *par)
 			    STR ("exec failed"));
     }
 }
+
+#ifdef HUB
+static void
+cmd_botdie (struct userrec *u, int idx, char *par)
+{
+  char *tbot, buf[1024];
+  putlog (LOG_CMDS, "*", STR ("#%s# botdie %s"), dcc[idx].nick, par);
+  tbot = newsplit (&par);
+  if (!tbot[0])
+    {
+      dprintf (idx, STR ("Usage: botdie <botname>\n"));
+      return;
+    }
+  if (nextbot (tbot) < 0)
+    {
+      dprintf (idx, STR ("No such linked bot\n"));
+      return;
+    }
+  sprintf (buf, STR ("die %s"), par);
+  botnet_send_cmd (botnetnick, tbot, dcc[idx].nick, idx, buf);
+}
+#endif
 static void
 cmd_botjump (struct userrec *u, int idx, char *par)
 {
@@ -4068,10 +4364,11 @@ rcmd_jump (char *frombot, char *fromhand, char *fromidx, char *par)
 #ifdef LEAF
   char *other;
   module_entry *me;
-  Function *func = me->funcs;
+  Function *func;
   int port, default_port = 0;
   if (!(me = module_find ("server", 0, 0)))
     return;
+  func = me->funcs;
   default_port = (*(int *) (func[24]));
   if (par[0])
     {
@@ -4127,6 +4424,14 @@ gotremotecmd (char *forbot, char *frombot, char *fromhand, char *fromidx,
     {
       rcmd_pong (frombot, fromhand, fromidx, par);
     }
+  else if (!strcmp (cmd, STR ("die")))
+    {
+      exit (0);
+    }
+  else if (!strcmp (cmd, STR ("update")))
+    {
+      rcmd_update (frombot, fromhand, fromidx, par);
+    }
   else
     {
       botnet_send_cmdreply (botnetnick, frombot, fromhand, fromidx,
@@ -4259,245 +4564,242 @@ cmd_whoami (struct userrec *u, int idx, char *par)
 {
   dprintf (idx, "You are %s@%s.\n", dcc[idx].nick, botnetnick);
   putlog (LOG_CMDS, "*", "#%s# whoami", dcc[idx].nick);
-} dcc_cmd_t C_dcc[] = {
-
+} dcc_cmd_t C_dcc[] =
+  { {"+host", "m|m", (Function) cmd_pls_host, NULL, NULL}, {"+ignore", "m",
+							    (Function)
+							    cmd_pls_ignore,
+							    NULL, NULL},
+  {"+user", "m", (Function) cmd_pls_user, NULL, NULL},
 #ifdef HUB
-  {"+bot", "a", (Function) cmd_pls_bot, NULL, NULL},
+{"-bot", "a", (Function) cmd_mns_user, NULL, NULL},
 #endif
-  {"+host", "m|m", (Function) cmd_pls_host, NULL, NULL}, {"+ignore", "m",
-							  (Function)
-							  cmd_pls_ignore,
-							  NULL, NULL},
-    {"+user", "m", (Function) cmd_pls_user, NULL, NULL},
+{"-host", "", (Function) cmd_mns_host, NULL, NULL}, {"-ignore", "m",
+						     (Function)
+						     cmd_mns_ignore, NULL,
+						     NULL}, {"-user", "m",
+							     (Function)
+							     cmd_mns_user,
+							     NULL, NULL},
 #ifdef HUB
-  {"-bot", "a", (Function) cmd_mns_user, NULL, NULL},
+{"addlog", "mo|o", (Function) cmd_addlog, NULL, NULL},
 #endif
-  {"-host", "", (Function) cmd_mns_host, NULL, NULL}, {"-ignore", "m",
-						       (Function)
-						       cmd_mns_ignore, NULL,
-						       NULL}, {"-user", "m",
-							       (Function)
-							       cmd_mns_user,
-							       NULL, NULL},
+{"away", "", (Function) cmd_away, NULL, NULL}, {"back", "",
+						(Function) cmd_back, NULL,
+						NULL},
 #ifdef HUB
-  {"addlog", "mo|o", (Function) cmd_addlog, NULL, NULL},
+{"backup", "m|m", (Function) cmd_backup, NULL, NULL}, {"binds", "m",
+						       (Function) cmd_binds,
+						       NULL, NULL}, {"boot",
+								     "m",
+								     (Function)
+								     cmd_boot,
+								     NULL,
+								     NULL},
+  {"botattr", "a", (Function) cmd_botattr, NULL, NULL}, {"botconfig", "n",
+							 (Function)
+							 cmd_botconfig, NULL,
+							 NULL}, {"botinfo",
+								 "",
+								 (Function)
+								 cmd_botinfo,
+								 NULL, NULL},
+  {"bots", "m", (Function) cmd_bots, NULL, NULL}, {"downbots", "m",
+						   (Function) cmd_downbots,
+						   NULL, NULL},
 #endif
-  {"away", "", (Function) cmd_away, NULL, NULL}, {"back", "",
-						  (Function) cmd_back, NULL,
-						  NULL},
+{"botconfig", "n", (Function) cmd_botconfig, NULL, NULL},
 #ifdef HUB
-  {"backup", "m|m", (Function) cmd_backup, NULL, NULL}, {"binds", "m",
-							 (Function) cmd_binds,
-							 NULL, NULL}, {"boot",
-								       "m",
-								       (Function)
-								       cmd_boot,
-								       NULL,
-								       NULL},
-    {"botattr", "a", (Function) cmd_botattr, NULL, NULL}, {"botconfig", "n",
-							   (Function)
-							   cmd_botconfig,
-							   NULL, NULL},
-    {"botinfo", "", (Function) cmd_botinfo, NULL, NULL}, {"bots", "m",
-							  (Function) cmd_bots,
-							  NULL, NULL},
-    {"downbots", "m", (Function) cmd_downbots, NULL, NULL},
+{"bottree", "n", (Function) cmd_bottree, NULL, NULL}, {"chaddr", "a",
+						       (Function) cmd_chaddr,
+						       NULL, NULL},
 #endif
-  {"botconfig", "n", (Function) cmd_botconfig, NULL, NULL},
+{"chat", "", (Function) cmd_chat, NULL, NULL}, {"chattr", "m|m",
+						(Function) cmd_chattr, NULL,
+						NULL},
 #ifdef HUB
-  {"bottree", "n", (Function) cmd_bottree, NULL, NULL}, {"chaddr", "a",
+{"chhandle", "m", (Function) cmd_chhandle, NULL, NULL}, {"chnick", "m",
 							 (Function)
-							 cmd_chaddr, NULL,
-							 NULL},
+							 cmd_chhandle, NULL,
+							 NULL}, {"chpass",
+								 "m",
+								 (Function)
+								 cmd_chpass,
+								 NULL, NULL},
+  {"chsecpass", "n", (Function) cmd_chsecpass, NULL, NULL},
+#ifdef S_DCCPASS
+{"cmdpass", "a", (Function) cmd_cmdpass, NULL, NULL},
+#endif
 #endif
-  {"chat", "", (Function) cmd_chat, NULL, NULL}, {"chattr", "m|m",
-						  (Function) cmd_chattr, NULL,
-						  NULL},
+{"color", "", (Function) cmd_color, NULL, NULL}, {"comment", "m|m",
+						  (Function) cmd_comment,
+						  NULL, NULL}, {"config", "n",
+								(Function)
+								cmd_config,
+								NULL, NULL},
+  {"console", "mo|o", (Function) cmd_console, NULL, NULL},
 #ifdef HUB
-  {"chhandle", "m", (Function) cmd_chhandle, NULL, NULL}, {"chnick", "m",
+{"dccstat", "a", (Function) cmd_dccstat, NULL, NULL},
+#endif
+{"debug", "a", (Function) cmd_debug, NULL, NULL}, {"die", "n",
+						   (Function) cmd_die, NULL,
+						   NULL}, {"echo", "",
 							   (Function)
-							   cmd_chhandle, NULL,
-							   NULL}, {"chpass",
-								   "m",
+							   cmd_echo, NULL,
+							   NULL}, {"fixcodes",
+								   "",
 								   (Function)
-								   cmd_chpass,
+								   cmd_fixcodes,
 								   NULL,
 								   NULL},
-#ifdef S_DCCPASS
-  {"cmdpass", "a", (Function) cmd_cmdpass, NULL, NULL},
-#endif
-#endif
-  {"color", "", (Function) cmd_color, NULL, NULL}, {"comment", "m|m",
-						    (Function) cmd_comment,
-						    NULL, NULL}, {"config",
-								  "n",
-								  (Function)
-								  cmd_config,
-								  NULL, NULL},
-    {"console", "mo|o", (Function) cmd_console, NULL, NULL},
+  {"handle", "", (Function) cmd_handle, NULL, NULL}, {"help", "",
+						      (Function) cmd_help,
+						      NULL, NULL}, {"ignores",
+								    "m",
+								    (Function)
+								    cmd_ignores,
+								    NULL,
+								    NULL},
 #ifdef HUB
-  {"dccstat", "a", (Function) cmd_dccstat, NULL, NULL},
+{"link", "n", (Function) cmd_link, NULL, NULL},
 #endif
-  {"debug", "a", (Function) cmd_debug, NULL, NULL}, {"die", "n",
-						     (Function) cmd_die, NULL,
-						     NULL}, {"echo", "",
+{"match", "m|m", (Function) cmd_match, NULL, NULL}, {"me", "",
+						     (Function) cmd_me, NULL,
+						     NULL}, {"motd", "",
 							     (Function)
-							     cmd_echo, NULL,
+							     cmd_motd, NULL,
 							     NULL},
-    {"fixcodes", "", (Function) cmd_fixcodes, NULL, NULL}, {"handle", "",
-							    (Function)
-							    cmd_handle, NULL,
-							    NULL}, {"help",
+#ifdef HUB
+{"mtcl", "a", (Function) cmd_mtcl, NULL, NULL}, {"newleaf", "n",
+						 (Function) cmd_newleaf, NULL,
+						 NULL},
+#endif
+{"newpass", "", (Function) cmd_newpass, NULL, NULL}, {"secpass", "",
+						      (Function) cmd_secpass,
+						      NULL, NULL}, {"nick",
 								    "",
 								    (Function)
-								    cmd_help,
+								    cmd_handle,
 								    NULL,
 								    NULL},
-    {"ignores", "m", (Function) cmd_ignores, NULL, NULL},
+  {"page", "", (Function) cmd_page, NULL, NULL}, {"quit", "", (Function) NULL,
+						  NULL, NULL}, {"relay", "i",
+								(Function)
+								cmd_relay,
+								NULL, NULL},
 #ifdef HUB
-  {"link", "n", (Function) cmd_link, NULL, NULL},
+{"reload", "m|m", (Function) cmd_reload, NULL, NULL},
 #endif
-  {"match", "m|m", (Function) cmd_match, NULL, NULL}, {"me", "",
-						       (Function) cmd_me,
-						       NULL, NULL}, {"motd",
-								     "",
-								     (Function)
-								     cmd_motd,
-								     NULL,
-								     NULL},
-#ifdef HUB
-  {"mtcl", "a", (Function) cmd_mtcl, NULL, NULL}, {"newleaf", "n",
-						   (Function) cmd_newleaf,
-						   NULL, NULL},
-#endif
-  {"newpass", "", (Function) cmd_newpass, NULL, NULL}, {"nick", "",
-							(Function) cmd_handle,
-							NULL, NULL}, {"page",
-								      "",
-								      (Function)
-								      cmd_page,
-								      NULL,
-								      NULL},
-    {"quit", "", (Function) NULL, NULL, NULL}, {"rehash", "m",
-						(Function) cmd_rehash, NULL,
-						NULL}, {"relay", "i",
-							(Function) cmd_relay,
-							NULL, NULL},
+{"restart", "m", (Function) cmd_restart, NULL, NULL},
 #ifdef HUB
-  {"reload", "m|m", (Function) cmd_reload, NULL, NULL},
+{"save", "m|m", (Function) cmd_save, NULL, NULL}, {"set", "a",
+						   (Function) cmd_set, NULL,
+						   NULL},
 #endif
-  {"restart", "m", (Function) cmd_restart, NULL, NULL},
-#ifdef HUB
-  {"save", "m|m", (Function) cmd_save, NULL, NULL}, {"set", "a",
-						     (Function) cmd_set, NULL,
-						     NULL},
-#endif
-  {"simul", "a", (Function) cmd_simul, NULL, NULL}, {"status", "m|m",
-						     (Function) cmd_status,
-						     NULL, NULL}, {"strip",
-								   "",
-								   (Function)
-								   cmd_strip,
-								   NULL,
-								   NULL},
-    {"su", "a", (Function) cmd_su, NULL, NULL}, {"tcl", "a",
-						 (Function) cmd_tcl, NULL,
-						 NULL},
-#ifdef HUB
-  {"trace", "n", (Function) cmd_trace, NULL, NULL},
-#endif
-  {"traffic", "m", (Function) cmd_traffic, NULL, NULL}, {"unlink", "m",
-							 (Function)
-							 cmd_unlink, NULL,
-							 NULL}, {"update",
-								 "a",
+{"simul", "a", (Function) cmd_simul, NULL, NULL}, {"status", "m|m",
+						   (Function) cmd_status,
+						   NULL, NULL}, {"strip", "",
 								 (Function)
-								 cmd_update,
+								 cmd_strip,
 								 NULL, NULL},
-    {"uptime", "m|m", (Function) cmd_uptime, NULL, NULL},
+  {"su", "a", (Function) cmd_su, NULL, NULL}, {"tcl", "a", (Function) cmd_tcl,
+					       NULL, NULL},
 #ifdef HUB
-  {"vbottree", "n", (Function) cmd_vbottree, NULL, NULL}, {"who", "n",
-							   (Function) cmd_who,
-							   NULL, NULL},
+{"trace", "n", (Function) cmd_trace, NULL, NULL},
 #endif
-  {"whois", "o|o", (Function) cmd_whois, NULL, NULL}, {"whom", "",
-						       (Function) cmd_whom,
-						       NULL, NULL}, {"whoami",
-								     "",
+{"traffic", "m", (Function) cmd_traffic, NULL, NULL}, {"unlink", "m",
+						       (Function) cmd_unlink,
+						       NULL, NULL}, {"update",
+								     "a",
 								     (Function)
-								     cmd_whoami,
+								     cmd_update,
 								     NULL,
 								     NULL},
-    {"botjump", "n", (Function) cmd_botjump, NULL, NULL}, {"botmsg", "o",
+#ifdef HUB
+{"botupdate", "a", (Function) cmd_botupdate, NULL, NULL}, {"botcrontab", "a",
 							   (Function)
-							   cmd_botmsg, NULL,
-							   NULL}, {"netmsg",
-								   "n",
+							   cmd_botcrontab,
+							   NULL, NULL},
+  {"netcrontab", "a", (Function) cmd_netcrontab, NULL, NULL},
+#endif
+{"uptime", "m|m", (Function) cmd_uptime, NULL, NULL}, {"crontab", "a",
+						       (Function) cmd_crontab,
+						       NULL, NULL},
+#ifdef HUB
+{"vbottree", "n", (Function) cmd_vbottree, NULL, NULL}, {"who", "n",
+							 (Function) cmd_who,
+							 NULL, NULL},
+#endif
+{"whois", "o|o", (Function) cmd_whois, NULL, NULL}, {"whom", "",
+						     (Function) cmd_whom,
+						     NULL, NULL}, {"whoami",
+								   "",
 								   (Function)
-								   cmd_netmsg,
+								   cmd_whoami,
 								   NULL,
 								   NULL},
-    {"botnick", "m", (Function) cmd_botnick, NULL, NULL}, {"netnick", "m",
-							   (Function)
-							   cmd_netnick, NULL,
-							   NULL}, {"botw",
-								   "n",
+  {"botjump", "n", (Function) cmd_botjump, NULL, NULL},
+#ifdef HUB
+{"botdie", "a", (Function) cmd_botdie, NULL, NULL},
+#endif
+{"botmsg", "o", (Function) cmd_botmsg, NULL, NULL}, {"netmsg", "n",
+						     (Function) cmd_netmsg,
+						     NULL, NULL}, {"botnick",
+								   "m",
 								   (Function)
-								   cmd_botw,
+								   cmd_botnick,
 								   NULL,
 								   NULL},
-    {"netw", "n", (Function) cmd_netw, NULL, NULL}, {"botps", "n",
-						     (Function) cmd_botps,
+  {"netnick", "m", (Function) cmd_netnick, NULL, NULL}, {"botw", "n",
+							 (Function) cmd_botw,
+							 NULL, NULL}, {"netw",
+								       "n",
+								       (Function)
+								       cmd_netw,
+								       NULL,
+								       NULL},
+  {"botps", "n", (Function) cmd_botps, NULL, NULL}, {"botkill", "n",
+						     (Function) cmd_botkill,
 						     NULL, NULL}, {"netps",
 								   "n",
 								   (Function)
 								   cmd_netps,
 								   NULL,
 								   NULL},
-    {"botlast", "n", (Function) cmd_botlast, NULL, NULL}, {"netlast", "n",
-							   (Function)
-							   cmd_netlast, NULL,
-							   NULL}, {"netlag",
-								   "m",
-								   (Function)
-								   cmd_netlag,
-								   NULL,
-								   NULL},
-    {"botserver", "m", (Function) cmd_botserver, NULL, NULL}, {"netserver",
-							       "m",
-							       (Function)
-							       cmd_netserver,
-							       NULL, NULL},
-    {"botversion", "o", (Function) cmd_botversion, NULL, NULL}, {"netversion",
-								 "o",
+  {"botlast", "n", (Function) cmd_botlast, NULL, NULL}, {"netlast", "n",
+							 (Function)
+							 cmd_netlast, NULL,
+							 NULL}, {"netlag",
+								 "m",
 								 (Function)
-								 cmd_netversion,
+								 cmd_netlag,
 								 NULL, NULL},
-    {"userlist", "m", (Function) cmd_userlist, NULL, NULL}, {"ps", "n",
-							     (Function)
-							     cmd_ps, NULL,
-							     NULL}, {"last",
-								     "n",
-								     (Function)
-								     cmd_last,
-								     NULL,
-								     NULL},
-    {"exec", "a", (Function) cmd_exec, NULL, NULL}, {"w", "n",
-						     (Function) cmd_w, NULL,
-						     NULL}, {"channels", "o",
+  {"botserver", "m", (Function) cmd_botserver, NULL, NULL}, {"netserver", "m",
 							     (Function)
-							     cmd_channels,
+							     cmd_netserver,
 							     NULL, NULL},
+  {"botversion", "o", (Function) cmd_botversion, NULL, NULL}, {"netversion",
+							       "o",
+							       (Function)
+							       cmd_netversion,
+							       NULL, NULL},
+  {"userlist", "m", (Function) cmd_userlist, NULL, NULL}, {"ps", "n",
+							   (Function) cmd_ps,
+							   NULL, NULL},
+  {"last", "n", (Function) cmd_last, NULL, NULL}, {"exec", "a",
+						   (Function) cmd_exec, NULL,
+						   NULL}, {"w", "n",
+							   (Function) cmd_w,
+							   NULL, NULL},
+  {"channels", "o", (Function) cmd_channels, NULL, NULL},
 #ifdef HUB
-  {"hublevel", "a", (Function) cmd_hublevel, NULL, NULL}, {"lagged", "m",
-							   (Function)
-							   cmd_lagged, NULL,
-							   NULL}, {"uplink",
-								   "a",
-								   (Function)
-								   cmd_uplink,
-								   NULL,
-								   NULL},
+{"hublevel", "a", (Function) cmd_hublevel, NULL, NULL}, {"lagged", "m",
+							 (Function)
+							 cmd_lagged, NULL,
+							 NULL}, {"uplink",
+								 "a",
+								 (Function)
+								 cmd_uplink,
+								 NULL, NULL},
 #endif
-  {NULL, NULL, NULL, NULL, NULL, NULL}
+{NULL, NULL, NULL, NULL, NULL, NULL}
 };

+ 16 - 6
src/dcc.c

@@ -28,9 +28,9 @@ int dcc_total = 0;
 int allow_new_telnets = 0;
 int use_telnet_banner = 0;
 char network[41] = "EFnet";
-int password_timeout = 30;
+int password_timeout = 15;
 int bot_timeout = 25;
-int identtimeout = 5;
+int identtimeout = 10;
 int dupwait_timeout = 5;
 int protect_telnet = 0;
 int flood_telnet_thr = 10;
@@ -65,6 +65,8 @@ rand_dccresp ()
 	"mIRC v6.03 File Server\n\nUse: cd dir ls get read help exit\n[\\]\n";
     case 8:
       return "got any porn?\n";
+    case 9:
+      return "?\n";
     default:
       return "";
     }
@@ -192,6 +194,7 @@ send_timesync (idx)
 	  if ((dcc[i].type == &DCC_BOT) && (bot_aggressive_to (dcc[i].user)))
 	    {
 	      dprintf (i, s);
+	      lower_bot_linked (i);
 	    }
 	}
 #else
@@ -428,8 +431,12 @@ eof_dcc_bot_new (int idx)
 } static void
 timeout_dcc_bot_new (int idx)
 {
+#ifdef LEAF
+  putlog (LOG_BOTS, "*", "Timeout: bot link to %s", dcc[idx].nick);
+#else
   putlog (LOG_BOTS, "*", DCC_TIMEOUT, dcc[idx].nick, dcc[idx].host,
 	  dcc[idx].port);
+#endif
   killsock (dcc[idx].sock);
   lostdcc (idx);
 } static void
@@ -462,10 +469,13 @@ dcc_bot (int idx, char *code, int i)
   strip_telnet (dcc[idx].sock, code, &i);
   if (debug_output)
     {
-      if (code[0] == 's')
-	putlog (LOG_BOTSHARE, "@", "{%s} %s", dcc[idx].nick, code + 2);
-      else
-	putlog (LOG_BOTNET, "@", "[%s] %s", dcc[idx].nick, code);
+      if (code[0] != 'h' && code[1] != 'l' && code[2] != ' ')
+	{
+	  if (code[0] == 's')
+	    putlog (LOG_BOTSHARE, "@", "{%s} %s", dcc[idx].nick, code + 2);
+	  else
+	    putlog (LOG_BOTNET, "@", "[%s] %s", dcc[idx].nick, code);
+	}
     }
   msg = strchr (code, ' ');
   if (msg)

+ 4 - 0
src/eggdrop.h

@@ -16,6 +16,10 @@
 #define SERVLEN 60
 #define LANGDIR	"./.language"
 #define BASELANG "english"
+#define op_time_slack (CFG_OPTIMESLACK.gdata ? atoi(CFG_OPTIMESLACK.gdata) : 60)
+#ifdef G_AUTOLOCK
+#define kill_threshold (CFG_KILLTHRESHOLD.gdata ? atoi(CFG_KILLTHRESHOLD.gdata) : 0)
+#endif
 #define PRIO_DEOP 1
 #define PRIO_KICK 2
 #define KICK_BANNED 1

+ 12 - 0
src/flags.h

@@ -16,6 +16,18 @@ struct flag_record
 #define FR_AND 0x20000000
 #define FR_ANYWH 0x10000000
 #define FR_ALL 0x0fffffff
+#define ROLE_KICK_MDOP (role)
+#define ROLE_KICK_MEAN (role)
+#define DEFLAG_BADCOOKIE 1
+#ifdef G_MANUALOP
+#define DEFLAG_MANUALOP 2
+#endif
+#ifdef G_MEAN
+#define DEFLAG_MEAN_DEOP 3
+#define DEFLAG_MEAN_KICK 4
+#define DEFLAG_MEAN_BAN 5
+#endif
+#define DEFLAG_MDOP 6
 #define USER_VALID 0x03ffffff
 #define CHAN_VALID 0x03ffffff
 #define BOT_VALID 0x7fe689C1

+ 23 - 17
src/main.c

@@ -54,8 +54,8 @@ extern jmp_buf alarmret;
 extern void check_last ();
 int role;
 int loading = 0;
-char egg_version[1024] = "1.0.04";
-int egg_numver = 1000400;
+char egg_version[1024] = "1.0.06";
+int egg_numver = 1000600;
 time_t lastfork = 0;
 #ifdef HUB
 int my_port;
@@ -533,16 +533,22 @@ core_10secondly ()
     check_trace ();
 #endif
 #ifdef S_LASTCHECK
-  if (curcheck == 2)
-    check_last ();
+#ifdef LEAF
+  if (localhub)
 #endif
-  if (curcheck == 3)
-    {
+    if (curcheck == 2)
+      check_last ();
+#endif
+#ifdef LEAF
+  if (localhub)
+#endif
+    if (curcheck == 3)
+      {
 #ifdef S_PROCESSCHECK
-      check_processes ();
+	check_processes ();
 #endif
-      curcheck = 0;
-    }
+	curcheck = 0;
+      }
   Context;
   autolink_cycle (NULL);
 }
@@ -781,9 +787,10 @@ extern module_entry *module_list;
 void restart_chons ();
 void check_static (char *, char *(*)());
 #include "mod/static.h"
-int init_mem (), init_dcc_max (), init_userent (), init_misc (), init_bots (),
-init_net (), init_modules (), init_tcl (int, char **), init_language (int),
-init_botcmd ();
+int init_userrec (), init_mem (), init_dcc_max (), init_userent (),
+init_misc (), init_bots (), init_net (), init_modules (), init_tcl (int,
+								    char **),
+init_language (int), init_botcmd ();
 void
 checklockfile ()
 {
@@ -1047,6 +1054,8 @@ main (int argc, char **argv)
     }
 #ifdef LEAF
   id = geteuid ();
+  if (!id)
+    fatal ("Cannot read userid.", 0);
   pw = getpwuid (id);
   if (!pw)
     fatal ("Cannot read from the passwd file.", 0);
@@ -1141,6 +1150,7 @@ main (int argc, char **argv)
   init_bots ();
   init_net ();
   init_modules ();
+  init_userrec ();
   if (backgrd)
     bg_prepare_split ();
   init_tcl (argc, argv);
@@ -1189,7 +1199,7 @@ main (int argc, char **argv)
 	      newsplit (&temps);
 	      sprintf (check, "%s %s", unix_n, vers_n);
 	      if (strcmp (temps, check))
-		fatal ("Go away.", 0);
+		fatal ("Go away..", 0);
 	    }
 	  else if (c[0] == '!')
 	    {
@@ -1307,13 +1317,9 @@ main (int argc, char **argv)
   module_load ("transfer");
   module_load ("share");
   module_load ("update");
-#ifdef HUB
   module_load ("notes");
-#endif
   module_load ("console");
-#ifdef LEAF
   module_load ("ctcp");
-#endif
   module_load ("compress");
   chanprog ();
 #ifdef LEAF

+ 46 - 10
src/misc.c

@@ -19,7 +19,7 @@ extern struct chanset_t *chanset;
 extern char version[], origbotname[], botname[], admin[], network[],
   motdfile[], ver[], botnetnick[], bannerfile[], logfile_suffix[], textdir[],
   *binname, pid_file[], netpass[], tempdir[], mhub[];
-extern int backgrd, con_chan, term_z, use_stderr, dcc_total,
+extern int backgrd, con_chan, term_z, use_stderr, dcc_total, timesync,
 #ifdef HUB
   my_port,
 #endif
@@ -1199,14 +1199,20 @@ check_last ()
   struct passwd *pw;
   Context;
   pw = getpwuid (geteuid ());
+  Context;
+  if (!pw)
+    return;
   strncpy0 (user, pw->pw_name ? pw->pw_name : "", sizeof (user));
+  Context;
   if (user[0])
     {
       char *out;
       char buf[50];
       sprintf (buf, "last %s", user);
+      Context;
       if (shell_exec (buf, NULL, &out, NULL))
 	{
+	  Context;
 	  if (out)
 	    {
 	      char *p;
@@ -1357,7 +1363,7 @@ userfile_cfg_line (char *ln)
       set_cfg_str (NULL, cfgent->name, ln[0] ? ln : NULL);
     }
   else
-    putlog (LOG_MISC, "*", STR ("Unrecognized config entry %s in userfile"),
+    putlog (LOG_ERRORS, "*", STR ("Unrecognized config entry %s in userfile"),
 	    name);
 }
 
@@ -1378,9 +1384,13 @@ got_config_share (int idx, char *ln)
       botnet_send_cfg_broad (idx, cfgent);
     }
   else
-    putlog (LOG_MISC, "*", STR ("Unrecognized config entry %s in userfile"),
+    putlog (LOG_ERRORS, "*", STR ("Unrecognized config entry %s in userfile"),
 	    name);
   cfg_noshare--;
+  Context;
+#ifdef HUB
+  write_userfile (-1);
+#endif
 }
 
 void
@@ -1437,14 +1447,12 @@ shell_exec (char *cmdline, char *input, char **output, char **erroutput)
     }
   p++;
   strcpy (p, ".i");
-  inpFile = fopen (fname, "w+");
   unlink (fname);
+  inpFile = fopen (fname, "w+");
   if (!inpFile)
     {
       putlog (LOG_MISC, "*", "exec: Couldn't open %s", fname);
       nfree (fname);
-      Context;
-      fclose (inpFile);
       return 0;
     }
   if (input)
@@ -1459,20 +1467,18 @@ shell_exec (char *cmdline, char *input, char **output, char **erroutput)
       fseek (inpFile, 0, SEEK_SET);
     }
   strcpy (p, ".e");
-  errFile = fopen (fname, "w+");
   unlink (fname);
+  errFile = fopen (fname, "w+");
   if (!errFile)
     {
       putlog (LOG_MISC, "*", "exec: Couldn't open %s", fname);
       nfree (fname);
       fclose (inpFile);
-      Context;
-      fclose (errFile);
       return 0;
     }
   strcpy (p, ".o");
-  outFile = fopen (fname, "w+");
   unlink (fname);
+  outFile = fopen (fname, "w+");
   if (!outFile)
     {
       putlog (LOG_MISC, "*", "exec: Couldn't open %s", fname);
@@ -1597,6 +1603,7 @@ updatelocal (void)
   botnet_send_chat (-1, botnetnick, "Updating...");
   botnet_send_bye ();
   fatal ("Updating...", 1);
+  usleep (2000 * 500);
   bg_send_quit (BG_ABORT);
   unlink (pid_file);
   system (binname);
@@ -1712,6 +1719,7 @@ updatebin (int idx, char *par, int autoi)
 	  botnet_send_chat (-1, botnetnick, "Updating...");
 	  botnet_send_bye ();
 	  fatal ("Updating...", 1);
+	  usleep (2000 * 500);
 	  bg_send_quit (BG_ABORT);
 	  exit (0);
 #ifdef LEAF
@@ -2020,3 +2028,31 @@ kickreason (int kind)
       return "!";
     }
 }
+char kickprefix[20] = "";
+char bankickprefix[20] = "";
+void
+makeplaincookie (char *chname, char *nick, char *buf)
+{
+  char work[256], work2[256];
+  int i, n;
+  sprintf (work, STR ("%010li"), (now + timesync));
+  strcpy (buf, (char *) &work[4]);
+  work[0] = 0;
+  if (strlen (nick) < 5)
+    while (strlen (work) + strlen (nick) < 5)
+      strcat (work, " ");
+  else
+    strcpy (work, (char *) &nick[strlen (nick) - 5]);
+  strcat (buf, work);
+  n = 3;
+  for (i = strlen (chname) - 1; (i >= 0) && (n >= 0); i--)
+    if (((unsigned char) chname[i] < 128) && ((unsigned char) chname[i] > 32))
+      {
+	work2[n] = tolower (chname[i]);
+	n--;
+      }
+  while (n >= 0)
+    work2[n--] = ' ';
+  work2[4] = 0;
+  strcat (buf, work2);
+}

+ 5 - 44
src/mod/channels.mod/channels.c

@@ -5,9 +5,6 @@
 static Function *global = NULL;
 static int setstatic;
 static int use_info;
-#ifdef ROLE
-static int role;
-#endif
 static char chanfile[121];
 static int chan_hack;
 static int quiet_save;
@@ -178,45 +175,11 @@ got_cjoin (char *botnick, char *code, char *par)
 #endif
     }
 }
-
-#ifdef ROLE
 static void
 got_role (char *botnick, char *code, char *par)
 {
   role = atoi (par);
   putlog (LOG_DEBUG, "*", "Got role index %i", role);
-} static int
-get_role (char *bot)
-{
-  int rl, i;
-  struct bot_addr *ba;
-  int r[5] = { 0, 0, 0, 0, 0 };
-  struct userrec *u, *u2;
-  u2 = get_user_by_handle (userlist, bot);
-  if (!u2)
-    return 1;
-  for (u = userlist; u; u = u->next)
-    {
-      if (u->flags & USER_BOT)
-	{
-	  if (strcmp (u->handle, bot))
-	    {
-	      ba = get_user (&USERENTRY_BOTADDR, u);
-	      if ((nextbot (u->handle) >= 0) && (ba) && (ba->roleid > 0)
-		  && (ba->roleid < 5))
-		r[(ba->roleid - 1)]++;
-	    }
-	}
-    }
-  rl = 0;
-  for (i = 1; i <= 4; i++)
-    if (r[i] < r[rl])
-      rl = i;
-  rl++;
-  ba = get_user (&USERENTRY_BOTADDR, u2);
-  if (ba)
-    ba->roleid = rl;
-  return rl;
 }
 
 #ifdef HUB
@@ -275,7 +238,6 @@ rebalance_roles ()
     }
 }
 #endif
-#endif
 static void
 channels_checkslowjoin ()
 {
@@ -826,12 +788,8 @@ cmd_t channels_bot[] = { {"cjoin", "", (Function) got_cjoin, NULL}
 , {"cset", "", (Function) got_cset, NULL}
 , {"cycle", "", (Function) got_cycle, NULL}
 , {"down", "", (Function) got_down, NULL}
-,
-#ifdef ROLE
-{"rl", "", (Function) got_role, NULL}
-,
-#endif
-{"sj", "", (Function) got_sj, NULL}
+, {"rl", "", (Function) got_role, NULL}
+, {"sj", "", (Function) got_sj, NULL}
 , {0, 0, 0, 0}
 };
 static tcl_ints my_tcl_ints[] =
@@ -974,6 +932,9 @@ channels_start (Function * global_funcs)
   add_hook (HOOK_SWITCH_STATIC, (Function) switch_static);
 #ifdef LEAF
   add_hook (HOOK_MINUTELY, (Function) check_limitraise);
+#endif
+#ifdef HUB
+  add_hook (HOOK_30SECONDLY, (Function) rebalance_roles);
 #endif
   add_hook (HOOK_MINUTELY, (Function) check_expired_bans);
 #ifdef S_IRCNET

+ 1 - 1
src/mod/channels.mod/tclchan.c

@@ -1936,7 +1936,7 @@ tcl_channel_add (Tcl_Interp * irp, char *newname, char *options)
       chan->stopnethack_mode = global_stopnethack_mode;
       chan->revenge_mode = global_revenge_mode;
       chan->idle_kick = global_idle_kick;
-      chan->limitraise = 0;
+      chan->limitraise = 20;
       chan->ban_time = global_ban_time;
       chan->exempt_time = global_exempt_time;
       chan->invite_time = global_invite_time;

+ 0 - 20
src/mod/console.mod/help/console.help

@@ -1,20 +0,0 @@
-%{help=console module}
-###  help for the %bconsole module%b
-   The console module provides the ability to store your console
-   settings so that next time you use the party line they are set.
-   You can use the %b'.store'%b command at any time to store
-   it, or it may be configured to save automatically.
-%{+n}
-   The following Tcl variables are available for setting up the
-   console module: (%b'.help set <variable>'%b for more info)
-     %bconsole-autosave%b   %bforce-channel%b
-     %binfo-party%b         
-%{help=store}
-###  %bstore%b
-   Stores you console settings so that they are set automatically
-   next time you join the party line.
-   
-See Also: set console-autosave
-%{help=all}
-###  commands for the %bconsole module%b
-  %bstore%b

+ 0 - 15
src/mod/console.mod/help/set/console.help

@@ -1,15 +0,0 @@
-%{help=set console-autosave}%{+n}
-###  %bset console-autosave%b 0/1
-   When this flag is set, a users console settings are automatically
-   saved for the next time the user joins the party line.
-   
-See Also: store
-%{help=set force-channel}%{+n}
-###  %bset force-channel%b <chan#>
-   This specifies the channel to dumb users who have no stored
-   console settings on, 0 is the party line, 1-99999 are global
-   chat lines & 10000-19999 are bot-only chat lines.
-%{help=set info-party}%{+n}
-###  %bset info-party%b 0/1
-   When set, this flag causes a users info line to be displayed
-   to the *current* chat channel when they join it.

+ 748 - 92
src/mod/ctcp.mod/ctcp.c

@@ -1,21 +1,471 @@
-#ifdef LEAF
 #define MODULE_NAME "ctcp"
 #define MAKING_CTCP
 #include "ctcp.h"
 #include "src/mod/module.h"
+#ifdef LEAF
 #include "server.mod/server.h"
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif
+#include <pwd.h>
+#include <ctype.h>
 static Function *global = NULL, *server_funcs = NULL;
-static char ctcp_version[121];
-static char ctcp_finger[121];
-static char ctcp_userinfo[121];
-static int ctcp_mode = 0;
-static int listen_time = 0;
+#else
+static Function *global = NULL;
+#endif
+#define CLOAK_COUNT 10
+#define CLOAK_PLAIN 1
+#define CLOAK_CRACKROCK 2
+#define CLOAK_NEONAPPLE 3
+#define CLOAK_TUNNELVISION 4
+#define CLOAK_ARGON 5
+#define CLOAK_EVOLVER 6
+#define CLOAK_PREVAIL 7
+#define CLOAK_CYPRESS 8
+#define CLOAK_MIRC 9
+int cloak_script = CLOAK_PLAIN;
+#ifdef LEAF
+#ifdef S_AUTOAWAY
+#define AVGAWAYTIME 60
+#define AVGHERETIME 5
+#endif
+int cloak_awaytime = 0;
+int cloak_heretime = 0;
+int listen_time = 0;
+char cloak_bxver[10];
+char cloak_os[20];
+char cloak_osver[100];
+char cloak_host[161];
+char ctcpversion[400];
+char ctcpuserinfo[400];
+char autoaway[100];
+char *
+strtolower (char *s)
+{
+  char *p, *p2 = nmalloc (strlen (s) + 1);
+  strcpy (p2, s);
+  p = p2;
+  while (*p)
+    {
+      *p = tolower (*p);
+      p++;
+    }
+  return p2;
+}
+
+void
+scriptchanged ()
+{
+  char tmp[200], *p;
+  switch (cloak_script)
+    {
+    case CLOAK_PLAIN:
+      sprintf (ctcpversion,
+	       STR
+	       ("\002BitchX-%s\002 by panasync - %s %s : \002Keep it to yourself!\002"),
+	       cloak_bxver, cloak_os, cloak_osver);
+      strcpy (ctcpuserinfo, "");
+      strcpy (autoaway, STR ("Auto-Away after 10 mins"));
+      strcpy (kickprefix, "");
+      strcpy (bankickprefix, "");
+      break;
+    case CLOAK_CRACKROCK:
+      sprintf (ctcpversion,
+	       STR
+	       ("BitchX-%s\002/\002%s %s:(\002c\002)\037rackrock\037/\002b\002X \037[\0373.0.1á9\037]\037 :\002 Keep it to yourself!\002"),
+	       cloak_bxver, cloak_os, cloak_osver);
+      strcpy (ctcpuserinfo, STR ("crack addict, help me."));
+      strcpy (autoaway, STR ("automatically dead"));
+      strcpy (kickprefix, STR ("\002c\002/\037k\037: "));
+      strcpy (bankickprefix, STR ("\002c\002/\037kb\037: "));
+      break;
+    case CLOAK_NEONAPPLE:
+      sprintf (tmp, STR ("%s %s"), cloak_os, cloak_osver);
+      p = strtolower (tmp);
+      sprintf (ctcpversion,
+	       STR
+	       ("bitchx-%s\037(\037%s\037):\037 \002n\002eon\037a\037ppl\002e\002\037/\037\002v\0020\037.\03714i : \002d\002ont you wish you had it\037?\037"),
+	       cloak_bxver, p);
+      nfree (p);
+      strcpy (ctcpuserinfo, STR ("neon apple"));
+      strcpy (autoaway,
+	      STR
+	      ("automatically away after 10 mins \037(\037\002n\002/\037a)\037"));
+      strcpy (kickprefix, STR ("\037[na\002(\037k\037)\002]\037 "));
+      strcpy (bankickprefix, "");
+      break;
+    case CLOAK_TUNNELVISION:
+      strcpy (tmp, cloak_bxver);
+      p = tmp;
+      p += strlen (tmp) - 1;
+      p[1] = p[0];
+      p[0] = '\037';
+      p[2] = '\037';
+      p[3] = 0;
+      sprintf (ctcpversion,
+	       STR ("\002b\002itchx-%s :tunnel\002vision\002/\0371.2\037"),
+	       tmp);
+      strcpy (ctcpuserinfo, "");
+      strcpy (autoaway, STR ("auto-gone"));
+      strcpy (kickprefix, "");
+      strcpy (bankickprefix, "");
+      break;
+    case CLOAK_ARGON:
+      sprintf (ctcpversion,
+	       STR
+	       (".\037.(\037argon\002/\0021g\037)\037 \002:\002bitchx-%s"),
+	       cloak_bxver);
+      strcpy (ctcpuserinfo, "");
+      strcpy (autoaway,
+	      STR ("\037(\037ar\037)\037 auto-away \037(\03710m\037)\037"));
+      strcpy (kickprefix, STR ("\037(\037ar\037)\037 "));
+      strcpy (bankickprefix, STR ("\037(\037ar\037)\037 "));
+      break;
+    case CLOAK_EVOLVER:
+      sprintf (ctcpversion,
+	       STR
+	       ("\037evolver\037(\00202x9\002)\037: bitchx\037(\002%s\002) \037í\037 %s\002/\002%s : eye yam pheerable now!"),
+	       cloak_bxver, cloak_os, cloak_osver);
+      strcpy (ctcpuserinfo, "");
+      strcpy (autoaway,
+	      STR ("[\037\002i\002dle for \037[\03710 minutes\037]]"));
+      strcpy (kickprefix, STR ("\037ev\002!\002k\037 "));
+      strcpy (bankickprefix, STR ("\037ev\002!\002bk\037 "));
+      break;
+    case CLOAK_PREVAIL:
+      sprintf (ctcpversion,
+	       STR
+	       ("%s\037!\037%s bitchx-%s \002-\002 prevail\037[\0370123\037]\037 :down with people"),
+	       cloak_os, cloak_osver, cloak_bxver);
+      strcpy (ctcpuserinfo, botrealname);
+      strcpy (autoaway, STR ("idle 10 minutes \037-\037 gone\037!\037"));
+      strcpy (kickprefix, STR ("\037[\037pv\037!\037k\037]\037 "));
+      strcpy (bankickprefix, STR ("\037[\037pv\037!\037bk\037]\037 "));
+      break;
+    case CLOAK_MIRC:
+      sprintf (ctcpversion, STR ("mIRC v6.03 Khaled Mardam-Bey"));
+      strcpy (ctcpuserinfo, botrealname);
+      strcpy (autoaway, STR ("auto-away after 10 minutes"));
+      break;
+    case CLOAK_CYPRESS:
+      {
+	char theme[30];
+	switch (random () % 25)
+	  {
+	  case 0:
+	    strcpy (theme, STR (" \037.\037.\002BX\002"));
+	    break;
+	  case 1:
+	    strcpy (theme, STR (" \037.\037.chl\037o\037rine"));
+	    break;
+	  case 2:
+	    strcpy (theme, STR (" \037.\037.\037<\037c\002x\002\037>\037"));
+	    break;
+	  case 3:
+	    strcpy (theme, STR (" \037.\037.supercyan"));
+	    break;
+	  case 4:
+	    strcpy (theme,
+		    STR
+		    (" \037.\037.\037c\037yan\002i\002\002\037z\037\002\037e\037d"));
+	    break;
+	  case 5:
+	    strcpy (theme, STR (" \037.\037.delusion"));
+	    break;
+	  case 6:
+	    strcpy (theme, STR (" \037.\037.\002e\002mbryonic"));
+	    break;
+	  case 7:
+	    strcpy (theme,
+		    STR
+		    (" \037.\037.e\002x\002tra\037.\037terrestr\037i\037al"));
+	    break;
+	  case 8:
+	    strcpy (theme, STR (" \037.\037.\002f\002ad\037e\037d"));
+	    break;
+	  case 9:
+	    strcpy (theme, STR (" \037.\037.fo\037c\037us"));
+	    break;
+	  case 10:
+	    strcpy (theme, STR (" \037.\037.\002h\002ade\037s\037"));
+	    break;
+	  case 11:
+	    strcpy (theme, STR (" \037.\037.hellbent\037.\037"));
+	    break;
+	  case 12:
+	    strcpy (theme, STR (" \037.\037.illusi\037o\037n"));
+	    break;
+	  case 13:
+	    strcpy (theme, STR (" \037.\037.\037j\037ungl\037e\037"));
+	    break;
+	  case 14:
+	    strcpy (theme, STR (" \037.\037.\002l\002abry\037i\037nth"));
+	    break;
+	  case 15:
+	    strcpy (theme, STR (" \037.\037.nightblue"));
+	    break;
+	  case 16:
+	    strcpy (theme,
+		    STR (" \037.\037.\037o\037bli\037v\037io\037n\037"));
+	    break;
+	  case 17:
+	    strcpy (theme, STR (" \037.\037.ph\002a\002ze"));
+	    break;
+	  case 18:
+	    strcpy (theme, STR (" \037.\037.sphere"));
+	    break;
+	  case 19:
+	    strcpy (theme, STR (" \037.\037.zip"));
+	    break;
+	  default:
+	    strcpy (theme, STR (""));
+	    break;
+	  }
+	switch (random () % 16)
+	  {
+	  case 0:
+	    sprintf (ctcpversion,
+		     STR
+		     ("bitchx\037-\037%s \037/\037 cypress\037.\03701i%s"),
+		     cloak_bxver, theme);
+	    break;
+	  case 1:
+	    sprintf (ctcpversion,
+		     STR
+		     ("cypress\037.\03701i%s \037/\037 bitchx\037-\037%s"),
+		     theme, cloak_bxver);
+	    break;
+	  case 2:
+	    sprintf (tmp, STR ("%s %s"), cloak_os, cloak_osver);
+	    p = strtolower (tmp);
+	    sprintf (ctcpversion,
+		     STR
+		     ("cypress\037.\03701i%s %s\037(\037%s\037)\037 bitchx\037-\037%s)"),
+		     theme, p, cloak_host, cloak_bxver);
+	    nfree (p);
+	    break;
+	  case 3:
+	    sprintf (tmp, STR ("%s %s"), cloak_os, cloak_osver);
+	    p = strtolower (tmp);
+	    sprintf (ctcpversion,
+		     STR
+		     ("bitchx\037-\037%s %s\037(\037%s\037)\037 cypress\037.\03701i%s"),
+		     cloak_bxver, p, cloak_host, theme);
+	    nfree (p);
+	    break;
+	  case 4:
+	    sprintf (ctcpversion,
+		     STR
+		     ("%s\002/\002%s: BitchX-%s \002[\002cypress\002]\002 v01i%s"),
+		     cloak_os, cloak_osver, cloak_bxver, theme);
+	    break;
+	  case 5:
+	    sprintf (tmp, STR ("%s"), cloak_os);
+	    p = strtolower (tmp);
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037.\037.cypress\037.\03701i%s %s\037(\037%s\037)\037 bitchx\037/\037%s"),
+		     theme, p, cloak_host, cloak_bxver);
+	    nfree (p);
+	    break;
+	  case 6:
+	    sprintf (tmp, STR ("%s"), cloak_os);
+	    p = strtolower (tmp);
+	    sprintf (ctcpversion,
+		     STR
+		     ("cypress\002.\00201i%s\037(\037bitchx\002.\002%s\037)\037\002.\002. %s\037(\037%s\037)\037"),
+		     theme, cloak_bxver, p, cloak_host);
+	    nfree (p);
+	    break;
+	  case 7:
+	    sprintf (tmp, STR ("%s"), cloak_os);
+	    p = strtolower (tmp);
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037.\037.cypress\037.\03701i%s - bitchx\037.\037%s\002/\002%s"),
+		     theme, cloak_bxver, p);
+	    nfree (p);
+	    break;
+	  case 8:
+	    sprintf (ctcpversion,
+		     STR ("\002BitchX-%s\002 by panasync \002-\002 %s %s"),
+		     cloak_bxver, cloak_os, cloak_osver);
+	    break;
+	  case 9:
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037[\037cypress\002/\00201i\037]\037 - %s \037[\037bx\002/\002%s\037]\037"),
+		     theme, cloak_bxver);
+	    break;
+	  case 10:
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037[\037\002b\002itchx\002.\002%s\037]\037 \002+\002 \037[\037cypress\002.\00201i\037]\037 %s"),
+		     cloak_bxver, theme);
+	    break;
+	  case 11:
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037[\037BitchX\002/\002%s\037(\037cypress\002/\00201i\037)]\037 %s"),
+		     cloak_bxver, theme);
+	    break;
+	  case 12:
+	    p = strtolower (cloak_os);
+	    sprintf (ctcpversion,
+		     STR
+		     ("bitchx\037/\037%s %s %s \037(\037cypress\037/\03701i\037)\037 %s"),
+		     cloak_bxver, p, cloak_osver, theme);
+	    nfree (p);
+	    break;
+	  case 13:
+	    sprintf (ctcpversion,
+		     STR
+		     ("\037.\037.cypress\037/\03701i\037!\037bitchx\037/\037%s\037.\037.%s"),
+		     cloak_bxver, theme);
+	    break;
+	  case 14:
+	    p = strtolower (cloak_bxver);
+	    sprintf (ctcpversion,
+		     STR
+		     ("cypress\002\037.\037\002\037.\03701i\002/\002bitchx\037.\037\002\037.\037\002%s%s"),
+		     p, theme);
+	    nfree (p);
+	    break;
+	  case 15:
+	    p = strtolower (cloak_bxver);
+	    sprintf (ctcpversion,
+		     STR
+		     ("cypress\037.\03701i\037/\037bx%s \037(\037%s\037)\037"),
+		     p, theme);
+	    nfree (p);
+	    break;
+	  }
+	strcpy (ctcpuserinfo, STR (""));
+	strcpy (autoaway, STR ("autoaway after 40 min"));
+	strcpy (kickprefix,
+		STR ("\002.\002.\037(\037\002c\002yp\002/\002k\037)\037 "));
+	strcpy (bankickprefix,
+		STR ("\002.\002.\037(\037\002c\002yp\002/\002bk\037)\037 "));
+	break;
+      }
+    }
+}
+
+#ifdef S_AUTOAWAY
+void
+sendaway ()
+{
+  char awtime[20];
+  int hrs, min, sec, gt;
+  gt = time (NULL) - cloak_awaytime;
+  hrs = gt / 3600;
+  min = (gt % 3600) / 60;
+  sec = gt % 60;
+  switch (cloak_script)
+    {
+    case CLOAK_PLAIN:
+      dprintf (DP_HELP, STR ("AWAY :is away: (%s) [\002BX\002-MsgLog Off]\n"),
+	       autoaway);
+      break;
+    case CLOAK_MIRC:
+      dprintf (DP_HELP, STR ("AWAY :is away: (%s)\n"), autoaway);
+      break;
+    case CLOAK_CRACKROCK:
+      if (hrs)
+	sprintf (awtime, STR ("%dh %dm %ds"), hrs, min, sec);
+      else if (min)
+	sprintf (awtime, STR ("%dm %ds"), min, sec);
+      else
+	sprintf (awtime, STR ("%ds"), sec);
+      dprintf (DP_HELP, STR ("AWAY :%s\002\037[\002%s\002]\037\002\n"),
+	       autoaway, awtime);
+      break;
+    case CLOAK_TUNNELVISION:
+      if (hrs)
+	sprintf (awtime, STR ("%dh%dm%ds"), hrs, min, sec);
+      else if (min)
+	sprintf (awtime, STR ("%dm%ds"), min, sec);
+      else
+	sprintf (awtime, STR ("%ds"), sec);
+      dprintf (DP_HELP, STR ("AWAY :%s \037(\037%s\037)\037\n"), autoaway,
+	       awtime);
+      break;
+    case CLOAK_ARGON:
+      if (hrs)
+	sprintf (awtime, STR ("%dh%dm%ds"), hrs, min, sec);
+      else if (min)
+	sprintf (awtime, STR ("%dm%ds"), min, sec);
+      else
+	sprintf (awtime, STR ("%ds"), sec);
+      dprintf (DP_HELP, STR ("AWAY :%s .\002.\002\037(\037%s\037)\037\n"),
+	       autoaway, awtime);
+      break;
+    case CLOAK_EVOLVER:
+      if (hrs)
+	sprintf (awtime, STR ("%dh %dm %ds"), hrs, min, sec);
+      else if (min)
+	sprintf (awtime, STR ("%dm %ds"), min, sec);
+      else
+	sprintf (awtime, STR ("%ds"), sec);
+      dprintf (DP_HELP,
+	       STR
+	       ("AWAY :away\037: %s (\037l\002:\002off\037,\037 p\002:\002off\037)\037 \037[\037gone\002:\002%s\037]\037\n"),
+	       autoaway, awtime);
+      break;
+    case CLOAK_PREVAIL:
+      if (hrs)
+	sprintf (awtime, STR ("%dh%dm%ds"), hrs, min, sec);
+      else if (min)
+	sprintf (awtime, STR ("%dm%ds"), min, sec);
+      else
+	sprintf (awtime, STR ("%ds"), sec);
+      dprintf (DP_HELP, STR ("AWAY :%s %s\n"), autoaway, awtime);
+      break;
+    case CLOAK_CYPRESS:
+      dprintf (DP_HELP,
+	       STR
+	       ("AWAY :is gone\037.\037. %s \037.\037.\037[\037\002c\002yp\037(\037l\002/\002off\002.\002p\002/\002off)]\n"),
+	       autoaway);
+      break;
+    }
+}
+#endif
 static void
 ctcp_minutely ()
 {
   int i;
+#ifdef S_AUTOAWAY
+  int n;
+  if ((cloak_awaytime == 0) && (cloak_heretime == 0))
+    {
+      cloak_heretime = time (NULL);
+      dprintf (DP_HELP, STR ("AWAY :\n"));
+      return;
+    }
+  n = random ();
+  if (cloak_awaytime == 0)
+    {
+      if (!(n % AVGHERETIME))
+	{
+	  cloak_heretime = 0;
+	  cloak_awaytime = time (NULL) - 600 - random () % 60;
+	  sendaway ();
+	}
+    }
+  else
+    {
+      if (!(n % AVGAWAYTIME))
+	{
+	  cloak_awaytime = 0;
+	  cloak_heretime = time (NULL);
+	  dprintf (DP_HELP, STR ("AWAY :\n"));
+	}
+      else
+	sendaway ();
+    }
+#endif
   if (listen_time <= 0)
     {
       for (i = 0; i < dcc_total; i++)
@@ -38,100 +488,235 @@ static int
 ctcp_FINGER (char *nick, char *uhost, char *handle, char *object,
 	     char *keyword, char *text)
 {
-  if (ctcp_mode != 1 && ctcp_finger[0])
-    simple_sprintf (ctcp_reply, "%s\001FINGER %s\001", ctcp_reply,
-		    ctcp_finger);
+  char *p;
+  int idletime;
+  struct passwd *pwd;
+  if (cloak_awaytime)
+    idletime = now - cloak_awaytime;
+  else if (cloak_heretime)
+    idletime = now - cloak_heretime;
+  else
+    idletime = 0;
+  if (!(pwd = getpwuid (geteuid ())))
+    return 0;
+#ifndef GECOS_DELIMITER
+#define GECOS_DELIMITER ','
+#endif
+  if ((p = strchr (pwd->pw_gecos, GECOS_DELIMITER)) != NULL)
+    *p = 0;
+  dprintf (DP_HELP,
+	   STR ("NOTICE %s :\001%s %s (%s@%s) Idle %ld second%c\001\n"), nick,
+	   keyword, pwd->pw_gecos, pwd->pw_name,
+	   (char *) (strchr (botuserhost, '@') + 1), idletime,
+	   (idletime == 1) ? "" : "s");
   return 1;
 }
 static int
-ctcp_ECHOERR (char *nick, char *uhost, char *handle, char *object,
-	      char *keyword, char *text)
+ctcp_ECHO (char *nick, char *uhost, char *handle, char *object, char *keyword,
+	   char *text)
 {
-  if (ctcp_mode != 1 && strlen (text) <= 80)
-    simple_sprintf (ctcp_reply, "%s\001%s %s\001", ctcp_reply, keyword, text);
+  char reply[60];
+  strncpy0 (reply, text, sizeof (reply));
+  dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s\001\n"), nick, keyword, reply);
   return 1;
 }
 static int
 ctcp_PING (char *nick, char *uhost, char *handle, char *object, char *keyword,
 	   char *text)
 {
-  struct userrec *u = get_user_by_handle (userlist, handle);
-  int atr = u ? u->flags : 0;
-  if ((ctcp_mode != 1 || (atr & USER_OP)) && strlen (text) <= 80)
-    simple_sprintf (ctcp_reply, "%s\001%s %s\001", ctcp_reply, keyword, text);
+  if (strlen (text) <= 80)
+    dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s\001\n"), nick, keyword,
+	     text);
   return 1;
 }
 static int
 ctcp_VERSION (char *nick, char *uhost, char *handle, char *object,
 	      char *keyword, char *text)
 {
-  if (ctcp_mode != 1 && ctcp_version[0])
-    simple_sprintf (ctcp_reply, "%s\001VERSION %s\001", ctcp_reply,
-		    ctcp_version);
+  char s[50] = "";
+  if (cloak_script == CLOAK_CYPRESS)
+    {
+      switch (random () % 8)
+	{
+	case 0:
+	  strcpy (s, STR (" :should of put the glock down."));
+	  break;
+	case 1:
+	  strcpy (s, STR (" :hot damn, I didn't want to kill a man."));
+	  break;
+	case 2:
+	  strcpy (s, STR (" :check me and I'll check ya back."));
+	  break;
+	case 3:
+	  strcpy (s, STR (" :put the blunt down just for a minute."));
+	  break;
+	case 4:
+	  strcpy (s, STR (" :tried to jack me, my homie got shot."));
+	  break;
+	case 5:
+	  strcpy (s, STR (" :insane in the membrane"));
+	  break;
+	case 6:
+	  strcpy (s, STR (" :slow hits from the bong"));
+	  break;
+	case 7:
+	  strcpy (s, STR (" :k\002-\002leet"));
+	  break;
+	}
+    }
+  dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s%s\001\n"), nick, keyword,
+	   ctcpversion, s);
+  return 1;
+}
+static int
+ctcp_WHOAMI (char *nick, char *uhost, char *handle, char *object,
+	     char *keyword, char *text)
+{
+  dprintf (DP_HELP, STR ("NOTICE %s :\002BitchX\002: Access Denied\n"), nick);
+  return 1;
+}
+static int
+ctcp_OP (char *nick, char *uhost, char *handle, char *object, char *keyword,
+	 char *text)
+{
+  char chan[256], *p;
+  if (text[0])
+    {
+      strncpy0 (chan, text, sizeof (chan));
+      p = strchr (chan, ' ');
+      if (p)
+	*p = 0;
+      dprintf (DP_HELP,
+	       STR
+	       ("NOTICE %s :\002BitchX\002: I'm not on %s or I'm not opped\n"),
+	       nick, chan);
+    }
+  return 1;
+}
+static int
+ctcp_INVITE_UNBAN (char *nick, char *uhost, char *handle, char *object,
+		   char *keyword, char *text)
+{
+  struct chanset_t *chan = chanset;
+  char chname[256], *p;
+  if (text[0] == '#')
+    {
+      strncpy0 (chname, text, sizeof (chname));
+      p = strchr (chname, ' ');
+      if (p)
+	*p = 0;
+      while (chan)
+	{
+	  if (chan->status & CHAN_ACTIVE)
+	    {
+	      if (!strcasecmp (chan->name, chname))
+		{
+		  dprintf (DP_HELP,
+			   STR ("NOTICE %s :\002BitchX\002: Access Denied\n"),
+			   nick);
+		  return 0;
+		}
+	    }
+	  chan = chan->next;
+	}
+      dprintf (DP_HELP,
+	       STR ("NOTICE %s :\002BitchX\002: I'm not on that channel\n"),
+	       nick);
+    }
   return 1;
 }
 static int
 ctcp_USERINFO (char *nick, char *uhost, char *handle, char *object,
 	       char *keyword, char *text)
 {
-  if (ctcp_mode != 1 && ctcp_userinfo[0])
-    simple_sprintf (ctcp_reply, "%s\001USERINFO %s\001", ctcp_reply,
-		    ctcp_userinfo);
+  if (cloak_script == CLOAK_TUNNELVISION)
+    strcpy (ctcpuserinfo, botname);
+  else if (cloak_script == CLOAK_PREVAIL)
+    {
+      strcpy (ctcpuserinfo, botname);
+      strcat (ctcpuserinfo, " ?");
+    }
+  dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s\001\n"), nick, keyword,
+	   ctcpuserinfo);
   return 1;
 }
 static int
-ctcp_CLIENTINFO (char *nick, char *uhosr, char *handle, char *object,
+ctcp_CLIENTINFO (char *nick, char *uhost, char *handle, char *object,
 		 char *keyword, char *msg)
 {
-  char *p = NULL;
-  if (ctcp_mode == 1)
-    return 1;
-  else if (!msg[0])
-    p = CLIENTINFO;
-  else if (!egg_strcasecmp (msg, "sed"))
-    p = CLIENTINFO_SED;
-  else if (!egg_strcasecmp (msg, "version"))
-    p = CLIENTINFO_VERSION;
-  else if (!egg_strcasecmp (msg, "clientinfo"))
-    p = CLIENTINFO_CLIENTINFO;
-  else if (!egg_strcasecmp (msg, "userinfo"))
-    p = CLIENTINFO_USERINFO;
-  else if (!egg_strcasecmp (msg, "errmsg"))
-    p = CLIENTINFO_ERRMSG;
-  else if (!egg_strcasecmp (msg, "finger"))
-    p = CLIENTINFO_FINGER;
-  else if (!egg_strcasecmp (msg, "time"))
-    p = CLIENTINFO_TIME;
-  else if (!egg_strcasecmp (msg, "action"))
-    p = CLIENTINFO_ACTION;
-  else if (!egg_strcasecmp (msg, "dcc"))
-    p = CLIENTINFO_DCC;
-  else if (!egg_strcasecmp (msg, "utc"))
-    p = CLIENTINFO_UTC;
-  else if (!egg_strcasecmp (msg, "ping"))
-    p = CLIENTINFO_PING;
-  else if (!egg_strcasecmp (msg, "echo"))
-    p = CLIENTINFO_ECHO;
-  if (p == NULL)
-    {
-      simple_sprintf (ctcp_reply,
-		      "%s\001ERRMSG CLIENTINFO: %s is not a valid function\001",
-		      ctcp_reply, msg);
+  char text[256];
+  if (!msg[0])
+    {
+      strcpy (text,
+	      STR
+	      ("SED UTC ACTION DCC CDCC BDCC XDCC VERSION CLIENTINFO USERINFO ERRMSG FINGER TIME PING ECHO INVITE WHOAMI OP OPS UNBAN IDENT XLINK UPTIME :Use CLIENTINFO <COMMAND> to get more specific information"));
     }
+  else if (!strcasecmp (msg, STR ("UNBAN")))
+    strcpy (text, STR ("UNBAN unbans the person from channel"));
+  else if (!strcasecmp (msg, STR ("OPS")))
+    strcpy (text, STR ("OPS ops the person if on userlist"));
+  else if (!strcasecmp (msg, STR ("ECHO")))
+    strcpy (text, STR ("ECHO returns the arguments it receives"));
+  else if (!strcasecmp (msg, STR ("WHOAMI")))
+    strcpy (text, STR ("WHOAMI user list information"));
+  else if (!strcasecmp (msg, STR ("INVITE")))
+    strcpy (text, STR ("INVITE invite to channel specified"));
+  else if (!strcasecmp (msg, STR ("PING")))
+    strcpy (text, STR ("PING returns the arguments it receives"));
+  else if (!strcasecmp (msg, STR ("UTC")))
+    strcpy (text, STR ("UTC substitutes the local timezone"));
+  else if (!strcasecmp (msg, STR ("XDCC")))
+    strcpy (text, STR ("XDCC checks cdcc info for you"));
+  else if (!strcasecmp (msg, STR ("BDCC")))
+    strcpy (text, STR ("BDCC checks cdcc info for you"));
+  else if (!strcasecmp (msg, STR ("CDCC")))
+    strcpy (text, STR ("CDCC checks cdcc info for you"));
+  else if (!strcasecmp (msg, STR ("DCC")))
+    strcpy (text, STR ("DCC requests a direct_client_connection"));
+  else if (!strcasecmp (msg, STR ("ACTION")))
+    strcpy (text, STR ("ACTION contains action descriptions for atmosphere"));
+  else if (!strcasecmp (msg, STR ("FINGER")))
+    strcpy (text,
+	    STR ("FINGER shows real name, login name and idle time of user"));
+  else if (!strcasecmp (msg, STR ("ERRMSG")))
+    strcpy (text, STR ("ERRMSG returns error messages"));
+  else if (!strcasecmp (msg, STR ("USERINFO")))
+    strcpy (text, STR ("USERINFO returns user settable information"));
+  else if (!strcasecmp (msg, STR ("CLIENTINFO")))
+    strcpy (text,
+	    STR
+	    ("CLIENTINFO gives information about available CTCP commands"));
+  else if (!strcasecmp (msg, STR ("SED")))
+    strcpy (text, STR ("SED contains simple_encrypted_data"));
+  else if (!strcasecmp (msg, "OP"))
+    strcpy (text, STR ("OP ops the person if on userlist"));
+  else if (!strcasecmp (msg, STR ("VERSION")))
+    strcpy (text, STR ("VERSION shows client type, version and environment"));
+  else if (!strcasecmp (msg, STR ("XLINK")))
+    strcpy (text, STR ("XLINK x-filez rule"));
+  else if (!strcasecmp (msg, STR ("IDENT")))
+    strcpy (text, STR ("IDENT change userhost of userlist"));
+  else if (!strcasecmp (msg, STR ("TIME")))
+    strcpy (text, STR ("TIME tells you the time on the user's host"));
+  else if (!strcasecmp (msg, STR ("UPTIME")))
+    strcpy (text, STR ("UPTIME my uptime"));
   else
-    simple_sprintf (ctcp_reply, "%s\001CLIENTINFO %s\001", ctcp_reply, p);
+    {
+      dprintf (DP_HELP,
+	       STR ("NOTICE %s :\001ERRMSG %s is not a valid function\001\n"),
+	       nick, msg);
+      return 0;
+    }
+  dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s\001\n"), nick, keyword, text);
   return 1;
 }
 static int
 ctcp_TIME (char *nick, char *uhost, char *handle, char *object, char *keyword,
 	   char *text)
 {
-  char tms[25];
-  if (ctcp_mode == 1)
-    return 1;
-  strncpy (tms, ctime (&now), 24);
-  tms[24] = 0;
-  simple_sprintf (ctcp_reply, "%s\001TIME %s\001", ctcp_reply, tms);
+  char tms[81];
+  strncpy0 (tms, ctime (&now), sizeof (tms));
+  dprintf (DP_HELP, STR ("NOTICE %s :\001%s %s\001\n"), nick, keyword, tms);
   return 1;
 }
 static int
@@ -166,23 +751,59 @@ ctcp_CHAT (char *nick, char *uhost, char *handle, char *object, char *keyword,
   return 1;
 }
 static cmd_t myctcp[] =
-  { {"FINGER", "", ctcp_FINGER, NULL}, {"ECHO", "", ctcp_ECHOERR, NULL},
-  {"PING", "", ctcp_PING, NULL}, {"ERRMSG", "", ctcp_ECHOERR, NULL},
-  {"VERSION", "", ctcp_VERSION, NULL}, {"USERINFO", "", ctcp_USERINFO, NULL},
-  {"CLIENTINFO", "", ctcp_CLIENTINFO, NULL}, {"TIME", "", ctcp_TIME, NULL},
-  {"CHAT", "", ctcp_CHAT, NULL}, {NULL, NULL, NULL, NULL} };
-static tcl_strings mystrings[] =
-  { {"ctcp-version", ctcp_version, 120, 0}, {"ctcp-finger", ctcp_finger, 120,
-					     0}, {"ctcp-userinfo",
-						  ctcp_userinfo, 120, 0},
-  {NULL, NULL, 0, 0} };
-static tcl_ints myints[] = { {"ctcp-mode", &ctcp_mode}, {NULL, NULL} };
+  { {"CLIENTINFO", "", ctcp_CLIENTINFO, NULL}, {"FINGER", "", ctcp_FINGER,
+						NULL}, {"WHOAMI", "",
+							ctcp_WHOAMI, NULL},
+  {"OP", "", ctcp_OP, NULL}, {"OPS", "", ctcp_OP, NULL}, {"INVITE", "",
+							  ctcp_INVITE_UNBAN,
+							  NULL}, {"UNBAN", "",
+								  ctcp_INVITE_UNBAN,
+								  NULL},
+  {"ERRMSG", "", ctcp_ECHO, NULL}, {"USERINFO", "", ctcp_USERINFO, NULL},
+  {"ECHO", "", ctcp_ECHO, NULL}, {"VERSION", "", ctcp_VERSION, NULL}, {"PING",
+								       "",
+								       ctcp_PING,
+								       NULL},
+  {"TIME", "", ctcp_TIME, NULL}, {"CHAT", "", ctcp_CHAT, NULL}, {NULL, NULL,
+								 NULL,
+								 NULL} };
+#endif
+void
+cloak_describe (struct cfg_entry *cfgent, int idx)
+{
+  dprintf (idx,
+	   STR
+	   ("cloak-script decides which BitchX script the bot cloaks. If set to 0, a random script will be cloaked.\n"));
+  dprintf (idx,
+	   STR
+	   ("Available: 1=plain bitchx, 2=crackrock, 3=neonapple, 4=tunnelvision, 5=argon, 6=evolver, 7=prevail 8=cypress 9=mIRC\n"));
+} void
+cloak_changed (struct cfg_entry *cfgent, char *oldval, int *valid)
+{
+  char *p;
+  int i;
+  if (!(p = cfgent->ldata ? cfgent->ldata : cfgent->gdata))
+    return;
+  i = atoi (p);
+#ifdef LEAF
+  if (i == 0)
+    i = (random () % CLOAK_COUNT) + 1;
+#endif
+  if ((*valid = ((i >= 0) && (i <= CLOAK_COUNT))))
+    cloak_script = i;
+#ifdef LEAF
+  scriptchanged ();
+#endif
+}
+struct cfg_entry CFG_CLOAK_SCRIPT =
+  { "cloak-script", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL, cloak_changed,
+cloak_changed, cloak_describe };
 static char *
 ctcp_close ()
 {
-  rem_tcl_strings (mystrings);
-  rem_tcl_ints (myints);
+#ifdef LEAF
   rem_builtins (H_ctcp, myctcp);
+#endif
   module_undepend (MODULE_NAME);
   return NULL;
 }
@@ -193,32 +814,67 @@ static Function ctcp_table[] =
 char *
 ctcp_start (Function * global_funcs)
 {
+#ifdef LEAF
+  char *p;
+#ifdef HAVE_UNAME
+  struct utsname un;
+#endif
+#endif
   global = global_funcs;
   module_register (MODULE_NAME, ctcp_table, 1, 0);
+#ifdef LEAF
   if (!(server_funcs = module_depend (MODULE_NAME, "server", 1, 0)))
     {
       module_undepend (MODULE_NAME);
       return "This module requires server module 1.0 or later.";
     }
-  add_tcl_strings (mystrings);
-  add_tcl_ints (myints);
-  add_builtins (H_ctcp, myctcp);
-  add_hook (HOOK_MINUTELY, (Function) ctcp_minutely);
-  if (!ctcp_version[0])
+#ifdef HAVE_UNAME
+  egg_bzero (&un, sizeof (un));
+  if (!uname (&un))
     {
-      strncpy (ctcp_version, ver, 120);
-      ctcp_version[120] = 0;
+      strncpy0 (cloak_os, un.sysname, sizeof (cloak_os));
+      strncpy0 (cloak_osver, un.release, sizeof (cloak_osver));
+      strncpy0 (cloak_host, un.nodename, sizeof (cloak_host));
     }
-  if (!ctcp_finger[0])
+  else
     {
-      strncpy (ctcp_finger, ver, 120);
-      ctcp_finger[120] = 0;
+#endif
+      switch (random () % 2)
+	{
+	case 0:
+	  strcpy (cloak_os, STR ("Linux"));
+	  strcpy (cloak_osver, STR ("2.4.20"));
+	  break;
+	case 1:
+	  strcpy (cloak_os, STR ("FreeBSD"));
+	  strcpy (cloak_osver, STR ("4.5-STABLE"));
+	  break;
+	}
+      strcpy (cloak_host, STR ("login"));
+#ifdef HAVE_UNAME
     }
-  if (!ctcp_userinfo[0])
+#endif
+  if ((p = strchr (cloak_host, '.')))
+    *p = 0;
+  switch (random () % 4)
     {
-      strncpy (ctcp_userinfo, ver, 120);
-      ctcp_userinfo[120] = 0;
+    case 0:
+      strcpy (cloak_bxver, STR ("1.0c17"));
+      break;
+    case 1:
+      strcpy (cloak_bxver, STR ("1.0c18"));
+      break;
+    case 2:
+      strcpy (cloak_bxver, STR ("1.0c19"));
+      break;
+    case 3:
+      strcpy (cloak_bxver, STR ("1.0c20cvs+"));
+      break;
     }
+  scriptchanged ();
+  add_builtins (H_ctcp, myctcp);
+  add_hook (HOOK_MINUTELY, (Function) ctcp_minutely);
+#endif
+  add_cfg (&CFG_CLOAK_SCRIPT);
   return NULL;
 }
-#endif

+ 0 - 2
src/mod/ctcp.mod/ctcp.h

@@ -1,4 +1,3 @@
-#ifdef LEAF
 #ifndef _EGG_MOD_CTCP_CTCP_H
 #define _EGG_MOD_CTCP_CTCP_H
 #define CLIENTINFO "SED VERSION CLIENTINFO USERINFO ERRMSG FINGER TIME ACTION DCC UTC PING ECHO  :Use CLIENTINFO <COMMAND> to get more specific information"
@@ -15,4 +14,3 @@
 #define CLIENTINFO_PING "PING returns the arguments it receives"
 #define CLIENTINFO_ECHO "ECHO returns the arguments it receives"
 #endif
-#endif

+ 72 - 50
src/mod/irc.mod/chan.c

@@ -5,18 +5,34 @@ static time_t last_invtime = (time_t) 0L;
 static char last_invchan[300] = "";
 #define CHANNEL_ID_LEN 5
 static memberlist *
-newmember (struct chanset_t *chan)
+newmember (struct chanset_t *chan, char *nick)
 {
-  memberlist *x;
-  for (x = chan->channel.member; x && x->nick[0]; x = x->next);
-  x->next = (memberlist *) channel_malloc (sizeof (memberlist));
-  x->next->next = NULL;
-  x->next->nick[0] = 0;
-  x->next->split = 0L;
-  x->next->last = 0L;
-  x->next->delay = 0L;
+  memberlist *x, *lx, *n;
+  x = chan->channel.member;
+  lx = NULL;
+  while (x && x->nick[0] && (rfc_casecmp (x->nick, nick) < 0))
+    {
+      lx = x;
+      x = x->next;
+    }
+  n = (memberlist *) channel_malloc (sizeof (memberlist));
+  n->next = NULL;
+  strncpy0 (n->nick, nick, sizeof (n->nick));
+  n->split = 0L;
+  n->last = 0L;
+  n->delay = 0L;
+  if (!lx)
+    {
+      n->next = chan->channel.member;
+      chan->channel.member = n;
+    }
+  else
+    {
+      n->next = lx->next;
+      lx->next = n;
+    }
   chan->channel.members++;
-  return x;
+  return n;
 }
 static void
 update_idle (char *chname, char *nick)
@@ -108,7 +124,7 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
       if (!m->user)
 	{
 	  char s[256];
-	  sprintf (s, "%s!%s", m->nick, m->userhost);
+	  sprintf (s, STR ("%s!%s"), m->nick, m->userhost);
 	  m->user = get_user_by_host (s);
 	}
       if (m->user
@@ -116,12 +132,12 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
 	      (USER_BOT | USER_OP)))
 	{
 	  ops++;
-	  if (!strcmp (m->nick, botname))
+	  if (match_my_nick (m->nick))
 	    bpos = (ops - 1);
 	}
       else if (!opsonly || chan_hasop (m))
 	{
-	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0 };
+	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
 	  if (m->user)
 	    get_user_flagrec (m->user, &fr, chan->dname);
 	  if (chan_deop (fr) || glob_deop (fr)
@@ -146,7 +162,7 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
     {
       if (!opsonly || chan_hasop (m))
 	{
-	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0 };
+	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
 	  if (m->user)
 	    get_user_flagrec (m->user, &fr, chan->dname);
 	  if (chan_deop (fr) || glob_deop (fr)
@@ -169,8 +185,9 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
 		    {
 		      actions++;
 		      sent++;
-		      dprintf (DP_MODE, "KICK %s %s :%s%s\n", chan->name,
-			       m->nick, kickprefix, kickreason (KICK_CLOSED));
+		      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"),
+			       chan->name, m->nick, kickprefix,
+			       kickreason (KICK_CLOSED));
 		      m->flags |= SENTKICK;
 		      if (actions >= ct)
 			return;
@@ -190,7 +207,7 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
     {
       if (!opsonly || chan_hasop (m))
 	{
-	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0 };
+	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
 	  if (m->user)
 	    get_user_flagrec (m->user, &fr, chan->dname);
 	  if (chan_deop (fr) || glob_deop (fr)
@@ -212,8 +229,9 @@ priority_do (struct chanset_t *chan, int opsonly, int action)
 		  else if ((action == PRIO_KICK) && !chan_sentkick (m))
 		    {
 		      actions++;
-		      dprintf (DP_MODE, "KICK %s %s :%s%s\n", chan->name,
-			       m->nick, kickprefix, kickreason (KICK_CLOSED));
+		      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"),
+			       chan->name, m->nick, kickprefix,
+			       kickreason (KICK_CLOSED));
 		      m->flags |= SENTKICK;
 		      if ((actions >= ct) || (sent > 5))
 			return;
@@ -229,6 +247,7 @@ target_priority (struct chanset_t *chan, memberlist * target, int opsonly)
 {
   memberlist *m;
   int ops = 0, targets = 0, bpos = 0, ft = 0, ct = 0, tp = (-1), pos = 0;
+  return 1;
   for (m = chan->channel.member; m && m->nick[0]; m = m->next)
     {
       if (m->user
@@ -236,12 +255,12 @@ target_priority (struct chanset_t *chan, memberlist * target, int opsonly)
 	      (USER_BOT | USER_OP)))
 	{
 	  ops++;
-	  if (!strcmp (m->nick, botname))
+	  if (match_my_nick (m->nick))
 	    bpos = ops;
 	}
       else if (!opsonly || chan_hasop (m))
 	{
-	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0 };
+	  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
 	  if (m->user)
 	    get_user_flagrec (m->user, &fr, chan->dname);
 	  if (chan_deop (fr) || glob_deop (fr)
@@ -410,8 +429,8 @@ detect_chan_flood (char *floodnick, char *floodhost, char *from,
 	  if (!chan_sentkick (m) && me_op (chan))
 	    {
 	      putlog (LOG_MODES, chan->dname, IRC_FLOODKICK, floodnick);
-	      dprintf (DP_MODE, "KICK %s %s :%s\n", chan->name, floodnick,
-		       CHAN_FLOOD);
+	      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"), chan->name,
+		       floodnick, kickprefix, kickreason (KICK_FLOOD));
 	      m->flags |= SENTKICK;
 	    }
 	  return 1;
@@ -450,11 +469,12 @@ detect_chan_flood (char *floodnick, char *floodhost, char *from,
 		    {
 		      m->flags |= SENTKICK;
 		      if (which == FLOOD_JOIN)
-			dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name,
-				 m->nick, IRC_JOIN_FLOOD);
+			dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name,
+				 m->nick, kickprefix, IRC_JOIN_FLOOD);
 		      else
-			dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name,
-				 m->nick, IRC_NICK_FLOOD);
+			dprintf (DP_SERVER, STR ("KICK %s %s :%s%s\n"),
+				 chan->name, m->nick, kickprefix,
+				 kickreason (KICK_NICKFLOOD));
 		    }
 		}
 	    }
@@ -464,8 +484,8 @@ detect_chan_flood (char *floodnick, char *floodhost, char *from,
 	    {
 	      putlog (LOG_MODES, chan->dname, "Kicking %s, for mass kick.",
 		      floodnick);
-	      dprintf (DP_MODE, "KICK %s %s :%s\n", chan->name, floodnick,
-		       IRC_MASSKICK);
+	      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"), chan->name,
+		       floodnick, kickprefix, kickreason (KICK_KICKFLOOD));
 	      m->flags |= SENTKICK;
 	    }
 	  return 1;
@@ -474,8 +494,8 @@ detect_chan_flood (char *floodnick, char *floodhost, char *from,
 	    {
 	      putlog (LOG_MODES, chan->dname, CHAN_MASSDEOP, chan->dname,
 		      from);
-	      dprintf (DP_MODE, "KICK %s %s :%s\n", chan->name, floodnick,
-		       CHAN_MASSDEOP_KICK);
+	      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"), chan->name,
+		       floodnick, kickprefix, kickreason (KICK_MASSDEOP));
 	      m->flags |= SENTKICK;
 	    }
 	  return 1;
@@ -487,6 +507,7 @@ static char *
 quickban (struct chanset_t *chan, char *uhost)
 {
   static char s1[512];
+  Context;
   maskhost (uhost, s1);
   if ((strlen (s1) != 1) && (strict_host == 0))
     s1[2] = '*';
@@ -541,15 +562,16 @@ kick_all (struct chanset_t *chan, char *hostmask, char *comment, int bantype)
 	  l = strlen (chan->name) + strlen (kicknick) + strlen (comment) + 5;
 	  if ((kick_method != 0 && k == kick_method) || (l > 480))
 	    {
-	      dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick,
-		       comment);
+	      dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, kicknick,
+		       kickprefix, comment);
 	      k = 0;
 	      kicknick[0] = 0;
 	    }
 	}
     }
   if (k > 0)
-    dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick, comment);
+    dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, kicknick,
+	     kickprefix, comment);
 }
 static void
 refresh_ban_kick (struct chanset_t *chan, char *user, char *nick)
@@ -854,6 +876,7 @@ check_this_member (struct chanset_t *chan, char *nick, struct flag_record *fr)
 {
   memberlist *m;
   char s[UHOSTLEN], *p;
+  Context;
   m = ismember (chan, nick);
   if (!m || match_my_nick (nick) || !me_op (chan))
     return;
@@ -898,17 +921,10 @@ check_this_member (struct chanset_t *chan, char *nick, struct flag_record *fr)
 	  check_exemptlist (chan, s);
 #endif
 	  quickban (chan, m->userhost);
+	  Context;
 	  p = get_user (&USERENTRY_COMMENT, m->user);
-	  if (p[0])
-	    {
-	      dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick,
-		       p ? p : IRC_POLITEKICK);
-	    }
-	  else
-	    {
-	      dprintf (DP_SERVER, STR ("KICK %s %s :%s%s\n"), chan->name,
-		       m->nick, bankickprefix, kickreason (KICK_KUSER));
-	    }
+	  dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick,
+		   bankickprefix, p ? p : kickreason (KICK_KUSER));
 	  m->flags |= SENTKICK;
 	}
     }
@@ -948,6 +964,7 @@ recheck_channel (struct chanset_t *chan, int dobans)
   static int stacking = 0;
   int botops = 0, botnonops = 0, nonbotops = 0;
   int stop_reset = 0;
+  Context;
   if (stacking)
     return;
   if (!userlist)
@@ -1019,18 +1036,23 @@ recheck_channel (struct chanset_t *chan, int dobans)
   for (m = chan->channel.member; m && m->nick[0]; m = m->next)
     {
       sprintf (s, "%s!%s", m->nick, m->userhost);
+      Context;
       if (!m->user && !m->tried_getuser)
 	{
 	  m->tried_getuser = 1;
 	  m->user = get_user_by_host (s);
 	}
+      Context;
       get_user_flagrec (m->user, &fr, chan->dname);
+      Context;
       if (glob_bot (fr) && chan_hasop (m) && !match_my_nick (m->nick))
 	stop_reset = 1;
       check_this_member (chan, m->nick, &fr);
     }
+  Context;
   if (channel_closed (chan))
     channel_check_locked (chan);
+  Context;
   if (dobans)
     {
       if (channel_nouserbans (chan) && !stop_reset)
@@ -1172,7 +1194,7 @@ got352or4 (struct chanset_t *chan, char *user, char *host, char *serv,
   m = ismember (chan, nick);
   if (!m)
     {
-      m = newmember (chan);
+      m = newmember (chan, nick);
       m->joined = m->split = m->delay = 0L;
       m->flags = 0;
       m->last = now;
@@ -1814,7 +1836,7 @@ gotjoin (char *from, char *chname)
 	    {
 	      if (m)
 		killmember (chan, nick);
-	      m = newmember (chan);
+	      m = newmember (chan, nick);
 	      m->joined = now;
 	      m->split = 0L;
 	      m->flags = 0;
@@ -2242,8 +2264,8 @@ gotmsg (char *from, char *msg)
 	    }
 	  if (kick_fun)
 	    {
-	      dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, nick,
-		       IRC_FUNKICK);
+	      dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, nick,
+		       kickprefix, IRC_FUNKICK);
 	      m->flags |= SENTKICK;
 	    }
 	}
@@ -2407,8 +2429,8 @@ gotnotice (char *from, char *msg)
 	    }
 	  if (kick_fun)
 	    {
-	      dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, nick,
-		       IRC_FUNKICK);
+	      dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, nick,
+		       kickprefix, IRC_FUNKICK);
 	      m->flags |= SENTKICK;
 	    }
 	}

+ 12 - 3
src/mod/irc.mod/cmdsirc.c

@@ -233,7 +233,8 @@ cmd_kickban (struct userrec *u, int idx, char *par)
     do_mask (chan, chan->channel.ban, s1, 'b');
   if (!par[0])
     par = "requested";
-  dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
+  dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick,
+	   bankickprefix, par);
   m->flags |= SENTKICK;
   u_addban (chan, s1, dcc[idx].nick, par, now + (60 * chan->ban_time), 0);
   dprintf (idx, "Okay, done.\n");
@@ -374,6 +375,10 @@ cmd_devoice (struct userrec *u, int idx, char *par)
 void
 do_op (char *nick, struct chanset_t *chan)
 {
+  memberlist *m;
+  m = ismember (chan, nick);
+  if (!m)
+    return;
   if (channel_fastop (chan))
     {
       add_mode (chan, '+', 'o', nick);
@@ -920,7 +925,8 @@ cmd_kick (struct userrec *u, int idx, char *par)
       dprintf (idx, "%s is another channel bot!\n", nick);
       return;
     }
-  dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
+  dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix,
+	   par);
   m->flags |= SENTKICK;
   dprintf (idx, "Okay, done.\n");
 }
@@ -1248,7 +1254,7 @@ cmd_adduser (struct userrec *u, int idx, char *par)
   char *nick, *hand;
   struct chanset_t *chan;
   memberlist *m = NULL;
-  char s[UHOSTLEN], s1[UHOSTLEN];
+  char s[UHOSTLEN], s1[UHOSTLEN], s3[20];
   char tmp[50], s2[30];
   int atr = u ? u->flags : 0;
   int statichost = 0;
@@ -1343,8 +1349,11 @@ cmd_adduser (struct userrec *u, int idx, char *par)
       set_user (&USERENTRY_ADDED, u, tmp);
       make_rand_str (s2, 10);
       set_user (&USERENTRY_PASS, u, s2);
+      make_rand_str (s3, 10);
+      set_user (&USERENTRY_PASS, u, s3);
       dprintf (idx, "Added [%s]%s with no flags.\n", hand, p1);
       dprintf (idx, STR ("%s's password set to \002%s\002.\n"), hand, s2);
+      dprintf (idx, STR ("%s's secpass set to \002%s\002.\n"), hand, s3);
     }
   else
     {

+ 13 - 39
src/mod/irc.mod/irc.c

@@ -27,8 +27,6 @@ static p_tcl_bind_list H_topc, H_splt, H_sign, H_rejn, H_part, H_pub, H_pubm;
 static p_tcl_bind_list H_nick, H_mode, H_kick, H_join, H_need;
 static Function *global = NULL, *channels_funcs = NULL, *server_funcs =
   NULL, *encryption_funcs = NULL;
-static char kickprefix[20] = "";
-static char bankickprefix[20] = "";
 static int ctcp_mode;
 static int net_type;
 static int strict_host;
@@ -60,33 +58,6 @@ static int include_lk = 1;
 #include "cmdsirc.c"
 #include "msgcmds.c"
 #include "tclirc.c"
-void
-makeplaincookie (char *chname, char *nick, char *buf)
-{
-  char work[256], work2[256];
-  int i, n;
-  sprintf (work, STR ("%010li"), (now + timesync));
-  strcpy (buf, (char *) &work[4]);
-  work[0] = 0;
-  if (strlen (nick) < 5)
-    while (strlen (work) + strlen (nick) < 5)
-      strcat (work, " ");
-  else
-    strcpy (work, (char *) &nick[strlen (nick) - 5]);
-  strcat (buf, work);
-  n = 3;
-  for (i = strlen (chname) - 1; (i >= 0) && (n >= 0); i--)
-    if (((unsigned char) chname[i] < 128) && ((unsigned char) chname[i] > 32))
-      {
-	work2[n] = tolower (chname[i]);
-	n--;
-      }
-  while (n >= 0)
-    work2[n--] = ' ';
-  work2[4] = 0;
-  strcat (buf, work2);
-}
-
 void
 makeopline (struct chanset_t *chan, char *nick, char *buf)
 {
@@ -97,15 +68,12 @@ makeopline (struct chanset_t *chan, char *nick, char *buf)
     strcpy (nck, m->nick);
   else
     strcpy (nck, nick);
-  makeplaincookie (chan->name, nck, plaincookie);
+  makeplaincookie (chan->dname, nck, plaincookie);
   strcpy (key, botname);
   strcat (key, netpass);
   p = encrypt_string (key, plaincookie);
   strcpy (enccookie, p);
   nfree (p);
-  p = enccookie + strlen (enccookie) - 1;
-  while (*p == '.')
-    *p-- = 0;
   sprintf (buf, STR ("MODE %s +o-b %s *!*@[%s]\n"), chan->name, nck,
 	   enccookie);
 }
@@ -541,6 +509,9 @@ check_hostmask ()
   Context;
   tmp = botuserhost;
   Context;
+  if (!tmp[0] || !tmp[1])
+    return;
+  Context;
   if (tmp[0] != '~')
     sprintf (s, STR ("*!%s"), tmp);
   else
@@ -565,6 +536,7 @@ request_op (struct chanset_t *chan)
   memberlist *botops[MAX_BOTS];
   char s[100], *l, myserv[SERVLEN];
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0 };
+  Context;
   chan->channel.do_opreq = 0;
   if (me_op (chan))
     return;
@@ -871,7 +843,8 @@ punish_badguy (struct chanset_t *chan, char *whobad, struct userrec *u,
 	  || !(chan_op (fr) || (glob_op (fr) && !chan_deop (fr))))
       && !chan_sentkick (m) && me_op (chan) && !mevictim)
     {
-      dprintf (DP_MODE, "KICK %s %s :%s\n", chan->name, badnick, kick_msg);
+      dprintf (DP_MODE, STR ("KICK %s %s :%s%s\n"), chan->name, m->nick,
+	       bankickprefix, kickreason (KICK_MEAN));
       m->flags |= SENTKICK;
     }
 }
@@ -1148,7 +1121,7 @@ check_expired_chanstuff ()
   memberlist *m, *n;
   char s[UHOSTLEN];
   struct chanset_t *chan;
-  struct userrec *buser;
+  struct userrec *buser = NULL;
   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
   struct flag_record fr3 = { FR_GLOBAL | FR_CHAN, 0, 0 };
   if (!server_online)
@@ -1233,8 +1206,9 @@ check_expired_chanstuff ()
 			   || (glob_op (fr) && !glob_deop (fr))
 			   || chan_friend (fr) || chan_op (fr)))
 			{
-			  dprintf (DP_SERVER, "KICK %s %s :idle %d min\n",
-				   chan->name, m->nick, chan->idle_kick);
+			  dprintf (DP_SERVER, "KICK %s %s :%sidle %d min\n",
+				   chan->name, m->nick, kickprefix,
+				   chan->idle_kick);
 			  m->flags |= SENTKICK;
 			}
 		    }
@@ -1256,7 +1230,7 @@ check_expired_chanstuff ()
 	      m = n;
 	    }
 	  buser = get_user_by_handle (userlist, botnetnick);
-	  get_user_flagrec (buser, &fr3, chan->name);
+	  get_user_flagrec (buser, &fr3, chan->dname);
 	  if (!loading && channel_active (chan) && me_op (chan) && (buser)
 	      && (chan_dovoice (fr3) || glob_dovoice (fr3)))
 	    {
@@ -1265,7 +1239,7 @@ check_expired_chanstuff ()
 		  if (m->user)
 		    {
 		      struct flag_record fr2 = { FR_GLOBAL | FR_CHAN, 0, 0 };
-		      get_user_flagrec (m->user, &fr2, chan->name);
+		      get_user_flagrec (m->user, &fr2, chan->dname);
 		      if ((!glob_bot (fr2)
 			   &&
 			   ((chan_voice (fr2)

+ 29 - 27
src/mod/irc.mod/mode.c

@@ -263,6 +263,7 @@ real_add_mode (struct chanset_t *chan, char plus, char mode, char *op)
   masklist *m;
   memberlist *mx;
   char s[21];
+  Context;
   if (!me_op (chan))
     return;
   if (mode == 'o')
@@ -455,6 +456,7 @@ got_op (struct chanset_t *chan, char *nick, char *from, char *who,
   struct userrec *u;
   int check_chan = 0;
   int snm = chan->stopnethack_mode;
+  Context;
   m = ismember (chan, who);
   if (!m)
     {
@@ -481,33 +483,22 @@ got_op (struct chanset_t *chan, char *nick, char *from, char *who,
     return;
   if (me_op (chan) && !match_my_nick (who) && nick[0])
     {
-#ifdef S_OWNEREXCEPT
       if ((channel_bitch (chan) || channel_closed (chan)
-	   || channel_take (chan)) && !(glob_master (*opper)
-					|| glob_bot (*opper))
-	  && !chan_master (*opper) && !(glob_op (victim) || glob_bot (victim))
-	  && !chan_op (victim))
-#else
-      if (channel_bitch (chan) && !(glob_bot (*opper))
-	  && !(glob_bot (victim) || glob_bot (victim)) && !chan_op (victim))
-#endif
-	add_mode (chan, '-', 'o', who);
-      else if ((chan_deop (victim) ||
-#ifdef S_OWNEREXCEPT
-		(glob_deop (victim) && !chan_op (victim)))
-	       && !glob_master (*opper) && !chan_master (*opper))
-#else
-		(glob_deop (victim) && !chan_op (victim))))
-#endif
-	add_mode (chan, '-', 'o', who);
-      else
-    if (reversing)
-      add_mode (chan, '-', 'o', who);
+	   || channel_take (chan)) && !glob_op (victim) && !chan_op (victim))
+	{
+	  if (target_priority (chan, m, 1))
+	    add_mode (chan, '-', 'o', who);
+	}
+      else if (reversing)
+	{
+	  add_mode (chan, '-', 'o', who);
+	}
     }
   else if (reversing && !match_my_nick (who))
     add_mode (chan, '-', 'o', who);
   if (!nick[0] && me_op (chan) && !match_my_nick (who))
     {
+      Context;
       if (chan_deop (victim) || (glob_deop (victim) && !chan_op (victim)))
 	{
 	  m->flags |= FAKEOP;
@@ -552,6 +543,7 @@ got_op (struct chanset_t *chan, char *nick, char *from, char *who,
   m->flags |= WASOP;
   if (check_chan)
     {
+      Context;
       recheck_channel (chan, 1);
       check_topic (chan);
     }
@@ -895,6 +887,7 @@ gotmode (char *from, char *origmsg)
   memberlist *m;
   struct chanset_t *chan;
   struct flag_record fr3 = { FR_GLOBAL | FR_CHAN, 0, 0 };
+  Context;
   strncpy (buf, origmsg, 510);
   buf[510] = 0;
   msg = buf;
@@ -906,6 +899,7 @@ gotmode (char *from, char *origmsg)
       chg = newsplit (&msg);
       reversing = 0;
       chan = findchan (ch);
+      Context;
       if (!chan)
 	{
 	  putlog (LOG_MISC, "*", CHAN_FORCEJOIN, ch);
@@ -913,8 +907,7 @@ gotmode (char *from, char *origmsg)
 	}
       else if (channel_active (chan) || channel_pending (chan))
 	{
-	  buser = get_user_by_handle (userlist, botnetnick);
-	  get_user_flagrec (buser, &fr3, chan->name);
+	  Context;
 	  z = strlen (msg);
 	  if (msg[--z] == ' ')
 	    msg[z] = 0;
@@ -923,6 +916,7 @@ gotmode (char *from, char *origmsg)
 	  u = get_user_by_host (from);
 	  get_user_flagrec (u, &user, ch);
 	  nick = splitnick (&from);
+	  Context;
 	  m = ismember (chan, nick);
 	  if (m)
 	    m->last = now;
@@ -935,22 +929,23 @@ gotmode (char *from, char *origmsg)
 	      if (chan_fakeop (m))
 		{
 		  putlog (LOG_MODES, ch, CHAN_FAKEMODE, ch);
-		  dprintf (DP_MODE, "KICK %s %s :%s\n", ch, nick,
-			   CHAN_FAKEMODE_KICK);
+		  dprintf (DP_MODE, "KICK %s %s :%s%s\n", ch, nick,
+			   kickprefix, CHAN_FAKEMODE_KICK);
 		  m->flags |= SENTKICK;
 		  reversing = 1;
 		}
 	      else if (!chan_hasop (m) && !channel_nodesynch (chan))
 		{
 		  putlog (LOG_MODES, ch, CHAN_DESYNCMODE, ch);
-		  dprintf (DP_MODE, "KICK %s %s :%s\n", ch, nick,
-			   CHAN_DESYNCMODE_KICK);
+		  dprintf (DP_MODE, "KICK %s %s :%s%s\n", ch, nick,
+			   kickprefix, CHAN_DESYNCMODE_KICK);
 		  m->flags |= SENTKICK;
 		  reversing = 1;
 		}
 	    }
 	  ms2[0] = '+';
 	  ms2[2] = 0;
+	  Context;
 	  while ((ms2[1] = *chg))
 	    {
 	      int todo = 0;
@@ -1028,10 +1023,14 @@ gotmode (char *from, char *origmsg)
 		    reversing = 1;
 		  break;
 		case 'l':
+		  Context;
+		  buser = get_user_by_handle (userlist, botnetnick);
+		  get_user_flagrec (buser, &fr3, ch);
 		  if ((!nick[0]) && (bounce_modes))
 		    reversing = 1;
 		  if (ms2[0] == '-')
 		    {
+		      Context;
 		      check_tcl_mode (nick, from, u, chan->dname, ms2, "");
 		      if (channel_active (chan))
 			{
@@ -1060,6 +1059,7 @@ gotmode (char *from, char *origmsg)
 		    }
 		  else
 		    {
+		      Context;
 		      op = newsplit (&msg);
 		      fixcolon (op);
 		      if (op == '\0')
@@ -1122,6 +1122,7 @@ gotmode (char *from, char *origmsg)
 		    }
 		  break;
 		case 'o':
+		  Context;
 		  op = newsplit (&msg);
 		  fixcolon (op);
 		  if (ms2[0] == '+')
@@ -1263,6 +1264,7 @@ gotmode (char *from, char *origmsg)
 		}
 	      chg++;
 	    }
+	  Context;
 	  if (chan->channel.do_opreq)
 	    request_op (chan);
 	  if (!me_op (chan) && !nick[0])

+ 6 - 3
src/mod/irc.mod/msgcmds.c

@@ -43,7 +43,7 @@ msg_pass (char *nick, char *host, struct userrec *u, char *par)
   if (strlen (new) < 8)
     {
       dprintf (DP_HELP,
-	       "NOTICE %s :insecure password, use >= 8 chars ucase, lcase and a number\n",
+	       "NOTICE %s :insecure password, use >= 8 chars uppercase, lowercase and a number\n",
 	       nick);
       return 0;
     }
@@ -60,7 +60,7 @@ msg_pass (char *nick, char *host, struct userrec *u, char *par)
   if ((ucase + ocase + lcase) != 3)
     {
       dprintf (DP_HELP,
-	       "NOTICE %s :insecure password, use >= 8 chars ucase, lcase and a number.\n",
+	       "NOTICE %s :insecure password, use >= 8 chars uppercase, lowercase and a number.\n",
 	       nick);
       return 0;
     }
@@ -153,7 +153,10 @@ msg_op (char *nick, char *host, struct userrec *u, char *par)
 		{
 		  get_user_flagrec (u, &fr, par);
 		  if (chan_op (fr) || (glob_op (fr) && !chan_deop (fr)))
-		    add_mode (chan, '+', 'o', nick);
+		    {
+		      stats_add (u, 0, 1);
+		      do_op (nick, chan);
+		    }
 		  putlog (LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host,
 			  u->handle, par);
 		  return 1;

+ 4 - 3
src/mod/irc.mod/tclirc.c

@@ -775,14 +775,15 @@ static int tcl_putkick STDVAR
       l = strlen (chan->name) + strlen (kicknick) + strlen (comment);
       if (((kick_method != 0) && (k == kick_method)) || (l > 480))
 	{
-	  dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick,
-		   comment);
+	  dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, kicknick,
+		   kickprefix, comment);
 	  k = 0;
 	  kicknick[0] = 0;
 	}
     }
   if (k > 0)
-    dprintf (DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick, comment);
+    dprintf (DP_SERVER, "KICK %s %s :%s%s\n", chan->name, kicknick,
+	     kickprefix, comment);
   return TCL_OK;
 }
 static tcl_cmds tclchan_cmds[] =

+ 5 - 0
src/mod/module.h

@@ -504,6 +504,11 @@
 #define isupdatehub ((int (*)(void))global[306])
 #define norestruct (*(int*)global[307])
 #define botlink ((int (*)(char *, int, char *))global[308])
+/* 309 - 312 */
+#define makeplaincookie ((void (*)(char *, char *, char *))global[309])
+#define kickprefix ((char *)(global[310]))
+#define bankickprefix ((char *)(global[311]))
+#define deflag_user ((void (*)(struct userrec *, int, char *))global[312])
 
 /* This is for blowfish module, couldnt be bothered making a whole new .h
  * file for it ;)

+ 9 - 2
src/mod/server.mod/server.c

@@ -3,7 +3,8 @@
 #define MAKING_SERVER
 #include "src/mod/module.h"
 #include "server.h"
-static Function *global = NULL;
+static Function *global = NULL, *encryption_funcs;
+extern struct cfg_entry CFG_OPTIMESLACK;
 static int ctcp_mode;
 static int serv;
 static int strict_host;
@@ -1880,7 +1881,8 @@ static Function server_table[] =
 (Function) & server_online, (Function) & min_servs, (Function) & H_raw, (Function) & H_wall,
 (Function) & H_msg, (Function) & H_msgm, (Function) & H_notc, (Function) & H_flud, (Function) & H_ctcp,
 (Function) & H_ctcr, (Function) ctcp_reply, (Function) get_altbotnick, (Function) & nick_len,
-(Function) check_tcl_notc, (Function) & server_lag, (Function) & curserv, (Function) cursrvname, };
+(Function) check_tcl_notc, (Function) & server_lag, (Function) & curserv, (Function) cursrvname,
+(Function) botrealname, };
 char *
 server_start (Function * global_funcs)
 {
@@ -1944,6 +1946,11 @@ server_start (Function * global_funcs)
   stack_limit = 4;
   server_table[4] = (Function) botname;
   module_register (MODULE_NAME, server_table, 1, 2);
+  if (!(encryption_funcs = module_depend (MODULE_NAME, "encryption", 0, 0)))
+    {
+      module_undepend (MODULE_NAME);
+      return "This module requires an encryption modules.";
+    }
   s = Tcl_GetVar (interp, "nick", TCL_GLOBAL_ONLY);
   if (s)
     strncpyz (origbotname, s, NICKLEN);

+ 1 - 0
src/mod/server.mod/server.h

@@ -41,6 +41,7 @@
 #define server_lag (*(int *)(server_funcs[39]))
 #define curserv (*(int *)(server_funcs[40))
 #define cursrvname ((char *)(server_funcs[41]))
+#define botrealname ((char *)(server_funcs[42]))
 #else
 #define free_null(ptr)	do {	nfree(ptr);	ptr = NULL;	} while (0)
 #endif

+ 308 - 1
src/mod/server.mod/servmsg.c

@@ -96,6 +96,7 @@ static int
 check_tcl_raw (char *from, char *code, char *msg)
 {
   int x;
+  Context;
   Tcl_SetVar (interp, "_raw1", from, 0);
   Tcl_SetVar (interp, "_raw2", code, 0);
   Tcl_SetVar (interp, "_raw3", msg, 0);
@@ -896,6 +897,7 @@ static int
 gotmode (char *from, char *msg)
 {
   char *ch;
+  Context;
   ch = newsplit (&msg);
   if (strchr (CHANMETA, ch[0]) == NULL)
     {
@@ -958,10 +960,49 @@ timeout_server (int idx)
 static struct dcc_table SERVER_SOCKET =
   { "SERVER", 0, eof_server, server_activity, NULL, timeout_server,
 display_server, NULL, kill_server, NULL };
+int
+isop (char *mode)
+{
+  int state = 0, cnt = 0;
+  char *p;
+  p = mode;
+  while ((*p) && (*p != ' '))
+    {
+      if (*p == '-')
+	state = 1;
+      else if (*p == '+')
+	state = 0;
+      else if ((!state) && (*p == 'o'))
+	cnt++;
+      p++;
+    }
+  return (cnt >= 1);
+}
+
+int
+ismdop (char *mode)
+{
+  int state = 0, cnt = 0;
+  char *p;
+  p = mode;
+  while ((*p) && (*p != ' '))
+    {
+      if (*p == '-')
+	state = 1;
+      else if (*p == '+')
+	state = 0;
+      else if ((state) && (*p == 'o'))
+	cnt++;
+      p++;
+    }
+  return (cnt >= 3);
+}
 static void
 server_activity (int idx, char *msg, int len)
 {
-  char *from, *code;
+  char *from, *code, tmp[1024];
+  char sign = '+';
+  Context;
   if (trying_server)
     {
       strcpy (dcc[idx].nick, "(server)");
@@ -977,6 +1018,272 @@ server_activity (int idx, char *msg, int len)
       from = newsplit (&msg);
     }
   code = newsplit (&msg);
+  if (!strcmp (code, STR ("MODE")) && (msg[0] == '#') && strchr (from, '!'))
+    {
+      char *modes[5] = { NULL, NULL, NULL, NULL, NULL };
+      char *nfrom, *hfrom;
+      int i;
+      struct userrec *ufrom = NULL;
+      struct chanset_t *chan = NULL;
+      char work[1024], *wptr, *p;
+      memberlist *m;
+      int modecnt = 0, ops = 0, deops = 0, bans = 0, unbans = 0;
+      strncpy0 (work, msg, sizeof (work));
+      wptr = work;
+      p = newsplit (&wptr);
+      chan = findchan (p);
+      p = newsplit (&wptr);
+      while (*p)
+	{
+	  char *mp;
+	  if (*p == '+')
+	    sign = '+';
+	  else if (*p == '-')
+	    sign = '-';
+	  else if (strchr (STR ("oblkvIe"), p[0]))
+	    {
+	      mp = newsplit (&wptr);
+	      if (strchr ("ob", p[0]))
+		{
+		  modes[modecnt] = nmalloc (strlen (mp) + 4);
+		  sprintf (modes[modecnt], STR ("%c%c %s"), sign, p[0], mp);
+		  modecnt++;
+		  if (p[0] == 'o')
+		    {
+		      if (sign == '+')
+			ops++;
+		      else
+			deops++;
+		    }
+		  if (p[0] == 'b')
+		    {
+		      if (sign == '+')
+			bans++;
+		      else
+			unbans++;
+		    }
+		}
+	    }
+	  else if (strchr (STR ("pstnmi"), p[0]))
+	    {
+	    }
+	  else
+	    {
+	      putlog (LOG_ERRORS, "*", STR ("Forgotten modechar: %c"), p[0]);
+	    }
+	  p++;
+	}
+      ufrom = get_user_by_host (from);
+      strncpy0 (work, from, sizeof (work));
+      p = strchr (work, '!');
+      *p++ = 0;
+      nfrom = work;
+      hfrom = p;
+      if ((chan) && (deops >= 3))
+	{
+	  if ((!ufrom) || (!(ufrom->flags & USER_BOT)))
+	    {
+	      if (ROLE_KICK_MDOP)
+		{
+		  m = ismember (chan, nfrom);
+		  if (!m || !chan_sentkick (m))
+		    {
+		      sprintf (tmp, STR ("KICK %s %s :%s%s\n"), chan->name,
+			       nfrom, kickprefix, kickreason (KICK_MASSDEOP));
+		      tputs (serv, tmp, strlen (tmp));
+		      if (m)
+			m->flags |= SENTKICK;
+		    }
+		}
+	    }
+	}
+      if (chan && ops && (ufrom) && (ufrom->flags & USER_BOT)
+	  && (!channel_fastop (chan)) && (!channel_take (chan)))
+	{
+	  int isbadop = 0;
+	  if ((modecnt != 2) || (strncmp (modes[0], "+o", 2))
+	      || (strncmp (modes[1], "-b", 2)))
+	    isbadop = 1;
+	  else
+	    {
+	      char enccookie[25], plaincookie[25], key[NICKLEN + 20],
+		goodcookie[25];
+	      strncpy0 (enccookie, (char *) &(modes[1][8]),
+			sizeof (enccookie));
+	      p = enccookie + strlen (enccookie) - 1;
+	      strcpy (key, nfrom);
+	      strcat (key, netpass);
+	      p = decrypt_string (key, enccookie);
+	      Context;
+	      strncpy0 (plaincookie, p, sizeof (plaincookie));
+	      nfree (p);
+	      makeplaincookie (chan->dname, (char *) (modes[0] + 3),
+			       goodcookie);
+	      if (strncmp
+		  ((char *) &plaincookie[6], (char *) &goodcookie[6], 5))
+		isbadop = 2;
+	      else
+		if (strncmp
+		    ((char *) &plaincookie[11], (char *) &goodcookie[11], 5))
+		isbadop = 3;
+	      else
+		{
+		  char tmp[20];
+		  long optime;
+		  int off;
+		  sprintf (tmp, STR ("%010li"), (now + timesync));
+		  strncpy0 ((char *) &tmp[4], plaincookie, 7);
+		  optime = atol (tmp);
+		  off = (now + timesync - optime);
+		  if (abs (off) > op_time_slack)
+		    {
+		      isbadop = 4;
+		      putlog (LOG_ERRORS, "*",
+			      "%s opped with bad ts: %li was off by %li",
+			      nfrom, optime, off);
+		    }
+		}
+	    }
+	  if (isbadop)
+	    {
+	      char trg[NICKLEN + 1] = "";
+	      int n, i;
+	      memberlist *m;
+	      Context;
+	      switch (role)
+		{
+		case 0:
+		  break;
+		case 1:
+		  m = ismember (chan, nfrom);
+		  if (!m || !chan_sentkick (m))
+		    {
+		      sprintf (tmp, STR ("KICK %s %s :%s%s\n"), chan->name,
+			       nfrom, kickprefix, kickreason (KICK_BADOP));
+		      tputs (serv, tmp, strlen (tmp));
+		      if (m)
+			m->flags |= SENTKICK;
+		    }
+		  sprintf (tmp, STR ("%s MODE %s"), from, msg);
+		  deflag_user (ufrom, DEFLAG_BADCOOKIE, tmp);
+		  break;
+		default:
+		  n = role - 1;
+		  i = 0;
+		  while ((i < 5) && (n > 0))
+		    {
+		      if (modes[i] && !strncmp (modes[i], "+o", 2))
+			n--;
+		      if (n)
+			i++;
+		    }
+		  if (!n)
+		    {
+		      strcpy (trg, (char *) &modes[i][3]);
+		      m = ismember (chan, trg);
+		      if (m)
+			{
+			  if (!(m->flags & CHANOP))
+			    {
+			      if (!chan_sentkick (m))
+				{
+				  sprintf (tmp, STR ("KICK %s %s :%s%s\n"),
+					   chan->name, trg, kickprefix,
+					   kickreason (KICK_BADOPPED));
+				  tputs (serv, tmp, strlen (tmp));
+				  m->flags |= SENTKICK;
+				}
+			    }
+			}
+		    }
+		}
+	      if (isbadop == 1)
+		putlog (LOG_WARN, "*", STR ("Missing cookie: %s MODE %s"),
+			from, msg);
+	      else if (isbadop == 2)
+		putlog (LOG_WARN, "*",
+			STR ("Invalid cookie (bad nick): %s MODE %s"), from,
+			msg);
+	      else if (isbadop == 3)
+		putlog (LOG_WARN, "*",
+			STR ("Invalid cookie (bad chan): %s MODE %s"), from,
+			msg);
+	      else if (isbadop == 4)
+		putlog (LOG_WARN, "*",
+			STR ("Invalid cookie (bad time): %s MODE %s"), from,
+			msg);
+	    }
+	  else
+	    putlog (LOG_DEBUG, "*", STR ("Good op: %s"), msg);
+	}
+#ifdef G_MANUALOP
+      if ((ops) && chan && !channel_manop (chan) && (ufrom)
+	  && !(ufrom->flags & USER_BOT))
+	{
+	  char trg[NICKLEN + 1] = "";
+	  int n, i;
+	  memberlist *m;
+	  switch (role)
+	    {
+	    case 0:
+	      break;
+	    case 1:
+	      m = ismember (chan, nfrom);
+	      if (!m || !chan_sentkick (m))
+		{
+		  sprintf (tmp, STR ("KICK %s %s :%s%s\n"), chan->name, nfrom,
+			   kickprefix, kickreason (KICK_MANUALOP));
+		  tputs (serv, tmp, strlen (tmp));
+		  if (m)
+		    m->flags |= SENTKICK;
+		}
+	      sprintf (tmp, STR ("%s MODE %s"), from, msg);
+	      deflag_user (ufrom, DEFLAG_MANUALOP, tmp);
+	      break;
+	    default:
+	      n = role - 1;
+	      i = 0;
+	      while ((i < 5) && (n > 0))
+		{
+		  if (modes[i] && !strncmp (modes[i], "+o", 2))
+		    n--;
+		  if (n)
+		    i++;
+		}
+	      if (!n)
+		{
+		  strcpy (trg, (char *) &modes[i][3]);
+		  m = ismember (chan, trg);
+		  if (m)
+		    {
+		      if (!(m->flags & CHANOP)
+			  && (rfc_casecmp (botname, trg)))
+			{
+			  if (!chan_sentkick (m))
+			    {
+			      sprintf (tmp, STR ("KICK %s %s :%s%s\n"),
+				       chan->name, trg, kickprefix,
+				       kickreason (KICK_MANUALOPPED));
+			      tputs (serv, tmp, strlen (tmp));
+			      m->flags |= SENTKICK;
+			    }
+			}
+		    }
+		  else
+		    {
+		      sprintf (tmp, STR ("KICK %s %s :%s%s\n"), chan->name,
+			       trg, kickprefix,
+			       kickreason (KICK_MANUALOPPED));
+		      tputs (serv, tmp, strlen (tmp));
+		    }
+		}
+	    }
+	}
+      for (i = 0; i < 5; i++)
+	if (modes[i])
+	  nfree (modes[i]);
+#endif
+    }
   if (use_console_r)
     {
       if (!strcmp (code, "PRIVMSG") || !strcmp (code, "NOTICE"))

+ 18 - 8
src/mod/share.mod/share.c

@@ -359,9 +359,11 @@ share_chattr (int idx, char *par)
 		  noshare = 0;
 		  build_flags (s, &fr, 0);
 		  fr.match = FR_CHAN;
+#ifndef LEAF
 		  if (!(dcc[idx].status & STAT_GETTING))
 		    putlog (LOG_CMDS, "@", "%s: chattr %s %s", dcc[idx].nick,
 			    hand, s);
+#endif
 		  if ((me = module_find ("irc", 0, 0)))
 		    {
 		      Function *func = me->funcs;
@@ -480,8 +482,10 @@ share_newuser (int idx, char *par)
 	      set_user_flagrec (u, &fr, 0);
 	      fr.match = FR_CHAN;
 	      noshare = 0;
+#ifndef LEAF
 	      putlog (LOG_CMDS, "@", "%s: newuser %s %s", dcc[idx].nick, nick,
 		      s);
+#endif
 	    }
 	}
     }
@@ -498,7 +502,9 @@ share_killuser (int idx, char *par)
       if (deluser (par))
 	{
 	  shareout_but (NULL, idx, "k %s\n", par);
+#ifndef LEAF
 	  putlog (LOG_CMDS, "@", "%s: killuser %s", dcc[idx].nick, par);
+#endif
 	}
       noshare = 0;
     }
@@ -516,7 +522,9 @@ share_pls_host (int idx, char *par)
 	{
 	  shareout_but (NULL, idx, "+h %s %s\n", hand, par);
 	  set_user (&USERENTRY_HOSTS, u, par);
+#ifndef LEAF
 	  putlog (LOG_CMDS, "@", "%s: +host %s %s", dcc[idx].nick, hand, par);
+#endif
 	}
     }
 }
@@ -544,9 +552,11 @@ share_pls_bothost (int idx, char *par)
 	      makepass (p);
 	      userlist = adduser (userlist, hand, par, p, USER_BOT);
 	    }
+#ifndef LEAF
 	  if (!(dcc[idx].status & STAT_GETTING))
 	    putlog (LOG_CMDS, "@", "%s: +host %s %s", dcc[idx].nick, hand,
 		    par);
+#endif
 	}
     }
 }
@@ -565,7 +575,9 @@ share_mns_host (int idx, char *par)
 	  noshare = 1;
 	  delhost_by_handle (hand, par);
 	  noshare = 0;
+#ifndef LEAF
 	  putlog (LOG_CMDS, "@", "%s: -host %s %s", dcc[idx].nick, hand, par);
+#endif
 	}
     }
 }
@@ -1219,8 +1231,7 @@ share_version (int idx, char *par)
     ~(STAT_SHARE | STAT_GETTING | STAT_SENDING | STAT_OFFERED |
       STAT_AGGRESSIVE);
   dcc[idx].u.bot->uff_flags = 0;
-  if ((dcc[idx].u.bot->numver == egg_numver)
-      && (bot_aggressive_to (dcc[idx].user)))
+  if (1 && (bot_aggressive_to (dcc[idx].user)))
     {
       if (can_resync (dcc[idx].nick))
 	dprintf (idx, "s r?\n");
@@ -1239,8 +1250,7 @@ hook_read_userfile ()
     {
       for (i = 0; i < dcc_total; i++)
 	if ((dcc[i].type->flags & DCT_BOT) && (dcc[i].status & STAT_SHARE)
-	    && !(dcc[i].status & STAT_AGGRESSIVE)
-	    && (dcc[i].u.bot->numver == egg_numver))
+	    && !(dcc[i].status & STAT_AGGRESSIVE) && (1))
 	  {
 	    if (dcc[i].status & STAT_SENDING)
 	      cancel_user_xfer (-i, 0);
@@ -1453,15 +1463,13 @@ check_expired_tbufs ()
 	  {
 	    if (now - dcc[i].timeval > 120)
 	      {
-		if (dcc[i].user && (bot_aggressive_to (dcc[i].user))
-		    && (dcc[i].u.bot->numver == egg_numver))
+		if (dcc[i].user && (bot_aggressive_to (dcc[i].user)) && (1))
 		  dprintf (i, "s u?\n");
 	      }
 	  }
 	else if (!(dcc[i].status & STAT_SHARE))
 	  {
-	    if (dcc[i].user && (bot_aggressive_to (dcc[i].user))
-		&& (dcc[i].u.bot->numver == egg_numver))
+	    if (dcc[i].user && (bot_aggressive_to (dcc[i].user)) && (1))
 	      dprintf (i, "s u?\n");
 	    dcc[i].status |= STAT_OFFERED;
 	  }
@@ -1751,8 +1759,10 @@ finish_share (int idx)
     for (i = 0; i < dcc_total; i++)
       dcc[i].user = get_user_by_handle (u, dcc[i].nick);
   loading = 1;
+  Context;
   if (!readuserfile (dcc[idx].u.xfer->filename, &u))
     {
+      Context;
       unlink (dcc[idx].u.xfer->filename);
       putlog (LOG_MISC, "@", "%s", USERF_CANTREAD);
       clear_userlist (u);

+ 18 - 24
src/mod/transfer.mod/transfer.c

@@ -3,12 +3,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "src/mod/module.h"
+#include "src/mod/update.mod/update.h"
 #include "src/tandem.h"
 #include "src/users.h"
 #include "transfer.h"
 #include <netinet/in.h>
 #include <arpa/inet.h>
-static Function *global = NULL;
+static Function *global = NULL, *update_funcs = NULL;
 static int copy_to_tmp = 1;
 static int wait_dcc_xfer = 40;
 static p_tcl_bind_list H_rcvd, H_sent, H_lost, H_tout;
@@ -787,17 +788,6 @@ eof_dcc_send (int idx)
 	  putlog (LOG_BOTS, "*", "Lost binary transfer from %s; aborting.",
 		  dcc[y].nick);
 	  unlink (dcc[idx].u.xfer->filename);
-	  dprintf (y, "bye\n");
-	  egg_snprintf (s, sizeof s,
-			"Disconnected %s (aborted binary transfer)",
-			dcc[y].nick);
-	  botnet_send_unlinked (y, dcc[y].nick, s);
-	  chatout ("*** %s\n", dcc[y].nick, s);
-	  if (y != idx)
-	    {
-	      killsock (dcc[y].sock);
-	      lostdcc (y);
-	    }
 	  killsock (dcc[idx].sock);
 	  lostdcc (idx);
 	}
@@ -965,10 +955,16 @@ dcc_get (int idx, char *buf, int len)
 		&& (dcc[x].type->flags & DCT_BOT))
 	      y = x;
 	  if (y != 0)
-	    dcc[y].status &= ~STAT_SENDINGU;
+	    {
+	      dcc[y].status &= ~STAT_SENDINGU;
+	      dcc[y].status |= STAT_UPDATED;
+	    }
 	  putlog (LOG_BOTS, "*", "Completed binary file send to %s",
 		  dcc[y].nick);
 	  xnick[0] = 0;
+#ifdef HUB
+	  bupdating = 0;
+#endif
 	}
       else
 	{
@@ -1034,16 +1030,10 @@ eof_dcc_get (int idx)
 	  y = x;
       putlog (LOG_BOTS, "*", "Lost binary transfer; aborting.");
       xnick[0] = 0;
-      dprintf (-dcc[y].sock, "bye\n");
-      egg_snprintf (s, sizeof s, "Disconnected %s (aborted binary transfer)",
-		    dcc[y].nick);
-      botnet_send_unlinked (y, dcc[y].nick, s);
-      chatout ("*** %s\n", s);
-      if (y != idx)
-	{
-	  killsock (dcc[y].sock);
-	  lostdcc (y);
-	}
+      dcc[y].status &= ~STAT_SENDINGU;
+#ifdef HUB
+      bupdating = 0;
+#endif
       killsock (dcc[idx].sock);
       lostdcc (idx);
       return;
@@ -1208,7 +1198,6 @@ tout_dcc_send (int idx)
 	{
 	  dcc[y].status &= ~STAT_GETTINGU;
 	}
-      unlink (dcc[idx].u.xfer->filename);
       putlog (LOG_BOTS, "*", "Timeout on binary transfer.");
     }
   else
@@ -1810,6 +1799,11 @@ transfer_start (Function * global_funcs)
   global = global_funcs;
   fileq = NULL;
   module_register (MODULE_NAME, transfer_table, 2, 2);
+  if (!(update_funcs = module_depend (MODULE_NAME, "update", 0, 0)))
+    {
+      module_undepend (MODULE_NAME);
+      return "This module requires update module 0.0 or later.";
+    }
   add_tcl_commands (mytcls);
   add_tcl_ints (myints);
   add_builtins (H_load, transfer_load);

+ 49 - 62
src/mod/update.mod/update.c

@@ -25,22 +25,25 @@ int updated = 0;
 static void
 update_ufno (int idx, char *par)
 {
-  putlog (LOG_BOTS, "*", "nary file rejected by %s: %s", dcc[idx].nick, par);
+  putlog (LOG_BOTS, "*", "binary file rejected by %s: %s", dcc[idx].nick,
+	  par);
   dcc[idx].status &= ~STAT_OFFEREDU;
 } static void
 update_ufyes (int idx, char *par)
 {
   if (dcc[idx].status & STAT_OFFEREDU)
     {
-      dcc[idx].status &= ~STAT_OFFEREDU;
-      dcc[idx].status |= STAT_SENDINGU;
       start_sending_binary (idx);
     }
 }
 static void
 update_fileq (int idx, char *par)
 {
+  if (dcc[idx].status & STAT_GETTINGU)
+    return;
 #ifdef LEAF
+  if (updated)
+    return;
   if (localhub)
     {
 #else
@@ -48,7 +51,6 @@ update_fileq (int idx, char *par)
     {
 #endif
       dprintf (idx, "sb uy\n");
-      dcc[idx].status |= STAT_GETTINGU;
     }
   else if (isupdatehub ())
     {
@@ -112,11 +114,11 @@ update_ufsend (int idx, char *par)
 }}} static void
 update_version (int idx, char *par)
 {
+  return;
 #ifdef HUB
   if (bupdating)
     return;
-  dcc[idx].status &=
-    ~(STAT_GETTINGU | STAT_SENDINGU | STAT_OFFEREDU | STAT_UPDATED);
+  dcc[idx].status &= ~(STAT_GETTINGU | STAT_SENDINGU | STAT_OFFEREDU);
   if ((dcc[idx].u.bot->numver < egg_numver) && (isupdatehub ()))
     {
       dprintf (idx, "sb u?\n");
@@ -134,14 +136,13 @@ static void
 got_nu (char *botnick, char *code, char *par)
 {
   int newver = 0;
+#ifdef LEAF
   tand_t *bot;
-#ifdef HUB
-  return;
-#endif
+  struct bot_addr *bi, *obi;
+  struct userrec *u1;
   bot = tandbot;
   if (!strcmp (bot->bot, botnick))
     return;
-#ifdef LEAF
   if (!localhub)
     return;
   if (localhub && updated)
@@ -152,10 +153,26 @@ got_nu (char *botnick, char *code, char *par)
   newver = atoi (newsplit (&par));
   if (newver > egg_numver)
     {
-      norestruct = 1;
+      Context;
+#ifdef LEAF
+      u1 = get_user_by_handle (userlist, botnetnick);
+      obi = get_user (&USERENTRY_BOTADDR, u1);
+      bi = user_malloc (sizeof (struct bot_addr));
+      bi->uplink = user_malloc (strlen (botnick) + 1);
+      strcpy (bi->uplink, botnick);
+      bi->address = user_malloc (strlen (obi->address) + 1);
+      strcpy (bi->address, obi->address);
+      bi->telnet_port = obi->telnet_port;
+      bi->relay_port = obi->relay_port;
+      bi->hublevel = obi->hublevel;
+      set_user (&USERENTRY_BOTADDR, u1, bi);
+      putlog (LOG_MISC, "*", "Changed uplink to %s for update.", botnick);
       botunlink (-2, bot->bot, "Restructure for update.");
       usleep (1000 * 500);
       botlink ("", -3, botnick);
+#else
+      putlog (LOG_MISC, "*", "I need to be updated with %d", newver);
+#endif
     }
 }
 static cmd_t update_bot[] =
@@ -182,7 +199,7 @@ finish_update (int idx)
   uid_t id;
   char buf[1024];
   char *buf2;
-  int result, i, ic, j = -1;
+  int i, j = -1;
   id = geteuid ();
   pw = getpwuid (id);
   for (i = 0; i < dcc_total; i++)
@@ -191,35 +208,14 @@ finish_update (int idx)
       j = i;
   if (j == -1)
     return;
-  ic = 0;
-next:;
-  ic++;
-  if (ic > 5)
-    {
-      putlog (LOG_MISC, "*", "COULD NOT UNCOMPRESS BINARY");
-      return;
-    }
-  result = 0;
-  result = is_compressedfile (dcc[idx].u.xfer->filename);
-  if (result == COMPF_COMPRESSED)
-    {
-      uncompress_file (dcc[idx].u.xfer->filename);
-      usleep (1000 * 500);
-      result = is_compressedfile (dcc[idx].u.xfer->filename);
-      if (result == COMPF_COMPRESSED)
-	goto next;
-    }
   sprintf (buf, "%s%s", pw->pw_dir, strrchr (dcc[idx].u.xfer->filename, '/'));
   movefile (dcc[idx].u.xfer->filename, buf);
   chmod (buf, S_IRUSR | S_IWUSR | S_IXUSR);
-  Context;
   sprintf (buf, "%s", strrchr (buf, '/'));
-  Context;
   buf2 = buf;
-  Context;
   buf2++;
-  Context;
   putlog (LOG_MISC, "*", "Updating with binary: %s", buf2);
+  Context;
   if (updatebin (0, buf2, 1))
     putlog (LOG_MISC, "*", "Failed to update to new binary..");
 #ifdef LEAF
@@ -232,12 +228,14 @@ start_sending_binary (int idx)
 {
 #ifdef HUB
   char update_file[1024];
-  char buf2[1024];
+  char buf2[1024], buf3[1024];
   struct stat sb;
-  int i = 1, result, ic;
+  int i = 1;
+  dcc[idx].status &= ~STAT_OFFEREDU;
   if (bupdating)
     return;
   bupdating = 1;
+  dcc[idx].status |= STAT_SENDINGU;
   putlog (LOG_BOTS, "*", "Sending binary send request to %s", dcc[idx].nick);
   if (!strcmp ("*", dcc[idx].u.bot->sysname))
     {
@@ -263,27 +261,10 @@ start_sending_binary (int idx)
 	      dcc[idx].nick, update_file);
       return;
     }
-  ic = 0;
-next:;
-  ic++;
-  if (ic > 5)
-    {
-      putlog (LOG_MISC, "*", "COULD NOT COMPRESS BINARY");
-      goto end;
-    }
-  result = 0;
-  result = is_compressedfile (update_file);
-  if (result == COMPF_UNCOMPRESSED)
-    {
-      compress_file (update_file, 9);
-      usleep (1000 * 500);
-    }
-  result = is_compressedfile (update_file);
-  if (result == COMPF_UNCOMPRESSED)
-    goto next;
-end:;
-  if ((i =
-       raw_dcc_send (update_file, "*binary", "(binary)", update_file)) > 0)
+  sprintf (buf3, "%s.%s", tempdir, update_file);
+  unlink (buf3);
+  copyfile (update_file, buf3);
+  if ((i = raw_dcc_send (buf3, "*binary", "(binary)", buf3)) > 0)
     {
       putlog (LOG_BOTS, "*", "%s -- can't send new binary",
 	      i == DCCSEND_FULL ? "NO MORE DCC CONNECTIONS" : i ==
@@ -301,8 +282,6 @@ end:;
 	       iptolong (natip[0] ? (IP) inet_addr (natip) : getmyip ()),
 	       dcc[i].port, dcc[i].u.xfer->length);
     }
-  dcc[idx].status |= (STAT_UPDATED);
-  bupdating = 0;
 #endif
 }
 static void (*def_dcc_bot_kill) (int, void *) = 0;
@@ -365,14 +344,17 @@ check_updates ()
   if (!isupdatehub ())
     return;
   cnt++;
-  if ((cnt == 3) && bupdating)
+  if ((cnt > 5) && bupdating)
     bupdating = 0;
   if (bupdating)
     return;
   cnt = 0;
   for (i = 0; i < dcc_total; i++)
     {
-      if (dcc[i].type->flags & DCT_BOT && !(dcc[i].status & STAT_UPDATED))
+      if (dcc[i].type->flags & DCT_BOT && (dcc[i].status & STAT_SHARE)
+	  && !(dcc[i].status & STAT_SENDINGU)
+	  && !(dcc[i].status & STAT_OFFEREDU)
+	  && !(dcc[i].status & STAT_UPDATED))
 	{
 	  dcc[i].status &= ~(STAT_GETTINGU | STAT_SENDINGU | STAT_OFFEREDU);
 	  if ((dcc[i].u.bot->numver < egg_numver) && (isupdatehub ()))
@@ -463,7 +445,12 @@ EXPORT_SCOPE char *update_start ();
 static Function update_table[] =
   { (Function) update_start, (Function) update_close,
 (Function) update_expmem, (Function) update_report, (Function) finish_update, (Function) 0, (Function) 0,
-(Function) 0 };
+#ifdef LEAF
+  (Function) 0
+#else
+  (Function) 0, (Function) & bupdating
+#endif
+};
 char *
 update_start (Function * global_funcs)
 {

+ 3 - 0
src/mod/update.mod/update.h

@@ -11,5 +11,8 @@ typedef struct
 } uff_table_t;
 #ifndef MAKING_update
 #define finish_update ((void (*) (int))update_funcs[4])
+#ifdef HUB
+#define bupdating (*(int*)update_funcs[8])
+#endif
 #endif
 #endif

+ 4 - 2
src/modules.c

@@ -8,7 +8,8 @@ extern Tcl_Interp *interp;
 extern struct userrec *userlist, *lastuser;
 extern char tempdir[], botnetnick[], botname[], natip[], hostname[],
   origbotname[], botuser[], admin[], userfile[], ver[], notify_new[],
-  version[], quit_msg[], hostname6[], netpass[], thepass[];
+  kickprefix[], bankickprefix[], version[], quit_msg[], hostname6[],
+  netpass[], thepass[];
 extern int noshare, loading, role, dcc_total, egg_numver, userfile_perm,
   use_console_r, ignore_time, must_be_owner, debug_output, default_flags,
   norestruct, max_dcc, share_greet, password_timeout, localhub,
@@ -249,7 +250,8 @@ Function global_table[] = { (Function) mod_malloc, (Function) mod_free,
     (Function) getting_users, (Function) add_builtins_dcc,
     (Function) rem_builtins_dcc, (Function) & USERENTRY_ADDED,
     (Function) thepass, (Function) isupdatehub, (Function) & norestruct,
-    (Function) botlink
+    (Function) botlink, (Function) makeplaincookie, (Function) bankickprefix,
+    (Function) kickprefix, (Function) deflag_user
 };
 void
 init_modules (void)

+ 1 - 1
src/net.c

@@ -39,7 +39,7 @@ char hostname6[121] = "";
 char firewall[121] = "";
 int firewallport = 1080;
 char botuser[21] = "wraith";
-int dcc_sanitycheck = 1;
+int dcc_sanitycheck = 0;
 sock_list *socklist = NULL;
 int MAXSOCKS = 0;
 jmp_buf alarmret;

+ 4 - 0
src/proto.h

@@ -141,6 +141,8 @@ char *get_language (int);
 void add_lang_section (char *);
 int del_lang_section (char *);
 int exist_lang_section (char *);
+int crontab_exists ();
+void crontab_create (int);
 void fatal (const char *, int);
 int expected_memory (void);
 void eggContext (const char *, int, const char *);
@@ -159,6 +161,7 @@ void tell_mem_status_dcc (int);
 void debug_mem_to_dcc (int);
 char *progname ();
 void init_settings ();
+void makeplaincookie (char *, char *, char *);
 int isupdatehub ();
 int getting_users ();
 char *kickreason (int);
@@ -248,6 +251,7 @@ void list_type_kill (struct list_type *);
 int list_type_expmem (struct list_type *);
 int xtra_set ();
 void stats_add (struct userrec *, int, int);
+void deflag_user (struct userrec *, int, char *);
 struct userrec *adduser (struct userrec *, char *, char *, char *, int);
 void addhost_by_handle (char *, char *);
 void clear_masks (struct maskrec *);

+ 67 - 0
src/salt.h

@@ -0,0 +1,67 @@
+/* The 1. Salt -> string containing anything, 25 chars */
+#define HUMRE1 "psxmafcosxazpwrgcdpakylgd"
+
+/* The 2. Salt -> string containing anything, 9 chars */
+#define HUMRE2 "kfdspaqzc"
+
+/* the 1. Code -> a one byte startup code */
+#define CODE1 74
+
+/* the 2. Code -> a one byte startup code */
+#define CODE2 66
+
+/* the 1. Salt Offset -> value from 0-24 */
+#define SA1 24
+
+/* the 2. Salt Offset -> value from 0-8 */
+#define SA2 8
+
+/* the make salt routine */
+/* dont wonder about the redundance, its needed to somehow hide the fully salts */
+
+/* salt buffers */
+
+unsigned char slt1[26];
+unsigned char slt2[10];
+
+int
+makesalt (void)
+{
+  slt1[0] = HUMRE1[1];
+  slt1[1] = HUMRE1[0];
+  slt1[2] = HUMRE1[3];
+  slt1[3] = HUMRE1[2];
+  slt1[4] = HUMRE1[5];
+  slt1[5] = HUMRE1[4];
+  slt1[6] = HUMRE1[6];
+  slt1[7] = HUMRE1[7];
+  slt1[8] = HUMRE1[8];
+  slt1[9] = HUMRE1[9];
+  slt1[10] = HUMRE1[11];
+  slt1[11] = HUMRE1[10];
+  slt1[12] = HUMRE1[12];
+  slt1[13] = HUMRE1[13];
+  slt1[14] = HUMRE1[15];
+  slt1[15] = HUMRE1[14];
+  slt1[16] = HUMRE1[16];
+  slt1[17] = HUMRE1[17];
+  slt1[18] = HUMRE1[18];
+  slt1[19] = HUMRE1[19];
+  slt1[20] = HUMRE1[22];
+  slt1[21] = HUMRE1[21];
+  slt1[22] = HUMRE1[20];
+  slt1[23] = HUMRE1[24];
+  slt1[24] = HUMRE1[23];
+  slt1[25] = 0;
+  slt2[0] = HUMRE2[1];
+  slt2[1] = HUMRE2[0];
+  slt2[2] = HUMRE2[2];
+  slt2[3] = HUMRE2[3];
+  slt2[4] = HUMRE2[4];
+  slt2[5] = HUMRE2[8];
+  slt2[6] = HUMRE2[6];
+  slt2[7] = HUMRE2[7];
+  slt2[8] = HUMRE2[5];
+  slt2[9] = 0;
+  return 0;
+}

+ 2 - 5
src/settings.c

@@ -5,7 +5,6 @@ char netpass[15] = "kd8e3nchasd93dk";	//Just 15 random chars here.. (DO CHANGE)
 
 //This pass will be used to encrypt files and other important things...
 //Just MD5 some word and put the hash in here..
-//An md5 program is include in wraith/md5/, just type ./md5
 char thepass[33] = "5f4dcc3b5aa765d61d8327deb882cf99";
 
 
@@ -42,7 +41,7 @@ char dcc_prefix[1] = "!";	/* Defines the command prefix */
 char owners[2048] = "";
 char hubs[2048] = "";
 
-char mhub[15] = "sbp";		// Put your main hub nick in there, needed for logging, temp fix.
+char mhub[15] = "hub";		// Put your main hub nick in there, needed for logging, temp fix.
 
 void
 init_settings ()
@@ -58,8 +57,6 @@ init_settings ()
 
 //By "ip/hostname" I mean ip OR hostname, I highly recommend setting up dns for your hub with a hostname.
 
-  THIS IS ONLY AN EXAMPLE, THE REAL LINES ARE FURTHER DOWN...
-
 char t_owners[2048] = "\
 nick pass *!u@host *!u@ip *!u@host *!u@host *!u@ip,\
 nick pass *!u@host\
@@ -67,7 +64,7 @@ nick pass *!u@host\
 char t_hubs[2048] = "\
 hubnick ip/hostname port 1 username username,\
 hubnick2 ip/hostname port 2 username username,\
-hubnick3 ip/hostname port 3 username username\       <-- note missing comma
+hubnick3 ip/hostname port 3 username username\
 ";
 
  * Give your main hub the number 1...

+ 9 - 1
src/tclmisc.c

@@ -13,7 +13,7 @@ extern char origbotname[], botnetnick[], quit_msg[];
 extern struct userrec *userlist;
 extern time_t now;
 extern module_entry *module_list;
-extern int max_logs;
+extern int max_logs, timesync;
 extern log_t *logs;
 extern Tcl_Interp *interp;
 extern char myipv6host[120];
@@ -439,6 +439,13 @@ static int tcl_backup STDVAR
   return TCL_OK;
 }
 #endif
+static int tcl_timesync STDVAR
+{
+  char buf[20];
+    sprintf (buf, "%li %li %li", (now + timesync), now, timesync);
+    Tcl_AppendResult (irp, buf, NULL);
+    return TCL_OK;
+}
 static int tcl_die STDVAR
 {
   char s[1024];
@@ -577,6 +584,7 @@ tcl_cmds tclmisc_cmds[] = {
 #endif
   {"ischanhub", tcl_ischanhub}
   , {"issechub", tcl_issechub}
+  , {"timesync", tcl_timesync}
   , {"exit", tcl_die}
   , {"die", tcl_die}
   , {"unames", tcl_unames}

+ 8 - 42
src/userent.c

@@ -19,6 +19,7 @@ init_userent ()
   add_entry_type (&USERENTRY_LASTON);
   add_entry_type (&USERENTRY_BOTADDR);
   add_entry_type (&USERENTRY_PASS);
+  add_entry_type (&USERENTRY_SECPASS);
   add_entry_type (&USERENTRY_HOSTS);
   add_entry_type (&USERENTRY_BOTFL);
   add_entry_type (&USERENTRY_STATS);
@@ -127,8 +128,10 @@ def_set (struct userrec *u, struct user_entry *e, void *buf)
 int
 def_gotshare (struct userrec *u, struct user_entry *e, char *data, int idx)
 {
+#ifdef HUB
   putlog (LOG_CMDS, "@", "%s: change %s %s", dcc[idx].nick, e->type->name,
 	  u->handle);
+#endif
   return e->type->set (u, e, data);
 }
 
@@ -501,48 +504,9 @@ pass_tcl_set (Tcl_Interp * irp, struct userrec *u, struct user_entry *e,
 struct user_entry_type USERENTRY_PASS =
   { 0, def_gotshare, 0, def_unpack, def_pack, def_write_userfile, def_kill,
 def_get, pass_set, def_tcl_get, pass_tcl_set, def_expmem, 0, "PASS" };
-int
-secpass_set (struct userrec *u, struct user_entry *e, void *buf)
-{
-  char new[32];
-  register char *pass = buf;
-  if (e->u.extra)
-    nfree (e->u.extra);
-  if (!pass || !pass[0] || (pass[0] == '-'))
-    e->u.extra = NULL;
-  else
-    {
-      unsigned char *p = (unsigned char *) pass;
-      if (strlen (pass) > 15)
-	pass[15] = 0;
-      while (*p)
-	{
-	  if ((*p <= 32) || (*p == 127))
-	    *p = '?';
-	  p++;
-	}
-      if ((u->flags & USER_BOT) || (pass[0] == '+'))
-	strcpy (new, pass);
-      else
-	encrypt_pass (pass, new);
-      e->u.extra = user_malloc (strlen (new) + 1);
-      strcpy (e->u.extra, new);
-    }
-  if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
-    shareout (NULL, "c SECPASS %s %s\n", u->handle, pass ? pass : "");
-  return 1;
-}
-static int
-secpass_tcl_set (Tcl_Interp * irp, struct userrec *u, struct user_entry *e,
-		 int argc, char **argv)
-{
-  BADARGS (3, 4, " handle SECPASS ?newpass?");
-  pass_set (u, e, argc == 3 ? NULL : argv[3]);
-  return TCL_OK;
-}
 struct user_entry_type USERENTRY_SECPASS =
-  { 0, def_gotshare, 0, def_unpack, def_pack, def_write_userfile, def_kill,
-def_get, secpass_set, def_tcl_get, secpass_tcl_set, def_expmem, 0, "SECPASS" };
+  { 0, def_gotshare, def_dupuser, def_unpack, def_pack, def_write_userfile,
+def_kill, def_get, def_set, 0, 0, def_expmem, def_display, "SECPASS" };
 static int
 laston_unpack (struct userrec *u, struct user_entry *e)
 {
@@ -773,7 +737,6 @@ botaddr_kill (struct user_entry *e)
   nfree (((struct bot_addr *) (e->u.extra))->uplink);
   nfree (e->u.extra);
   nfree (e);
-  Context;
   return 1;
 }
 static int
@@ -1236,6 +1199,9 @@ xtra_write_userfile, xtra_kill, def_get, xtra_set, xtra_tcl_get, xtra_tcl_set, x
       }
     if (s[0])
       dprintf (idx, "%s\n", s);
+#endif
+#ifdef LEAF
+    dprintf (idx, "  HOSTS:          Hidden on leaf bots.\n");
 #endif
   }
   static int hosts_set (struct userrec *u, struct user_entry *e, void *buf)

+ 170 - 0
src/userrec.c

@@ -827,3 +827,173 @@ user_del_chan (char *dname)
 	}
     }
 }
+struct cfg_entry CFG_BADCOOKIE,
+#ifdef G_MANUALOP
+  CFG_MANUALOP,
+#endif
+#ifdef G_MEAN
+  CFG_MEANDEOP, CFG_MEANKICK, CFG_MEANBAN,
+#endif
+  CFG_MDOP;
+int deflag_dontshare = 0;
+char deflag_tmp[20];
+#define DEFL_IGNORE 0
+#define DEFL_DEOP 1
+#define DEFL_KICK 2
+#define DEFL_DELETE 3
+void
+deflag_describe (struct cfg_entry *cfgent, int idx)
+{
+  if (cfgent == &CFG_BADCOOKIE)
+    dprintf (idx,
+	     STR
+	     ("bad-cookie decides what happens to a bot if it does an illegal op (no/incorrect op cookie)\n"));
+#ifdef G_MANUALOP
+  else if (cfgent == &CFG_MANUALOP)
+    dprintf (idx,
+	     STR
+	     ("manualop decides what happens to a user doing a manual op in a -manualop channel\n"));
+#endif
+#ifdef G_MEAN
+  else if (cfgent == &CFG_MEANDEOP)
+    dprintf (idx,
+	     STR
+	     ("mean-deop decides what happens to a user deopping a bot in a +mean channel\n"));
+  else if (cfgent == &CFG_MEANKICK)
+    dprintf (idx,
+	     STR
+	     ("mean-kick decides what happens to a user kicking a bot in a +mean channel\n"));
+  else if (cfgent == &CFG_MEANBAN)
+    dprintf (idx,
+	     STR
+	     ("mean-ban decides what happens to a user banning a bot in a +mean channel\n"));
+#endif
+  else if (cfgent == &CFG_MDOP)
+    dprintf (idx,
+	     STR ("mdop decides what happens to a user doing a mass deop\n"));
+  dprintf (idx,
+	   STR
+	   ("Valid settings are: ignore (No flag changes), deop (give -fmnop+d), kick (give -fmnop+dk) or delete (remove from userlist)\n"));
+}
+
+void
+deflag_changed (struct cfg_entry *entry, char *oldval, int *valid)
+{
+  char *p = (char *) entry->gdata;
+  if (!p)
+    return;
+  if (strcmp (p, STR ("ignore")) && strcmp (p, STR ("deop"))
+      && strcmp (p, STR ("kick")) && strcmp (p, STR ("delete")))
+    *valid = 0;
+}
+struct cfg_entry CFG_BADCOOKIE =
+  { "bad-cookie", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL,
+deflag_describe };
+#ifdef G_MANUALOP
+struct cfg_entry CFG_MANUALOP =
+  { "manualop", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL,
+deflag_describe };
+#endif
+#ifdef G_MEAN
+struct cfg_entry CFG_MEANDEOP =
+  { "mean-deop", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL,
+deflag_describe };
+struct cfg_entry CFG_MEANKICK =
+  { "mean-kick", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL,
+deflag_describe };
+struct cfg_entry CFG_MEANBAN =
+  { "mean-ban", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL,
+deflag_describe };
+#endif
+struct cfg_entry CFG_MDOP =
+  { "mdop", CFGF_GLOBAL, NULL, NULL, deflag_changed, NULL, deflag_describe };
+void
+deflag_user (struct userrec *u, int why, char *msg)
+{
+  char tmp[256], tmp2[1024];
+  struct cfg_entry *ent = NULL;
+  struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0 };
+  if (!u)
+    return;
+  switch (why)
+    {
+    case DEFLAG_BADCOOKIE:
+      strcpy (tmp, STR ("Bad op cookie"));
+      ent = &CFG_BADCOOKIE;
+      break;
+#ifdef G_MANUALOP
+    case DEFLAG_MANUALOP:
+      strcpy (tmp, STR ("Manual op in -manualop channel"));
+      ent = &CFG_MANUALOP;
+      break;
+#endif
+#ifdef G_MEAN
+    case DEFLAG_MEAN_DEOP:
+      strcpy (tmp, STR ("Deopped bot in +mean channel"));
+      ent = &CFG_MEANDEOP;
+      break;
+    case DEFLAG_MEAN_KICK:
+      strcpy (tmp, STR ("Kicked bot in +mean channel"));
+      ent = &CFG_MEANDEOP;
+      break;
+    case DEFLAG_MEAN_BAN:
+      strcpy (tmp, STR ("Banned bot in +mean channel"));
+      ent = &CFG_MEANDEOP;
+      break;
+#endif
+    case DEFLAG_MDOP:
+      strcpy (tmp, STR ("Mass deop"));
+      ent = &CFG_MDOP;
+      break;
+    default:
+      ent = NULL;
+      sprintf (tmp, STR ("Reason #%i"), why);
+    }
+  if (ent && ent->gdata && !strcmp (ent->gdata, STR ("deop")))
+    {
+      putlog (LOG_WARN, "*", STR ("Setting %s +d (%s): %s\n"), u->handle, tmp,
+	      msg);
+      sprintf (tmp2, STR ("+d: %s (%s)"), tmp, msg);
+      set_user (&USERENTRY_COMMENT, u, tmp2);
+      get_user_flagrec (u, &fr, NULL);
+      fr.global = USER_DEOP;
+      set_user_flagrec (u, &fr, NULL);
+    }
+  else if (ent && ent->gdata && !strcmp (ent->gdata, STR ("kick")))
+    {
+      putlog (LOG_WARN, "*", STR ("Setting %s +dk (%s): %s\n"), u->handle,
+	      tmp, msg);
+      sprintf (tmp2, STR ("+dk: %s (%s)"), tmp, msg);
+      set_user (&USERENTRY_COMMENT, u, tmp2);
+      get_user_flagrec (u, &fr, NULL);
+      fr.global = USER_DEOP | USER_KICK;
+      set_user_flagrec (u, &fr, NULL);
+    }
+  else if (ent && ent->gdata && !strcmp (ent->gdata, STR ("delete")))
+    {
+      putlog (LOG_WARN, "*", STR ("Deleting %s (%s): %s\n"), u->handle, tmp,
+	      msg);
+      deluser (u->handle);
+    }
+  else
+    {
+      putlog (LOG_WARN, "*", STR ("No user flag effects for %s (%s): %s\n"),
+	      u->handle, tmp, msg);
+      sprintf (tmp2, STR ("Warning: %s (%s)"), tmp, msg);
+      set_user (&USERENTRY_COMMENT, u, tmp2);
+    }
+}
+void
+init_userrec ()
+{
+  add_cfg (&CFG_BADCOOKIE);
+#ifdef G_MANUALOP
+  add_cfg (&CFG_MANUALOP);
+#endif
+#ifdef G_MEAN
+  add_cfg (&CFG_MEANDEOP);
+  add_cfg (&CFG_MEANKICK);
+  add_cfg (&CFG_MEANBAN);
+#endif
+  add_cfg (&CFG_MDOP);
+}

+ 8 - 0
src/users.c

@@ -1286,23 +1286,28 @@ autolink_cycle (char *start)
     }
   if (curhub[0])
     {
+      Context;
       if (!strcmp (curhub, uplink))
 	return;
       if (start)
 	return;
       if (uplink[0])
 	{
+	  Context;
 	  botlink ("", -3, uplink);
 	  return;
 	}
       return;
+      Context;
     }
   else
     {
+      Context;
       if (!start)
 	{
 	  if (uplink[0])
 	    {
+	      Context;
 	      botlink ("", -3, uplink);
 	      return;
 	    }
@@ -1310,12 +1315,15 @@ autolink_cycle (char *start)
 	}
       else
 	{
+	  Context;
 	  botlinkcount++;
 	  if (botlinkcount >= 3)
 	    return;
+	  Context;
 	  strcpy (avoidbot, start);
 	}
     }
+  Context;
   ul = userlist;
   hlc = 0;
   Context;

+ 1 - 1
src/users.h

@@ -34,7 +34,7 @@ struct user_entry_type
 extern struct user_entry_type USERENTRY_COMMENT, USERENTRY_LASTON,
   USERENTRY_INFO, USERENTRY_BOTADDR, USERENTRY_HOSTS, USERENTRY_PASS,
   USERENTRY_BOTFL, USERENTRY_STATS, USERENTRY_ADDED, USERENTRY_CONFIG,
-  USERENTRY_XTRA;
+  USERENTRY_SECPASS, USERENTRY_XTRA;
 #endif
 struct laston_info
 {