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

s_user.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: s_user.c,v 1.220.2.2 2005/06/26 18:47:07 amcwilliam Exp $
 */

#include "struct.h"
#include "patchlevel.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "h.h"
#include "memory.h"
#include "ssl.h"
#include "isupport.h"
#include "hook.h"
#include "dlink.h"
#include "xmode.h"
#include "user_ban.h"
#include <sys/stat.h>
#include <utmp.h>
#include <fcntl.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif

static char *ClientAuth_rejmsg[] = {
      NULL, /* CLIENTAUTH_MATCHED */
      "no matched allow block",
      "class is full",
      "invalid password",
      "too many connections"
};

static char *ClientAuth_errmsg[] = {
      NULL, /* CLIENTAUTH_MATCH */
      "You are not authorised to connect",
      "Your connection class is full",
      "Invalid password",
      "Too many connections from your IP address"
};

BlockHeap *client_heap = NULL;
BlockHeap *localclient_heap = NULL;

BlockHeap *user_heap = NULL;
BlockHeap *localuser_heap = NULL;

static void check_list_pings(dlink_list *list)
{
      dlink_node *node, *next = NULL;
      aClient *cptr;
      int ping;

      DLINK_FOREACH_SAFE_DATA(list->head, node, next, cptr, aClient) {
            if (DeadSocket(cptr)) {
                  exit_client(cptr, cptr, &me, SendQEx(cptr) ? "SendQ Exceeded" : "Dead Socket");
                  continue;
            }

            ping = (IsRegistered(cptr)) ? cptr->localClient->class->ping_time : CONNECTTIMEOUT;
            if (ping < (timeofday - cptr->lasttime)) {
                  if ((PingSent(cptr) && (timeofday - cptr->lasttime) >= (ping * 2)) ||
                    (!IsRegistered(cptr) && (timeofday - cptr->since) >= ping)) {
                        char timeout_str[32];

                        if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) {
                              char *path = get_client_name(cptr, HIDE_IP);

                              send_gnotice("No response from %s, closing link.", path);
                              sendto_serv_msg_butone(cptr, &me, &CMD_GNOTICE,
                                    ":No response from %s, closing link.", path);
                        }

                        ircsprintf(timeout_str, "Ping timeout: %d seconds",
                              timeofday - cptr->lasttime);
                        exit_client(cptr, cptr, &me, timeout_str);
                        continue;
                  }
                  else if (!PingSent(cptr) && !IsConnecting(cptr) && !IsHandshake(cptr)
                    && (!IsServer(cptr) || (IsServer(cptr) && !SendingBurst(cptr)))) {
                        SetPingSent(cptr);
                        cptr->lasttime = timeofday - ping;
                        sendto_one_client_nopostfix(cptr, NULL, &CMD_PING, ":%s", me.name);
                  }
            }
      }
}

static void check_unknown_pings(dlink_list *list)
{
      dlink_node *node, *next = NULL;
      aClient *cptr;

      DLINK_FOREACH_SAFE_DATA(list->head, node, next, cptr, aClient) {
            if (cptr->firsttime ? ((timeofday - cptr->firsttime) > 30) : 0) {
                  exit_client(cptr, cptr, &me, "Connection timed out");
            }
      }
}

static void check_pings()
{
      check_list_pings(&lclient_list);
      check_list_pings(&lserver_list);
      check_unknown_pings(&lunknown_list);
      Debug((DEBUG_DEBUG, "Next check_pings(): %s", myctime(timeofday + 9)));
}

void init_clients()
{
      client_heap = BlockHeapCreate(sizeof(aClient), CLIENT_HEAP_SIZE);
      localclient_heap = BlockHeapCreate(sizeof(LocalClient), LOCALCLIENT_HEAP_SIZE);

      user_heap = BlockHeapCreate(sizeof(anUser), USER_HEAP_SIZE);
      localuser_heap = BlockHeapCreate(sizeof(LocalUser), LOCALUSER_HEAP_SIZE);

      add_event("check_pings", check_pings, NULL, 9, 1);
}

aClient *next_client(aClient *next, char *ch)
{
      aClient *tmp = next;

      next = find_client(ch, tmp);
      if (tmp != NULL && tmp->prev == next) {
            return NULL;
      }
      if (next != tmp) {
            return next;
      }
      for (; next != NULL; next = next->next) {
            if (!match(ch, next->name)) {
                  break;
            }
      }
      return next;
}

