Exemple #1
0
void
InitJupes()

{
	struct Jupe *tmpjupe;
	char sendstr[MAXLINE + 1];
	char **av;

	for (tmpjupe = JupeList; tmpjupe; tmpjupe = tmpjupe->next)
	{
		if (tmpjupe->isnick)
		{
#ifdef DANCER
			ircsprintf(sendstr, "NICK %s 1 1 +i juped juped.com %s :%s\r\n",
			           tmpjupe->name, Me.name, tmpjupe->reason ? tmpjupe->reason :
			           "Jupitered Nickname");
#else
			/* collide the nickname */
			ircsprintf(sendstr, "NICK %s 1 1 +i %s %s %s :%s\r\n",
			           tmpjupe->name, JUPED_USERNAME, JUPED_HOSTNAME, Me.name,
			           tmpjupe->reason ? tmpjupe->reason : "Jupitered Nickname");
#endif /* DANCER */

			toserv("%s", sendstr);

			SplitBuf(sendstr, &av);
			AddClient(av);
			MyFree(av);
		}
		else
		{
		  char *tptr;

		  /* check for wildcards */
		  for (tptr = tmpjupe->name; *tptr != '\0' && !IsMWildChar(*tptr); tptr++)
		    ;

		  if (*tptr == '\0')
		    {
			ircsprintf(sendstr, ":%s SERVER %s 2 :Juped: %s", Me.name,
			           tmpjupe->name, tmpjupe->reason);

			toserv(":%s SQUIT %s :%s (%s)\r\n%s\r\n",
			       Me.name,
			       tmpjupe->name,
			       tmpjupe->reason,
			       tmpjupe->who,
			       sendstr);

			SplitBuf(sendstr, &av);
			AddServer(5, av);
			MyFree(av);
		}
	}
	}
} /* InitJupes() */
Exemple #2
0
void
ss_process(char *nick, char *command)

{
	int acnt;
	char **arv;
	struct Command *sptr;
	struct Luser *lptr;

	if (!command || !(lptr = FindClient(nick)))
		return;

	if (Network->flags & NET_OFF)
	{
		notice(n_StatServ, lptr->nick,
		       "Services are currently \002disabled\002");
		return;
	}

	acnt = SplitBuf(command, &arv);
	if (acnt == 0)
	{
		MyFree(arv);
		return;
	}

	sptr = GetCommand(statcmds, arv[0]);

	if (!sptr || (sptr == (struct Command *) -1))
	{
		notice(n_StatServ, lptr->nick,
		       "%s command [%s]",
		       (sptr == (struct Command *) -1) ? "Ambiguous" : "Unknown",
		       arv[0]);
		MyFree(arv);
		return;
	}

	/*
	 * Check if the command is for admins only - if so,
	 * check if they match an admin O: line.  If they do,
	 * check if they are registered with OperServ,
	 * if so, allow the command
	 */
	if ((sptr->level == LVL_ADMIN) && !(IsValidAdmin(lptr)))
	{
		notice(n_StatServ, lptr->nick, "Unknown command [%s]",
		       arv[0]);
		MyFree(arv);
		return;
	}

	/* call sptr->func to execute command */
	(*sptr->func)(lptr, acnt, arv);

	MyFree(arv);

	return;
} /* ss_process() */
void
SetModes(char *source, int plus, char mode, struct Channel *chptr, char *args)

{
  int acnt, mcnt, ii;
  char done[MAXLINE], sendstr[MAXLINE];
  char **av, *temp, *mtmp;

  if (!source || !chptr || !args)
    return;

  temp = MyStrdup(args);
  acnt = SplitBuf(temp, &av);
  memset(&done, 0, MAXLINE);
  mcnt = 1;
  for (ii = 0; ii < acnt; ii++)
  {
    strcat(done, av[ii]);
    /* Rewrote this to fix that nasty " " at the end of done[] -kre */
    if (mcnt != MaxModes)
      strcat(done, " ");
    else
    {
      mcnt = 0;
      mtmp = modestr(MaxModes, mode);
      ircsprintf(sendstr, "%s%s %s",
        plus ? "+" : "-", mtmp, done);
      toserv(":%s MODE %s %s\n",
        source,
        chptr->name,
        sendstr);
      UpdateChanModes(0, source, chptr, sendstr);
      MyFree(mtmp);
      memset(&done, 0, MAXLINE);
    }
    mcnt++;
  }

  if (done[0] != '\0')
  {
    mtmp = modestr(mcnt - 1, mode);
    ircsprintf(sendstr, "%s%s %s",
      plus ? "+" : "-",
      mtmp,
      done);
    toserv(":%s MODE %s %s\n",
      source,
      chptr->name,
      sendstr);
    UpdateChanModes(0, source, chptr, sendstr);
    MyFree(mtmp);
  }
  MyFree(temp);
  MyFree(av);
} /* SetModes() */
void es_add(char *nick, char *user, char *host, char *msg, time_t time,
            int type)
{
    int ac;
    char userhost[USERLEN + HOSTLEN + 2], **av, *mymsg;
    aSeen *seen = MyMalloc(sizeof(aSeen));

#ifdef NOSQUITSEEN
    if (type == 1)
    {
        mymsg = MyStrdup(msg);
        ac = SplitBuf(mymsg, &av);
        if (ac == 2)
        {
            if (FindServer(av[0]) && FindServer(av[1]))
            {
                MyFree(mymsg);
                MyFree(av);
                return ;
            }
        }
        MyFree(mymsg);
        MyFree(av);
    }
#endif
    if (++seenc > SeenMaxRecs)
    {
        aSeen *sp = seenb;
        MyFree(seenb->userhost);
        MyFree(seenb->msg);
        if (seenb->next)
            seenb->next->prev = NULL;
        seenb = seenb->next;
        MyFree(sp);
        seenc--;
    }
    memset(userhost, 0, sizeof(userhost));
    memset(seen, 0, sizeof(aSeen));
    strncpy(seen->nick, nick, NICKLEN);
    strncpy(userhost, user, USERLEN);
    strcat(userhost, "@");
    strncat(userhost, host, HOSTLEN);
    seen->userhost = MyStrdup(userhost);
    seen->msg = (type == 1) ? MyStrdup(msg) : NULL;
    seen->time = time;
    seen->type = type;
    seen->prev = seenp;
    seen->next = NULL;
    if (seenp)
        seenp->next = seen;
    seenp = seen;
    if (!seenb)
        seenb = seen;
}
void
KickBan(int ban, char *source, struct Channel *channel, char *nicks, char *reason)

