Пример #1
0
/* Check timers, execute the ones that have expired.
 */
void do_check_timers(tcl_timer_t ** stack)
{
  tcl_timer_t *mark = *stack, *old = NULL;
  char x[16];

  /* New timers could be added by a Tcl script inside a current timer
   * so i'll just clear out the timer list completely, and add any
   * unexpired timers back on.
   */
  *stack = NULL;
  while (mark) {
    if (mark->mins > 0)
      mark->mins--;
    old = mark;
    mark = mark->next;
    if (!old->mins) {
      egg_snprintf(x, sizeof x, "timer%lu", old->id);
      do_tcl(x, old->cmd);
      if (old->count == 1) {
        nfree(old->cmd);
        nfree(old);
        continue;
      } else {
        old->mins = old->interval;
        if (old->count > 1)
          old->count--;
      }
    }
    old->next = *stack;
    *stack = old;
  }
}
Пример #2
0
/* 001: welcome to IRC (use it to fix the server name) */
static int got001(char *from, char *msg)
{
  int i;
  char *key;
  struct chanset_t *chan;
  struct server_list *x = serverlist;

  /* FIXME - x should never be NULL anywhere in this function, but
   * apparently it sometimes is. */
  if (x) {
    for (i = curserv; i > 0 && x; i--)
      x = x->next;
    if (!x) {
      putlog(LOG_MISC, "*", "Invalid server list!");
    } else {
      if (x->realname)
        nfree(x->realname);
      x->realname = nmalloc(strlen(from) + 1);
      strcpy(x->realname, from);
    }
    if (realservername)
      nfree(realservername);
    realservername = nmalloc(strlen(from) + 1);
    strcpy(realservername, from);
  } else
    putlog(LOG_MISC, "*", "No server list!");

  server_online = now;
  fixcolon(msg);
  strncpyz(botname, msg, NICKLEN);
  altnick_char = 0;
  dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
  if (initserver[0])
    do_tcl("init-server", initserver); /* Call Tcl init-server */
  check_tcl_event("init-server");

  if (!x)
    return 0;

  if (module_find("irc", 0, 0)) {  /* Only join if the IRC module is loaded. */
    for (chan = chanset; chan; chan = chan->next) {
      chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
      if (!channel_inactive(chan)) {

        key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
        if (key[0])
          dprintf(DP_SERVER, "JOIN %s %s\n",
                  chan->name[0] ? chan->name : chan->dname, key);
        else
          dprintf(DP_SERVER, "JOIN %s\n",
                  chan->name[0] ? chan->name : chan->dname);
      }
    }
  }

  return 0;
}
Пример #3
0
/* If i'm the only person on the channel, and i'm not op'd,
 * might as well leave and rejoin. If i'm NOT the only person
 * on the channel, but i'm still not op'd, demand ops.
 */
static void check_lonely_channel(struct chanset_t *chan)
{
    memberlist *m;
    char s[UHOSTLEN];
    int i = 0;

    if (channel_pending(chan) || !channel_active(chan) || me_op(chan) ||
            channel_inactive(chan) || (chan->channel.mode & CHANANON))
        return;
    /* Count non-split channel members */
    for (m = chan->channel.member; m && m->nick[0]; m = m->next)
        if (!chan_issplit(m))
            i++;
    if (i == 1 && channel_cycle(chan) && !channel_stop_cycle(chan)) {
        if (chan->name[0] != '+') { /* Its pointless to cycle + chans for ops */
            putlog(LOG_MISC, "*", "Trying to cycle %s to regain ops.", chan->dname);
            dprintf(DP_MODE, "PART %s\n", chan->name);

            /* If it's a !chan, we need to recreate the channel with !!chan <cybah> */
            if (chan->key_prot[0])
                dprintf(DP_MODE, "JOIN %s%s %s\n", (chan->dname[0] == '!') ? "!" : "",
                        chan->dname, chan->key_prot);
            else
                dprintf(DP_MODE, "JOIN %s%s\n", (chan->dname[0] == '!') ? "!" : "",
                        chan->dname);
            chan->status &= ~CHAN_WHINED;
        }
    } else if (any_ops(chan)) {
        chan->status &= ~CHAN_WHINED;
        check_tcl_need(chan->dname, "op");
        if (chan->need_op[0])
            do_tcl("need-op", chan->need_op);
    } else {
        /* Other people here, but none are ops. If there are other bots make
         * them LEAVE!
         */
        int ok = 1;
        struct userrec *u;

        if (!channel_whined(chan)) {
            /* + is opless. Complaining about no ops when without special
             * help(services), we cant get them - Raist
             */
            if (chan->name[0] != '+' && channel_logstatus(chan))
                putlog(LOG_MISC, "*", "%s is active but has no ops :(", chan->dname);
            chan->status |= CHAN_WHINED;
        }
        for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
            sprintf(s, "%s!%s", m->nick, m->userhost);
            u = get_user_by_host(s);
            if (!match_my_nick(m->nick) && (!u || !(u->flags & USER_BOT))) {
                ok = 0;
                break;
            }
        }
        if (ok && channel_cycle(chan)) {
            /* ALL bots!  make them LEAVE!!! */
            for (m = chan->channel.member; m && m->nick[0]; m = m->next)
                if (!match_my_nick(m->nick))
                    dprintf(DP_SERVER, "PRIVMSG %s :go %s\n", m->nick, chan->dname);
        } else {
            /* Some humans on channel, but still op-less */
            check_tcl_need(chan->dname, "op");
            if (chan->need_op[0])
                do_tcl("need-op", chan->need_op);
        }
    }
}
Пример #4
0
/* Hook up to a server
 */
