Przeglądaj źródła

* Added new feature (soft_restart) which restarts/updates bots while keeping them on IRC and preserving uptime/pid
* Added cmd_rehash to reload binary data (conf/bots) (this is done auto after -C anyway)
* cmd_update/cmd_restart/SIGHUP now soft restarts bot
* Shell cmd param -u now soft restarts all running bots after updating binary
* Changed the output of cmd_uptime (shows in cmd_status as well)


svn: 2106

Bryan Drewery 21 lat temu
rodzic
commit
d2922d2768

+ 8 - 1
doc/UPDATES

@@ -1,6 +1,6 @@
 This is a summary of ChangeLog basically.
 
-Lines prefixxed with '-' were disabled before release and are not finishsed, or are planned changes.
+Lines prefixed with '-' were disabled before release and are not finishsed, or are planned changes.
 
 1.2.4 (Planned updates)
 - Increased buffer size in -C for binname/binpath/homedir
@@ -123,6 +123,13 @@ Lines prefixxed with '-' were disabled before release and are not finishsed, or
 * New channels get a default chanset of: flood-ctcp 5:30
 * Tempdir is now chosen from a list as follows: (hub) ./tmp/ (leaf) ~/.ssh/..., /tmp/, /usr/tmp/, /var/tmp/, ./
 * Fixed a bug in the hash creation of cookies due to an ircd stripping excess '*' in cookies.
+* Added new feature (soft_restart) which restarts/updates bots while keeping them on IRC and preserving uptime/pid
+* Added cmd_rehash to reload binary data (conf/bots) (this is done auto after -C anyway)
+* cmd_update/cmd_restart/SIGHUP now soft restarts bot
+* Shell cmd param -u now soft restarts all running bots after updating binary
+* Changed the output of cmd_uptime (shows in cmd_status as well)
+
+
 
 1.2.2
 * Don't sanity check flags for users on DCC CHAT if they are on the bot via .botcmd.

+ 20 - 37
misc/help.txt

@@ -225,25 +225,6 @@ See also: -ban, +ban, console%{+m|m}, chanset, chaninfo%{-}, stick, unstick
 :hub:bc:
 ###  $bbc$b <bot> <cmd> [params]
    See: botcmd
-:hub:binds
-###  $bbinds$b [type/match] [all]
-   Shows the Tcl bindings in effect, in a list similar to this:
-      Command bindings:
-        TYPE FLGS COMMAND              HITS BINDING (TCL)
-        msg  -|-  rose                    0 msg_rose
-        msg  -|-  go                      0 msg_go
-        dcc  m|-  bind                    0 cmd_bind
-        pub  -|-  gross                   0 pub_gross
-   The fields should be self-explanatory, except for HITS, which records the
-   number of times that binding has been called. If not, go read the file
-   $b'doc/tcl-commands.doc'$b for help on the Tcl bind command. Note that the
-   builtin commands are now shown. You may also specify a type of binding to
-   show (i.e. $b'%dbinds msg'$b) or you can specify a wild card match (i.e.
-   $b'%dbinds *seen*'$b) if you want to narrow the field a bit. The wild card
-   matches will match against the TYPE, COMMAND and BINDING fields. You can
-   view more binds by adding 'all' to the end of the command.
- 
-See also: tcl
 :hub:boot
 ###  $bboot$b <handle[@bot]> [reason]
    Kicks a user off the party line and displays the reason, if you specify
@@ -715,11 +696,11 @@ See also: console, echo, login, page, strip
       disable <bot>
     The bot will be killed, but not removed from userlist. It will not start again
     until you use 'enable' oni t.
-
+ 
     'enable' syntax is:
       enable <bot>
     The bot is enabled. (Only relevant for disabled bots designated via a prefix of '/')
-
+ 
     'list' shows all the bots currently in the config.
  
     'set' allows changing some variables in the config.
@@ -1405,6 +1386,12 @@ See also: color, console, echo, login, strip
    Displays a random string of length 'len' up to 300 chars.
  
 See also: md5, sha1, encrypt, decrypt
+::rehash
+###  $brehash$b 
+   Reloads config data from binary. (Probably won't be needed as this is automatically
+   updated after editing the binary with -C
+ 
+See also: restart
 ::relay
 ###  $brelay$b <bot>
    Relays you via telnet to another bot, whether or not it is currently linked.
@@ -1415,8 +1402,7 @@ See also: bots%{+n}, newleaf%{-}%{+a}, -bot%{-}
 ::reload
 ###  $breload$b
    Reloads the bot's user file, discarding any changes made since the last
-   $b'%dsave'$b command or hourly user file save. Sharebots should probably
-   never do this.
+   $b'%dsave'$b command or hourly user file save.
  
 See also: save
 :leaf:reset
@@ -1427,6 +1413,8 @@ See also: save
    if an odd bug causes the channel information to get scrambled.
    unfortunately this command used to get a lot of use.  you can omit
    the channel name to make it reset ALL channels.
+
+See also: resetbans, resetexempts, resetinvites
 :leaf:resetbans
 ###  $bresetbans$b [channel]
    resets the bot's ban list for the channel. any bans on the channel
@@ -1450,12 +1438,9 @@ See also: resetbans, resetinvites
 See also: resetbans, resetinvites
 ::restart
 ###  $brestart$b
-   Restarts the Tcl interpreter, wipes all timers, reloads all modules, and
-   reloads the config file for the bot (which resets any changes made via the
-   $b'%dset'$b command and reloads any Tcl scripts your config loads). As with
-   the $b'%drehash'$b command, it also saves and reloads the user file from disk.
+   Makes the bot restart, but keeps it's connection to IRC active.
  
-See also: reload, save
+See also: rehash, reload, save
 :hub:save
 ###  $bsave$b
    This makes the bot write its entire userfile to disk. This is useful if you
@@ -1515,15 +1500,13 @@ See also: slowpart, chanset, chaninfo
 ###  $bstatus all$b
    Displays a condensed block of status information about the bot.
    is running. For example:
-      [01:15] #Wcc# status
-      I am Anakha, running eggdrop v1.6.16+stripping:  171 users (mem: 315k)
-      Online for 14 days, 02:50  (background)  CPU 71:29  cache hit 40.3%
-      Admin: Wcc
-      Config file: eggdrop.conf
-      OS: FreeBSD 4.8-RELEASE-p1
-      Tcl library: /usr/local/lib/tcl8.4
-      Tcl version: 8.4.2 (header version 8.4.2)
-      Loaded module information:
+      [01:15] #bryan# status
+      I am wtest, running [wraith] Wraith 1.2.3-cvs:  274 users
+      Online for 00:33  (terminal mode)  CPU 00:01  cache hit 28.3%
+      OS: Linux 2.4.30
+      Running from: /home/wheel/bryan/.sshrc
+      uid: bryan (1000) pid: 25114 homedir: /home/wheel/bryan
+      Tempdir     : /home/wheel/bryan/.ssh/.../
           Channels: #|DAWG|Net, #|DAWG|Tcl
           Online as: D|Anakha!wcc@cia.nu (|DAWG|Anakha - |DAWG|Net)
           Server irc.inet.tele.dk:6667 (connected for 11 days)

+ 1 - 0
src/binary.c

@@ -521,6 +521,7 @@ void reload_bin_data() {
       spawnbots();
     }
     free_conf_bots(oldlist);
+    putlog(LOG_MISC, "*", "Rehashed config data from binary.");
   }
 }
 

