Logo Search packages:      
Sourcecode: rageircd version File versions  Download package

send.c

/*
 * RageIRCd: an advanced Internet Relay Chat daemon (ircd).
 * (C) 2000-2005 the RageIRCd Development Team, all rights reserved.
 *
 * This software is free, licensed under the General Public License.
 * Please refer to doc/LICENSE and doc/README for further details.
 *
 * $Id: send.c,v 1.153.2.4 2005/05/06 22:57:40 amcwilliam Exp $
 */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "numeric.h"
#include "ssl.h"
#include "zlink.h"
#include "memory.h"
#include "msg.h"
#include "fd.h"
#include "dlink.h"
#include "hook.h"
#include "xmode.h"
#include <stdio.h>
#include <time.h>

static unsigned long sent_serial = 0L;

static char local_buf[BUFSIZE + 1];
static char id_buf[BUFSIZE + 1];
static char name_buf[BUFSIZE + 1];

static int local_len = 0;
static int id_len = 0;
static int name_len = 0;

#ifdef USE_OPENSSL
char rc4buf[RC4_BUF_SIZE];
#endif

void send_queued_buffers()
{
      aClient *cptr;
      dlink_node *node;

      /* Send any queued data if it's not blocked */
      /* zip_out() will be 0 if !USE_ZLIB */

      DLINK_FOREACH_PREV_DATA(lserver_list.tail, node, cptr, aClient) {
            if ((SBufLength(&cptr->localClient->sendQ) || zip_out(cptr)) && !IsBlocked(cptr)) {
                  engine_send_queued(cptr);
            }
      }
      DLINK_FOREACH_PREV_DATA(lunknown_list.tail, node, cptr, aClient) {
            if ((SBufLength(&cptr->localClient->sendQ) || zip_out(cptr)) && !IsBlocked(cptr)) {
                  engine_send_queued(cptr);
            }
      }
      DLINK_FOREACH_PREV_DATA(lclient_list.tail, node, cptr, aClient) {
            if (SBufLength(&cptr->localClient->sendQ) && !IsBlocked(cptr)) {
                  engine_send_queued(cptr);
            }
      }
}

static int make_buffer(char *buf, char *pattern, va_list *pattern_args, char *prefix, ...)
{
      int len = 0;

      buf[0] = '\0';

      if (prefix != NULL) {
            va_list prefix_args;

            va_start(prefix_args, prefix);
            len = ircvsprintf(buf, prefix, prefix_args);
            va_end(prefix_args);
      }

      if (pattern_args != NULL) {
            len += ircvsnprintf(&buf[len], BUFSIZE - len, pattern, *pattern_args);
      }

      return len;
}

static void send_message(aClient *to, char *buf, int len, void *shared_buf)
{
      static int SQinK;
      int no_shared = 0;

      ASSERT(to != NULL);
      ASSERT(to->localClient != NULL);

      if ((shared_buf == NULL) || OutputZIP(to) || OutputRC4(to)) {
            if (IsServer(to) || DoingDKEY(to)) {
                  if (len > 510) {
                        len = 511;
                  }
                  buf[len++] = '\n';
                  buf[len] = '\0';
            }
            else {
                  if (len > 509) {
                        len = 510;
                  }
                  buf[len++] = '\r';
                  buf[len++] = '\n';
                  buf[len] = '\0';
            }
            no_shared = 1;
      }

#ifdef DEBUGMODE
      if (IsMe(to)) {
            sendto_realops_lev(DEBUG_LEV, "Trying to send to myself! [%s]", buf);
            return;
      }
#endif
      if (DeadSocket(to)) {
            sendto_realops_lev(DEBUG_LEV, "Trying to send to dead(%s)! [%s]", to->name, buf);
            return;
      }

      if (SBufLength(&to->localClient->sendQ) + len > SENDQLENGTH(to)) {
            if (IsServer(to)) {
                  sendto_realops_lev(FLOOD_LEV, "Max SendQ limit exceeded for %s: %d > %d",
                        get_client_name(to, HIDE_IP), SBufLength(&to->localClient->sendQ),
                        SENDQLENGTH(to));
            }

            SetSendQEx(to);
            engine_write_error(to, "Max SendQ exceeded for %s, closing link", 0);
            return;
      }

      to->localClient->sendM++;
      me.localClient->sendM++;
      if (to->localClient->listener != NULL) {
            to->localClient->listener->sendM++;
      }

#ifdef USE_ZLIB
      if (OutputZIP(to)) {
            int ldata = SendingBurst(to);

            buf = zip_output(to->serv->zip_out, buf, &len, 0, &ldata);
            if (len == -1) {
                  sendto_realops("Zip output error for %s: (%d) %s", to->name, ldata, buf);
                  engine_write_error(to, "Zip output error for %s", IRCERR_ZIP);
                  return;
            }
            if (!len) {
                  return;
            }
      }
#endif

#ifdef USE_OPENSSL
      if (OutputRC4(to)) {
            rc4_process_stream_to_buf(to->serv->rc4_out, buf, rc4buf, len);
            buf = rc4buf;
      }
#endif

      if (no_shared) {
            if (sbuf_put(&to->localClient->sendQ, buf, len) < 0) {
                  engine_write_error(to, "Buffer allocation error for %s, closing link", IRCERR_BUFALLOC);
                  return;
            }
      }
      else {
            if (sbuf_put_share(&to->localClient->sendQ, shared_buf) < 0) {
                  engine_write_error(to, "Buffer allocation error for %s, closing link", IRCERR_BUFALLOC);
                  return;
            }
      }

      if (IsBlocked(to)) {
            return;
      }

#ifdef ALWAYS_SEND_DURING_SPLIT
      if (Internal.net_split) {
            engine_send_queued(to);
            return;
      }
#endif

      SQinK = (SBufLength(&to->localClient->sendQ) >> 10);
      if (IsServer(to)) {
            if (SQinK > (to->localClient->last_sendq + 8)) {
                  engine_send_queued(to);
            }
      }
      else {
            if (SQinK > (to->localClient->last_sendq + 2)) {
                  engine_send_queued(to);
            }
      }
}

