Beispiel #1
0
static bool check_tempdir(bool do_mod)
{
  mkdir_p(tempdir);

  if (!can_stat(tempdir))
    return 0;

  if (do_mod && fixmod(tempdir))
    return 0;

  /* test tempdir: it's vital */
  Tempfile *testdir = new Tempfile("test");

  /* There was an error creating a file in this directory, return to move on in list of dirs */
  if (!testdir || testdir->error) {
    if (testdir)
      delete testdir;
    return 0;
  }

  fprintf(testdir->f, "\n");
  int result = fflush(testdir->f);
  delete testdir;
  if (result) {
    sdprintf("%s: %s", tempdir, strerror(errno));
    return 0;
  }
  return 1;
}
Beispiel #2
0
char *move_bin(const char *ipath, const char *file, bool run)
{
  char *path = strdup(ipath);

  expand_tilde(&path);

  /* move the binary to the correct place */
  static char newbin[DIRMAX] = "";
  char real[DIRMAX] = "";

  simple_snprintf(newbin, sizeof newbin, "%s%s%s", path, path[strlen(path) - 1] == '/' ? "" : "/", file);

  ContextNote(STR("realpath()"));
  realpath(binname, real);            /* get the realpath of binname */
  ContextNote(STR("realpath(): Success"));
  /* running from wrong dir, or wrong bin name.. lets try to fix that :) */
  sdprintf(STR("binname: %s"), binname);
  sdprintf(STR("newbin: %s"), newbin);
  sdprintf(STR("real: %s"), real);
  if (strcmp(binname, newbin) && strcmp(newbin, real)) {              /* if wrong path and new path != current */
    bool ok = 1;

    sdprintf(STR("wrong dir, is: %s :: %s"), binname, newbin);

    unlink(newbin);
    if (copyfile(binname, newbin))
      ok = 0;

    if (ok && !can_stat(newbin)) {
       unlink(newbin);
       ok = 0;
    }

    if (ok && fixmod(newbin)) {
        unlink(newbin);
        ok = 0;
    }

    if (ok) {
      sdprintf(STR("Binary successfully moved to: %s"), newbin);
      unlink(binname);
      if (run) {
        simple_snprintf(newbin, sizeof newbin, "%s%s%s", 
                        path, path[strlen(path) - 1] == '/' ? "" : "/", shell_escape(file));
        system(newbin);
        sdprintf(STR("exiting to let new binary run..."));
        exit(0);
      }
    } else {
      if (run)
        werr(ERR_WRONGBINDIR);
      sdprintf(STR("Binary move failed to: %s"), newbin);
      return binname;
    }
  }
  return newbin;
}
Beispiel #3
0
int updatebin(int idx, char *par, int secs)
{
  if (!par || !par[0]) {
    logidx(idx, "Not enough parameters.");
    return 1;
  }

  size_t path_siz = strlen(binname) + strlen(par) + 2;
  char *path = (char *) my_calloc(1, path_siz);
  char *newbin = NULL, buf[DIRMAX] = "";
  const char* argv[5];
  int i;

  strlcpy(path, binname, path_siz);
  newbin = strrchr(path, '/');
  if (!newbin) {
    free(path);
    logidx(idx, STR("Don't know current binary name"));
    return 1;
  }
  newbin++;
  if (strchr(par, '/')) {
    *newbin = 0;
    logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path);
    free(path);
    return 1;
  }
  strcpy(newbin, par);
  if (!strcmp(path, binname)) {
    free(path);
    logidx(idx, STR("Can't update with the current binary"));
    return 1;
  }
  if (!can_stat(path)) {
    logidx(idx, STR("%s can't be accessed"), path);
    free(path);
    return 1;
  }
  if (fixmod(path)) {
    logidx(idx, STR("Can't set mode 0600 on %s"), path);
    free(path);
    return 1;
  }

  /* Check if the new binary is compatible */
  int initialized_code = check_bin_initialized(path);
  if (initialized_code == 2) {
    logidx(idx, STR("New binary is corrupted or the wrong architecture/operating system."));
    free(path);
    return 1;
  } else if (initialized_code == 1 && !check_bin_compat(path)) {
    logidx(idx, STR("New binary must be initialized as pack structure has been changed in new version."));
    free(path);
    return 1;
  }


  /* make a backup just in case. */

  simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir);
  copyfile(binname, buf);

  write_settings(path, -1, 0, initialized_code ? 0 : 1);	/* re-write the binary with our packdata */

  Tempfile *conffile = new Tempfile("conf");

  if (writeconf(NULL, conffile->fd, CONF_ENC)) {
    logidx(idx, STR("Failed to write temporary config file for update."));
    delete conffile;
    return 1;
  }

  /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s -2"), path);
  argv[0] = path;
  argv[1] = "-2";
  argv[2] = 0;
  i = simple_exec(argv);
  if (i == -1 || WEXITSTATUS(i) != 2) {
    logidx(idx, STR("Couldn't restart new binary (error %d)"), i);
    delete conffile;
    return i;
  }

  /* now to send our config to the new binary */
  putlog(LOG_DEBUG, "*", STR("Running for update conf: %s -4 %s"), path, conffile->file);
  argv[0] = path;
  argv[1] = "-4";
  argv[2] = conffile->file;
  argv[3] = 0;
  i = simple_exec(argv);
  delete conffile;
  if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
    logidx(idx, STR("Couldn't pass config to new binary (error %d)"), i);
    return i;
  }

  if (movefile(path, binname)) {
    logidx(idx, STR("Can't rename %s to %s"), path, binname);
    free(path);
    return 1;
  }

  if (updating == UPDATE_EXIT) {	  /* dont restart/kill/spawn bots, just die ! */
    printf(STR("* Moved binary to: %s\n"), binname);
    fatal(STR("Binary updated."), 0);
  }
  if (updating == UPDATE_AUTO) {
    /* Make all other bots do a soft restart */
    conf_checkpids(conf.bots);
    conf_killbot(conf.bots, NULL, NULL, SIGHUP);

    if (conf.bot->pid)
      kill(conf.bot->pid, SIGHUP);
    exit(0);
  }

  if (!conf.bot->hub && secs > 0) {
    /* Make all other bots do a soft restart */
    conf_checkpids(conf.bots);
    conf_killbot(conf.bots, 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;
    if (secs > 1) {
      egg_timeval_t howlong;
      howlong.sec = secs;
      howlong.usec = 0;
      timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) (long) idx, 0);
    } else
      restart(idx);

    return 0;
  } else
    restart(idx);	/* no timer */

 /* this should never be reached */
  return 2;
}
Beispiel #4
0
void
restart(int idx)
{
  const char *reason = updating ? STR("Updating...") : STR("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);
    }
  }

  const char salt1[] = SALT1;
  EncryptedStream stream(salt1);

  /* write out all leftover dcc[] entries */
  for (fd = 0; fd < dcc_total; fd++)
    if (dcc[fd].type && dcc[fd].sock != STDOUT)
      dcc_write(stream, fd);

  /* write out all leftover socklist[] entries */
  for (fd = 0; fd < MAXSOCKS; fd++)
    if (socklist[fd].sock != STDOUT)
      sock_write(stream, fd);

  if (server_online) {
    if (botname[0])
      stream << bd::String::printf(STR("+botname %s\n"), botname);
    if (rolls)
      stream << bd::String::printf(STR("+rolls %d\n"), rolls);
    if (altnick_char)
      stream << bd::String::printf(STR("+altnick_char %c\n"), altnick_char);
    if (burst)
      stream << bd::String::printf(STR("+burst %d\n"), burst);
    if (flood_count)
      stream << bd::String::printf(STR("+flood_count %d\n"), flood_count);
    if (my_cookie_counter)
      stream << bd::String::printf(STR("+my_cookie_counter %lu\n"), my_cookie_counter);
    stream << bd::String::printf(STR("+server_online %li\n"), (long)server_online);
  }
  stream << bd::String::printf(STR("+online_since %li\n"), (long)online_since);
  if (floodless)
    stream << bd::String::printf(STR("+server_floodless %d\n"), floodless);
  if (in_deaf)
    stream << bd::String::printf(STR("+in_deaf\n"));
  if (in_callerid)
    stream << bd::String::printf(STR("+in_callerid\n"));
  for (struct chanset_t *chan = chanset; chan; chan = chan->next)
    if (shouldjoin(chan) && (channel_active(chan) || channel_pending(chan)))
      stream << bd::String::printf(STR("+chan %s\n"), chan->dname);
  stream << bd::String::printf(STR("+buildts %li\n"), (long)buildts);
  stream << bd::String::printf(STR("+ip4 %s\n"), myipstr(AF_INET));
  stream << bd::String::printf(STR("+ip6 %s\n"), myipstr(AF_INET6));
  replay_cache(-1, &stream);

  stream.writeFile(socks->fd);

  socks->my_close();

  write_userfile(idx);
/*
  if (server_online) {
    do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL);
    dprintf(DP_DUMP, STR("JOIN 0\n"));
  }
*/
  fixmod(binname);

  /* replace image now */
  char *argv[4] = { NULL, NULL, NULL, NULL };

  argv[0] = strdup(binname);

  if (!backgrd || term_z || sdebug) {
    char shit[7] = "";

    simple_snprintf(shit, sizeof(shit), STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : "");
    argv[1] = strdup(shit);
    argv[2] = strdup(conf.bot->nick);
  } else {
    argv[1] = strdup(conf.bot->nick);
  }

  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, "*", STR("Could not restart: %s"), strerror(errno));
  return;
}