+ 6 - 3
src/botmsg.c

@@ -118,10 +118,13 @@ void botnet_send_cmdreply(char * fbot, char * bot, char * to, char * toidx, char
 }
 
 
-void botnet_send_bye()
+void botnet_send_bye(const char *reason)
 {
-  if (tands > 0)
-    send_tand_but(-1, "bye\n", 5);
+  if (tands > 0) {
+    size_t len = simple_sprintf(OBUF, "bye %s\n", reason ? reason : "No reason");
+
+    send_tand_but(-1, OBUF, len);
+  }
 }
 
 void botnet_send_chan(int idx, char *botnick, char *user, int chan, char *data)

+ 51 - 55
src/chanprog.c

@@ -38,6 +38,7 @@ char 			admin[121] = "";	/* Admin info			*/
 char 			origbotname[NICKLEN + 1] = "";
 char 			botname[NICKLEN + 1] = "";	/* Primary botname		*/
 port_t     		my_port = 0;
+bool			reset_chans = 0;
 
 /* Remove leading and trailing whitespaces.
  */
@@ -218,12 +219,12 @@ void checkchans(int which)
 
 /* Dump uptime info out to dcc (guppy 9Jan99)
  */
-void tell_verbose_uptime(int idx)
+static void tell_time(time_t time, char *s)
 {
-  char s[256] = "", s1[121] = "";
   time_t now2, hr, min;
 
-  now2 = now - online_since;
+  s[0] = 0;
+  now2 = now - time;
   if (now2 > 86400) {
     /* days */
     simple_sprintf(s, "%d day", (int) (now2 / 86400));
@@ -236,7 +237,21 @@ void tell_verbose_uptime(int idx)
   now2 -= (hr * 3600);
   min = (time_t) ((int) now2 / 60);
   sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
-  s1[0] = 0;
+}
+
+void tell_verbose_uptime(int idx)
+{
+  char s[256] = "", s1[121] = "", s2[81] = "", outbuf[501] = "";
+  time_t total, hr, min;
+#if HAVE_GETRUSAGE
+  struct rusage ru;
+#else
+# if HAVE_CLOCK
+  clock_t cl;
+# endif
+#endif /* HAVE_GETRUSAGE */
+
+  tell_time(online_since, s);
   if (backgrd)
     strcpy(s1, "background");
   else {
@@ -245,23 +260,42 @@ void tell_verbose_uptime(int idx)
     else
       strcpy(s1, "log dump mode");
   }
-  dprintf(idx, "Online for %s  (%s)\n", s, s1);
+  simple_sprintf(outbuf,  "Online for %s", s);
+  if (restart_time) {
+    tell_time(restart_time, s);
+    simple_sprintf(outbuf, "%s (%s %s)", outbuf, restart_was_update ? "updated" : "restarted", s);
+  }
+
+#if HAVE_GETRUSAGE
+  getrusage(RUSAGE_SELF, &ru);
+  total = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+  hr = (int) (total / 60);
+  min = (int) (total - (hr * 60));
+  sprintf(s2, "CPU %02d:%02d (load avg %3.1f%%)", (int) hr, (int) min, 
+  100.0 * ((float) total / (float) (now - online_since)));
+#else
+# if HAVE_CLOCK
+  cl = (clock() / CLOCKS_PER_SEC);
+  hr = (int) (cl / 60);
+  min = (int) (cl - (hr * 60));
+  sprintf(s2, "CPU %02d:%02d (load avg %3.1f%%)", (int) hr, (int) min,
+  100.0 * ((float) cl / (float) (now - online_since)));
+# else
+  simple_sprintf(s2, "CPU ???");
+# endif
+#endif /* HAVE_GETRUSAGE */
+  dprintf(idx, "%s  (%s)  %s  cache hit %4.1f%%\n",
+          outbuf, s1, s2,
+          100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
+
 }
 
 /* Dump status info out to dcc
  */
 void tell_verbose_status(int idx)
 {
-  char s[256] = "", s1[121] = "", s2[81] = "", *vers_t = NULL, *uni_t = NULL;
+  char *vers_t = NULL, *uni_t = NULL;
   int i;
-  time_t now2, hr, min;
-#if HAVE_GETRUSAGE
-  struct rusage ru;
-#else
-# if HAVE_CLOCK
-  clock_t cl;
-# endif
-#endif /* HAVE_GETRUSAGE */
   struct utsname un;
 
   if (!uname(&un) < 0) {
@@ -279,53 +313,15 @@ void tell_verbose_status(int idx)
     dprintf(idx, "I am a localhub.\n");
   if (conf.bot->hub && isupdatehub())
     dprintf(idx, "I am an update hub.\n");
-  now2 = now - online_since;
-  s[0] = 0;
-  if (now2 > 86400) {
-    /* days */
-    simple_sprintf(s, "%d day", (int) (now2 / 86400));
-    if ((int) (now2 / 86400) >= 2)
-      strcat(s, "s");
-    strcat(s, ", ");
-    now2 -= (((int) (now2 / 86400)) * 86400);
-  }
-  hr = (time_t) ((int) now2 / 3600);
-  now2 -= (hr * 3600);
-  min = (time_t) ((int) now2 / 60);
-  sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
-  s1[0] = 0;
-  if (backgrd)
-    strcpy(s1, "background");
-  else {
-    if (term_z)
-      strcpy(s1, "terminal mode");
-    else
-      strcpy(s1, "log dump mode");
-  }
-#if HAVE_GETRUSAGE
-  getrusage(RUSAGE_SELF, &ru);
-  hr = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) / 60);
-  min = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) - (hr * 60));
-  sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min);	/* Actally min/sec */
-#else
-# if HAVE_CLOCK
-  cl = (clock() / CLOCKS_PER_SEC);
-  hr = (int) (cl / 60);
-  min = (int) (cl - (hr * 60));
-  sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min);	/* Actually min/sec */
-# else
-  simple_sprintf(s2, "CPU ???");
-# endif
-#endif /* HAVE_GETRUSAGE */
-  dprintf(idx, "Online for %s  (%s)  %s  cache hit %4.1f%%\n",
-	  s, s1, s2,
-	  100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
+
+  tell_verbose_uptime(idx);
 
   if (admin[0])
     dprintf(idx, "Admin: %s\n", admin);
 
   dprintf(idx, "OS: %s %s\n", uni_t, vers_t);
   dprintf(idx, "Running from: %s\n", binname);
+  dprintf(idx, "uid: %s (%d) pid: %d homedir: %s\n", conf.username, conf.uid, mypid, conf.homedir);
   if (tempdir[0])
     dprintf(idx, "Tempdir     : %s\n", tempdir);
 }