{
  char *mask, *tempnix, **av, *bans;
  char temp[MAXLINE];
  int ac, ii;
  struct Luser *lptr;

  if (!source || !channel || !nicks)
    return;

  tempnix = MyStrdup(nicks);
  ac = SplitBuf(tempnix, &av);

  if (ban)
  {
    bans = (char *) MyMalloc(sizeof(char));
    bans[0] = '\0';
    for (ii = 0; ii < ac; ii++)
    {
      if (!(lptr = FindClient(av[ii])))
        continue;
      mask = HostToMask(lptr->username, lptr->hostname);
      ircsprintf(temp, "*!%s", mask);
      bans = (char *) MyRealloc(bans, strlen(bans)
          + strlen(temp) + (2 * sizeof(char)));
      strcat(bans, temp);
      strcat(bans, " ");
      MyFree(mask);
    }

    SetModes(source, 1, 'b', channel, bans);
    MyFree(bans);
  }

  for (ii = 0; ii < ac; ii++)
  {
    toserv(":%s REMOVE %s %s :%s\n",
      source,
      channel->name,
      av[ii],
      reason ? reason : "");
    RemoveFromChannel(channel, FindClient(av[ii]));
  }

  MyFree(tempnix);
  MyFree(av);
} /* KickBan() */
Exemple #6
0
void
FakeServer(char *serv, char *reason)
{
  char **arv, sendstr[MAXLINE + 1];
  int arc;

	ircsprintf(sendstr, ":%s SERVER %s 2 :Juped: %s\r\n", Me.name, serv,
	           reason);

	toserv("%s", sendstr);

  arc = SplitBuf(sendstr, &arv);
  AddServer(arc, arv);

	MyFree(arv);
}
Exemple #7
0
int
CheckJuped(char *name)

{
	struct Jupe *tempjupe;
	struct Server *tempserv;
	char sendstr[MAXLINE + 1], **arv;

	for (tempjupe = JupeList; tempjupe; tempjupe = tempjupe->next)
	{
		if (match(tempjupe->name, name))
		{
			if (tempjupe->isnick)
			{
				struct Luser *lptr;

				if (!(lptr = FindClient(name)))
					return 0;

				/* its a nick jupe, not a server jupe */

#ifdef DANCER

				ircsprintf(sendstr,
				           "NICK %s 1 %ld +i juped juped.com %s %lu :%s\r\n",
				           tempjupe->name,
#ifdef NICKSERVICES
				           (long) (lptr->nick_ts - 1),
#else
				           (long) (lptr->since - 1),
#endif /* NICKSERVICES */
				           Me.name, 0xffffffffL, tempjupe->reason ?
				           tempjupe->reason : "Jupitered Nickname");
#else
				/* collide the nickname */
				ircsprintf(sendstr, "NICK %s 1 %ld +i %s %s %s :%s\r\n",
				           tempjupe->name,
#ifdef NICKSERVICES
				           (long) (lptr->nick_ts - 1),
#else
				(long) (lptr->since - 1),
#endif /* NICKSERVICES */
				           JUPED_USERNAME, JUPED_HOSTNAME, Me.name,
				           tempjupe->reason ? tempjupe->reason :
				           "Jupitered Nickname");
#endif /* DANCER */

				toserv("%s", sendstr);

				DeleteClient(lptr);

				SplitBuf(sendstr, &arv);
				AddClient(arv);
				MyFree(arv);

				if (Me.sptr)
					Me.sptr->numoperkills++;
				Network->TotalOperKills++;
#ifdef STATSERVICES

				if (Network->TotalOperKills > Network->OperKillsT)
					Network->OperKillsT = Network->TotalOperKills;
#endif

			}
			else
			{
				toserv("SQUIT %s :Juped: %s (%s)\r\n", name,
				       tempjupe->reason, tempjupe->who);

				tempserv = FindServer(name);
				DeleteServer(tempserv);

			/* If the fake server is introduced before the remote server has quited,
			 * we get "server already exists" and services get SQUIT'ed,
			 * so we'll introduce it in s_squit()
			 */


			}
			return 1;
		}
	}
	return 0;
} /* CheckJuped */
Exemple #8
0
static void
ss_stats(struct Luser *lptr, int ac, char **av)