aClient *next_client_double(aClient *next, char *ch)
{
      aClient *tmp = next;

      next = find_client(ch, tmp);
      if (tmp != NULL && (tmp->prev == next)) {
            return NULL;
      }
      if (next != tmp) {
            return next;
      }
      for (; next != NULL; next = next->next) {
            if (!match(ch, next->name) || !match(next->name, ch)) {
                  break;
            }
      }
      return next;
}

int use_or_deliver(aClient *cptr, aClient *sptr, msg_ptr *msg, char *format, int server, int parc,
  char *parv[])
{
      aClient *acptr;
      int wilds, localc = MyClient(sptr);

      if (parc <= server || BadPtr(parv[server]) || (localc && !match(me.name, parv[server]))) {
            return HUNTED_ISME;
      }
      if ((acptr = localc ? find_client(parv[server], NULL) : find_target(parv[server])) != NULL) {
            if ((!IsMe(acptr) && !IsRegistered(acptr)) || (acptr->from == sptr->from && !MyConnect(acptr))) {
                  acptr = NULL;
            }
      }
      if (acptr == NULL) {
            collapse(parv[server]);

            if (!(wilds = has_wilds(parv[server]))) {
                  if ((acptr = find_server(parv[server], NULL)) == NULL) {
                        send_me_numeric(sptr, ERR_NOSUCHSERVER, parv[server]);
                        return HUNTED_NOSUCH;
                  }
            }
            else {
                  for (acptr = client; (acptr = next_client(acptr, parv[server])) != NULL; acptr = acptr->next) {
                        if (acptr->from == sptr->from && !MyConnect(acptr)) {
                              continue;
                        }
                        if (IsRegistered(acptr) && acptr != cptr) {
                              break;
                        }
                  }
            }
      }
      if (acptr != NULL) {
            if (IsMe(acptr) || MyClient(acptr)) {
                  return HUNTED_ISME;
            }

            parv[server] = use_id(acptr, acptr->from);

            sendto_one_client_nopostfix(acptr, sptr, msg, format, parv[1], parv[2],
                  parv[3], parv[4], parv[5], parv[6], parv[7], parv[8]);
            return HUNTED_PASS;
      }

      send_me_numeric(sptr, ERR_NOSUCHSERVER, parv[server]);
      return HUNTED_NOSUCH;
}

char *canonize(char *buffer)
{
      static char cbuf[BUFSIZE];
      char *s, *t, *cp = cbuf, *p = NULL, *p2;
      int l = 0;

      *cp = '\0';
      for (s = strtoken(&p, buffer, ","); s != NULL; s = strtoken(&p, NULL, ",")) {
            if (l > 0) {
                  for (p2 = NULL, t = strtoken(&p2, cbuf, ","); t != NULL; t = strtoken(&p2, NULL, ",")) {
                        if (!mycmp(s, t)) {
                              break;
                        }
                        else if (p2 != NULL) {
                              p2[-1] = ',';
                        }
                  }
            }
            else {
                  t = NULL;
            }
            if (t == NULL) {
                  if (l > 0) {
                        *(cp - 1) = ',';
                  }
                  else {
                        l = 1;
                  }
                  strcpy(cp, s);
                  if (p != NULL) {
                        cp += (p - s);
                  }
            }
            else if (p2 != NULL) {
                  p2[-1] = ',';
            }
      }
      return cbuf;
}