+ 1 - 0
src/chanprog.h

@@ -28,5 +28,6 @@ char *samechans(const char *, const char *);
 extern struct chanset_t		*chanset;
 extern char			admin[], origbotname[], botname[];
 extern port_t			my_port;
+extern bool			reset_chans;
 
 #endif /* !_CHANPROG_H */

+ 15 - 4
src/cmds.c

@@ -32,6 +32,7 @@
 #include "botcmd.h"	
 #include "botnet.h"
 #include "tandem.h"
+#include "misc_file.h"
 #include "help.h"
 #include "socket.h"
 #include "traffic.h" /* egg_traffic_t */
@@ -268,8 +269,6 @@ static void cmd_config(int idx, char *par)
       no++;
     if (!egg_strcasecmp(name, "bad-cookie"))
       no++;
-    if (!egg_strcasecmp(name, "manop"))
-      no++;
 
     if (no) {
       dprintf(idx, "Only permanent owners may change '%s'.\n", name);
@@ -1936,8 +1935,6 @@ static void cmd_decrypt(int idx, char *par)
   free(buf);
 }
 
-static void cmd_restart(int, char *) __attribute__((noreturn));
-
 static void cmd_restart(int idx, char *par)
 {
   putlog(LOG_CMDS, "*", "#%s# restart", dcc[idx].nick);
@@ -1951,6 +1948,13 @@ static void cmd_reload(int idx, char *par)
   reload();
 }
 
+static void cmd_rehash(int idx, char *par)
+{
+  putlog(LOG_CMDS, "*", "#%s# rehash", dcc[idx].nick);
+  dprintf(idx, "Rehashing config data from binary...\n");
+  reload_bin_data();
+}
+
 static void cmd_die(int idx, char *par)
 {
   char s1[1024] = "", s2[1024] = "";
@@ -4239,6 +4243,11 @@ static void cmd_quit(int idx, char *text)
 	}
 }
 