{
	float avgops, avguc, avgus;
	struct tm *tmp_tm;
	char str[MAXLINE + 1], tmp[MAXLINE + 1];
	char **tav;
	time_t currtime;

	RecordCommand("%s: %s!%s@%s STATS",
	              n_StatServ,
	              lptr->nick,
	              lptr->username,
	              lptr->hostname);

	avgops = Network->TotalOperators / Network->TotalServers;
	if (Network->TotalChannels > 0.0)
		avguc = Network->TotalUsers / Network->TotalChannels;
	else
		avguc = 0;
	avgus = Network->TotalUsers / Network->TotalServers;

	notice(n_StatServ, lptr->nick,
	       "Current Users:              %1.0f (avg. %1.2f users per server)",
	       Network->TotalUsers,
	       avgus);
	notice(n_StatServ, lptr->nick,
	       "Current Operators:          %1.0f (avg. %1.2f operators per server)",
	       Network->TotalOperators,
	       avgops);
	notice(n_StatServ, lptr->nick,
	       "Current Channels:           %1.0f (avg. %1.2f users per channel)",
	       Network->TotalChannels,
	       avguc);
	notice(n_StatServ, lptr->nick,
	       "Current Servers:            %1.0f",
	       Network->TotalServers);

	strlcpy(str, ctime(&Network->MaxUsers_ts), sizeof(str));
	str[strlen(str) - 1] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Users:                  %ld on %s",
	       Network->MaxUsers,
	       str);

	if (Network->MaxOperators_ts)
	{
		strlcpy(str, "on ", sizeof(str));
		strlcat(str, ctime(&Network->MaxOperators_ts), sizeof(str));
		str[strlen(str) - 1] = '\0';
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Operators:              %ld %s",
	       Network->MaxOperators,
	       str);

	if (Network->MaxChannels_ts)
	{
		strlcpy(str, "on ", sizeof(str));
		strlcat(str, ctime(&Network->MaxChannels_ts), sizeof(str));
		str[strlen(str) - 1] = '\0';
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Channels:               %ld %s",
	       Network->MaxChannels,
	       str);

	strlcpy(str, ctime(&Network->MaxServers_ts), sizeof(str));
	str[strlen(str) - 1] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Servers:                %ld on %s",
	       Network->MaxServers,
	       str);

	notice(n_StatServ, lptr->nick,
	       "Identd Users:               %ld",
	       Network->Identd);
	notice(n_StatServ, lptr->nick,
	       "Non-Identd Users:           %ld",
	       Network->NonIdentd);
	notice(n_StatServ, lptr->nick,
	       "Resolving Host Users:       %ld",
	       Network->ResHosts);
	notice(n_StatServ, lptr->nick,
	       "Non-Resolving Host Users:   %ld",
	       (long) Network->TotalUsers - Network->ResHosts);

	currtime = current_ts;
	strlcpy(tmp, ctime(&currtime), sizeof(tmp));
	SplitBuf(tmp, &tav);
	ircsprintf(str, "%s %s %s, %s", tav[0], tav[1], tav[2], tav[4]);
	notice(n_StatServ, lptr->nick,
	       "-- \002So far today:\002 (%s) --",
	       str);
	MyFree(tav);

	if (Network->MaxUsersT_ts)
	{
		tmp_tm = localtime(&Network->MaxUsersT_ts);
		ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min,
		           tmp_tm->tm_sec);
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Users:                  %ld %s",
	       Network->MaxUsersT,
	       str);

	if (Network->MaxOperatorsT_ts)
	{
		tmp_tm = localtime(&Network->MaxOperatorsT_ts);
		ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min,
		           tmp_tm->tm_sec);
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Operators:              %ld %s",
	       Network->MaxOperatorsT,
	       str);

	if (Network->MaxChannelsT_ts)
	{
		tmp_tm = localtime(&Network->MaxChannelsT_ts);
		ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min,
		           tmp_tm->tm_sec);
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Channels:               %ld %s",
	       Network->MaxChannelsT,
	       str);

	if (Network->MaxServersT_ts)
	{
		tmp_tm = localtime(&Network->MaxServersT_ts);
		ircsprintf(str, "at %d:%02d:%02d", tmp_tm->tm_hour, tmp_tm->tm_min,
		           tmp_tm->tm_sec);
	}
	else
		str[0] = '\0';
	notice(n_StatServ, lptr->nick,
	       "Max Servers:                %ld %s",
	       Network->MaxServersT,
	       str);

	notice(n_StatServ, lptr->nick,
	       "Operator Kills:             %ld",
	       Network->OperKillsT);
	notice(n_StatServ, lptr->nick,
	       "Server Kills:               %ld",
	       Network->ServKillsT);
} /* ss_stats() */
Exemple #9
0
int
ss_loaddata()