static inline int fake_direction(aClient *from, aClient *to)
{
      if (!MyClient(from) && IsPerson(to) && (to->from == from->from)) {
            if (IsServer(from)) {
                  sendto_realops("Message to %s [%s] from %s dropped: fake direction",
                        to->name, to->from->name, from->name);
                  return 1;
            }

            sendto_realops("Ghosted: %s[%s@%s] from %s[%s@%s] (%s)", to->name, to->username,
                  to->host, from->name, from->username, from->host, to->from->name);
            sendto_serv_kill_msg_butone(NULL, &me, to, ":%s (%s[%s@%s] Ghosted %s)",
                  me.name, to->name, to->username, MaskedHost(to), to->from->name);

            if (IsPerson(from)) {
                  send_me_numeric(from, ERR_GHOSTEDCLIENT, to->name);
            }

            SetKilled(to);
            exit_client(NULL, to, &me, "Ghosted Client");

            return 1;
      }

      return 0;
}

void sendto_one_client(aClient *to, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      aClient *realto;
      va_list args;

      ASSERT(to != NULL);
      ASSERT(from != NULL);

      realto = (to->from != NULL) ? to->from : to;
      if (DeadSocket(realto)) {
            return;
      }

      va_start(args, pattern);
      local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s ",
            use_id(from, realto), use_msg(msg, realto), use_id(to, realto));
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_one_client_real(aClient *realto, aClient *to, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      va_list args;

      if (realto->from != NULL) {
            realto = realto->from;
      }
      if (DeadSocket(realto)) {
            return;
      }

      ASSERT(to != NULL);

      va_start(args, pattern);
      if (from != NULL) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s ",
                  use_id(from, realto), use_msg(msg, realto), use_id(to, realto));
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, "%s %s ",
                  use_msg(msg, realto), use_id(to, realto));
      }
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_one_client_prefixed(aClient *to, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      aClient *realto;
      va_list args;

      ASSERT(to != NULL);
      ASSERT(from != NULL);

      realto = (to->from != NULL) ? to->from : to;
      if (DeadSocket(realto)) {
            return;
      }

      va_start(args, pattern);
      if (IsServer(realto)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s ",
                  use_id(from, realto), use_msg(msg, realto), use_id(to, realto));
      }
      else if (IsPerson(from)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s %s %s ",
                  from->name, from->username, MaskedHost(from), msg->msg_str, to->name);
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s ",
                  from->name, msg->msg_str, to->name);
      }
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_one_client_nopostfix(aClient *to, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      aClient *realto;
      va_list args;

      ASSERT(to != NULL);

      realto = (to->from != NULL) ? to->from : to;
      if (DeadSocket(realto)) {
            return;
      }

      va_start(args, pattern);
      if (from != NULL) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s ",
                  use_id(from, realto), use_msg(msg, realto));
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, "%s ", use_msg(msg, realto));
      }
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_one_client_onserver(aClient *to, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      aClient *realto;
      va_list args;

      ASSERT(to != NULL);
      ASSERT(from != NULL);

      realto = (to->from != NULL) ? to->from : to;
      if (DeadSocket(realto)) {
            return;
      }

      va_start(args, pattern);
      if (IsServer(realto)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s ",
                  use_id(from, realto), use_msg(msg, realto), use_id(to, realto));
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s %s@%s ",
                  from->name, msg->msg_str, to->name, to->uplink->name);
      }
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_one_client_numeric(aClient *to, aClient *from, char *format, int numeric, ...)
{
      aClient *realto;
      va_list args;

      ASSERT(to != NULL);
      ASSERT(from != NULL);

      realto = (to->from != NULL) ? to->from : to;
      if (DeadSocket(realto)) {
            return;
      }

      if (format == NULL) {
            format = get_reply(numeric);
      }

      va_start(args, numeric);
      local_len = make_buffer(local_buf, format, &args, ":%s %03d %s ",
            use_id(from, realto), numeric, use_id(to, realto));
      va_end(args);

      send_message(realto, local_buf, local_len, NULL);
}