static void connect_server(void)
{
  char pass[121], botserver[UHOSTLEN];
  int servidx;
  unsigned int botserverport = 0;

  lastpingcheck = 0;
  trying_server = now;
  empty_msgq();
  if (newserverport) {          /* Jump to specified server */
    curserv = -1;             /* Reset server list */
    strcpy(botserver, newserver);
    botserverport = newserverport;
    strcpy(pass, newserverpass);
    newserver[0] = 0;
    newserverport = 0;
    newserverpass[0] = 0;
  } else {
    if (curserv == -1)
      curserv = 999;
    pass[0] = 0;
  }
  if (!cycle_time) {
    struct chanset_t *chan;
    struct server_list *x = serverlist;

    if (!x && !botserverport) {
      putlog(LOG_SERV, "*", "No servers in server list");
      cycle_time = 300;
      return;
    }

    servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
    if (servidx < 0) {
      putlog(LOG_SERV, "*",
             "NO MORE DCC CONNECTIONS -- Can't create server connection.");
      return;
    }

    if (connectserver[0])       /* drummer */
      do_tcl("connect-server", connectserver);
    check_tcl_event("connect-server");
    next_server(&curserv, botserver, &botserverport, pass);
#ifdef TLS
    putlog(LOG_SERV, "*", "%s [%s]:%s%d", IRC_SERVERTRY, botserver,
           use_ssl ? "+" : "", botserverport);
    dcc[servidx].ssl = use_ssl;
#else
    putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
           botserverport);
#endif
    dcc[servidx].port = botserverport;
    strcpy(dcc[servidx].nick, "(server)");
    strncpyz(dcc[servidx].host, botserver, UHOSTLEN);

    botuserhost[0] = 0;

    nick_juped = 0;
    for (chan = chanset; chan; chan = chan->next)
      chan->status &= ~CHAN_JUPED;

    dcc[servidx].timeval = now;
    dcc[servidx].sock = -1;
    dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1);
    strcpy(dcc[servidx].u.dns->host, dcc[servidx].host);
    dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1);
    strcpy(dcc[servidx].u.dns->cbuf, pass);
    dcc[servidx].u.dns->dns_success = server_resolve_success;
    dcc[servidx].u.dns->dns_failure = server_resolve_failure;
    dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
    dcc[servidx].u.dns->type = &SERVER_SOCKET;

    if (server_cycle_wait)
      /* Back to 1st server & set wait time.
       * Note: Put it here, just in case the server quits on us quickly
       */
      cycle_time = server_cycle_wait;
    else
      cycle_time = 0;

    /* I'm resolving... don't start another server connect request */
    resolvserv = 1;
    /* Resolve the hostname. */
    dcc_dnsipbyhost(dcc[servidx].host);
  }
}
Пример #5
0
static void got_deop(struct chanset_t *chan, char *nick, char *from,
                     char *who, struct userrec *opu)
{
  memberlist *m;
  char ch[sizeof chan->name];
  char s[UHOSTLEN], s1[UHOSTLEN];
  struct userrec *u;
  int had_halfop;

  m = ismember(chan, who);
  if (!m) {
    if (channel_pending(chan))
      return;
    putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    return;
  }

  strcpy(ch, chan->name);
  simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  simple_sprintf(s1, "%s!%s", nick, from);
  u = get_user_by_host(s);
  get_user_flagrec(u, &victim, chan->dname);

  had_halfop = chan_hasop(m);
  /* Flags need to be set correctly right from the beginning now, so that
   * add_mode() doesn't get irritated.
   */
  m->flags &= ~(CHANOP | SENTDEOP | FAKEOP);
  check_tcl_mode(nick, from, opu, chan->dname, "-o", who);
  if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
      !(m = ismember(chan, who)))
    return;
  m->flags &= ~WASOP;

  if (channel_pending(chan))
    return;

  if (HALFOP_CANDOMODE('o')) {
    int ok = 1;

    if (!glob_deop(victim) && !chan_deop(victim)) {
      if (channel_protectops(chan) && (glob_master(victim) ||
          chan_master(victim) || glob_op(victim) || chan_op(victim)))
        ok = 0;
      else if (channel_protectfriends(chan) && (glob_friend(victim) ||
               chan_friend(victim)))
        ok = 0;
    }
    if ((reversing || !ok) && had_halfop && !match_my_nick(nick) &&
        rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) &&
        !chan_master(user) && !glob_bot(user) && ((chan_op(victim) ||
        (glob_op(victim) && !chan_deop(victim))) || !channel_bitch(chan)))
      add_mode(chan, '+', 'o', who);
  }

  if (!nick[0])
    putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s",
           chan->dname, who, from);

  /* Check for mass deop */
  if (nick[0])
    detect_chan_flood(nick, from, s1, chan, FLOOD_DEOP, who, 0);

  /* Having op hides your +v and +h status -- so now that someone's lost ops,
   * check to see if they have +v or +h
   */
  if (!(m->flags & (CHANVOICE | CHANHALFOP | STOPWHO))) {
    chan->status |= CHAN_PEND;
    refresh_who_chan(chan->name);
    m->flags |= STOPWHO;
  }

  /* Was the bot deopped? */
  if (match_my_nick(who)) {
    /* Cancel any pending kicks and modes */
    memberlist *m2;

    for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
      m2->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTVOICE | SENTDEVOICE);

    check_tcl_need(chan->dname, "op");
    if (chan->need_op[0])
      do_tcl("need-op", chan->need_op);
    if (!nick[0])
      putlog(LOG_MODES, chan->dname, "TS resync deopped me on %s :(",
             chan->dname);
  }
  if (nick[0])
    maybe_revenge(chan, s1, s, REVENGE_DEOP);
}