{
	FILE *fp;
	char line[MAXLINE + 1], **av;
	char *keyword;
	int ac, ret = 1, cnt;

	if ((fp = fopen(StatServDB, "r")) == NULL)
	{
		/* StatServ data file doesn't exist */
		return (-1);
	}

	cnt = 0;
	/* load data into list */
	while (fgets(line, sizeof(line), fp))
	{
		cnt++;
		ac = SplitBuf(line, &av);
		if (!ac)
		{
			/* probably a blank line */
			MyFree(av);
			continue;
		}

		if (av[0][0] == ';')
		{
			MyFree(av);
			continue;
		}

		if (!ircncmp("->", av[0], 2))
		{
			/*
			 * check if there are enough args
			 */
			if (ac < 3)
			{
				fatal(1, "%s:%d Invalid database format (FATAL)",
				      StatServDB,
				      cnt);
				ret = -2;
				MyFree(av);
				continue;
			}

			keyword = av[0] + 2;
			if (!ircncmp(keyword, "USERS", 5))
			{
				if (Network->TotalUsers <= atol(av[1]))
				{
					Network->MaxUsers = atol(av[1]);
					Network->MaxUsers_ts = atol(av[2]);
				}
			}
			else if (!ircncmp(keyword, "OPERS", 5))
			{
				if (Network->TotalOperators <= atol(av[1]))
				{
					Network->MaxOperators = atol(av[1]);
					Network->MaxOperators_ts = atol(av[2]);
				}
			}
			else if (!ircncmp(keyword, "CHANS", 5))
			{
				if (Network->TotalChannels <= atol(av[1]))
				{
					Network->MaxChannels = atol(av[1]);
					Network->MaxChannels_ts = atol(av[2]);
				}
			}
			else if (!ircncmp(keyword, "SERVS", 5))
			{
				if (Network->TotalServers <= atol(av[1]))
				{
					Network->MaxServers = atol(av[1]);
					Network->MaxServers_ts = atol(av[2]);
				}
			}
		}

		MyFree(av);
	} /* while */

	fclose(fp);

	return (ret);
} /* ss_loaddata */
void
ms_process(char *nick, char *command)

{
  int acnt;
  char **arv;
  struct Command *mptr;
  struct Luser *lptr;
  struct NickInfo *nptr, *master;

  if (!command || !(lptr = FindClient(nick)))
    return;

  if (Network->flags & NET_OFF)
  {
    notice(n_MemoServ, lptr->nick,
      "Services are currently \002disabled\002");
    return;
  }

  acnt = SplitBuf(command, &arv);
  if (acnt == 0)
  {
    MyFree(arv);
    return;
  }

  mptr = GetCommand(memocmds, arv[0]);

  if (!mptr || (mptr == (struct Command *) -1))
  {
    notice(n_MemoServ, lptr->nick,
      "%s command [%s]",
      (mptr == (struct Command *) -1) ? "Ambiguous" : "Unknown",
      arv[0]);
    MyFree(arv);
    return;
  }

  /*
   * Check if the command is for admins only - if so,
   * check if they match an admin O: line.  If they do,
   * check if they are EITHER oper'd, or registered with OperServ,
   * if either of these is true, allow the command
   */
  if ((mptr->level == LVL_ADMIN) && !(IsValidAdmin(lptr)))
  {
    notice(n_MemoServ, lptr->nick, "Unknown command [%s]",
      arv[0]);
    MyFree(arv);
    return;
  }

  nptr = FindNick(lptr->nick);
  master = GetMaster(nptr);

  if (!nptr && !master && (mptr->level != LVL_NONE))
  {
    /* the command requires a registered nickname */

    notice(n_MemoServ, lptr->nick,
      "Your nickname is not registered");
    notice(n_MemoServ, lptr->nick,
      ERR_MORE_INFO,
      n_NickServ,
      "REGISTER");
    MyFree(arv);
    return;
  }

  if (nptr)
  {
    if (nptr->flags & NS_FORBID)
    {
      notice(n_MemoServ, lptr->nick,
        "Cannot execute commands for forbidden nicknames");
      MyFree(arv);
      return;
    }

    if (mptr->level != LVL_NONE)
    {
      if (!(nptr->flags & NS_IDENTIFIED))
      {
        notice(n_MemoServ, lptr->nick,
          "Password identification is required for [\002%s\002]",
          mptr->cmd);
        notice(n_MemoServ, lptr->nick, 
          "Type \002/msg %s IDENTIFY <password>\002 and retry",
          n_NickServ);
        MyFree(arv);
        return;
      }
    }
  } /* if (nptr) */

  /* call mptr->func to execute command */
  (*mptr->func)(lptr, master, acnt, arv);

  MyFree(arv);

  return;
} /* ms_process() */
int
ms_loaddata()