void sendto_match_msg_butone(aClient *one, aClient *from, char *mask, int what, msg_ptr *msg,
  char *pattern, ...)
{
      int l_msg = 1, g_msg = 1;
      dlink_node *node, *next = NULL;
      aClient *acptr;
      va_list args;
      void *share_bufs[3] = { NULL, NULL, NULL };

      ASSERT(from != NULL);

      if (MyConnect(from)) {
            if (!OPHasFlag(from, OFLAG_LNOTICE)) {
                  l_msg = 0;
            }
            if (!OPHasFlag(from, OFLAG_GNOTICE)) {
                  g_msg = 0;
            }
      }
      if (!l_msg && !g_msg) {
            return;
      }

      va_start(args, pattern);
      if (IsPerson(from)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s %s ",
                  from->name, from->username, MaskedHost(from), msg->msg_str);
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s ",
                  from->name, msg->msg_str);
      }
      id_len = make_buffer(id_buf, pattern, &args, ":%s %s ", get_id(from), get_msg(msg));
      name_len = make_buffer(name_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      va_end(args);

      sbuf_begin_share(local_buf, local_len, &share_bufs[0]);
      sbuf_begin_share(id_buf, id_len, &share_bufs[1]);
      sbuf_begin_share(name_buf, name_len, &share_bufs[2]);

      if (l_msg) {
            DLINK_FOREACH_SAFE_DATA(lclient_list.head, node, next, acptr, aClient) {
                  if (acptr == one || DeadSocket(acptr)) {
                        continue;
                  }
                  if (match(mask, (what == MATCH_HOST) ? acptr->host : acptr->user->server)) {
                        continue;
                  }
                  send_message(acptr, local_buf, local_len, share_bufs[0]);
            }
      }

      if (g_msg) {
            DLINK_FOREACH_SAFE_DATA(lserver_list.head, node, next, acptr, aClient) {
                  if (acptr == one || DeadSocket(acptr)) {
                        continue;
                  }
                  if (CapID(acptr)) {
                        send_message(acptr, id_buf, id_len, share_bufs[1]);
                  }
                  else {
                        send_message(acptr, name_buf, name_len, share_bufs[2]);
                  }
            }
      }

      sbuf_end_share(share_bufs, 3);
}