+void cmd_test(int idx, char *par)
+{
+  putlog(LOG_CMDS, "*", "#%s# test", dcc[idx].nick);
+}
+
 /* DCC CHAT COMMANDS
  */
 /* Function call should be:
@@ -4304,6 +4313,7 @@ cmd_t C_dcc[] =
   {"quit",		"",	(Function) cmd_quit,		NULL, 0},
   {"relay",		"i",	(Function) cmd_relay,		NULL, 0},
   {"reload",		"m|m",	(Function) cmd_reload,		NULL, HUB},
+  {"rehash",		"a",	(Function) cmd_rehash,		NULL, 0},
   {"restart",		"m",	(Function) cmd_restart,		NULL, 0},
   {"save",		"m|m",	(Function) cmd_save,		NULL, HUB},
   {"simul",		"a",	(Function) cmd_simul,		NULL, 0},
@@ -4345,6 +4355,7 @@ cmd_t C_dcc[] =
   {"exec", 		"a", 	(Function) cmd_exec, 		NULL, 0},
   {"w", 		"n", 	(Function) cmd_w, 		NULL, 0},
   {"channels", 		"", 	(Function) cmd_channels, 	NULL, 0},
+  {"test",		"",	(Function) cmd_test,		NULL, 0},
   {"randstring", 	"", 	(Function) cmd_randstring, 	NULL, AUTH_ALL},
   {"md5",		"",	(Function) cmd_md5,		NULL, AUTH_ALL},
   {"sha1",		"",	(Function) cmd_sha1,		NULL, AUTH_ALL},

+ 32 - 23
src/conf.c

@@ -95,7 +95,7 @@ void spawnbot(const char *nick)
 
 /* spawn and kill bots accordingly
  * bots prefixxed with '/' will be killed auto if running.
- * if (updating) then we were called with -L and -P, we need to restart all running bots except our parent and localhub */
+ * if (updating) then we were called with -U or -u */
 void
 spawnbots()
 {
@@ -110,7 +110,7 @@ spawnbots()
         kill(bot->pid, SIGKILL);
       else
         continue;
-    /* if we're updating automatically, we were called with -L -P, and are only supposed to kill non-localhubs
+    /* if we're updating automatically, we were called with -u and are only supposed to kill non-localhubs
       -if updating and we find our nick, skip
       -if pid exists and not updating, bot is running and we have nothing more to do, skip.
      */
@@ -118,11 +118,10 @@ spawnbots()
       sdprintf(" ... skipping. Updating: %d, pid: %d", updating, bot->pid);
       continue;
     } else {
-      /* if we are updating with -L -P, then we need to restart ALL bots */
+      /* if we are updating with -u then we need to restart ALL bots */
       if (updating == UPDATE_AUTO && bot->pid) {
-        kill(bot->pid, SIGKILL);
-        /* remove the pid incase we start the new bot before the old dies */
-        unlink(bot->pid_file);
+        kill(bot->pid, SIGHUP);
+        continue;
       }
 
       spawnbot(bot->nick);
@@ -378,7 +377,8 @@ pid_t
 checkpid(const char *nick, conf_bot *bot)
 {
   FILE *f = NULL;
-  char buf[DIRMAX] = "", s[11] = "", *tmpnick = NULL, *tmp_ptr = NULL;
+  char buf[DIRMAX] = "", *tmpnick = NULL, *tmp_ptr = NULL;
+  pid_t pid = 0;
 
   tmpnick = tmp_ptr = strdup(nick);
 
@@ -391,26 +391,35 @@ checkpid(const char *nick, conf_bot *bot)
     str_redup(&bot->pid_file, buf);
 
   if ((f = fopen(buf, "r"))) {
-    pid_t xx = 0;
+    char *bufp = NULL, *pids = NULL;
 
-    fgets(s, 10, f);
-    remove_crlf(s);
+    fgets(buf, sizeof(buf), f);
     fclose(f);
-    xx = atoi(s);
-//    if (bot) {
-      int x = 0;
-
-      x = kill(xx, SIGCHLD);
-      if (x == -1 && errno == ESRCH)
-        return 0;
-      else if (x == 0)
-        return xx;
-//    } else {
-//      return xx ? xx : 0;
-//    }
+    remove_crlf(buf);
+
+    if (!buf || !buf[0])
+      return 0;
+  
+    bufp = buf;
+    pids = newsplit(&bufp);
+
+    if (str_isdigit(pids)) {
+      pid = atoi(pids);
+
+      if (kill(pid, SIGCHLD))	//Problem killing, most likely it's just not running.
+        pid = 0;
+    }
+
+    //There is a socksfile given and it's accessable, plus the pid in the file is my own
+    //So it's a good chance we just did a soft restart
+    if (bufp[0] && pid && can_stat(bufp) && (getpid() == pid) &&
+        !egg_strcasecmp(nick, origbotname)) {
+      socksfile = strdup(bufp);
+      return 0;
+    }
   }
 
-  return 0;
+  return pid;
 }
 
 void

+ 3 - 3
src/dcc.h

@@ -8,6 +8,7 @@
 #include "types.h"
 #include "crypt.h"
 #include "eggdrop.h"
+#include "src/mod/server.mod/server.h"
 
 /* Public structure of all the dcc connections */
 struct dcc_table {
@@ -39,7 +40,6 @@ struct dcc_t {
   } u;                          /* Special use depending on type        */
 
   in_addr_t addr;                      /* IP address in host byte order         */
-  addr_t addru;
   time_t simultime;             /* the time when the simul dcc is initiated, expires after a number of seconds */
   time_t timeval;               /* Use for any timing stuff
                                    - this is used for timeout checking  */
@@ -51,8 +51,8 @@ struct dcc_t {
   int simul;                    /* this will hold the idx on the remote bot to return result. */
   bool irc;			/* forward the output back to irc? */
   bool hub;			// is this bot a hub?
-  int auth;
-  int whowas;
+//  int auth;
+  bool whowas;
   int dns_id;
   port_t port;
   char simulbot[NICKLEN];       /* used for hub->leaf cmd simulation, holds bot that results should be sent to */

+ 83 - 0
src/dccutil.c

@@ -430,6 +430,86 @@ void trim_dcclist(int top_index)
   dcc_total = top_index + 1;    
 }
 
+int
+dcc_read(FILE *f)
+{
+  char inbuf[1024] = "", *type = NULL, *buf = NULL;
+  int idx = -1;
+  bool isserv = 0;
+
+  while (fgets(inbuf, sizeof(inbuf), f) != NULL) {
+    remove_crlf(inbuf);
+    buf = inbuf;
+
+    if (!strcmp(buf, "+dcc"))
+      return idx;
+    
+    type = newsplit(&buf);
+    if (!strcmp(type, "type")) {
+      struct dcc_table *dcc_type = NULL;
+      size_t dcc_size = 0;
+
+//      if (!strcmp(buf, "CHAT"))
+//        dcc_type = &DCC_CHAT;
+      if (!strcmp(buf, "SERVER")) {
+        dcc_type = &SERVER_SOCKET;
+        isserv = 1;
+      }
+//      if (!strcmp(buf, "BOT"))
+//        dcc_type = &DCC_BOT;
+    
+      if (dcc_type) {
+        idx = new_dcc(dcc_type, dcc_size);
+        if (isserv)
+          servidx = idx;
+      }
+    }
+
+    if (idx >= 0) {
+      if (!strcmp(type, "addr"))
+        dcc[idx].addr = my_atoul(buf);
+      if (!strcmp(type, "sock")) {
+        dcc[idx].sock = atoi(buf);
+        if (isserv)
+          serv = dcc[idx].sock;
+      }
+      if (!strcmp(type, "port"))
+        dcc[idx].port = atoi(buf);
+      if (!strcmp(type, "nick"))
+        strlcpy(dcc[idx].nick, buf, NICKLEN);
+      if (!strcmp(type, "host")) {
+        strlcpy(dcc[idx].host, buf, UHOSTLEN);
+      }
+    }
+  }
+  return -1;
+}
+
+void 
+dcc_write(FILE *f, int idx)
+{
+  if (dcc[idx].sock > 0) {
+    fprintf(f, "-dcc\n");
+    if (dcc[idx].type)
+      fprintf(f, "type %s\n", dcc[idx].type->name);
+//  if (user)
+//  fprintf(f, "user %s\n", dcc[idx].user->handle);
+    if (dcc[idx].addr)
+      fprintf(f, "addr %u\n", dcc[idx].addr);
+    if (dcc[idx].status)
+      fprintf(f, "status %lu\n", dcc[idx].status);
+    fprintf(f, "sock %d\n", dcc[idx].sock);
+//  fprintf(f, "simul %d\n", dcc[idx].simul);
+    if (dcc[idx].port)
+      fprintf(f, "port %d\n", dcc[idx].port);  
+    if (dcc[idx].nick[0])
+      fprintf(f, "nick %s\n", dcc[idx].nick);
+    if (dcc[idx].host[0])
+      fprintf(f, "host %s\n", dcc[idx].host);
+    fprintf(f, "+dcc\n");
+  }
+}
+
 /* Mark an entry as lost and deconstruct it's contents. It will be securely
  * removed from the dcc list in the main loop.
  */
@@ -589,6 +669,9 @@ flush_lines(int idx, struct chat_info *ci)
 int
 new_dcc(struct dcc_table *type, int xtra_size)
 {
+  if (!type)
+    return -1;
+
   if (dcc_total == max_dcc)
     return -1;
 

+ 3 - 0
src/dccutil.h

@@ -53,6 +53,9 @@ void identd_open();
 void identd_close();
 port_t listen_all(port_t, bool);
 bool valid_idx(int);
+int dcc_read(FILE *);
+void dcc_write(FILE *, int);
+
 extern int		max_dcc;
 extern time_t		connect_timeout;
 

+ 6 - 4
src/debug.c

@@ -280,20 +280,22 @@ static void got_ill(int z)
 #endif /* DEBUG_CONTEXT */
 }
 
-static void got_hup(int) __attribute__((noreturn));
-
 static void
 got_hup(int z)
 {
+  signal(SIGHUP, got_hup);
   putlog(LOG_MISC, "*", "GOT SIGHUP -- RESTARTING");
-  restart(-1);
+  do_restart = 1;
+//  restart(-1);
 }
 
 static void
 got_usr1(int z)
 {
+  signal(SIGUSR1, got_usr1);
   putlog(LOG_DEBUG, "*", "GOT SIGUSR1 -- RECHECKING BINARY");
-  reload_bin_data();
+  do_restart = 2;
+//  reload_bin_data();
 }
 
 void init_signals() 

+ 26 - 25
src/main.c

@@ -76,6 +76,7 @@ bool	have_take = 1;
 int	default_flags = 0;	/* Default user flags and */
 int	default_uflags = 0;	/* Default userdefinied flags for people
 				   who say 'hello' or for .adduser */
+int     do_restart = 0;
 bool	backgrd = 1;		/* Run in the background? */
 uid_t   myuid;
 pid_t   mypid;
@@ -84,6 +85,8 @@ int 	updating = 0; 		/* this is set when the binary is called from itself. */
 char 	tempdir[DIRMAX] = "";
 char 	*binname = NULL;
 time_t	online_since;		/* Unix-time that the bot loaded up */
+time_t  restart_time;
+bool	restart_was_update = 0;
 
 char	owner[121] = "";	/* Permanent owner(s) of the bot */
 char	version[81] = "";	/* Version info (long form) */
@@ -98,7 +101,7 @@ static char do_killbot[21] = "";
 static int kill_sig;
 static char *update_bin = NULL;
 static bool checktrace = 1;		/* Check for trace when starting up? */
-
+char *socksfile = NULL;
 
 static char *getfullbinname(const char *argv_zero)
 {
@@ -272,12 +275,11 @@ static void show_help()
 }
 
 // leaf: BkLP
-#define PARSE_FLAGS STR("0234:aB:cCd:De:EH:k:L:P:hnr:stu:U:v")
+#define PARSE_FLAGS STR("0234:aB:cCd:De:EH:k:hnr:stu:U:v")
 #define FLAGS_CHECKPASS STR("cCdDeEhknrtuUv")
 static void dtx_arg(int argc, char *argv[])
 {
   int i = 0;
-  int localhub_pid = 0;
   char *p = NULL;
   
   opterr = 0;
@@ -388,18 +390,6 @@ static void dtx_arg(int argc, char *argv[])
         }
 	exit(0);
       }
-      case 'L':
-      {
-        localhub_pid = checkpid(optarg, NULL);
-        break;
-      }
-      case 'P':
-        if (atoi(optarg) && localhub_pid && (atoi(optarg) != localhub_pid))
-          exit(3);
-        else
-          sdprintf("Updating...");
-        updating = UPDATE_AUTO;
-        break;
       case '?':
       default:
         break;
@@ -597,14 +587,12 @@ static void startup_checks(int hack) {
     } else {
       /* this needs to be both hub/leaf */
       if (update_bin) {					/* invokved with -u/-U */
-        if (updating == UPDATE_AUTO && conf.bot && conf.bot->pid) {		/* invoked with -u bin, so kill  */
-          
-          kill(conf.bot->pid, SIGKILL);
-          unlink(conf.bot->pid_file);
-          writepid(conf.bot->pid_file, mypid);
-        } else if (!conf.bot)
+        if (!conf.bot)
           updating = UPDATE_EXIT;		//if we don't have a botlist, dont bother with restarting bots...
 
+//        if (updating == UPDATE_AUTO && conf.bot && conf.bot->pid)
+//          kill(conf.bot->pid, SIGHUP);
+
         updatebin(DP_STDOUT, update_bin, 1);	/* will call restart all bots */
         /* never reached */
         exit(0);
@@ -727,7 +715,7 @@ printf("out: %s\n", out);
   /* Check and load conf file */
   startup_checks(0);
 
-  if ((conf.bot->localhub && !updating) || !conf.bot->localhub) {
+  if (!socksfile && ((conf.bot->localhub && !updating) || !conf.bot->localhub)) {
     if ((conf.bot->pid > 0) && conf.bot->pid_file) {
       sdprintf("%s is already running, pid: %d", conf.bot->nick, conf.bot->pid);
       exit(1);
@@ -800,7 +788,8 @@ printf("out: %s\n", out);
 
   if (backgrd) {
 #ifndef CYGWIN_HACKS
-    mypid = do_fork();
+    if (!socksfile) {
+      mypid = do_fork();
 
 /*
     printf("  |- %-10s (%d)\n", conf.bot->nick, pid);
@@ -821,13 +810,16 @@ printf("out: %s\n", out);
             COLOR_END(-1), BOLD(-1), BOLD_END(-1), BOLD(-1), BOLD_END(-1), BOLD(-1), BOLD_END(-1),
             BOLD(-1), BOLD_END(-1), YELLOW(-1), COLOR_END(-1), mypid, YELLOW(-1), COLOR_END(-1));
 #endif
+    } else
+      writepid(conf.bot->pid_file, mypid);
     close_tty();
   } else {
 #endif /* !CYGWIN_HACKS */
 #ifdef CYGWIN_HACKS
     FreeConsole();
 #endif /* CYGWIN_HACKS */
-    printf("%s[%s%s%s]%s -%s- initiated\n", BOLD(-1), BOLD_END(-1), settings.packname, BOLD(-1), BOLD_END(-1), conf.bot->nick);
+    if (!socksfile)
+      printf("%s[%s%s%s]%s -%s- initiated\n", BOLD(-1), BOLD_END(-1), settings.packname, BOLD(-1), BOLD_END(-1), conf.bot->nick);
     writepid(conf.bot->pid_file, mypid);
   }
 
@@ -838,7 +830,7 @@ printf("out: %s\n", out);
     dcc[n].addr = iptolong(getmyip());
     dcc[n].sock = STDOUT;
     dcc[n].timeval = now;
-    dcc[n].u.chat->con_flags = conmask;
+    dcc[n].u.chat->con_flags = conmask | LOG_ALL;
     dcc[n].u.chat->strip_flags = STRIP_ALL;
     dcc[n].status = STAT_ECHO;
     strcpy(dcc[n].nick, "HQ");
@@ -866,6 +858,9 @@ printf("out: %s\n", out);
   timer_create_secs(3600, "core_hourly", (Function) core_hourly);
   timer_create_secs(1800, "core_halfhourly", (Function) core_halfhourly);
 
+  if (socksfile)
+    readsocks(socksfile);
+
   debug0("main: entering loop");
 
   int socket_cleanup = 0, status = 0, xx, i = 0, idx = 0;
@@ -965,6 +960,12 @@ printf("out: %s\n", out);
         flush_modes();
       socket_cleanup = 0;	/* If we've been idle, cleanup & flush */
     }
+    if (do_restart) {
+      if (do_restart == 1)
+        restart(-1);
+      else
+        reload_bin_data();
+    }
   }
 
   return 0;		/* never reached but what the hell */

+ 4 - 4
src/main.h

@@ -14,10 +14,10 @@ enum {
 };
 
 extern int		role, default_flags, default_uflags, do_confedit,
-			updating;
-extern bool		use_stderr, backgrd, used_B, term_z, loading, have_take;
-extern char		tempdir[], *binname, owner[], version[], ver[], quit_msg[];
-extern time_t		online_since, now;
+			updating, do_restart;
+extern bool		use_stderr, backgrd, used_B, term_z, loading, have_take, restart_was_update;
+extern char		tempdir[], *binname, owner[], version[], ver[], quit_msg[], *socksfile;
+extern time_t		online_since, now, restart_time;
 extern uid_t		myuid;
 extern pid_t            mypid;
 extern const time_t	buildts;

+ 161 - 23
src/misc.c

@@ -31,6 +31,7 @@
 #include "src/mod/irc.mod/irc.h"
 #include "userrec.h"
 #include "stat.h"
+#include "net.h"
 
 #include <sys/wait.h>
 #include <stdarg.h>
@@ -555,29 +556,153 @@ void kill_bot(char *s1, char *s2)
     server_die();
   chatout("*** %s\n", s1);
   botnet_send_chat(-1, conf.bot->nick, s1);
-  botnet_send_bye();
+  botnet_send_bye(s2);
   fatal(s2, 0);
 }
 
+void
+readsocks(const char *fname)
+{
+  FILE *f = NULL;
+
+  if (!(f = fopen(fname, "r"))) {
+    fatal("CANT READ SOCKSFILE", 0);
+  }
+
+  char buf[1024] = "", *nick = NULL, *bufp = NULL, *type = NULL;
+  time_t old_buildts = 0;
+
+  while (fgets(buf, sizeof(buf), f) != NULL) {
+    remove_crlf(buf);
+    bufp = buf;
+
+//    dprintf(DP_STDOUT, "read line: %s\n", buf);
+    type = newsplit(&bufp);
+    if (!strcmp(type, "-dcc"))
+      dprintf(DP_STDOUT, "Added dcc: %d\n", dcc_read(f));
+    else if (!strcmp(type, "-sock"))
+      dprintf(DP_STDOUT, "Added fd: %d\n", sock_read(f));
+    else if (!strcmp(type, "+online_since"))
+      online_since = strtol(bufp, NULL, 10);
+    else if (!strcmp(type, "+buildts"))
+      old_buildts = strtol(bufp, NULL, 10);
+    else if (!strcmp(type, "+botname"))
+      nick = strdup(bufp);
+  }
+
+  restart_time = now;
+  if (old_buildts && buildts > old_buildts)
+    restart_was_update = 1;
+
+  tell_dcc(DP_STDOUT);
+  tell_netdebug(DP_STDOUT);
+
+  unlink(fname);
+  fclose(f);
+  if (servidx >= 0) {
+    rehash_server(dcc[servidx].host, nick);
+    dprintf(DP_DUMP, "VERSION\n");
+    reset_chans = 1;
+  }
+  free(nick);
+  if (socksfile)
+    free(socksfile);
+}
+
+
 /* Update system code
  */
 
-void 
+void
 restart(int idx)
 {
-  char buf[1024] = "";
   const char *reason = updating ? "Updating..." : "Restarting...";
+  Tempfile *socks = new Tempfile("socks");
+  int fd = 0;
+
+  sdprintf("%s", reason); 
+
+
+  if (tands > 0) {
+    botnet_send_chat(-1, conf.bot->nick, (char *) reason);
+    botnet_send_bye(reason);
+  }
+
+  /* kill all connections except STDOUT/server */
+  for (fd = 0; fd < dcc_total; fd++) {
+    if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) {
+      if (dcc[fd].sock >= 0)
+        killsock(dcc[fd].sock);
+      lostdcc(fd);
+    }
+  }
+
+  /* write out all leftover dcc[] entries */
+  for (fd = 0; fd < dcc_total; fd++)
+    if (dcc[fd].type && dcc[fd].sock != STDOUT)
+      dcc_write(socks->f, fd);
+
+  /* write out all leftover socklist[] entries */
+  for (fd = 0; fd < MAXSOCKS; fd++)
+    if (socklist[fd].sock != STDOUT)
+      sock_write(socks->f, fd);
+
+  if (server_online) {
+    if (botname[0])
+      fprintf(socks->f, "+botname %s\n", botname);
+    fprintf(socks->f, "+online_since %li\n", online_since);
+    fprintf(socks->f, "+buildts %li\n", buildts);
+  }
+  fflush(socks->f);
+  socks->my_close();
+
+  if (conf.bot->hub)
+    write_userfile(idx);
+
+  if (server_online) {
+    do_chanset(NULL, NULL, "+inactive", DO_LOCAL);
+    dprintf(DP_DUMP, "JOIN 0\n");
+  }
+
+  fixmod(binname);
+
+  /* replace image now */
+  char *argv[5] = { NULL, NULL, NULL, NULL, NULL };
+  char shit[5] = "";
+
+  simple_sprintf(shit, "-%s%s%s", !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : "");
+
+  argv[0] = strdup(binname);
+  argv[1] = strdup(shit);
+  argv[2] = strdup("-B");
+  argv[3] = strdup(conf.bot->nick);
+  argv[4] = NULL;
+
+  unlink(conf.bot->pid_file);
+  FILE *fp = NULL;
+  if (!(fp = fopen(conf.bot->pid_file, "w")))
+    return;
+  fprintf(fp, "%d %s\n", getpid(), socks->file);
+  fclose(fp);
+
+  execvp(argv[0], &argv[0]);
+
+  /* hopefully this is never reached */
+  putlog(LOG_MISC, "*", "Could not restart: %s", strerror(errno));
+  return;
+}
+
+#ifdef NO
+void 
+hard_restart(int idx)
+{
+  char buf[1024] = "";
 
-  sdprintf("restarting [%s]", reason); 
   write_userfile(idx);
   if (!conf.bot->hub) {
     nuke_server((char *) reason);		/* let's drop the server connection ASAP */
     cycle_time = 0;
   }
-  if (tands > 0) {
-    botnet_send_chat(-1, conf.bot->nick, (char *) reason);
-    botnet_send_bye();
-  }
   fatal(idx <= 0x7FF0 ? reason : NULL, 1);
   usleep(2000 * 500);
   simple_sprintf(buf, "%s -B %s\n", binname, conf.bot->nick);
@@ -585,6 +710,7 @@ restart(int idx)
   system(buf); /* start new bot. */
   exit(0);
 }
+#endif
 
 int updatebin(int idx, char *par, int secs)
 {
@@ -594,7 +720,7 @@ int updatebin(int idx, char *par, int secs)
   }
 
   char *path = (char *) my_calloc(1, strlen(binname) + strlen(par) + 2);
-  char *newbin = NULL, old[DIRMAX] = "", testbuf[DIRMAX] = "";
+  char *newbin = NULL, buf[DIRMAX] = "";
   int i;
 
   strcpy(path, binname);
@@ -638,8 +764,8 @@ int updatebin(int idx, char *par, int secs)
 
   /* make a backup just in case. */
 
-  simple_snprintf(old, sizeof old, "%s.bin.old", tempdir);
-  copyfile(binname, old);
+  simple_snprintf(buf, sizeof(buf), "%s.bin.old", tempdir);
+  copyfile(binname, buf);
 
   write_settings(path, -1, 0);	/* re-write the binary with our packdata */
 
@@ -652,10 +778,10 @@ int updatebin(int idx, char *par, int secs)
   }
 
   /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
-  simple_snprintf(testbuf, sizeof testbuf, STR("%s -2"), path);
+  simple_snprintf(buf, sizeof(buf), STR("%s -2"), path);
 #ifndef CYGWIN_HACKS
-  putlog(LOG_DEBUG, "*", "Running for update binary test: %s", testbuf);
-  i = system(testbuf);
+  putlog(LOG_DEBUG, "*", "Running for update binary test: %s", buf);
+  i = system(buf);
   if (i == -1 || WEXITSTATUS(i) != 2) {
     dprintf(idx, "Couldn't restart new binary (error %d)\n", i);
     putlog(LOG_MISC, "*", "Couldn't restart new binary (error %d)", i);
@@ -665,10 +791,10 @@ int updatebin(int idx, char *par, int secs)
 #endif /* !CYGWIN_HACKS */
 
   /* now to send our config to the new binary */
-  simple_snprintf(testbuf, sizeof testbuf, STR("%s -4 %s"), path, conffile->file);
+  simple_snprintf(buf, sizeof(buf), STR("%s -4 %s"), path, conffile->file);
 #ifndef CYGWIN_HACKS
-  putlog(LOG_DEBUG, "*", "Running for update conf: %s", testbuf);
-  i = system(testbuf);
+  putlog(LOG_DEBUG, "*", "Running for update conf: %s", buf);
+  i = system(buf);
   delete conffile;
   if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
     dprintf(idx, "Couldn't pass config to new binary (error %d)\n", i);
@@ -698,15 +824,27 @@ int updatebin(int idx, char *par, int secs)
     printf("* Moved binary to: %s\n", binname);
     fatal("Binary updated.", 0);
   }
+  if (updating == UPDATE_AUTO) {
+    /* Make all other bots do a soft restart */
+    conf_checkpids();
+    conf_killbot(NULL, NULL, SIGHUP);
+
+    if (conf.bot->pid)
+      kill(conf.bot->pid, SIGHUP);
+    exit(0);
+  }
 
   if (!conf.bot->hub && secs > 0) {
-    char buf[DIRMAX] = "";
-
-    /* this forces all running bots to be restarted (except localhub/me) */
-    simple_snprintf(buf, sizeof buf, STR("%s -L %s -P %d"), binname, conf.bot->nick, getpid());
-    putlog(LOG_DEBUG, "*", "Running for update: %s", buf);
-    system(buf);	/* restarts other bots running, removes pid files */
+    /* Make all other bots do a soft restart */
+    conf_checkpids();
+    conf_killbot(NULL, NULL, SIGHUP);
     
+    /* invoked with -u */
+    if (updating == UPDATE_AUTO) {
+      if (conf.bot->pid)
+        kill(conf.bot->pid, SIGHUP);
+      exit(0);
+    }
     /* this odd statement makes it so specifying 1 sec will restart other bots running
      * and then just restart with no delay */
     updating = UPDATE_AUTO;

+ 2 - 1
src/misc.h

@@ -13,7 +13,7 @@
 
 
 char *wbanner(void);
-void restart(int) __attribute__((noreturn));
+void restart(int);
 int coloridx(int);
 const char *color(int, int, int);
 void shuffle(char *, char *);
@@ -22,6 +22,7 @@ void showhelp(int, struct flag_record *, char *);
 char *replace(const char *, const char *, const char *);
 int goodpass(char *, int, char *);
 int bot_aggressive_to(struct userrec *);
+void readsocks(const char *);
 int updatebin(int, char *, int);
 size_t my_strcpy(char *, char *);
 void maskhost(const char *, char *);

+ 1 - 2
src/mod/irc.mod/chan.c

@@ -2371,8 +2371,7 @@ static int gotjoin(char *from, char *chname)
 	  /* It was me joining! Need to update the channel record with the
 	   * unique name for the channel (as the server see's it). <cybah>
 	   */
-	  strncpy(chan->name, chname, 81);
-	  chan->name[80] = 0;
+	  strlcpy(chan->name, chname, 81);
 	  chan->status &= ~CHAN_JUPED;
 
           /* ... and log us joining. Using chan->dname for the channel is

+ 1 - 1
src/mod/irc.mod/cmdsirc.c

@@ -1689,7 +1689,7 @@ static void cmd_reset(int idx, char *par)
     putlog(LOG_CMDS, "*", "#%s# reset all", dcc[idx].nick);
     dprintf(idx, "Resetting channel info for all channels...\n");
     for (chan = chanset; chan; chan = chan->next) {
-      if (channel_active(chan))
+      if (channel_active(chan) || (!channel_active(chan) && shouldjoin(chan)))
 	reset_chan_info(chan);
     }
   }

+ 9 - 7
src/mod/irc.mod/irc.c

@@ -931,8 +931,7 @@ my_setkey(struct chanset_t *chan, char *k)
     chan->channel.key = (char *) my_calloc(1, 1);
     return;
   }
-  chan->channel.key = (char *) my_calloc(1, strlen(k) + 1);
-  strcpy(chan->channel.key, k);
+  chan->channel.key = strdup(k);
 }
 
 /* Adds a ban, exempt or invite mask to the list
@@ -949,10 +948,8 @@ new_mask(masklist *m, char *s, char *who)
   m->next->next = NULL;
   m->next->mask = (char *) my_calloc(1, 1);
   free(m->mask);
-  m->mask = (char *) my_calloc(1, strlen(s) + 1);
-  strcpy(m->mask, s);
-  m->who = (char *) my_calloc(1, strlen(who) + 1);
-  strcpy(m->who, who);
+  m->mask = strdup(s);
+  m->who = strdup(who);
   m->timer = now;
 }
 
@@ -1043,9 +1040,14 @@ any_ops(struct chanset_t *chan)
 
 /* Reset the channel information.
  */
-static void
+void
 reset_chan_info(struct chanset_t *chan)
 {
+  if (!chan) return;
+
+  if (!chan->name[0])
+    strlcpy(chan->name, chan->dname, 81);
+
   /* Don't reset the channel if we're already resetting it */
   if (!shouldjoin(chan)) {
     dprintf(DP_MODE, "PART %s\n", chan->name);

+ 1 - 1
src/mod/irc.mod/irc.h

@@ -77,7 +77,6 @@ static void detect_autokick(char *, char *, struct chanset_t *, char *);
 static bool do_op(char *, struct chanset_t *, time_t, bool);
 static void request_op(struct chanset_t *);
 static void request_in(struct chanset_t *);
-static void reset_chan_info(struct chanset_t *);
 static void my_setkey(struct chanset_t *, char *);
 static void maybe_revenge(struct chanset_t *, char *, char *, int);
 static bool detect_chan_flood(char *, char *, char *, struct chanset_t *, int,
@@ -111,6 +110,7 @@ void recheck_channel(struct chanset_t *, int);
 void recheck_channel_modes(struct chanset_t *);
 void irc_report(int, int);
 void flush_modes();
+void reset_chan_info(struct chanset_t *);
 
 extern int		max_bans, max_exempts, max_invites, max_modes;
 extern bool		use_354;

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

@@ -7,6 +7,7 @@
 #define _EGG_MOD_SERVER_SERVER_H
 
 #include "src/tclhash.h"
+#include "src/dcc.h"
 
 #define DO_LOST 1
 #define NO_LOST 0
@@ -52,7 +53,7 @@ extern time_t		server_online, cycle_time, flud_time, flud_ctcp_time;
 extern char		cursrvname[], botrealname[], botuserhost[], ctcp_reply[],
 			newserver[], newserverpass[], curnetwork[], botuserip[];
 extern struct server_list *serverlist;
-
+extern struct dcc_table SERVER_SOCKET;
 int check_bind_ctcpr(char *, char *, struct userrec *, char *, char *, char *, bind_table_t *);
 
 #define check_bind_ctcp(a, b, c, d, e, f) check_bind_ctcpr(a, b, c, d, e, f, BT_ctcp)
@@ -67,4 +68,6 @@ void add_server(char *);
 void clearq(struct server_list *);
 void nuke_server(const char *);
 bool match_my_nick(char *);
+void rehash_server(const char *, const char *);
+void join_chans();
 

+ 32 - 16
src/mod/server.mod/servmsg.c

@@ -143,26 +143,24 @@ bool match_my_nick(char *nick)
   return (!rfc_casecmp(nick, botname));
 }
 
-/* 001: welcome to IRC (use it to fix the server name)
- */
-static int got001(char *from, char *msg)
+void rehash_server(const char *servname, const char *nick)
 {
-  struct server_list *x = NULL;
-
   server_online = now;
-  fixcolon(msg);
-  /* Ok...param #1 of 001 = what server thinks my nick is */
-  strlcpy(botname, msg, NICKLEN);
   altnick_char = 0;
-  strlcpy(cursrvname, from, sizeof(cursrvname));
+  strlcpy(cursrvname, servname, sizeof(cursrvname));
 
-  dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
-  dprintf(DP_SERVER, "USERHOST %s\n", botname); /* get user@ip */
-  dprintf(DP_SERVER, "MODE %s +iws\n", botname);
-  x = serverlist;
-  if (x == NULL)
-    return 0;			/* Uh, no server list */
+  if (nick && nick[0]) {
+    strlcpy(botname, nick, NICKLEN);
 
+    dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
+    dprintf(DP_SERVER, "USERHOST %s\n", botname); /* get user@ip */
+    dprintf(DP_SERVER, "MODE %s +iws\n", botname);
+  }
+}
+
+void 
+join_chans()
+{
   for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
     chan->status &= ~(CHAN_ACTIVE | CHAN_PEND | CHAN_JOINING);
     if (shouldjoin(chan)) {
@@ -171,7 +169,25 @@ static int got001(char *from, char *msg)
       chan->status |= CHAN_JOINING;
     }
   }
+}
+
+/* 001: welcome to IRC (use it to fix the server name)
+ */
+static int got001(char *from, char *msg)
+{
+
+  fixcolon(msg);
+  rehash_server(from, msg);
+  /* Ok...param #1 of 001 = what server thinks my nick is */
+
+  join_chans();
+
   if (egg_strcasecmp(from, dcc[servidx].host)) {
+    struct server_list *x = serverlist;
+
+    if (x == NULL)
+      return 0;			/* Uh, no server list */
+
     putlog(LOG_MISC, "*", "(%s claims to be %s; updating server list)", dcc[servidx].host, from);
     for (int i = curserv; i > 0 && x != NULL; i--)
       x = x->next;
@@ -962,7 +978,7 @@ static void timeout_server(int idx)
 
 static void server_activity(int, char *, int);
 
-static struct dcc_table SERVER_SOCKET =
+struct dcc_table SERVER_SOCKET =
 {
   "SERVER",
   0,

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

@@ -1276,6 +1276,14 @@ finish_share(int idx)
   trigger_cfg_changed();	/* Set our local cfg settings from our userentry */
   reaffirm_owners();            /* Make sure my owners are +a   */
   updatebot(-1, dcc[j].nick, '+', 0, 0, NULL);
+
+  if (reset_chans) {
+    reset_chans = 0;
+//    putlog(LOG_DEBUG, "*", "Resetting channel info for all channels...");
+//    for (chan = chanset; chan; chan = chan->next)
+//      reset_chan_info(chan);
+    join_chans();
+  }
 }
 
 /* Begin the user transfer process.

+ 50 - 0
src/net.c

@@ -225,6 +225,7 @@ void init_net()
     socklist[i].ssl = NULL;
 #endif /* HAVE_SSL */
     socklist[i].flags = SOCK_UNUSED;
+    socklist[i].sock = -1;
   }
 #ifdef HAVE_SSL
   SSL_load_error_strings();
@@ -360,6 +361,55 @@ int sockoptions(int sock, int operation, int sock_options)
   return -1;
 }
 
+int
+sock_read(FILE *f)
+{
+  char inbuf[1024] = "", *type = NULL, *buf = NULL;
+  int fd = -1;
+
+  while (fgets(inbuf, sizeof(inbuf), f) != NULL) {
+    remove_crlf(inbuf);
+
+    buf = inbuf;
+    if (!strcmp(buf, "+sock"))
+      return fd;
+
+    type = newsplit(&buf);
+    if (!strcmp(type, "sock")) {
+      int sock = atoi(newsplit(&buf)), options = atoi(newsplit(&buf));
+
+      fd = allocsock(sock, options);
+    }
+
+    if (fd >= 0) {
+      if (!strcmp(type, "af"))
+        socklist[fd].af = atoi(buf);
+      if (!strcmp(type, "host"))
+        socklist[fd].host = strdup(buf);
+      if (!strcmp(type, "port"))
+        socklist[fd].port = atoi(buf);
+    }
+  }
+  return -1;
+}
+
+void 
+sock_write(FILE *f, int fd)
+{
+  if (socklist[fd].sock > 0) {
+    fprintf(f, "-sock\n");
+    fprintf(f, "sock %d %d\n", socklist[fd].sock, socklist[fd].flags);
+#ifdef USE_IPV6
+    fprintf(f, "af %u\n", socklist[fd].af);
+#endif
+    if (socklist[fd].host)
+      fprintf(f, "host %s\n", socklist[fd].host);
+    if (socklist[fd].port)
+      fprintf(f, "port %d\n", socklist[fd].port);
+    fprintf(f, "+sock\n");
+  }    
+}
+
 /* Return a free entry in the socket entry
  */
 int allocsock(int sock, int options)

+ 2 - 0
src/net.h

@@ -166,6 +166,8 @@ char *iptostr(in_addr_t);
 bool sock_has_data(int, int);
 int sockoptions(int sock, int operation, int sock_options);
 void init_net(void);
+int sock_read(FILE *);
+void sock_write(FILE *, int);
 
 extern union sockaddr_union 		cached_myip4_so;
 #ifdef USE_IPV6

+ 1 - 1
src/tandem.h

@@ -67,7 +67,7 @@ void botnet_send_join_idx(int);
 void botnet_send_join_party(int, int, int);
 void botnet_send_part_idx(int, char *);
 void botnet_send_part_party(int, int, char *, int);
-void botnet_send_bye();
+void botnet_send_bye(const char *);
 void botnet_send_nkch_part(int, int, char *);
 void botnet_send_nkch(int, char *);
 int bots_in_subtree(tand_t *);