{
  FILE *fp;
  char line[MAXLINE], **av;
  char *keyword;
  int ac, ret = 1, cnt;
  struct MemoInfo *mi = NULL;
  struct NickInfo *nickptr;

  if (!(fp = fopen(MemoServDB, "r")))
  {
    /* MemoServ data file doesn't exist */
    return -1;
  }

  cnt = 0;
  /* load data into list */
  while (fgets(line, MAXLINE - 1, fp))
  {
    cnt++;
    ac = SplitBuf(line, &av);
    if (!ac)
    {
      /* probably a blank line */
      MyFree(av);
      continue;
    }

    if (av[0][0] == ';')
    {
      /* its a comment */
      MyFree(av);
      continue;
    }

    if (!ircncmp("->", av[0], 2))
    {
      /* 
       * check if there are enough args
       */
      if (ac < 5)
      {
        fatal(1, "%s:%d Invalid database format (FATAL)",
          MemoServDB,
          cnt);
        ret = -2;
        MyFree(av);
        continue;
      }

      /* check if there is no nickname before it */
      if (!mi)
      {
        fatal(1, "%s:%d No nickname associated with data",
          MemoServDB,
          cnt);
        if (ret > 0)
          ret = -1;
        MyFree(av);
        continue;
      }

      keyword = av[0] + 2;
      if (!ircncmp(keyword, "TEXT", 4))
      {
        struct Memo *memoptr;

        memoptr = MakeMemo();
        memoptr->sender = MyStrdup(av[1]);
        memoptr->sent = atol(av[2]);
        memoptr->flags = atol(av[3]);
        if (!(memoptr->flags & MS_READ))
          mi->newmemos++;
        memoptr->text = MyStrdup(av[4] + 1);
        memoptr->index = ++mi->memocnt;
        AddMemo(mi, memoptr);
      }

    } /* if (!ircncmp("->", keyword, 2)) */
    else
    {
      if (mi)
      {
        if (!mi->memos)
        {
          fatal(1, "%s:%d No memos for entry [%s] (skipping)",
            MemoServDB,
            cnt,
            mi->name);
          MyFree(mi->name);
          MyFree(mi);
          mi = NULL;
          if (ret > 0)
            ret = -1;
        }
        else
          AddMemoList(mi);
      }

      /*
       * make sure there are enough args on the line:
       * <nickname>
       */
      if (ac < 1)
      {
        fatal(1, "%s:%d Invalid database format (FATAL)",
          MemoServDB,
          cnt);
        ret = -2;
        mi = NULL;
        MyFree(av);
        continue;
      }

      if (!(nickptr = FindNick(av[0])))
      {
        fatal(1, "%s:%d Memo entry [%s] is not a registered nickname (skipping)",
          MemoServDB,
          cnt,
          av[0]);
        if (ret > 0)
          ret = -1;
        mi = NULL;
        MyFree(av);
        continue;
      }

    #ifdef LINKED_NICKNAMES
      if (nickptr->master)
      {
        /*
         * nickptr is a leaf nickname - they should not have
         * memo entries
         */
        fatal(1, "%s:%d Memo entry [%s] is not a master nickname (skipping)",
          MemoServDB,
          cnt,
          av[0]);
        if (ret > 0)
          ret = (-1);
        mi = NULL;
        MyFree(av);
        continue;
      }
    #endif /* LINKED_NICKNAMES */

      mi = MakeMemoList();
      mi->name = MyStrdup(av[0]);
    }

    MyFree(av);
  } /* while (fgets(line, MAXLINE - 1, fp)) */

  if (mi)
  {
    if (!mi->memos)
    {
      fatal(1, "%s:%d No memos for entry [%s] (skipping)",
        MemoServDB,
        cnt,
        mi->name);
      MyFree(mi->name);
      MyFree(mi);
      if (ret > 0)
        ret = -1;
    }
    else
      AddMemoList(mi);
  }

  fclose (fp);
  return (ret);
} /* ms_loaddata() */
void
UpdateChanModes(struct Luser *lptr, char *who, struct Channel *cptr,
                char *modes)