static inline void welcome_local_user(aClient *sptr)
{
      char *lusers_parv[2] = { sptr->name, NULL };
      
      send_me_numeric(sptr, RPL_WELCOME, NetworkConfig.name, sptr->name, sptr->username, sptr->host);
      send_me_numeric(sptr, RPL_YOURHOST, me.name, sptr->localClient->listener->ipaddr,
            sptr->localClient->listener->port, ircd_version);
      send_me_numeric(sptr, RPL_CREATED, creation);
      send_me_numeric(sptr, RPL_MYINFO, me.name, ircd_version, usermode_str, chanmode_str);

      send_me_numeric(sptr, RPL_ISUPPORT, isupport_buf[0]);
      send_me_numeric(sptr, RPL_ISUPPORT, isupport_buf[1]);

#ifdef USE_OPENSSL
      if (IsSecure(sptr) && (sptr->localClient->ssl != NULL)) {
            send_me_notice(sptr, ":*** You are connected with %s.",
                  ssl_get_cipher_info(sptr->localClient->ssl));
      }
#endif
      if (IsSpoofed(sptr)) {
#ifdef HIDE_SPOOFED_IPS
            send_me_notice(sptr, ":*** Your %shost and IP address have been spoofed.",
                  IsSpoofedUn(sptr) ? "user" : "");
#else
            send_me_notice(sptr, ":*** Your %shost has been spoofed.",
                  IsSpoofedUn(sptr) ? "user" : "");
#endif
      }
      if (IsKlineExempt(sptr)) {
            send_me_noticeNA(sptr, ":*** You are exempt from k-lines.");
      }
#ifdef USE_THROTTLE
      if (IsThrottleExempt(sptr)) {
            send_me_noticeNA(sptr, ":*** You are exempt from throttle.");
      }
#endif

      send_lusers(sptr, sptr, 1, lusers_parv);

      if (GeneralConfig.short_motd) {
            send_me_noticeNA(sptr, ":*** Please read the full motd if you haven't read it.");
            send_me_numeric(sptr, RPL_MOTDSTART, me.name);
            send_me_numeric(sptr, RPL_MOTD, "*** This is the short motd ***");
            send_me_numericNA(sptr, RPL_ENDOFMOTD);
      }
      else {
            send_motd(sptr);
      }
}