void sendto_serv_msg_butone(aClient *one, aClient *from, msg_ptr *msg, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      void *share_bufs[2] = { NULL, NULL };

      va_start(args, pattern);
      if (from != NULL) {
            id_len = make_buffer(id_buf, pattern, &args, ":%s %s ", get_id(from), get_msg(msg));
            name_len = make_buffer(name_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      }
      else {
            id_len = make_buffer(id_buf, pattern, &args, "%s ", get_msg(msg));
            name_len = make_buffer(name_buf, pattern, &args, "%s ", msg->msg_str);
      }
      va_end(args);

      sbuf_begin_share(id_buf, id_len, &share_bufs[0]);
      sbuf_begin_share(name_buf, name_len, &share_bufs[1]);

      DLINK_FOREACH_DATA(lserver_list.head, node, acptr, aClient) {
            if (((one != NULL) && (acptr == one->from)) || DeadSocket(acptr)) {
                  continue;
            }

            if (CapID(acptr)) {
                  send_message(acptr, id_buf, id_len, share_bufs[0]);
            }
            else {
                  send_message(acptr, name_buf, name_len, share_bufs[1]);
            }
      }

      sbuf_end_share(share_bufs, 2);
}

void sendto_serv_kill_msg_butone(aClient *one, aClient *from, aClient *to, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      void *share_bufs[2] = { NULL, NULL };

      ASSERT(from != NULL);
      ASSERT(to != NULL);

      va_start(args, pattern);
      id_len = make_buffer(id_buf, pattern, &args, ":%s %s %s ",
            get_id(from), get_msg(&CMD_KILL), get_id(to));
      name_len = make_buffer(name_buf, pattern, &args, ":%s KILL %s ",
            from->name, to->name);
      va_end(args);

      sbuf_begin_share(id_buf, id_len, &share_bufs[0]);
      sbuf_begin_share(name_buf, name_len, &share_bufs[1]);

      DLINK_FOREACH_DATA(lserver_list.head, node, acptr, aClient) {
            if (((one != NULL) && (acptr == one->from)) || DeadSocket(acptr)) {
                  continue;
            }

            if (CapID(acptr)) {
                  send_message(acptr, id_buf, id_len, share_bufs[0]);
            }
            else {
                  send_message(acptr, name_buf, name_len, share_bufs[1]);
            }
      }

      sbuf_end_share(share_bufs, 2);
}

void sendto_serv_capab_msg_butone(aClient *one, aClient *from, unsigned int inc, unsigned int exc,
  msg_ptr *msg, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      void *share_bufs[2] = { NULL, NULL };

      va_start(args, pattern);
      if (from != NULL) {
            id_len = make_buffer(id_buf, pattern, &args, ":%s %s ", get_id(from), get_msg(msg));
            name_len = make_buffer(name_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      }
      else {
            id_len = make_buffer(id_buf, pattern, &args, "%s ", get_msg(msg));
            name_len = make_buffer(name_buf, pattern, &args, "%s ", msg->msg_str);
      }           
      va_end(args);

      sbuf_begin_share(id_buf, id_len, &share_bufs[0]);
      sbuf_begin_share(name_buf, name_len, &share_bufs[1]);

      DLINK_FOREACH_DATA(lserver_list.head, node, acptr, aClient) {
            if (((one != NULL) && (acptr == one->from)) || DeadSocket(acptr)) {
                  continue;
            }
            if (inc && ((acptr->localClient->capabs & inc) != inc)) {
                  continue;
            }
            if (exc && ((acptr->localClient->capabs & exc) != 0)) {
                  continue;
            }

            if (CapID(acptr)) {
                  send_message(acptr, id_buf, id_len, share_bufs[0]);
            }
            else {
                  send_message(acptr, name_buf, name_len, share_bufs[1]);
            }
      }

      sbuf_end_share(share_bufs, 2);
}

void sendto_channel_msg_butone(aClient *one, aClient *from, aChannel *chptr,
  unsigned int flags, msg_ptr *msg, char *pattern, ...)
{
      chanMember *cm;
      aClient *acptr;
      va_list args;
      void *share_bufs[3] = { NULL, NULL, NULL };

      sent_serial++;

      ASSERT(from != NULL);
      ASSERT(chptr != NULL);

      va_start(args, pattern);
      if (IsPerson(from)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s %s ",
                  from->name, from->username, MaskedHost(from), msg->msg_str);
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s ",
                  from->name, msg->msg_str);
      }
      id_len = make_buffer(id_buf, pattern, &args, ":%s %s ", get_id(from), get_msg(msg));
      name_len = make_buffer(name_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      va_end(args);

      sbuf_begin_share(local_buf, local_len, &share_bufs[0]);
      sbuf_begin_share(id_buf, id_len, &share_bufs[1]);
      sbuf_begin_share(name_buf, name_len, &share_bufs[2]);

      for (cm = chptr->members; cm != NULL; cm = cm->nextuser) {
            acptr = cm->cptr;

            if ((acptr->from == one) || DeadSocket(acptr->from)) {
                  continue;
            }
            if (HasMode(acptr, UMODE_DEAF) || (flags && !(cm->flags & flags))) {
                  continue;
            }

            if (MyClient(acptr)) {
                  if (fake_direction(from, acptr)) {
                        continue;
                  }
                  if (acptr->serial != sent_serial) {
                        send_message(acptr, local_buf, local_len, share_bufs[0]);
                        acptr->serial = sent_serial;
                  }
            }
            else if (acptr->from->serial != sent_serial) {
                  if (fake_direction(from, acptr)) {
                        continue;
                  }

                  if (CapID(acptr->from)) {
                        send_message(acptr->from, id_buf, id_len, share_bufs[1]);
                  }
                  else {
                        send_message(acptr->from, name_buf, name_len, share_bufs[2]);
                  }
                  acptr->from->serial = sent_serial;
            }
      }

      sbuf_end_share(share_bufs, 3);
}

void sendto_channel_local_msg_butone(aClient *one, aClient *from, aChannel *chptr,
  unsigned int flags, msg_ptr *msg, char *pattern, ...)
{
      chanMember *cm;
      aClient *acptr;
      va_list args;
      void *share_buf = NULL;

      ASSERT(from != NULL);
      ASSERT(chptr != NULL);

      sent_serial++;

      va_start(args, pattern);
      if (IsPerson(from)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s %s ",
                  from->name, from->username, MaskedHost(from), msg->msg_str);
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      }
      va_end(args);

      sbuf_begin_share(local_buf, local_len, &share_buf);

      for (cm = chptr->members; cm != NULL; cm = cm->nextuser) {
            acptr = cm->cptr;

            if (!MyConnect(acptr) || acptr == one || DeadSocket(acptr)) {
                  continue;
            }
            if (HasMode(acptr, UMODE_DEAF) || (flags && !(cm->flags & flags))) {
                  continue;
            }

            if (fake_direction(from, acptr)) {
                  continue;
            }

            if (acptr->serial != sent_serial) {
                  send_message(acptr, local_buf, local_len, share_buf);
                  acptr->serial = sent_serial;
            }
      }

      sbuf_end_share(&share_buf, 1);
}