{
  int add;
  char *tmp, *p;
  register char ch;
  struct Luser *userptr;
#if defined(NICKSERVICES) && defined(CHANNELSERVICES)
  int cs_deoped = 0; /* was chanserv deoped? */
#endif

  char **modeargs; /* arguements to +l/k/o/v modes */
  char tempargs[MAXLINE];
  int argcnt; /* number of arguements */
  int argidx; /* current index in modeargs[] */

#ifndef SAVE_TS
  char sendstr[MAXLINE];
#endif

  if (!cptr)
    return;

  assert(lptr || who);

  if (lptr)
  {
    SendUmode(OPERUMODE_M,
      "*** %s: Mode [%s] by %s!%s@%s",
      cptr->name,
      modes,
      lptr->nick,
      lptr->username,
      lptr->hostname);

    putlog(LOG3,
      "%s: mode change \"%s\" by %s!%s@%s",
      cptr->name,
      modes,
      lptr->nick,
      lptr->username,
      lptr->hostname);
  }
  else
  {
    SendUmode(OPERUMODE_M,
      "*** %s: Mode [%s] by %s",
      cptr->name,
      modes,
      who);

    putlog(LOG3,
      "%s: mode change \"%s\" by %s",
      cptr->name,
      modes,
      who);
  }

  if ((tmp = strchr(modes, ' ')))
    strcpy(tempargs, *(tmp + 1) ? tmp + 1 : "");
  else
    tempargs[0] = '\0';

  argcnt = SplitBuf(tempargs, &modeargs);

  /*
   * This routine parses the given channel modes and keeps
   * the corresponding lists correctly updated - also make
   * sure OperServ and ChanServ remain opped
   */

  add = 0;
  argidx = (-1);

  for (tmp = modes; *tmp; ++tmp)
  {
    ch = *tmp;

    if (IsSpace(ch))
      break;

    switch (ch)
    {
      case ' ':
      case '\n':
      case '\r': break;

      case '-':
      {
        add = 0;
        break;
      }
      case '+':
      {
        add = 1;
        break;
      }

      /*
       * Op/DeOp
       */
      case 'o':
      {
        ++argidx;
        if (argidx >= argcnt)
        {
          /*
           * there are more 'o' flags than there are nicknames,
           * just break
           */
          break;
        }

        if (!(userptr = FindClient(modeargs[argidx])))
          break;

        SetChannelMode(cptr, add, MODE_O, userptr, 0);

        if (add)
        {
        #ifdef STATSERVICES
          if (lptr)
            ++lptr->numops;
        #endif
        } /* if (add) */
        else
        {
          if (userptr == Me.osptr)
          {
            if (!FloodCheck(cptr, lptr, Me.osptr, 0))
            {
	      #ifdef SAVE_TS
                os_part(cptr);
                os_join(cptr);
	      #else
                toserv(":%s MODE %s +o %s\n",
                  n_OperServ,
                  cptr->name,
                  n_OperServ);
	      #endif
            }

            if (!lptr)
            {
              putlog(LOG1, "%s: %s attempted to deop %s",
                cptr->name,
                who,
                n_OperServ);
            }
            else
            {
              putlog(LOG1, "%s: %s!%s@%s attempted to deop %s",
                cptr->name,
                lptr->nick,
                lptr->username,
                lptr->hostname,
                n_OperServ);
            }
          }
        #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
          else if (userptr == Me.csptr)
          {
            cs_deoped = 1;
          }
        #endif /* defined(NICKSERVICES) && defined(CHANNELSERVICES) */

        #ifdef STATSERVICES
          if (lptr)
            ++lptr->numdops;
        #endif
        } /* else if (!add) */

        #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
          cs_CheckModes(lptr,
            FindChan(cptr->name),
            !add,
            MODE_O,
            userptr);
        #endif

        break;
      } /* case 'o' */

      /*
       * Voice/DeVoice
       */
      case 'v':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

        if (!(userptr = FindClient(modeargs[argidx])))
          break;

        SetChannelMode(cptr, add, MODE_V, userptr, 0);

        if (add)
        {
        #ifdef STATSERVICES
          if (lptr)
            ++lptr->numvoices;
        #endif
        }
        else
        {
        #ifdef STATSERVICES
          if (lptr)
            ++lptr->numdvoices;
        #endif
        } /* else if (!add) */

      #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        cs_CheckModes(lptr,
          FindChan(cptr->name),
          !add,
          MODE_V,
          userptr);
      #endif

        break;
      } /* case 'v' */

#ifdef HYBRID7
      /* HalfOp/DeHalfOp -Janos */
      case 'h':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

        if (!(userptr = FindClient(modeargs[argidx])))
          break;

        SetChannelMode(cptr, add, MODE_H, userptr, 0);

        if (add)
        {
#ifdef STATSERVICES
          if (lptr)
            ++lptr->numhops;
#endif
        }
        else
        {
#ifdef STATSERVICES
          if (lptr)
            ++lptr->numdhops;
#endif
        } /* else if (!add) */

#if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_H, userptr);
#endif
        break;
      } /* case 'h'*/
#endif /* HYBRID7 */

      /*
       * Channel limit
       */
      case 'l':
      {
        if (add)
        {
          ++argidx;
          if (argidx >= argcnt)
            break;

          cptr->limit = atoi(modeargs[argidx]);
        }
        else
          cptr->limit = 0;

      #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        cs_CheckModes(lptr,
          FindChan(cptr->name),
          !add,
          MODE_L,
          0);
      #endif

        break;
      } /* case 'l' */

      /*
       * Channel key
       */
      case 'k':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

      #ifndef BLOCK_ALLOCATION
        if (cptr->key)
          MyFree(cptr->key);
      #endif

        if (add)
        {
        #ifdef BLOCK_ALLOCATION
          strncpy(cptr->key, modeargs[argidx], KEYLEN);
          cptr->key[KEYLEN] = '\0';
        #else
          cptr->key = MyStrdup(modeargs[argidx]);
        #endif /* BLOCK_ALLOCATION */
        }
        else
        {
        #ifdef BLOCK_ALLOCATION
          cptr->key[0] = '\0';
        #else
          cptr->key = 0;
        #endif /* BLOCK_ALLOCATION */
        }

      #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        cs_CheckModes(lptr,
          FindChan(cptr->name),
          !add,
          MODE_K,
          0);
      #endif

        break;
      } /* case 'k' */

      /*
       * Channel forwarding target
       */
      case 'f':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

      #ifndef BLOCK_ALLOCATION
        if (cptr->forward)
          MyFree(cptr->forward);
      #endif

        if (add)
        {
        #ifdef BLOCK_ALLOCATION
          strncpy(cptr->forward, modeargs[argidx], CHANNELLEN);
          cptr->forward[CHANNELLEN] = '\0';
        #else
          cptr->forward = MyStrdup(modeargs[argidx]);
        #endif /* BLOCK_ALLOCATION */
        }
        else
        {
        #ifdef BLOCK_ALLOCATION
          cptr->forward[0] = '\0';
        #else
          cptr->forward = 0;
        #endif /* BLOCK_ALLOCATION */
        }

      #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        cs_CheckModes(lptr,
          FindChan(cptr->name),
          !add,
          MODE_F,
          0);
      #endif

        break;
      } /* case 'f' */

      /*
       * Channel ban
       */
      case 'b':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

	/* if it's a forwarding ban like nick!ident@host!#channel
	 * just drop the forward channel
	 * found by CheeToS  -- jilles */
	p = strchr(modeargs[argidx], '!');
	if (p != NULL)
	{
	  p = strchr(p + 1, '!');
	  if (p != NULL)
	    *p = '\0';
	}

        if (add)
          AddBan(who, cptr, modeargs[argidx]);
        else
          DeleteBan(cptr, modeargs[argidx]);

	if (p != NULL)
	  *p = '!';

        break;
      } /* case 'b' */