int register_user(aClient *cptr, aClient *sptr, char *nick, char *username)
{
      static char ubuf[32]; /* Max of 32 modes. */
      HookData hdata = HOOKDATA_INIT;

      ASSERT(sptr != NULL);
      ASSERT(sptr->user != NULL);

      if (MyConnect(sptr)) {
            char tmp[512], *p;
            int auth, bad_dns = 0;
            userBan *uban;

            ASSERT(sptr->localClient != NULL);
            ASSERT(sptr->localUser != NULL);

            sptr->localUser->last = timeofday;

            switch ((auth = check_client(sptr))) {
                  case CLIENTAUTH_MATCHED:
                        break;
                  default:
                        ircstp->is_ref++;

                        sendto_realops_lev(REJ_LEV, "Unauthorised user connection from %s (%s)",
                              get_client_name(cptr, FALSE), ClientAuth_rejmsg[auth]);
                        return exit_client(cptr, sptr, &me, ClientAuth_errmsg[auth]);
            }

            for (p = sptr->host; *p != '\0'; p++) {
                  if (!IsAlNum(*p)) {
                        if (*p != '-' && *p != '.') {
                              bad_dns = 1;
                              break;
                        }
                  }
            }
            if (bad_dns) {
                  send_me_noticeNA(sptr, ":*** You have bad characters in your hostname");
                  strcpy(sptr->host, sptr->hostip);
                  strcpy(sptr->localClient->sockhost, sptr->hostip);
            }

            if (!GotID(sptr) && !IsSpoofedUn(sptr)) {
                  ASSERT(sptr->localUser->allow != NULL);

                  if (sptr->localUser->allow->flags & ALLOW_NEEDIDENTD) {
                        send_me_noticeNA(sptr, ":*** You need identd to connect to this server");
                        return exit_client(cptr, sptr, &me, "You need identd to connect");
                  }

                  if (sptr->localUser->allow->flags & ALLOW_NOTILDE) {
                        if (username != sptr->username) {
                              strncpyzt(sptr->username, username, USERLEN + 1);
                        }
                  }
                  else {
                        char tmp_username[USERLEN + 1];
                        strncpyzt(tmp_username, username, USERLEN + 1);

                        *sptr->username = '~';
                        strncpy(&sptr->username[1], tmp_username, USERLEN - 1);
                        sptr->username[USERLEN] = '\0';
                  }
            }

            if (sptr->localClient->fd >= (ServerInfo->max_clients + MAX_BUFFER)
              || (sptr->localClient->fd >= (ServerInfo->max_clients - 5))) {
                  sendto_realops_lev(REJ_LEV, "Too many clients, rejecting %s[%s]", nick,
                        sptr->localClient->sockhost);
                  ircstp->is_ref++;
                  return exit_client(cptr, sptr, &me, "Sorry, server is full - try later");
            }

            if (!IsKlineExempt(sptr)) {
                  if ((uban = user_find_ban(sptr, UBAN_CIDR|UBAN_IPV4, UBAN_WILDUSER)) != NULL) {
                        return exit_client_zap(cptr, sptr, uban);
                  }
                  if ((uban = user_find_ban(sptr, UBAN_HOST, 0)) != NULL) {
                        return exit_client_kill(cptr, sptr, uban);
                  }
            }

            {
                  char *str;
                  unsigned char c;
                  int special = 0;

                  if (strchr(sptr->username, '@') || strchr(username, '@')) {
                        sendto_realops_lev(REJ_LEV, "Illegal \"@\" in username: %s (%s)",
                              get_client_name(sptr, FALSE), username);
                        ircstp->is_ref++;
                        ircsprintf(tmp, "Invalid username [%s] - '@' is not allowed!", username);
                        return exit_client(cptr, sptr, sptr, tmp);
                  }

                  str = (*sptr->username == '~') ? (sptr->username + 1) : sptr->username;
                  while (*str != '\0') {
                        c = *str++;
                        if ((!IsAlNum(c) && !strchr(" -_.", c)) || (c > 127) || (c < 32)) {
                              special++;
                        }
                  }
                  if (special) {
                        sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)", nick,
                              sptr->username, sptr->host);
                        ircstp->is_ref++;
                        ircsprintf(tmp, "Invalid username [%s]", sptr->username);
                        return exit_client(cptr, sptr, &me, tmp);
                  }

                  if (irccmp(sptr->username, username)) {
                        str = (*username == '~') ? (username + 1) : username;
                        while (*str != '\0') {
                              c = *str++;
                              if ((!IsAlNum(c) && !strchr(" -_.", c)) || (c > 127)) {
                                    special++;
                              }
                        }
                        if (special) {
                              sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)",
                                    nick, username, sptr->host);
                              ircstp->is_ref++;
                              ircsprintf(tmp, "Invalid username [%s]", username);
                              return exit_client(cptr, sptr, &me, tmp);
                        }
                  }
            }

            if (*(sptr->username + 1) == '\0' && !IsAlpha(*sptr->username)) {
                  sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)", nick,
                        sptr->username, sptr->host);
                  ircstp->is_ref++;
                  ircsprintf(tmp, "Invalid username [%s]", sptr->username);
                  return exit_client(cptr, sptr, &me, tmp);
            }
            
            hdata.sptr = sptr;
            if (hook_run_until(h_register_user_local, &hdata, FLUSH_BUFFER) == FLUSH_BUFFER) {
                  return FLUSH_BUFFER;
            }

            ircdlog(LOG_CLIENT, "client connecting on port %d: %s", sptr->localClient->listener->port,
                  get_client_name(sptr, FALSE));
            sendto_realops_lev(CCONN_LEV, "Client connecting: %s (%s@%s) {%s}", nick,
                  sptr->username, sptr->host, sptr->localClient->class->name);

            if (++Count.local > Count.max_loc) {
                  Count.max_loc = Count.local;
            }
            if (timeofday - Count.day > 86400) {
                  Count.today = 0;
                  Count.day = timeofday;
            }
            if (timeofday - Count.week > 604800) {
                  Count.weekly = 0;
                  Count.week = timeofday;
            }
            if (timeofday - Count.month > 2592000) {
                  Count.monthly = 0;
                  Count.month = timeofday;
            }
            if (timeofday - Count.year > 31536000) {
                  Count.yearly = 0;
                  Count.year = timeofday;
            }
            Count.today++;
            Count.weekly++;
            Count.monthly++;
            Count.yearly++;
      }
      else {
            strncpyzt(sptr->username, username, USERLEN + 1);
            
            hdata.cptr = cptr;
            hdata.sptr = sptr;
            hook_run(h_register_user_remote, &hdata);
      }

      SetClient(sptr);

      if (++Count.total > Count.max_tot) {
            Count.max_tot = Count.total;
      }
      if (HasMode(sptr, UMODE_INVISIBLE)) {
            Count.invisi++;
      }

      if (MyConnect(sptr)) {
            dlink_del_nofree(&lunknown_list, NULL, &sptr->localClient->self);
            dlink_add_node(&lclient_list, &sptr->localClient->self, sptr);
            
            Count.unknown--;
            Count.cli_restart++;
            
            assign_local_userid(sptr);
            
#ifdef INCREASE_SOCK_BUFS
            increase_sock_bufs(sptr->localClient->fd, 0);
#endif

            strncpyzt(sptr->user->maskedhost, maskme(sptr), HOSTLEN + 1);

            welcome_local_user(sptr);
      }
      else if (IsServer(cptr)) {
            aClient *acptr;

            if ((acptr = find_server(sptr->user->server, NULL)) == NULL) {
                  sendto_one_client(sptr, &me, &CMD_KILL, ":%s GHOST (no server %s on this net)",
                        sptr->user->server);
                  sendto_realops_lev(DEBUG_LEV, "No server %s for user %s[%s@%s] from %s",
                        sptr->user->server, sptr->name, sptr->username, sptr->host,
                        sptr->from->name);
                  SetKilled(sptr);
                  return exit_client(sptr, sptr, &me, "Ghosted Client");
            }
            else if (acptr != NULL && (acptr->from != sptr->from)) {
                  sendto_one_client(sptr, &me, &CMD_KILL, ":%s (%s != %s[%s] USER from wrong direction)",
                        me.name, sptr->user->server, acptr->from->name, acptr->from->localClient->sockhost);
                  sendto_realops_lev(DEBUG_LEV, "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
                        cptr->name, nick, sptr->username, sptr->host, sptr->user->server,
                        acptr->name, acptr->from->name);
                  SetKilled(sptr);
                  return exit_client(sptr, sptr, &me, "USER server wrong direction");
            }
            
            /* Clients on pre-2.0.1 servers will not be announced via gcliconn,
             * however if we get here then !CapSNICK(cptr) is TRUE! :-(
             */
            if (GotNBurst(cptr) && !IsULine(sptr)) {
                  sendto_realops_lev(GCCONN_LEV, "Client connecting at %s: %s (%s@%s)",
                        sptr->user->server, sptr->name, sptr->username, sptr->host);
            }
      }
      
      /* This is our user mode string to be sent netwide, so we use SEND_UMODES */
      send_umode(NULL, sptr, 0, SEND_UMODES, ubuf);
      if (*ubuf == '\0') {
            *ubuf = '+';
            *(ubuf + 1) = '\0';
      }

      hash_check_watch(sptr, RPL_LOGON);
      introduce_user(cptr, sptr, ubuf);

      if (MyClient(sptr)) {
            aClient *nsptr;
            if (((nsptr = find_person(NICKSERV, NULL)) != NULL) && (*sptr->localClient->passwd != '\0')) {
                  sendto_one_client_onserver(nsptr, sptr, &CMD_PRIVMSG, ":IDENTIFY %s",
                        sptr->localClient->passwd);
            }
            memset(sptr->localClient->passwd, '\0', PASSWDLEN + 1);
            
            /* hdata.cptr will be null here. */
            hdata.sptr = sptr;
            hook_run(h_post_register_user, &hdata);
            
            /* And this is what is sent to the client, so we use ALL_UMODES.
             * 
             * FIXME --
             * This should eventually be optimised so we don't loop
             * through the user mode table twice. All in good time.
             */
            send_umode(cptr, sptr, 0, ALL_UMODES, ubuf);
      }
      
      return 0;
}