void sendto_channel_local_msg_common(aClient *from, msg_ptr *msg, char *pattern, ...)
{
      chanMember *c, *u;
      aClient *acptr;
      va_list args;
      void *share_buf = NULL;

      ASSERT(from != NULL);

      sent_serial++;

      va_start(args, pattern);
      if (IsPerson(from)) {
            local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s %s ",
                  from->name, from->username, MaskedHost(from), msg->msg_str);
      }
      else {
            local_len = make_buffer(local_buf, pattern, &args, ":%s %s ", from->name, msg->msg_str);
      }
      va_end(args);

      sbuf_begin_share(local_buf, local_len, &share_buf);

      if (from->user != NULL) {
            for (c = from->user->channel; c != NULL; c = c->nextchan) {
                  for (u = c->chptr->members; u != NULL; u = u->nextuser) {
                        acptr = u->cptr;

                        if (!MyConnect(acptr) || DeadSocket(acptr)) {
                              continue;
                        }
                        if (acptr->serial == sent_serial) {
                              continue;
                        }
                        if (fake_direction(from, acptr)) {
                              continue;
                        }

                        send_message(acptr, local_buf, local_len, share_buf);
                        acptr->serial = sent_serial;
                  }
            }
      }

      if (MyConnect(from) && (from->serial != sent_serial)) {
            send_message(from, local_buf, local_len, share_buf);
            from->serial = sent_serial;
      }

      sbuf_end_share(&share_buf, 1);
}

void sendto_realops(char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      char buf[BUFSIZE];

      va_start(args, pattern);
      ircvsnprintf(buf, BUFSIZE, pattern, args);
      va_end(args);

      DLINK_FOREACH_DATA(oper_list.head, node, acptr, aClient) {
            send_me_notice(acptr, ":*** Notice -- %s", buf);
      }
}