#ifdef GECOSBANS
      /*
       * Channel deny
       */
      case 'd':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

        if (add)
          AddGecosBan(who, cptr, modeargs[argidx]);
        else
          DeleteGecosBan(cptr, modeargs[argidx]);

        break;
      } /* case 'd' */
#endif /* GECOSBANS */

      /*
       * Channel exception
       */
      case 'e':
      {
        ++argidx;
        if (argidx >= argcnt)
          break;

        if (add)
          AddException(who, cptr, modeargs[argidx]);
        else
          DeleteException(cptr, modeargs[argidx]);

        break;
      } /* case 'e' */

#ifdef HYBRID7
    /* Channel invite exception -Janos */
     case 'I':
     {
       ++argidx;
       if (argidx >= argcnt)
         break;

       if (add)
         AddInviteException(who, cptr, modeargs[argidx]);
       else
         DeleteInviteException(cptr, modeargs[argidx]);
       break;
     } /* case 'I' */
#endif /* HYBRID7 */

      default:
      {
        int modeflag = 0;

        if (ch == 's')
          modeflag = MODE_S;
        else if (ch == 'p')
          modeflag = MODE_P;
        else if (ch == 'n')
          modeflag = MODE_N;
        else if (ch == 't')
          modeflag = MODE_T;
        else if (ch == 'm')
          modeflag = MODE_M;
        else if (ch == 'i')
          modeflag = MODE_I;
        else if (ch == 'r')
          modeflag = MODE_R;
        else if (ch == 'z')
          modeflag = MODE_Z;
        else if (ch == 'P')
          modeflag = MODE_CAPP;
#if 0
        /* doesn't exist in 1.0.34 */
        else if (ch == 'F')
          modeflag = MODE_CAPF;
#endif
        else if (ch == 'Q')
          modeflag = MODE_CAPQ;
#ifdef HYBRID7
        else if (ch == 'a')
          modeflag = MODE_A;
#endif 
        else if (ch == 'c')
          modeflag = MODE_C;
        else if (ch == 'g')
          modeflag = MODE_G;
        else if (ch == 'L')
          modeflag = MODE_CAPL;
        else if (ch == 'R')
          modeflag = MODE_CAPR;

        if (modeflag)
        {
          if (add)
            cptr->modes |= modeflag;
          else
            cptr->modes &= ~modeflag;
        }

      #if defined(NICKSERVICES) && defined(CHANNELSERVICES)
        if (modeflag)
          cs_CheckModes(lptr,
            FindChan(cptr->name),
            !add,
            modeflag,
            0);
      #endif

        break;
      } /* default: */
    } /* switch (*tmp) */
  } /* for (tmp = modes; *tmp; ++tmp) */

  MyFree(modeargs);

#if defined(NICKSERVICES) && defined(CHANNELSERVICES)
  if ((cs_deoped) && (!FloodCheck(cptr, lptr, Me.csptr, 0)))
  {
    /* reop ChanServ */
    #ifdef SAVE_TS
      cs_part(cptr);
      cs_join(FindChan(cptr->name));
    #else
      toserv(":%s MODE %s +o %s\n",
        n_ChanServ,
        cptr->name,
        n_ChanServ);
    #endif

    if (!lptr)
      putlog(LOG1, "%s: %s attempted to deop %s",
        cptr->name,
        who,
        n_ChanServ);
    else
      putlog(LOG1, "%s: %s!%s@%s attempted to deop %s",
        cptr->name,
        lptr->nick,
        lptr->username,
        lptr->hostname,
        n_ChanServ);
  }
#endif /* defined(NICKSERVICES) && defined(CHANNELSERVICES) */

} /* UpdateChanModes() */
struct Channel *
AddChannel(char **line, int nickcnt, char **nicks)