/* a la bahamut-1.6, "kludging our way towards a release" ... */
#define nick_maskedhost(x) (HasMode((x), UMODE_MASKED) ? (x)->user->maskedhost : "*")
#define nick_id(x) (HasSUID((x)) ? (x)->id.string : (x)->user->server)

void introduce_user(aClient *one, aClient *sptr, char *umode_buf)
{
      /* First deal with SNICKs, as the network should be rage2-compliant */
      sendto_serv_capab_msg_butone(one, NULL, CAP_SN2, ID_CAPS, &CMD_SNICK,
            "%s %ld %d %s %s %lu %s %s %lu %s :%s", sptr->name, sptr->tsinfo, sptr->hopcount + 1,
            sptr->username, sptr->host, htonl(sptr->ip.s_addr), nick_maskedhost(sptr),
            sptr->user->server, sptr->user->servicestamp, umode_buf, sptr->info);
      sendto_serv_capab_msg_butone(one, NULL, ID_CAPS|CAP_SN2, NO_CAPS, &CMD_SNICK,
            "%s %B %d %s %s %B %s %s %B %s :%s", sptr->name, sptr->tsinfo, sptr->hopcount + 1,
            sptr->username, sptr->host, sptr->ip.s_addr, nick_maskedhost(sptr), nick_id(sptr),
            sptr->user->servicestamp, umode_buf, sptr->info);
      
      /* Now deal out non-SNICKs */
      sendto_serv_capab_msg_butone(one, NULL, NO_CAPS, ID_CAPS|CAP_SN2, &CMD_NICK,
            "%s %d %ld %s %s %s %s %lu %lu :%s", sptr->name, sptr->hopcount + 1, sptr->tsinfo,
            umode_buf, sptr->username, sptr->host, sptr->user->server, sptr->user->servicestamp,
            htonl(sptr->ip.s_addr), sptr->info);
      sendto_serv_capab_msg_butone(one, NULL, ID_CAPS, CAP_SN2, &CMD_NICK,
            "%s %d %B %s %s %s %s %B %B :%s", sptr->name, sptr->hopcount + 1, sptr->tsinfo,
            umode_buf, sptr->username, sptr->host, nick_id(sptr), sptr->user->servicestamp,
            sptr->ip.s_addr, sptr->info);
}