void sendto_realops_lev(int lev, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      char buf[BUFSIZE], *notice;
      unsigned long mode = 0L;

      va_start(args, pattern);
      ircvsnprintf(buf, BUFSIZE, pattern, args);
      va_end(args);

      switch (lev) {
            case CCONN_LEV:
                  mode = UMODE_LCLICONN;
                  notice = "Client";
                  break;
            case GCCONN_LEV:
                  mode = UMODE_GCLICONN;
                  notice = "Client";
                  break;
            case REJ_LEV:
                  mode = UMODE_REJNOTICES;
                  notice = "Reject";
                  break;
            case SKILL_LEV:
                  mode = UMODE_SNOTICE;
                  notice = "Notice";
                  break;
            case SPY_LEV:
                  mode = UMODE_SPYING;
                  notice = "Spy";
                  break;
            case DEBUG_LEV:
                  mode = UMODE_DNOTICE;
                  notice = "Debug";
                  break;
            case FLOOD_LEV:
                  mode = UMODE_FNOTICE;
                  notice = "Flood";
                  break;
            case SPAM_LEV:
                  mode = UMODE_SPAMBOT;
                  notice = "Spam";
                  break;
            case DCCSEND_LEV:
                  mode = UMODE_DCCNOTICE;
                  notice = "Notice";
                  break;
            default:
                  ircdlog(LOG_ERROR, "Ignoring unknown notification level: %d", lev);
                  return;
      }

      DLINK_FOREACH_DATA(oper_list.head, node, acptr, aClient) {
            if (HasMode(acptr, mode)) {
                  send_me_notice(acptr, ":*** %s -- %s", notice, buf);
            }
      }
}

void send_quit_to_common_channels(aClient *from, char *reason)
{
      chanMember *c, *u;
      aClient *acptr;
      void *share_buf = NULL;

      local_len = ircsnprintf(local_buf, BUFSIZE, ":%s!%s@%s QUIT :%s",
            from->name, from->username, MaskedHost(from), reason);
      sbuf_begin_share(local_buf, local_len, &share_buf);

      sent_serial++;
      from->serial = sent_serial; /* Dont send the QUIT to the client... */

      for (c = from->user->channel; c != NULL; c = c->nextchan) {
            if (can_send(from, c->chptr, reason)) {
                  continue;
            }
            for (u = c->chptr->members; u != NULL; u = u->nextuser) {
                  acptr = u->cptr;

                  if (!MyConnect(acptr) || DeadSocket(acptr)) {
                        continue;
                  }
                  if (acptr->serial == sent_serial) {
                        continue;
                  }
                  if (fake_direction(from, acptr)) {
                        continue;
                  }

                  send_message(acptr, local_buf, local_len, share_buf);
                  acptr->serial = sent_serial;
            }
      }

      sbuf_end_share(&share_buf, 1);
}

void send_part_to_common_channels(aClient *from, char *reason)
{
      chanMember *c, *u;
      aClient *acptr;
      void *share_buf = NULL;

      for (c = from->user->channel; c != NULL; c = c->nextchan) {
            if (!can_send(from, c->chptr, reason)) {
                  continue;
            }

            local_len = ircsnprintf(local_buf, BUFSIZE, ":%s!%s@%s PART %s",
                  from->name, from->username, MaskedHost(from), c->chptr->chname);
            sbuf_begin_share(local_buf, local_len, &share_buf);

            sent_serial++;
            from->serial = sent_serial; /* Don't send the PART to the client */

            for (u = c->chptr->members; u != NULL; u = u->nextuser) {
                  acptr = u->cptr;

                  if (!MyConnect(acptr) || DeadSocket(acptr)) {
                        continue;
                  }
                  if (acptr->serial == sent_serial) {
                        continue;
                  }
                  if (fake_direction(from, acptr)) {
                        continue;
                  }

                  send_message(acptr, local_buf, local_len, share_buf);
                  acptr->serial = sent_serial;
            }

            sbuf_end_share(&share_buf, 1);
      }
}

void send_wallops(aClient *from, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      void *share_buf = NULL;

      va_start(args, pattern);
      local_len = make_buffer(local_buf, pattern, &args, ":%s!%s@%s WALLOPS :",
            from->name, from->username, MaskedHost(from));
      va_end(args);

      sbuf_begin_share(local_buf, local_len, &share_buf);

      DLINK_FOREACH_DATA(oper_list.head, node, acptr, aClient) {
            if (HasMode(acptr, UMODE_WALLOPS)) {
                  send_message(acptr, local_buf, local_len, share_buf);
            }
      }

      sbuf_end_share(&share_buf, 1);
}

void sendto_mode(unsigned long mode, char *notice, char *pattern, ...)
{
      aClient *acptr;
      dlink_node *node;
      va_list args;
      char buf[BUFSIZE];

      va_start(args, pattern);
      ircvsnprintf(buf, BUFSIZE, pattern, args);
      va_end(args);

      DLINK_FOREACH_DATA(lclient_list.head, node, acptr, aClient) {
            if (!(mode && !HasMode(acptr, mode))) {
                  send_me_notice(acptr, ":*** %s -- %s", notice, buf);
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index