{
  char *names;
  char **anames;
  char *currnick;
  char modes[MAXLINE];
  struct Channel *chname, *cptr;
  struct Channel *tempchan;
  int ii, ncnt, acnt;

  ncnt = 5; /* default position for channel nicks, if no limit/key */
  strcpy(modes, line[4]);
  while (line[ncnt][0] != ':')
    {
      strcat(modes, " ");
      strcat(modes, line[ncnt]);
      ncnt++;
    }

  if (nickcnt > 0)
  {
    acnt = nickcnt;
    anames = nicks;
  }
  else
  {
    names = line[ncnt];
    names++; /* point past the leading : */

    ii = strlen(names);

    /* kill the \n char on the end */
    if (IsSpace(names[ii - 2]))
      names[ii - 2] = '\0';
    else if (IsSpace(names[ii - 1]))
      names[ii - 1] = '\0';

    acnt = SplitBuf(names, &anames);
  }

  if (!(cptr = FindChannel(line[3])))
  {
  #ifdef BLOCK_ALLOCATION

    tempchan = (struct Channel *) BlockSubAllocate(ChannelHeap);
    memset(tempchan, 0, sizeof(struct Channel));
    strncpy(tempchan->name, line[3], CHANNELLEN);

  #else

    tempchan = (struct Channel *) MyMalloc(sizeof(struct Channel));
    memset(tempchan, 0, sizeof(struct Channel));
    tempchan->name = MyStrdup(line[3]);

  #endif /* BLOCK_ALLOCATION */

    tempchan->since = atol(line[2]);
    tempchan->numusers = acnt;

    tempchan->next = ChannelList;
    tempchan->prev = NULL;
    if (tempchan->next)
      tempchan->next->prev = tempchan;

    HashAddChan(tempchan);

    ChannelList = tempchan;
    chname = ChannelList;

    ++Network->TotalChannels;
  #ifdef STATSERVICES
    if (Network->TotalChannels > Network->MaxChannels)
    {
      Network->MaxChannels = Network->TotalChannels;
      Network->MaxChannels_ts = current_ts;

      if ((Network->MaxChannels % 10) == 0)
      {
        /* notify +y people about new max channel count */
        SendUmode(OPERUMODE_Y,
          "*** New Max Channel Count: %ld",
          Network->MaxChannels);
      }
    }
    if (Network->TotalChannels > Network->MaxChannelsT)
    {
      Network->MaxChannelsT = Network->TotalChannels;
      Network->MaxChannelsT_ts = current_ts;
    }
  #endif /* STATSERVICES */
  }
  else /* it's an existing channel, but someone has joined it */
  {
    cptr->numusers += acnt;
    chname = cptr;
  }

  /* Add the channel to each nick's channel list */
  for (ii = 0; ii < acnt; ii++)
  {
    currnick = GetNick(anames[ii]);
    if (!currnick)
      continue;

    if (!IsChannelMember(chname, FindClient(currnick)))
    {
      /*
       * Use anames[ii] instead of currnick here so we get
       * the @/+ flags
       */
      AddToChannel(chname, anames[ii]);
    }
    else
      chname->numusers--;
  }
  
  /* finally, add the modes for the channel */
  UpdateChanModes(0, line[0] + 1, chname, modes);

  /*
   * Only free anames[] if there was no nick list
   * given
   */
  if (!nickcnt)
    MyFree(anames);

  return (chname);
} /* AddChannel() */
/*
 * es_loaddata()
 *
 * Load Seen database - return 1 if successful, -1 if not, and -2 if the
 * errors are unrecoverable
 */
int es_loaddata()
{
    FILE *fp;
    char line[MAXLINE], **av;
    char *keyword;
    int ac, ret = 1, cnt, type = 0;
    aSeen *seen;

    if ((fp = fopen(SeenServDB, "r")) == NULL)
    {
        /* SeenServ data file doesn't exist */
        return ( -1);
    }

    FreeSeen();
    cnt = 0;
    /* load data into list */
    while (fgets(line, MAXLINE - 1, fp))
    {
        cnt++;
        ac = SplitBuf(line, &av);
        if (!ac)
        {
            /* probably a blank line */
            MyFree(av);
            continue;
        }

        if (av[0][0] == ';')
        {
            MyFree(av);
            continue;
        }

        if (!ircncmp("->", av[0], 2))
        {
            /*
             * check if there are enough args
             */
            if (ac < 4)
            {
                fatal(1, "%s:%d Invalid database format (FATAL)", SeenServDB,
                      cnt);
                ret = -2;
                MyFree(av);
                continue;
            }

            keyword = av[0] + 2;
            type = 0;
            if (!ircncmp(keyword, "QUIT", 4))
            {
                type = 1;
            }
            else if (!ircncmp(keyword, "NICK", 4))
            {
                type = 2;
            }
            if (type)
            {
                seen = MyMalloc(sizeof(aSeen));
                memset(seen, 0, sizeof(aSeen));
                strncpy(seen->nick, av[1], NICKLEN);
                seen->userhost = MyStrdup(av[2]);
                seen->msg = (type == 1) ? MyStrdup(av[4] + 1) : NULL;
                seen->time = atol(av[3]);
                seen->type = type;
                seen->prev = seenp;
                seen->next = NULL;
                if (seenp)
                    seenp->next = seen;
                seenp = seen;
                if (!seenb)
                    seenb = seen;
                ++seenc;
            }
        }

        MyFree(av);
    } /* while */

    fclose(fp);

    return (ret);
} /* es_loaddata */