int do_user(char *nick, aClient *cptr, aClient *sptr, char *username, char *host,
  char *server, unsigned long serviceid, unsigned int ip, char *realname)
{
      make_user(sptr);

      if (!MyConnect(sptr)) {
            sptr->user->server = find_or_add(server);
            strncpyzt(sptr->host, host, HOSTLEN + 1);
      }
      else {
            if (!IsUnknown(sptr)) {
                  send_me_numericNA(sptr, ERR_ALREADYREGISTRED);
                  return 0;
            }

            make_localuser(sptr);
            sptr->localUser->oflags = 0;
            sptr->user->server = me.name;

            AddMode(sptr, GeneralConfig.modes_on_connect);
            AddMode(sptr, ONCONNECT_UMODES);
#ifdef USE_OPENSSL
            if (IsSecure(sptr)) {
                  AddMode(sptr, UMODE_SECURE);
            }
#endif
      }

      strncpyzt(sptr->info, realname, sizeof(sptr->info));
      sptr->user->servicestamp = serviceid;

      if (!MyConnect(sptr)) {
            sptr->ip.s_addr = ntohl(ip);
#ifdef USE_THROTTLE
            if (ip) {
                  throttle_check((char *)inetntoa((const char *)&sptr->ip), -1, sptr->tsinfo);
            }
#endif
      }

      if (*sptr->name != '\0') {
            return register_user(cptr, sptr, sptr->name, username);
      }
      else {
            strncpyzt(sptr->username, username, USERLEN + 1);
      }
      return 0;
}

int is_silenced(aClient *sptr, aClient *acptr)
{
      SLink *lp;
      char *sender;

      if (acptr->user == NULL || acptr->user->silence == NULL || sptr->user == NULL) {
            return 0;
      }

      sender = make_nick_user_host(sptr->name, sptr->username, sptr->host);
      for (lp = acptr->user->silence; lp != NULL; lp = lp->next) {
            if (!match(lp->value.cp, sender)) {
                  if (!MyConnect(sptr)) {
                        sendto_one_client(sptr, acptr, &CMD_SILENCE, "%s", lp->value.cp);
                        lp->flags = 1;
                  }
                  return 1;
            }
      }
      return 0;
}

int del_silence(aClient *sptr, char *mask)
{
      SLink **lp, *tmp;
      for (lp = &(sptr->user->silence); *lp != NULL; lp = &((*lp)->next)) {
            if (!mycmp(mask, (*lp)->value.cp)) {
                  tmp = *lp;
                  *lp = tmp->next;
                  MyFree(tmp->value.cp);
                  free_slink(tmp);
                  return 0;
            }
      }
      return 1;
}

int add_silence(aClient *sptr, char *mask)
{
      SLink *lp;
      int cnt = 0, len = 0;

      for (lp = sptr->user->silence; lp !=  NULL; lp = lp->next) {
            len += strlen(lp->value.cp);
            if (MyClient(sptr)) {
                  if (len > MAXSILELENGTH || ++cnt >= MAXSILES) {
                        send_me_numeric(sptr, ERR_SILELISTFULL, mask);
                        return -1;
                  }
                  if (!match(lp->value.cp, mask)) {
                        return -1;
                  }
            }
            else if (!mycmp(lp->value.cp, mask)) {
                  return -1;
            }
      }

      lp = make_slink();
      lp->next = sptr->user->silence;
      lp->value.cp = (char *)MyMalloc(strlen(mask) + 1);
      strcpy(lp->value.cp, mask);
      sptr->user->silence = lp;
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index