aboutsummaryrefslogtreecommitdiff
path: root/common/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/parse.c')
-rw-r--r--common/parse.c786
1 files changed, 786 insertions, 0 deletions
diff --git a/common/parse.c b/common/parse.c
new file mode 100644
index 0000000..9bb496c
--- /dev/null
+++ b/common/parse.c
@@ -0,0 +1,786 @@
+/************************************************************************
+ * IRC - Internet Relay Chat, common/parse.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char rcsid[] = "@(#)$Id: parse.c,v 1.25 1999/04/14 17:29:36 kalt Exp $";
+#endif
+
+#include "os.h"
+#ifndef CLIENT_COMPILE
+# include "s_defines.h"
+#else
+# include "c_defines.h"
+#endif
+#define PARSE_C
+#ifndef CLIENT_COMPILE
+# include "s_externs.h"
+#else
+# include "c_externs.h"
+#endif
+#undef PARSE_C
+
+struct Message msgtab[] = {
+ { MSG_PRIVATE, m_private, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+#ifndef CLIENT_COMPILE
+ { MSG_NJOIN, m_njoin, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+#endif
+ { MSG_JOIN, m_join, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_MODE, m_mode, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_NICK, m_nick, MAXPARA, MSG_LAG, 0, 0, 0L},
+ { MSG_PART, m_part, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_QUIT, m_quit, MAXPARA, MSG_LAG, 0, 0, 0L},
+ { MSG_NOTICE, m_notice, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_KICK, m_kick, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_SERVER, m_server, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+#ifndef CLIENT_COMPILE
+ { MSG_TRACE, m_trace, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+#endif
+ { MSG_TOPIC, m_topic, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_INVITE, m_invite, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_WALLOPS, m_wallops, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L},
+ { MSG_PING, m_ping, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_PONG, m_pong, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_ERROR, m_error, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L},
+#ifdef OPER_KILL
+ { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L},
+#else
+ { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L},
+#endif
+#ifndef CLIENT_COMPILE
+ { MSG_USER, m_user, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+ { MSG_AWAY, m_away, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_UMODE, m_umode, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_ISON, m_ison, 1, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_SQUIT, m_squit, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L},
+ { MSG_WHOIS, m_whois, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_WHO, m_who, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_WHOWAS, m_whowas, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_LIST, m_list, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_NAMES, m_names, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_USERHOST,m_userhost, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_PASS, m_pass, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+ { MSG_LUSERS, m_lusers, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_TIME, m_time, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_OPER, m_oper, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_CONNECT, m_connect, MAXPARA,
+ MSG_LAG|MSG_REGU|MSG_OP|MSG_LOP, 0, 0, 0L},
+ { MSG_VERSION, m_version, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_STATS, m_stats, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_LINKS, m_links, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_ADMIN, m_admin, MAXPARA, MSG_LAG, 0, 0, 0L},
+ { MSG_USERS, m_users, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_SUMMON, m_summon, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_HELP, m_help, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_INFO, m_info, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_MOTD, m_motd, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_CLOSE, m_close, MAXPARA, MSG_LAG|MSG_REGU|MSG_OP, 0, 0, 0L},
+ { MSG_RECONECT,m_reconnect,MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+ { MSG_SERVICE, m_service, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L},
+#ifdef USE_SERVICES
+ { MSG_SERVSET, m_servset, MAXPARA, MSG_LAG|MSG_SVC, 0, 0, 0L},
+#endif
+ { MSG_SQUERY, m_squery, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L},
+ { MSG_SERVLIST,m_servlist, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_HASH, m_hash, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+ { MSG_DNS, m_dns, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L},
+#ifdef OPER_REHASH
+ { MSG_REHASH, m_rehash, MAXPARA, MSG_REGU|MSG_OP
+# ifdef LOCOP_REHASH
+ |MSG_LOP
+# endif
+ , 0, 0, 0L},
+#endif
+#ifdef OPER_RESTART
+ { MSG_RESTART, m_restart, MAXPARA, MSG_REGU|MSG_OP
+# ifdef LOCOP_RESTART
+ |MSG_LOP
+# endif
+ , 0, 0, 0L},
+#endif
+#ifdef OPER_DIE
+ { MSG_DIE, m_die, MAXPARA, MSG_REGU|MSG_OP
+# ifdef LOCOP_DIE
+ |MSG_LOP
+# endif
+ , 0, 0, 0L},
+#endif
+#endif /* !CLIENT_COMPILE */
+ { (char *) 0, (int (*)()) 0, 0, 0, 0, 0, 0L}
+};
+
+/*
+ * NOTE: parse() should not be called recursively by other functions!
+ */
+static char *para[MAXPARA+1];
+
+#ifdef CLIENT_COMPILE
+static char sender[NICKLEN+USERLEN+HOSTLEN+3];
+char userhost[USERLEN+HOSTLEN+2];
+#define timeofday time(NULL)
+#else
+static char sender[HOSTLEN+1];
+static int cancel_clients __P((aClient *, aClient *, char *));
+static void remove_unknown __P((aClient *, char *));
+#endif
+
+/*
+** Find a client (server or user) by name.
+**
+** *Note*
+** Semantics of this function has been changed from
+** the old. 'name' is now assumed to be a null terminated
+** string and the search is the for server and user.
+*/
+#ifndef CLIENT_COMPILE
+aClient *find_client(name, cptr)
+char *name;
+Reg aClient *cptr;
+ {
+ aClient *acptr = cptr;
+
+ if (name && *name)
+ acptr = hash_find_client(name, cptr);
+
+ return acptr;
+ }
+
+aClient *find_service(name, cptr)
+char *name;
+Reg aClient *cptr;
+ {
+ aClient *acptr = cptr;
+
+ if (index(name, '@'))
+ acptr = hash_find_client(name, cptr);
+ return acptr;
+ }
+
+#else /* CLIENT_COMPILE */
+
+aClient *find_client(name, cptr)
+char *name;
+aClient *cptr;
+ {
+ Reg aClient *c2ptr = cptr;
+
+ if (!name || !*name)
+ return c2ptr;
+
+ for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
+ if (mycmp(name, c2ptr->name) == 0)
+ return c2ptr;
+ return cptr;
+ }
+#endif /* CLIENT_COMPILE */
+
+/*
+** Find a user@host (server or user).
+**
+** *Note*
+** Semantics of this function has been changed from
+** the old. 'name' is now assumed to be a null terminated
+** string and the search is the for server and user.
+*/
+aClient *find_userhost(user, host, cptr, count)
+char *user, *host;
+aClient *cptr;
+int *count;
+ {
+ Reg aClient *c2ptr;
+ Reg aClient *res = cptr;
+
+ *count = 0;
+ if (user)
+ for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
+ {
+ if (!MyClient(c2ptr)) /* implies mine and a user */
+ continue;
+ if ((!host || !match(host, c2ptr->user->host)) &&
+ mycmp(user, c2ptr->user->username) == 0)
+ {
+ (*count)++;
+ res = c2ptr;
+ }
+ }
+ return res;
+ }
+
+/*
+** Find server by name.
+**
+** This implementation assumes that server and user names
+** are unique, no user can have a server name and vice versa.
+** One should maintain separate lists for users and servers,
+** if this restriction is removed.
+**
+** *Note*
+** Semantics of this function has been changed from
+** the old. 'name' is now assumed to be a null terminated
+** string.
+*/
+#ifndef CLIENT_COMPILE
+/*
+** Find a server from hash table, given its name
+*/
+aClient *find_server(name, cptr)
+char *name;
+Reg aClient *cptr;
+{
+ aClient *acptr = cptr;
+
+ if (name && *name)
+ acptr = hash_find_server(name, cptr);
+ return acptr;
+}
+
+/*
+** Given a server name, find the server mask behind which the server
+** is hidden.
+*/
+aClient *find_mask(name, cptr)
+char *name;
+aClient *cptr;
+{
+ static char servermask[HOSTLEN+1];
+ Reg aClient *c2ptr = cptr;
+ Reg char *mask = servermask;
+
+ if (!name || !*name)
+ return c2ptr;
+ if ((c2ptr = hash_find_server(name, cptr)))
+ return (c2ptr);
+ if (index(name, '*'))
+ return c2ptr;
+ strcpy (servermask, name);
+ while (*mask)
+ {
+ if (*(mask+1) == '.')
+ {
+ *mask = '*';
+ if ((c2ptr = hash_find_server(mask, cptr)))
+ return (c2ptr);
+ }
+ mask++;
+ }
+ return (c2ptr ? c2ptr : cptr);
+}
+
+/*
+** Find a server from hash table, given its token
+*/
+aServer *find_tokserver(token, cptr, c2ptr)
+int token;
+aClient *cptr, *c2ptr;
+{
+ return hash_find_stoken(token, cptr, c2ptr);
+}
+
+/*
+** Find a server, given its name (which might contain *'s, in which case
+** the first match will be return [not the best one])
+*/
+aClient *find_name(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg aClient *c2ptr = cptr;
+ Reg aServer *sp = NULL;
+
+ if (!name || !*name)
+ return c2ptr;
+
+ if ((c2ptr = hash_find_server(name, cptr)))
+ return (c2ptr);
+ if (!index(name, '*'))
+ return c2ptr;
+ for (sp = svrtop; sp; sp = sp->nexts)
+ {
+ /*
+ ** A server present in the list necessarily has a non NULL
+ ** bcptr pointer.
+ */
+ if (match(name, sp->bcptr->name) == 0)
+ break;
+ if (index(sp->bcptr->name, '*'))
+ if (match(sp->bcptr->name, name) == 0)
+ break;
+ }
+ return (sp ? sp->bcptr : cptr);
+}
+#else
+aClient *find_server(name, cptr)
+char *name;
+aClient *cptr;
+{
+ Reg aClient *c2ptr = cptr;
+
+ if (!name || !*name)
+ return c2ptr;
+
+ for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
+ {
+ if (!IsServer(c2ptr) && !IsMe(c2ptr))
+ continue;
+ if (match(c2ptr->name, name) == 0 ||
+ match(name, c2ptr->name) == 0)
+ break;
+ }
+ return (c2ptr ? c2ptr : cptr);
+}
+#endif /* CLIENT_COMPILE */
+
+/*
+** Find person by (nick)name.
+*/
+aClient *find_person(name, cptr)
+char *name;
+aClient *cptr;
+ {
+ Reg aClient *c2ptr = cptr;
+
+ c2ptr = find_client(name, c2ptr);
+
+ if (c2ptr && IsClient(c2ptr) && c2ptr->user)
+ return c2ptr;
+ else
+ return cptr;
+ }
+
+/*
+ * parse a buffer.
+ * Return values:
+ * errors: -3 for unknown origin/sender, -2 for FLUSH_BUFFER, -1 for bad cptr
+ *
+ * NOTE: parse() should not be called recusively by any other fucntions!
+ */
+int parse(cptr, buffer, bufend)
+aClient *cptr;
+char *buffer, *bufend;
+ {
+ Reg aClient *from = cptr;
+ Reg char *ch, *s;
+ Reg int len, i, numeric = 0, paramcount;
+ Reg struct Message *mptr = NULL;
+ int ret;
+
+#ifndef CLIENT_COMPILE
+ Debug((DEBUG_DEBUG, "Parsing %s: %s",
+ get_client_name(cptr, FALSE), buffer));
+ if (IsDead(cptr))
+ return -1;
+#endif
+
+ s = sender;
+ *s = '\0';
+ for (ch = buffer; *ch == ' '; ch++)
+ ;
+ para[0] = from->name;
+ if (*ch == ':')
+ {
+ /*
+ ** Copy the prefix to 'sender' assuming it terminates
+ ** with SPACE (or NULL, which is an error, though).
+ */
+ for (++ch, i = 0; *ch && *ch != ' '; ++ch )
+ if (s < (sender + sizeof(sender)-1))
+ *s++ = *ch; /* leave room for NULL */
+ *s = '\0';
+#ifdef CLIENT_COMPILE
+ if ((s = index(sender, '!')))
+ {
+ *s++ = '\0';
+ strncpyzt(userhost, s, sizeof(userhost));
+ }
+ else if ((s = index(sender, '@')))
+ {
+ *s++ = '\0';
+ strncpyzt(userhost, s, sizeof(userhost));
+ }
+#endif
+ /*
+ ** Actually, only messages coming from servers can have
+ ** the prefix--prefix silently ignored, if coming from
+ ** a user client...
+ **
+ ** ...sigh, the current release "v2.2PL1" generates also
+ ** null prefixes, at least to NOTIFY messages (e.g. it
+ ** puts "sptr->nickname" as prefix from server structures
+ ** where it's null--the following will handle this case
+ ** as "no prefix" at all --msa (": NOTICE nick ...")
+ */
+ if (*sender && IsServer(cptr))
+ {
+ from = find_client(sender, (aClient *) NULL);
+ if (!from ||
+ /*
+ ** I really believe that the followin line is
+ ** useless. What a waste, especially with 2.9
+ ** hostmasks.. at least the test on from->name
+ ** will make it a bit better. -krys
+ */
+ (*from->name == '*' && match(from->name, sender)))
+ from = find_server(sender, (aClient *)NULL);
+#ifndef CLIENT_COMPILE
+ /* Is there svc@server prefix ever? -Vesa */
+ /* every time a service talks -krys */
+ if (!from && index(sender, '@'))
+ from = find_service(sender, (aClient *)NULL);
+ if (!from)
+ from = find_mask(sender, (aClient *) NULL);
+#endif
+
+ para[0] = sender;
+
+ /* Hmm! If the client corresponding to the
+ * prefix is not found--what is the correct
+ * action??? Now, I will ignore the message
+ * (old IRC just let it through as if the
+ * prefix just wasn't there...) --msa
+ * Since 2.9 we pick them up and .. --Vesa
+ */
+ if (!from)
+ {
+ Debug((DEBUG_ERROR,
+ "Unknown prefix (%s)(%s) from (%s)",
+ sender, buffer, cptr->name));
+ ircstp->is_unpf++;
+#ifndef CLIENT_COMPILE
+ remove_unknown(cptr, sender);
+#endif
+ return -3; /* Grab it in read_message() */
+ }
+ if (from->from != cptr)
+ {
+ ircstp->is_wrdi++;
+ Debug((DEBUG_ERROR,
+ "Message (%s) coming from (%s)",
+ buffer, cptr->name));
+#ifndef CLIENT_COMPILE
+ return cancel_clients(cptr, from, buffer);
+#else
+ return -1;
+#endif
+ }
+ }
+ while (*ch == ' ')
+ ch++;
+ }
+ if (*ch == '\0')
+ {
+ ircstp->is_empt++;
+ Debug((DEBUG_NOTICE, "Empty message from host %s:%s",
+ cptr->name, from->name));
+ return -1;
+ }
+ /*
+ ** Extract the command code from the packet. Point s to the end
+ ** of the command code and calculate the length using pointer
+ ** arithmetic. Note: only need length for numerics and *all*
+ ** numerics must have paramters and thus a space after the command
+ ** code. -avalon
+ */
+ s = (char *)index(ch, ' '); /* s -> End of the command code */
+ len = (s) ? (s - ch) : 0;
+ if (len == 3 &&
+ isdigit(*ch) && isdigit(*(ch + 1)) && isdigit(*(ch + 2)))
+ {
+ numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10
+ + (*(ch + 2) - '0');
+ paramcount = MAXPARA;
+ ircstp->is_num++;
+ }
+ else
+ {
+ if (s)
+ *s++ = '\0';
+ for (mptr = msgtab; mptr->cmd; mptr++)
+ if (mycmp(mptr->cmd, ch) == 0)
+ break;
+
+ if (!mptr->cmd)
+ {
+ /*
+ ** Note: Give error message *only* to recognized
+ ** persons. It's a nightmare situation to have
+ ** two programs sending "Unknown command"'s or
+ ** equivalent to each other at full blast....
+ ** If it has got to person state, it at least
+ ** seems to be well behaving. Perhaps this message
+ ** should never be generated, though... --msa
+ ** Hm, when is the buffer empty -- if a command
+ ** code has been found ?? -Armin
+ */
+ if (buffer[0] != '\0')
+ {
+ cptr->flags |= FLAGS_UNKCMD;
+ if (IsPerson(from))
+ sendto_one(from,
+ ":%s %d %s %s :Unknown command",
+ me.name, ERR_UNKNOWNCOMMAND,
+ from->name, ch);
+#ifdef CLIENT_COMPILE
+ Debug((DEBUG_ERROR,"Unknown (%s) from %s[%s]",
+ ch, cptr->name, cptr->sockhost));
+#else
+ else if (IsServer(cptr))
+ sendto_flag(SCH_ERROR,
+ "Unknown command from %s:%s",
+ get_client_name(cptr, TRUE), ch);
+ Debug((DEBUG_ERROR,"Unknown (%s) from %s",
+ ch, get_client_name(cptr, TRUE)));
+#endif
+ }
+ ircstp->is_unco++;
+ return -1;
+ }
+ paramcount = mptr->parameters;
+ i = bufend - ((s) ? s : ch);
+ mptr->bytes += i;
+#ifndef CLIENT_COMPILE
+ if ((mptr->flags & MSG_LAG) &&
+ !(IsServer(cptr) || IsService(cptr)))
+ { /* Flood control partly migrated into penalty */
+ if (bootopt & BOOT_PROT)
+ cptr->since += (1 + i / 100);
+ else
+ cptr->since = timeofday;
+ /* Allow only 1 msg per 2 seconds
+ * (on average) to prevent dumping.
+ * to keep the response rate up,
+ * bursts of up to 5 msgs are allowed
+ * -SRB
+ */
+ }
+#endif
+ }
+ /*
+ ** Must the following loop really be so devious? On
+ ** surface it splits the message to parameters from
+ ** blank spaces. But, if paramcount has been reached,
+ ** the rest of the message goes into this last parameter
+ ** (about same effect as ":" has...) --msa
+ */
+
+ /* Note initially true: s==NULL || *(s-1) == '\0' !! */
+
+#ifdef CLIENT_COMPILE
+ if (me.user)
+ para[0] = sender;
+#endif
+ i = 0;
+ if (s)
+ {
+ if (paramcount > MAXPARA)
+ paramcount = MAXPARA;
+ for (;;)
+ {
+ /*
+ ** Never "FRANCE " again!! ;-) Clean
+ ** out *all* blanks.. --msa
+ */
+ while (*s == ' ')
+ *s++ = '\0';
+
+ if (*s == '\0')
+ break;
+ if (*s == ':')
+ {
+ /*
+ ** The rest is single parameter--can
+ ** include blanks also.
+ */
+ para[++i] = s + 1;
+ break;
+ }
+ para[++i] = s;
+ if (i >= paramcount-1)
+ break;
+ for (; *s != ' ' && *s; s++)
+ ;
+ }
+ }
+ para[++i] = NULL; /* at worst, ++i is paramcount (MAXPARA) */
+ if (mptr == NULL)
+ return (do_numeric(numeric, cptr, from, i, para));
+ mptr->count++;
+ if (!MyConnect(from))
+ mptr->rcount++;
+ if (IsRegisteredUser(cptr) &&
+#ifdef IDLE_FROM_MSG
+ mptr->func == m_private)
+#else
+ mptr->func != m_ping && mptr->func != m_pong)
+#endif
+ from->user->last = timeofday;
+ Debug((DEBUG_DEBUG, "Function: %#x = %s parc %d parv %#x",
+ mptr->func, mptr->cmd, i, para));
+#ifndef CLIENT_COMPILE
+ if ((mptr->flags & MSG_REGU) && check_registered_user(from))
+ return -1;
+ if ((mptr->flags & MSG_SVC) && check_registered_service(from))
+ return -1;
+ if ((mptr->flags & MSG_REG) && check_registered(from))
+ return -1;
+ if ((mptr->flags & MSG_NOU) && (MyPerson(from) || MyService(from)))
+ {
+ sendto_one(from, err_str(ERR_ALREADYREGISTRED, para[0]));
+ return-1;
+ }
+ if (MyConnect(from) && !IsServer(from) &&
+ (mptr->flags & (MSG_LOP|MSG_OP)) &&
+ !((mptr->flags & MSG_OP) && (IsOper(from))) &&
+ !((mptr->flags & MSG_LOP) && (IsLocOp(from))))
+ {
+ sendto_one(from, err_str(ERR_NOPRIVILEGES, para[0]));
+ return -1;
+ }
+#endif
+ /*
+ ** ALL m_functions return now UNIFORMLY:
+ ** -2 old FLUSH_BUFFER return value (unchanged).
+ ** -1 if parsing of a protocol message leads in a syntactic/semantic
+ ** error and NO penalty scoring should be applied.
+ ** >=0 if protocol message processing was successful. The return
+ ** value indicates the penalty score.
+ */
+ ret = (*mptr->func)(cptr, from, i, para);
+
+#ifndef CLIENT_COMPILE
+ /*
+ ** Add penalty score for sucessfully parsed command if issued by
+ ** a LOCAL user client.
+ */
+ if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT))
+ {
+ cptr->since += ret;
+/* only to lurk
+ sendto_one(cptr,
+ ":%s NOTICE %s :*** Penalty INCR [%s] +%d",
+ me.name, cptr->name, ch, ret);
+*/
+ }
+#endif
+ return (ret != FLUSH_BUFFER) ? 2 : FLUSH_BUFFER;
+}
+
+/*
+ * field breakup for ircd.conf file.
+ */
+char *getfield(irc_newline)
+char *irc_newline;
+{
+ static char *line = NULL;
+ char *end, *field;
+
+ if (irc_newline)
+ line = irc_newline;
+ if (line == NULL)
+ return(NULL);
+
+ field = line;
+ if ((end = (char *)index(line, IRCDCONF_DELIMITER)) == NULL)
+ {
+ line = NULL;
+ if ((end = (char *)index(field,'\n')) == NULL)
+ end = field + strlen(field);
+ }
+ else
+ line = end + 1;
+ *end = '\0';
+ return(field);
+}
+
+#ifndef CLIENT_COMPILE
+static int cancel_clients(cptr, sptr, cmd)
+aClient *cptr, *sptr;
+char *cmd;
+{
+ /*
+ * kill all possible points that are causing confusion here,
+ * I'm not sure I've got this all right...
+ * - avalon
+ */
+ sendto_flag(SCH_NOTICE, "Message (%s) for %s[%s!%s@%s] from %s",
+ cmd, sptr->name, sptr->from->name, sptr->from->username,
+ sptr->from->sockhost, get_client_name(cptr, TRUE));
+ /*
+ * Incorrect prefix for a server from some connection. If it is a
+ * client trying to be annoying, just QUIT them, if it is a server
+ * then the same deal.
+ */
+ if (IsServer(sptr) || IsMe(sptr))
+ {
+ sendto_flag(SCH_NOTICE, "Dropping server %s",cptr->name);
+ return exit_client(cptr, cptr, &me, "Fake Direction");
+ }
+ /*
+ * Ok, someone is trying to impose as a client and things are
+ * confused. If we got the wrong prefix from a server, send out a
+ * kill, else just exit the lame client.
+ */
+ if (IsServer(cptr))
+ {
+ sendto_serv_butone(NULL, ":%s KILL %s :%s (%s[%s] != %s)",
+ me.name, sptr->name, me.name,
+ sptr->name, sptr->from->name,
+ get_client_name(cptr, TRUE));
+ sptr->flags |= FLAGS_KILLED;
+ return exit_client(cptr, sptr, &me, "Fake Prefix");
+ }
+ return exit_client(cptr, cptr, &me, "Fake prefix");
+}
+
+static void remove_unknown(cptr, sender)
+aClient *cptr;
+char *sender;
+{
+ if (!IsRegistered(cptr) || IsClient(cptr))
+ return;
+ /*
+ * Not from a server so don't need to worry about it.
+ */
+ if (!IsServer(cptr))
+ return;
+ /*
+ * squit if it is a server because it means something is really
+ * wrong.
+ */
+ if (index(sender, '.') /* <- buggy, it could be a service! */
+ && !index(sender, '@')) /* better.. */
+ {
+ sendto_flag(SCH_LOCAL, "Squitting unknown %s brought by %s.",
+ sender, get_client_name(cptr, FALSE));
+ sendto_one(cptr, ":%s SQUIT %s :(Unknown from %s)",
+ me.name, sender, get_client_name(cptr, FALSE));
+ }
+ else
+ /*
+ * Do kill if it came from a server because it means there is a ghost
+ * user on the other server which needs to be removed. -avalon
+ * it can simply be caused by lag (among other things), so just
+ * drop it if it is not a server. -krys
+ * services aren't prone to collisions, so lag shouldn't be responsible
+ * if we get here and sender is a service, we should probably issue
+ * a kill in this case! -krys
+ */
+ sendto_flag(SCH_LOCAL, "Dropping unknown %s brought by %s.",
+ sender, get_client_name(cptr, FALSE));
+}
+#endif