This commit was generated by cvs2svn to compensate for changes in r2,
[ircu2.10.12-pk.git] / ircd / s_user.c
1 /*
2  * IRC - Internet Relay Chat, ircd/s_user.c (formerly ircd/s_msg.c)
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 1, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "sys.h"
25 #include <sys/stat.h>
26 #include <utmp.h>
27 #if HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30 #include <stdlib.h>
31 #if HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #ifdef USE_SYSLOG
35 #include <syslog.h>
36 #endif
37 #include "h.h"
38 #include "struct.h"
39 #include "common.h"
40 #include "s_serv.h"
41 #include "numeric.h"
42 #include "send.h"
43 #include "s_conf.h"
44 #include "s_misc.h"
45 #include "match.h"
46 #include "hash.h"
47 #include "s_bsd.h"
48 #include "whowas.h"
49 #include "list.h"
50 #include "s_err.h"
51 #include "parse.h"
52 #include "ircd.h"
53 #include "s_user.h"
54 #include "support.h"
55 #include "s_user.h"
56 #include "channel.h"
57 #include "random.h"
58 #include "version.h"
59 #include "msg.h"
60 #include "userload.h"
61 #include "numnicks.h"
62 #include "sprintf_irc.h"
63 #include "querycmds.h"
64 #include "IPcheck.h"
65 #include "class.h"
66
67 RCSTAG_CC("$Id$");
68
69 /* *INDENT-OFF* */
70
71 /* This is not ANSI, but we have it anyway... */
72 __BEGIN_DECLS
73 char *crypt(const char *key, const char *salt);
74 __END_DECLS
75
76 /* *INDENT-ON* */
77
78 static char buf[BUFSIZE], buf2[BUFSIZE];
79
80 /*
81  * m_functions execute protocol messages on this server:
82  *
83  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
84  *            structure (with an open socket connected!). This
85  *            identifies the physical socket where the message
86  *            originated (or which caused the m_function to be
87  *            executed--some m_functions may call others...).
88  *
89  *    sptr    is the source of the message, defined by the
90  *            prefix part of the message if present. If not
91  *            or prefix not found, then sptr==cptr.
92  *
93  *            (!IsServer(cptr)) => (cptr == sptr), because
94  *            prefixes are taken *only* from servers...
95  *
96  *            (IsServer(cptr))
97  *                    (sptr == cptr) => the message didn't
98  *                    have the prefix.
99  *
100  *                    (sptr != cptr && IsServer(sptr) means
101  *                    the prefix specified servername. (?)
102  *
103  *                    (sptr != cptr && !IsServer(sptr) means
104  *                    that message originated from a remote
105  *                    user (not local).
106  *
107  *            combining
108  *
109  *            (!IsServer(sptr)) means that, sptr can safely
110  *            taken as defining the target structure of the
111  *            message in this server.
112  *
113  *    *Always* true (if 'parse' and others are working correct):
114  *
115  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
116  *
117  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
118  *            *cannot* be a local connection, unless it's
119  *            actually cptr!). [MyConnect(x) should probably
120  *            be defined as (x == x->from) --msa ]
121  *
122  *    parc    number of variable parameter strings (if zero,
123  *            parv is allowed to be NULL)
124  *
125  *    parv    a NULL terminated list of parameter pointers,
126  *
127  *                    parv[0], sender (prefix string), if not present
128  *                            this points to an empty string.
129  *                    parv[1]...parv[parc-1]
130  *                            pointers to additional parameters
131  *                    parv[parc] == NULL, *always*
132  *
133  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
134  *                    non-NULL pointers.
135  */
136
137 /*
138  * next_client
139  *
140  * Local function to find the next matching client. The search
141  * can be continued from the specified client entry. Normal
142  * usage loop is:
143  *
144  * for (x = client; x = next_client(x,mask); x = x->next)
145  *     HandleMatchingClient;
146  *
147  */
148 aClient *next_client(aClient *next, char *ch)
149 {
150   Reg3 aClient *tmp = next;
151
152   if (!tmp)
153     return NULL;
154
155   next = FindClient(ch);
156   next = next ? next : tmp;
157   if (tmp->prev == next)
158     return NULL;
159   if (next != tmp)
160     return next;
161   for (; next; next = next->next)
162     if (!match(ch, next->name))
163       break;
164   return next;
165 }
166
167 /*
168  * hunt_server
169  *
170  *    Do the basic thing in delivering the message (command)
171  *    across the relays to the specific server (server) for
172  *    actions.
173  *
174  *    Note:   The command is a format string and *MUST* be
175  *            of prefixed style (e.g. ":%s COMMAND %s ...").
176  *            Command can have only max 8 parameters.
177  *
178  *    server  parv[server] is the parameter identifying the
179  *            target server.
180  *
181  *    *WARNING*
182  *            parv[server] is replaced with the pointer to the
183  *            real servername from the matched client (I'm lazy
184  *            now --msa).
185  *
186  *    returns: (see #defines)
187  */
188 int hunt_server(int MustBeOper, aClient *cptr, aClient *sptr, char *command,
189     int server, int parc, char *parv[])
190 {
191   aClient *acptr;
192   char y[8];
193
194   /* Assume it's me, if no server or an unregistered client */
195   if (parc <= server || BadPtr(parv[server]) || IsUnknown(sptr))
196     return (HUNTED_ISME);
197
198   /* Make sure it's a server */
199   if (MyUser(sptr) || Protocol(cptr) < 10)
200   {
201     /* Make sure it's a server */
202     if (!strchr(parv[server], '*'))
203     {
204       if (0 == (acptr = FindClient(parv[server])))
205         return HUNTED_NOSUCH;
206       if (acptr->user)
207         acptr = acptr->user->server;
208     }
209     else if (!(acptr = find_match_server(parv[server])))
210     {
211       sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
212           me.name, parv[0], parv[server]);
213       return (HUNTED_NOSUCH);
214     }
215   }
216   else if (!(acptr = FindNServer(parv[server])))
217     return (HUNTED_NOSUCH);     /* Server broke off in the meantime */
218
219   if (IsMe(acptr))
220     return (HUNTED_ISME);
221
222   if (MustBeOper && !IsPrivileged(sptr))
223   {
224     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
225     return HUNTED_NOSUCH;
226   }
227
228 #ifdef NO_PROTOCOL9
229   if (MyUser(sptr))
230   {
231     strcpy(y, acptr->yxx);
232     parv[server] = y;
233   }
234 #else
235   if (Protocol(acptr->from) > 9)
236   {
237     strcpy(y, acptr->yxx);
238     parv[server] = y;
239   }
240   else
241     parv[server] = acptr->name;
242 #endif
243
244   sendto_one(acptr, command, parv[0], parv[1], parv[2], parv[3], parv[4],
245       parv[5], parv[6], parv[7], parv[8]);
246
247   return (HUNTED_PASS);
248 }
249
250 /*
251  * 'do_nick_name' ensures that the given parameter (nick) is really a proper
252  * string for a nickname (note, the 'nick' may be modified in the process...)
253  *
254  * RETURNS the length of the final NICKNAME (0, if nickname is invalid)
255  *
256  * Nickname characters are in range 'A'..'}', '_', '-', '0'..'9'
257  *  anything outside the above set will terminate nickname.
258  * In addition, the first character cannot be '-' or a Digit.
259  *
260  * Note:
261  *  The '~'-character should be allowed, but a change should be global,
262  *  some confusion would result if only few servers allowed it...
263  */
264
265 static int do_nick_name(char *nick)
266 {
267   Reg1 char *ch;
268
269   if (*nick == '-' || isDigit(*nick))   /* first character in [0..9-] */
270     return 0;
271
272   for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++)
273     if (!isIrcNk(*ch))
274       break;
275
276   *ch = '\0';
277
278   return (ch - nick);
279 }
280
281 /*
282  * canonize
283  *
284  * reduce a string of duplicate list entries to contain only the unique
285  * items.  Unavoidably O(n^2).
286  */
287 char *canonize(char *buffer)
288 {
289   static char cbuf[BUFSIZ];
290   register char *s, *t, *cp = cbuf;
291   register int l = 0;
292   char *p = NULL, *p2;
293
294   *cp = '\0';
295
296   for (s = strtoken(&p, buffer, ","); s; s = strtoken(&p, NULL, ","))
297   {
298     if (l)
299     {
300       p2 = NULL;
301       for (t = strtoken(&p2, cbuf, ","); t; t = strtoken(&p2, NULL, ","))
302         if (!strCasediff(s, t))
303           break;
304         else if (p2)
305           p2[-1] = ',';
306     }
307     else
308       t = NULL;
309     if (!t)
310     {
311       if (l)
312         *(cp - 1) = ',';
313       else
314         l = 1;
315       strcpy(cp, s);
316       if (p)
317         cp += (p - s);
318     }
319     else if (p2)
320       p2[-1] = ',';
321   }
322   return cbuf;
323 }
324
325 /*
326  * clean_user_id
327  *
328  * Copy `source' to `dest', replacing all occurances of '~' and characters that
329  * are not `isIrcUi' by an underscore.
330  * Copies at most USERLEN - 1 characters or up till the first control character.
331  * If `tilde' is true, then a tilde is prepended to `dest'.
332  * Note that `dest' and `source' can point to the same area or to different
333  * non-overlapping areas.
334  */
335
336 static char *clean_user_id(char *dest, char *source, int tilde)
337 {
338   register char ch;
339   char *d = dest;
340   char *s = source;
341   int rlen = USERLEN;
342
343   ch = *s++;                    /* Store first character to copy: */
344   if (tilde)
345   {
346     *d++ = '~';                 /* If `dest' == `source', then this overwrites `ch' */
347     --rlen;
348   }
349   while (ch && !isCntrl(ch) && rlen--)
350   {
351     register char nch = *s++;   /* Store next character to copy */
352     *d++ = isIrcUi(ch) ? ch : '_';      /* This possibly overwrites it */
353     if (nch == '~')
354       ch = '_';
355     else
356       ch = nch;
357   }
358   *d = 0;
359   return dest;
360 }
361
362 /*
363  * register_user
364  *
365  * This function is called when both NICK and USER messages
366  * have been accepted for the client, in whatever order. Only
367  * after this the USER message is propagated.
368  *
369  * NICK's must be propagated at once when received, although
370  * it would be better to delay them too until full info is
371  * available. Doing it is not so simple though, would have
372  * to implement the following:
373  *
374  * 1) user telnets in and gives only "NICK foobar" and waits
375  * 2) another user far away logs in normally with the nick
376  *    "foobar" (quite legal, as this server didn't propagate it).
377  * 3) now this server gets nick "foobar" from outside, but
378  *    has already the same defined locally. Current server
379  *    would just issue "KILL foobar" to clean out dups. But,
380  *    this is not fair. It should actually request another
381  *    nick from local user or kill him/her...
382  */
383
384 static int register_user(aClient *cptr, aClient *sptr,
385     char *nick, char *username)
386 {
387   Reg1 aConfItem *aconf;
388   char *parv[3], *tmpstr, *tmpstr2;
389   char c = 0 /* not alphanum */ , d = 'a' /* not a digit */ ;
390   short oldstatus_ismaster = IsMaster(sptr), upper = 0, lower = 0;
391   short pos = 0, leadcaps = 0, other = 0, digits = 0, badid = 0;
392   short digitgroups = 0;
393   anUser *user = sptr->user;
394   Dlink *lp;
395   char ip_base64[8];
396
397   user->last = now;
398   parv[0] = sptr->name;
399   parv[1] = parv[2] = NULL;
400
401   if (MyConnect(sptr))
402   {
403     static time_t last_too_many1, last_too_many2;
404     switch (check_client(sptr))
405     {
406       case ACR_OK:
407         break;
408       case ACR_NO_AUTHORIZATION:
409         sendto_op_mask(SNO_UNAUTH, "Unauthorized connection from %s.",
410             get_client_host(sptr));
411         ircstp->is_ref++;
412         return exit_client(cptr, sptr, &me,
413             "No Authorization - use another server");
414       case ACR_TOO_MANY_IN_CLASS:
415         if (now - last_too_many1 >= (time_t) 60)
416         {
417           last_too_many1 = now;
418           sendto_op_mask(SNO_TOOMANY, "Too many connections in class for %s.",
419               get_client_host(sptr));
420         }
421         IPcheck_connect_fail(sptr);
422         ircstp->is_ref++;
423         return exit_client(cptr, sptr, &me,
424             "Sorry, your connection class is full - try again later or try another server");
425       case ACR_TOO_MANY_FROM_IP:
426         if (now - last_too_many2 >= (time_t) 60)
427         {
428           last_too_many2 = now;
429           sendto_op_mask(SNO_TOOMANY,
430               "Too many connections from same IP for %s.",
431               get_client_host(sptr));
432         }
433         ircstp->is_ref++;
434         return exit_client(cptr, sptr, &me,
435             "Too many connections from your host");
436       case ACR_ALREADY_AUTHORIZED:
437         /* Can this ever happen? */
438       case ACR_BAD_SOCKET:
439         IPcheck_connect_fail(sptr);
440         return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
441     }
442     if (IsUnixSocket(sptr))
443       strncpy(user->host, me.sockhost, HOSTLEN);
444     else
445       strncpy(user->host, sptr->sockhost, HOSTLEN);
446     aconf = sptr->confs->value.aconf;
447
448     clean_user_id(user->username,
449         (sptr->flags & FLAGS_GOTID) ? sptr->username : username,
450         (sptr->flags & FLAGS_DOID) && !(sptr->flags & FLAGS_GOTID));
451
452     if ((user->username[0] == '\000')
453         || ((user->username[0] == '~') && (user->username[1] == '\000')))
454       return exit_client(cptr, sptr, &me, "USER: Bogus userid.");
455
456     if (!BadPtr(aconf->passwd)
457         && !(isDigit(*aconf->passwd) && !aconf->passwd[1])
458 #ifdef USEONE
459         && strcmp("ONE", aconf->passwd)
460 #endif
461         && strcmp(sptr->passwd, aconf->passwd))
462     {
463       ircstp->is_ref++;
464       sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
465       IPcheck_connect_fail(sptr);
466       return exit_client(cptr, sptr, &me, "Bad Password");
467     }
468     memset(sptr->passwd, 0, sizeof(sptr->passwd));
469     /*
470      * following block for the benefit of time-dependent K:-lines
471      */
472     if (find_kill(sptr))
473     {
474       ircstp->is_ref++;
475       return exit_client(cptr, sptr, &me, "K-lined");
476     }
477 #ifdef R_LINES
478     if (find_restrict(sptr))
479     {
480       ircstp->is_ref++;
481       return exit_client(cptr, sptr, &me, "R-lined");
482     }
483 #endif
484
485     /*
486      * Check for mixed case usernames, meaning probably hacked.  Jon2 3-94
487      * Summary of rules now implemented in this patch:         Ensor 11-94
488      * In a mixed-case name, if first char is upper, one more upper may
489      * appear anywhere.  (A mixed-case name *must* have an upper first
490      * char, and may have one other upper.)
491      * A third upper may appear if all 3 appear at the beginning of the
492      * name, separated only by "others" (-/_/.).
493      * A single group of digits is allowed anywhere.
494      * Two groups of digits are allowed if at least one of the groups is
495      * at the beginning or the end.
496      * Only one '-', '_', or '.' is allowed (or two, if not consecutive).
497      * But not as the first or last char.
498      * No other special characters are allowed.
499      * Name must contain at least one letter.
500      */
501     tmpstr2 = tmpstr = (username[0] == '~' ? &username[1] : username);
502     while (*tmpstr && !badid)
503     {
504       pos++;
505       c = *tmpstr;
506       tmpstr++;
507       if (isLower(c))
508       {
509         lower++;
510       }
511       else if (isUpper(c))
512       {
513         upper++;
514         if ((leadcaps || pos == 1) && !lower && !digits)
515           leadcaps++;
516       }
517       else if (isDigit(c))
518       {
519         digits++;
520         if (pos == 1 || !isDigit(d))
521         {
522           digitgroups++;
523           if (digitgroups > 2)
524             badid = 1;
525         }
526       }
527       else if (c == '-' || c == '_' || c == '.')
528       {
529         other++;
530         if (pos == 1)
531           badid = 1;
532         else if (d == '-' || d == '_' || d == '.' || other > 2)
533           badid = 1;
534       }
535       else
536         badid = 1;
537       d = c;
538     }
539     if (!badid)
540     {
541       if (lower && upper && (!leadcaps || leadcaps > 3 ||
542           (upper > 2 && upper > leadcaps)))
543         badid = 1;
544       else if (digitgroups == 2 && !(isDigit(tmpstr2[0]) || isDigit(c)))
545         badid = 1;
546       else if ((!lower && !upper) || !isAlnum(c))
547         badid = 1;
548     }
549     if (badid && (!(sptr->flags & FLAGS_GOTID) ||
550         strcmp(sptr->username, username) != 0))
551     {
552       ircstp->is_ref++;
553       sendto_one(cptr, ":%s %d %s :Your username is invalid.",
554           me.name, ERR_INVALIDUSERNAME, cptr->name);
555       sendto_one(cptr,
556           ":%s %d %s :Connect with your real username, in lowercase.",
557           me.name, ERR_INVALIDUSERNAME, cptr->name);
558       sendto_one(cptr, ":%s %d %s :If your mail address were foo@bar.com, "
559           "your username would be foo.",
560           me.name, ERR_INVALIDUSERNAME, cptr->name);
561       return exit_client(cptr, sptr, &me, "USER: Bad username");
562     }
563
564     if (oldstatus_ismaster && MyConnect(sptr))
565       m_oper(&me, sptr, 1, parv);
566
567     Count_unknownbecomesclient(sptr, nrof);
568   }
569   else
570   {
571     strncpy(user->username, username, USERLEN);
572     Count_newremoteclient(nrof);
573   }
574   SetUser(sptr);
575   if (IsInvisible(sptr))
576     ++nrof.inv_clients;
577   if (IsOper(sptr))
578     ++nrof.opers;
579
580   if (MyConnect(sptr))
581   {
582     sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, nick);
583     /* This is a duplicate of the NOTICE but see below... */
584     sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
585         get_client_name(&me, FALSE), version);
586     sendto_one(sptr, rpl_str(RPL_CREATED), me.name, nick, creation);
587     sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0], me.name, version);
588     m_lusers(sptr, sptr, 1, parv);
589     update_load();
590 #ifdef NODEFAULTMOTD
591     m_motd(sptr, NULL, 1, parv);
592 #else
593     m_motd(sptr, sptr, 1, parv);
594 #endif
595     nextping = now;
596     if (sptr->snomask & SNO_NOISY)
597       set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD);
598 #ifdef ALLOW_SNO_CONNEXIT
599 #ifdef SNO_CONNEXIT_IP
600     sprintf_irc(sendbuf,
601         ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
602         me.name, nick, user->username, user->host, inetntoa(sptr->ip),
603         get_client_class(sptr));
604     sendbufto_op_mask(SNO_CONNEXIT);
605 #else /* SNO_CONNEXIT_IP */
606     sprintf_irc(sendbuf,
607         ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s)",
608         me.name, nick, user->username, user->host);
609     sendbufto_op_mask(SNO_CONNEXIT);
610 #endif /* SNO_CONNEXIT_IP */
611 #endif /* ALLOW_SNO_CONNEXIT */
612     IPcheck_connect_succeeded(sptr);
613   }
614   else
615     /* if (IsServer(cptr)) */
616   {
617     aClient *acptr;
618
619     acptr = user->server;
620     if (acptr->from != sptr->from)
621     {
622       if (Protocol(cptr) < 10)
623         sendto_one(cptr, ":%s KILL %s :%s (%s != %s[%s])",
624             me.name, sptr->name, me.name, user->server->name, acptr->from->name,
625             acptr->from->sockhost);
626       else
627         sendto_one(cptr, "%s KILL %s%s :%s (%s != %s[%s])",
628             NumServ(&me), NumNick(sptr), me.name, user->server->name,
629             acptr->from->name, acptr->from->sockhost);
630       sptr->flags |= FLAGS_KILLED;
631       return exit_client(cptr, sptr, &me, "NICK server wrong direction");
632     }
633     else
634       sptr->flags |= (acptr->flags & FLAGS_TS8);
635
636     /*
637      * Check to see if this user is being propogated
638      * as part of a net.burst, or is using protocol 9.
639      * FIXME: This can be speeded up - its stupid to check it for
640      * every NICK message in a burst again  --Run.
641      */
642     for (acptr = user->server; acptr != &me; acptr = acptr->serv->up)
643       if (IsBurst(acptr) || Protocol(acptr) < 10)
644         break;
645     if (IPcheck_remote_connect(sptr, user->host, (acptr != &me)) == -1)
646       /* We ran out of bits to count this */
647       return exit_client(cptr, sptr, &me,
648           "More then 255 connections from this IP number");
649   }
650 #ifdef NO_PROTOCOL9             /* Use this when all servers are 2.10 (but test it first) --Run */
651
652   tmpstr = umode_str(sptr);
653   sendto_serv_butone(cptr, *tmpstr ?
654       "%s NICK %s %d %d %s %s +%s %s %s%s :%s" :
655       "%s NICK %s %d %d %s %s %s%s %s%s :%s",
656       NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
657       user->username, user->host, tmpstr,
658       inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
659       NumNick(sptr), sptr->info);
660
661 #else /* Remove the following when all servers are 2.10 */
662
663   /* First send message to all 2.9 servers */
664   sprintf_irc(sendbuf, ":%s NICK %s %d " TIME_T_FMT " %s %s %s :%s",
665       user->server->name, nick, sptr->hopcount + 1, sptr->lastnick,
666       user->username, user->host, user->server->name, sptr->info);
667   for (lp = me.serv->down; lp; lp = lp->next)
668   {
669     if (lp->value.cptr == cptr)
670       continue;
671     if (Protocol(lp->value.cptr) < 10)
672       sendbufto_one(lp->value.cptr);
673   }
674
675   /* If the user has no umode, no need to generate a user MODE */
676   if (*(tmpstr = umode_str(sptr)) && (MyConnect(sptr) || Protocol(cptr) > 9))
677     /* Is it necessary to generate an user MODE message ? */
678   {
679     for (lp = me.serv->down; lp; lp = lp->next)
680     {
681       if (lp->value.cptr == cptr)
682         continue;
683       if (Protocol(lp->value.cptr) < 10)
684         sendto_one(lp->value.cptr, ":%s MODE %s :%s", sptr->name,
685             sptr->name, tmpstr);
686     }
687   }
688
689   /* Now send message to all 2.10 servers */
690   sprintf_irc(sendbuf, *tmpstr ?
691       "%s NICK %s %d %d %s %s +%s %s %s%s :%s" :
692       "%s NICK %s %d %d %s %s %s%s %s%s :%s",
693       NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
694       user->username, user->host, tmpstr,
695       inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
696       NumNick(sptr), sptr->info);
697   for (lp = me.serv->down; lp; lp = lp->next)
698   {
699     if (lp->value.cptr == cptr || Protocol(lp->value.cptr) < 10)
700       continue;
701     sendbufto_one(lp->value.cptr);
702   }
703
704 #endif
705
706   /* Send umode to client */
707   if (MyUser(sptr))
708   {
709     send_umode(cptr, sptr, 0, ALL_UMODES);
710     if (sptr->snomask != SNO_DEFAULT && (sptr->flags & FLAGS_SERVNOTICE))
711       sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
712           sptr->snomask, sptr->snomask);
713   }
714
715   return 0;
716 }
717
718 /* *INDENT-OFF* */
719
720 static int user_modes[] = {
721   FLAGS_OPER,           'o',
722   FLAGS_LOCOP,          'O',
723   FLAGS_INVISIBLE,      'i',
724   FLAGS_WALLOP,         'w',
725   FLAGS_SERVNOTICE,     's',
726   FLAGS_DEAF,           'd',
727   FLAGS_CHSERV,         'k',
728   FLAGS_DEBUG,          'g',
729   0,                    0
730 };
731
732 /* *INDENT-ON* */
733
734 #define COOKIE_VERIFIED ((unsigned int)-1)
735
736 /*
737  * m_nick
738  *
739  * parv[0] = sender prefix
740  * parv[1] = nickname
741  *
742  * If from server, source is client:
743  *   parv[2] = timestamp
744  *
745  * Source is server:
746  *   parv[2] = hopcount
747  *   parv[3] = timestamp
748  *   parv[4] = username
749  *   parv[5] = hostname
750  *   parv[6] = umode (optional)
751  *   parv[parc-3] = IP#                 <- Only Protocol >= 10
752  *   parv[parc-2] = YXX, numeric nick   <- Only Protocol >= 10
753  *   parv[parc-1] = info
754  *   parv[0] = server
755  */
756 int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
757 {
758   aClient *acptr;
759   aClient *server = NULL;
760   char nick[NICKLEN + 2];
761   char *s;
762   Link *lp;
763   time_t lastnick = (time_t) 0;
764   int differ = 1;
765
766   if (parc < 2)
767   {
768     sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
769     return 0;
770   }
771   else if ((IsServer(sptr) && parc < 8) || (IsServer(cptr) && parc < 3))
772   {
773     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "NICK");
774     sendto_ops("bad NICK param count for %s from %s",
775         parv[1], get_client_name(cptr, FALSE));
776     return 0;
777   }
778   if (MyConnect(sptr) && (s = strchr(parv[1], '~')))
779     *s = '\0';
780   strncpy(nick, parv[1], NICKLEN + 1);
781   nick[sizeof(nick) - 1] = 0;
782   /*
783    * If do_nick_name() returns a null name OR if the server sent a nick
784    * name and do_nick_name() changed it in some way (due to rules of nick
785    * creation) then reject it. If from a server and we reject it,
786    * and KILL it. -avalon 4/4/92
787    */
788   if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1])))
789   {
790     sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], parv[1]);
791
792     if (IsServer(cptr))
793     {
794       ircstp->is_kill++;
795       sendto_ops("Bad Nick: %s From: %s %s",
796           parv[1], parv[0], get_client_name(cptr, FALSE));
797       if (Protocol(cptr) < 10)
798         sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
799             me.name, parv[1], me.name, parv[1], nick, cptr->name);
800       else
801         sendto_one(cptr, "%s KILL %s :%s (%s <- %s[%s])",
802             NumServ(&me), IsServer(sptr) ? parv[parc - 2] : parv[0], me.name,
803             parv[1], nick, cptr->name);
804       if (!IsServer(sptr))      /* bad nick _change_ */
805       {
806         sendto_lowprot_butone(cptr, 9, ":%s KILL %s :%s (%s <- %s!%s@%s)",
807             me.name, parv[0], me.name, get_client_name(cptr, FALSE), parv[0],
808             sptr->user ? sptr->username : "",
809             sptr->user ? sptr->user->server->name : cptr->name);
810         sendto_highprot_butone(cptr, 10, "%s KILL %s :%s (%s <- %s!%s@%s)",
811             NumServ(&me), parv[0], me.name, get_client_name(cptr, FALSE),
812             parv[0], sptr->user ? sptr->username : "",
813             sptr->user ? sptr->user->server->name : cptr->name);
814         sptr->flags |= FLAGS_KILLED;
815         return exit_client(cptr, sptr, &me, "BadNick");
816       }
817     }
818     return 0;
819   }
820
821   /* 
822    * Check if this is a LOCAL user trying to use a reserved (Juped)
823    * nick, if so tell him that it's a nick in use...
824    */
825
826   if ((!IsServer(cptr)) && isNickJuped(nick))
827   {
828     sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
829         /* parv[0] is empty when connecting */
830         BadPtr(parv[0]) ? "*" : parv[0], nick);
831     return 0;                   /* NICK message ignored */
832   }
833
834   /*
835    * Check against nick name collisions.
836    *
837    * Put this 'if' here so that the nesting goes nicely on the screen :)
838    * We check against server name list before determining if the nickname
839    * is present in the nicklist (due to the way the below for loop is
840    * constructed). -avalon
841    */
842   if ((acptr = FindServer(nick)))
843     if (MyConnect(sptr))
844     {
845       sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
846           BadPtr(parv[0]) ? "*" : parv[0], nick);
847       return 0;                 /* NICK message ignored */
848     }
849   /*
850    * acptr already has result from previous FindServer()
851    */
852   if (acptr)
853   {
854     /*
855      * We have a nickname trying to use the same name as
856      * a server. Send out a nick collision KILL to remove
857      * the nickname. As long as only a KILL is sent out,
858      * there is no danger of the server being disconnected.
859      * Ultimate way to jupiter a nick ? >;-). -avalon
860      */
861     sendto_ops("Nick collision on %s(%s <- %s)",
862         sptr->name, acptr->from->name, get_client_name(cptr, FALSE));
863     ircstp->is_kill++;
864     if (Protocol(cptr) < 10)
865       sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
866           me.name, sptr->name, me.name, acptr->from->name,
867           get_client_name(cptr, FALSE));
868     else
869       sendto_one(cptr, "%s KILL %s%s :%s (%s <- %s)",
870           NumServ(&me), NumNick(sptr), me.name, acptr->from->name,
871           /*
872            * NOTE: Cannot use get_client_name twice here, it returns static
873            *       string pointer--the other info would be lost.
874            */
875           get_client_name(cptr, FALSE));
876     sptr->flags |= FLAGS_KILLED;
877     return exit_client(cptr, sptr, &me, "Nick/Server collision");
878   }
879
880   if (!(acptr = FindClient(nick)))
881     goto nickkilldone;          /* No collisions, all clear... */
882   /*
883    * If acptr == sptr, then we have a client doing a nick
884    * change between *equivalent* nicknames as far as server
885    * is concerned (user is changing the case of his/her
886    * nickname or somesuch)
887    */
888   if (acptr == sptr)
889   {
890     if (strcmp(acptr->name, nick) != 0)
891       /*
892        * Allows change of case in his/her nick
893        */
894       goto nickkilldone;        /* -- go and process change */
895     else
896       /*
897        * This is just ':old NICK old' type thing.
898        * Just forget the whole thing here. There is
899        * no point forwarding it to anywhere,
900        * especially since servers prior to this
901        * version would treat it as nick collision.
902        */
903       return 0;                 /* NICK Message ignored */
904   }
905
906   /*
907    * Note: From this point forward it can be assumed that
908    * acptr != sptr (point to different client structures).
909    */
910   /*
911    * If the older one is "non-person", the new entry is just
912    * allowed to overwrite it. Just silently drop non-person,
913    * and proceed with the nick. This should take care of the
914    * "dormant nick" way of generating collisions...
915    */
916   if (IsUnknown(acptr) && MyConnect(acptr))
917   {
918     IPcheck_connect_fail(acptr);
919     exit_client(cptr, acptr, &me, "Overridden by other sign on");
920     goto nickkilldone;
921   }
922   /*
923    * Decide, we really have a nick collision and deal with it
924    */
925   if (!IsServer(cptr))
926   {
927     /*
928      * NICK is coming from local client connection. Just
929      * send error reply and ignore the command.
930      */
931     sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
932         /* parv[0] is empty when connecting */
933         BadPtr(parv[0]) ? "*" : parv[0], nick);
934     return 0;                   /* NICK message ignored */
935   }
936   /*
937    * NICK was coming from a server connection.
938    * This means we have a race condition (two users signing on
939    * at the same time), or two net fragments reconnecting with the same nick.
940    * The latter can happen because two different users connected
941    * or because one and the same user switched server during a net break.
942    * If the TimeStamps are equal, we kill both (or only 'new'
943    * if it was a ":server NICK new ...").
944    * Otherwise we kill the youngest when user@host differ,
945    * or the oldest when they are the same.
946    * We treat user and ~user as different, because if it wasn't
947    * a faked ~user the AUTH wouldn't have added the '~'.
948    * --Run
949    *
950    */
951   if (IsServer(sptr))
952   {
953     /*
954      * A new NICK being introduced by a neighbouring
955      * server (e.g. message type ":server NICK new ..." received)
956      */
957     lastnick = atoi(parv[3]);
958     differ = (strCasediff(acptr->user->username, parv[4]) ||
959         strCasediff(acptr->user->host, parv[5]));
960     sendto_ops("Nick collision on %s (%s " TIME_T_FMT " <- %s " TIME_T_FMT
961         " (%s user@host))", acptr->name, acptr->from->name, acptr->lastnick,
962         get_client_name(cptr, FALSE), lastnick, differ ? "Different" : "Same");
963   }
964   else
965   {
966     /*
967      * A NICK change has collided (e.g. message type ":old NICK new").
968      */
969     lastnick = atoi(parv[2]);
970     differ = (strCasediff(acptr->user->username, sptr->user->username) ||
971         strCasediff(acptr->user->host, sptr->user->host));
972     sendto_ops("Nick change collision from %s to %s (%s " TIME_T_FMT " <- %s "
973         TIME_T_FMT ")", sptr->name, acptr->name, acptr->from->name,
974         acptr->lastnick, get_client_name(cptr, FALSE), lastnick);
975   }
976   /*
977    * Now remove (kill) the nick on our side if it is the youngest.
978    * If no timestamp was received, we ignore the incoming nick
979    * (and expect a KILL for our legit nick soon ):
980    * When the timestamps are equal we kill both nicks. --Run
981    * acptr->from != cptr should *always* be true (?).
982    */
983   if (acptr->from != cptr)
984   {
985     if ((differ && lastnick >= acptr->lastnick) ||
986         (!differ && lastnick <= acptr->lastnick))
987     {
988       if (!IsServer(sptr))
989       {
990         ircstp->is_kill++;
991         sendto_lowprot_butone(cptr, 9,  /* Kill old from outgoing servers */
992             ":%s KILL %s :%s (%s <- %s (Nick collision))",
993             me.name, sptr->name, me.name, acptr->from->name,
994             get_client_name(cptr, FALSE));
995         sendto_highprot_butone(cptr, 10,        /* Kill old from outgoing servers */
996             "%s KILL %s%s :%s (%s <- %s (Nick collision))",
997             NumServ(&me), NumNick(sptr), me.name, acptr->from->name,
998             get_client_name(cptr, FALSE));
999         if (MyConnect(sptr) && IsServer(cptr) && Protocol(cptr) > 9)
1000           sendto_one(cptr, "%s KILL %s%s :%s (Ghost2)",
1001               NumServ(&me), NumNick(sptr), me.name);
1002         sptr->flags |= FLAGS_KILLED;
1003         exit_client(cptr, sptr, &me, "Nick collision (you're a ghost)");
1004       }
1005       if (lastnick != acptr->lastnick)
1006         return 0;               /* Ignore the NICK */
1007     }
1008     sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, nick);
1009   }
1010   ircstp->is_kill++;
1011   acptr->flags |= FLAGS_KILLED;
1012   if (differ)
1013   {
1014     sendto_lowprot_butone(cptr, 9,      /* Kill our old from outgoing servers */
1015         ":%s KILL %s :%s (%s <- %s (older nick overruled))",
1016         me.name, acptr->name, me.name, acptr->from->name,
1017         get_client_name(cptr, FALSE));
1018     sendto_highprot_butone(cptr, 10,    /* Kill our old from outgoing servers */
1019         "%s KILL %s%s :%s (%s <- %s (older nick overruled))",
1020         NumServ(&me), NumNick(acptr), me.name, acptr->from->name,
1021         get_client_name(cptr, FALSE));
1022     if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1023       sendto_one(cptr, "%s%s QUIT :Local kill by %s (Ghost)",
1024           NumNick(acptr), me.name);
1025     exit_client(cptr, acptr, &me, "Nick collision (older nick overruled)");
1026   }
1027   else
1028   {
1029     sendto_lowprot_butone(cptr, 9,      /* Kill our old from outgoing servers */
1030         ":%s KILL %s :%s (%s <- %s (nick collision from same user@host))",
1031         me.name, acptr->name, me.name, acptr->from->name,
1032         get_client_name(cptr, FALSE));
1033     sendto_highprot_butone(cptr, 10,    /* Kill our old from outgoing servers */
1034         "%s KILL %s%s :%s (%s <- %s (nick collision from same user@host))",
1035         NumServ(&me), NumNick(acptr), me.name, acptr->from->name,
1036         get_client_name(cptr, FALSE));
1037     if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1038       sendto_one(cptr,
1039           "%s%s QUIT :Local kill by %s (Ghost: switched servers too fast)",
1040           NumNick(acptr), me.name);
1041     exit_client(cptr, acptr, &me, "Nick collision (You collided yourself)");
1042   }
1043   if (lastnick == acptr->lastnick)
1044     return 0;
1045
1046 nickkilldone:
1047   if (IsServer(sptr))
1048   {
1049     int flag, *s;
1050     char *p;
1051 #ifndef NO_PROTOCOL9
1052     const char *nnp9 = NULL;    /* Init. to avoid compiler warning */
1053 #endif
1054
1055     /* A server introducing a new client, change source */
1056     if (!server)
1057       server = sptr;
1058 #ifndef NO_PROTOCOL9
1059     /*
1060      * Numeric Nicks does, in contrast to all other protocol enhancements,
1061      * translation from protocol 9 -> protocol 10 !
1062      * The reason is that I just can't know what protocol it is when I
1063      * receive a "MODE #channel +o Run", because I can't 'find' "Run"
1064      * before I know the protocol, and I can't know the protocol if I
1065      * first have to find the server of "Run".
1066      * Therefore, in THIS case, the protocol is determined by the Connected
1067      * server: cptr.
1068      */
1069     if (Protocol(cptr) < 10 && !(nnp9 = CreateNNforProtocol9server(server)))
1070       return exit_client_msg(cptr, server, &me,
1071           "Too many clients (> %d) from P09 server (%s)", 64, server->name);
1072 #endif
1073     sptr = make_client(cptr, STAT_UNKNOWN);
1074     sptr->hopcount = atoi(parv[2]);
1075     sptr->lastnick = atoi(parv[3]);
1076     if (Protocol(cptr) > 9 && parc > 7 && *parv[6] == '+')
1077       for (p = parv[6] + 1; *p; p++)
1078         for (s = user_modes; (flag = *s); s += 2)
1079           if (((char)*(s + 1)) == *p)
1080           {
1081             sptr->flags |= flag;
1082             break;
1083           }
1084     /*
1085      * Set new nick name.
1086      */
1087     strcpy(sptr->name, nick);
1088     sptr->user = make_user(sptr);
1089     sptr->user->server = server;
1090 #ifndef NO_PROTOCOL9
1091     if (Protocol(cptr) < 10)
1092     {
1093       if (!SetRemoteNumNick(sptr, nnp9))
1094       {
1095         /*
1096          * if this fails squit the server and free the client
1097          */
1098         free_client(sptr);
1099         return exit_client_msg(cptr, server, &me, "Invalid numeric index");
1100       }
1101       sptr->ip.s_addr = 0;
1102     }
1103     else
1104     {
1105 #endif
1106       if (!SetRemoteNumNick(sptr, parv[parc - 2]))
1107       {
1108         /*
1109          * if this fails squit the server and free the client
1110          */
1111         free_client(sptr);
1112         return exit_client_msg(cptr, server, &me, "Invalid numeric index");
1113       }
1114       sptr->ip.s_addr = htonl(base64toint(parv[parc - 3]));
1115       /* IP# of remote client */
1116 #ifndef NO_PROTOCOL9
1117     }
1118 #endif
1119     add_client_to_list(sptr);
1120     hAddClient(sptr);
1121
1122     server->serv->ghost = 0;    /* :server NICK means end of net.burst */
1123     strncpy(sptr->info, parv[parc - 1], sizeof(sptr->info) - 1);
1124     strncpy(sptr->user->host, parv[5], sizeof(sptr->user->host) - 1);
1125     return register_user(cptr, sptr, sptr->name, parv[4]);
1126   }
1127   else if (sptr->name[0])
1128   {
1129     /*
1130      * Client changing its nick
1131      *
1132      * If the client belongs to me, then check to see
1133      * if client is on any channels where it is currently
1134      * banned.  If so, do not allow the nick change to occur.
1135      */
1136     if (MyUser(sptr))
1137     {
1138       for (lp = cptr->user->channel; lp; lp = lp->next)
1139         if (can_send(cptr, lp->value.chptr) == MODE_BAN)
1140         {
1141           sendto_one(cptr, err_str(ERR_BANNICKCHANGE), me.name, parv[0],
1142               lp->value.chptr->chname);
1143           return 0;
1144         }
1145       /*
1146        * Refuse nick change if the last nick change was less
1147        * then 30 seconds ago. This is intended to get rid of
1148        * clone bots doing NICK FLOOD. -SeKs
1149        * If someone didn't change their nick for more then 60 seconds
1150        * however, allow to do two nick changes immedately after another
1151        * before limiting the nick flood. -Run
1152        */
1153       if (now < cptr->nextnick)
1154       {
1155         cptr->nextnick += 2;
1156         sendto_one(cptr, err_str(ERR_NICKTOOFAST),
1157             me.name, parv[0], parv[1], cptr->nextnick - now);
1158         /* Send error message */
1159         sendto_prefix_one(cptr, cptr, ":%s NICK %s", parv[0], parv[0]);
1160         /* bounce NICK to user */
1161         return 0;               /* ignore nick change! */
1162       }
1163       else
1164       {
1165         /* Limit total to 1 change per NICK_DELAY seconds: */
1166         cptr->nextnick += NICK_DELAY;
1167         /* However allow _maximal_ 1 extra consecutive nick change: */
1168         if (cptr->nextnick < now)
1169           cptr->nextnick = now;
1170       }
1171     }
1172     /*
1173      * Also set 'lastnick' to current time, if changed.
1174      */
1175     if (strCasediff(parv[0], nick))
1176       sptr->lastnick = (sptr == cptr) ? TStime() : atoi(parv[2]);
1177
1178     /*
1179      * Client just changing his/her nick. If he/she is
1180      * on a channel, send note of change to all clients
1181      * on that channel. Propagate notice to other servers.
1182      */
1183     if (IsUser(sptr))
1184     {
1185       sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
1186       add_history(sptr, 1);
1187 #ifdef NO_PROTOCOL9
1188       sendto_serv_butone(cptr,
1189           "%s%s NICK %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
1190 #else
1191       sendto_lowprot_butone(cptr, 9,
1192           ":%s NICK %s " TIME_T_FMT, parv[0], nick, sptr->lastnick);
1193       sendto_highprot_butone(cptr, 10,
1194           "%s%s NICK %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
1195 #endif
1196     }
1197     else
1198       sendto_one(sptr, ":%s NICK :%s", parv[0], nick);
1199     if (sptr->name[0])
1200       hRemClient(sptr);
1201     strcpy(sptr->name, nick);
1202     hAddClient(sptr);
1203   }
1204   else
1205   {
1206     /* Local client setting NICK the first time */
1207
1208     strcpy(sptr->name, nick);
1209     if (!sptr->user)
1210     {
1211       sptr->user = make_user(sptr);
1212       sptr->user->server = &me;
1213     }
1214     SetLocalNumNick(sptr);
1215     hAddClient(sptr);
1216
1217     /*
1218      * If the client hasn't gotten a cookie-ping yet,
1219      * choose a cookie and send it. -record!jegelhof@cloud9.net
1220      */
1221     if (!sptr->cookie)
1222     {
1223       do
1224         sptr->cookie = (ircrandom() & 0x7fffffff);
1225       while (!sptr->cookie);
1226       sendto_one(cptr, "PING :%u", sptr->cookie);
1227     }
1228     else if (*sptr->user->host && sptr->cookie == COOKIE_VERIFIED)
1229     {
1230       /*
1231        * USER and PONG already received, now we have NICK.
1232        * register_user may reject the client and call exit_client
1233        * for it - must test this and exit m_nick too !
1234        */
1235       sptr->lastnick = TStime();        /* Always local client */
1236       if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED)
1237         return CPTR_KILLED;
1238     }
1239   }
1240   return 0;
1241 }
1242
1243 /*
1244  * add_target
1245  *
1246  * sptr must be a local client!
1247  *
1248  * Cannonifies target for client `sptr'.
1249  */
1250 void add_target(aClient *sptr, void *target)
1251 {
1252   register unsigned char *p;
1253   register unsigned int tmp = ((size_t)target & 0xffff00) >> 8;
1254   unsigned char hash = (tmp * tmp) >> 12;
1255   if (sptr->targets[0] == hash) /* Last person that we messaged ourself? */
1256     return;
1257   for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
1258     if (*++p == hash)
1259       return;                   /* Already in table */
1260
1261   /* New target */
1262   memmove(&sptr->targets[RESERVEDTARGETS + 1],
1263       &sptr->targets[RESERVEDTARGETS], MAXTARGETS - RESERVEDTARGETS - 1);
1264   sptr->targets[RESERVEDTARGETS] = hash;
1265   return;
1266 }
1267
1268 /*
1269  * check_target_limit
1270  *
1271  * sptr must be a local client !
1272  *
1273  * Returns 'true' (1) when too many targets are addressed.
1274  * Returns 'false' (0) when it's ok to send to this target.
1275  */
1276 int check_target_limit(aClient *sptr, void *target, const char *name,
1277     int created)
1278 {
1279   register unsigned char *p;
1280   register unsigned int tmp = ((size_t)target & 0xffff00) >> 8;
1281   unsigned char hash = (tmp * tmp) >> 12;
1282   if (sptr->targets[0] == hash) /* Same target as last time ? */
1283     return 0;
1284   for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
1285     if (*++p == hash)
1286     {
1287       memmove(&sptr->targets[1], &sptr->targets[0], p - sptr->targets);
1288       sptr->targets[0] = hash;
1289       return 0;
1290     }
1291
1292   /* New target */
1293   if (!created)
1294   {
1295     if (now < sptr->nexttarget)
1296     {
1297       if (sptr->nexttarget - now < TARGET_DELAY + 8)    /* No server flooding */
1298       {
1299         sptr->nexttarget += 2;
1300         sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
1301             me.name, sptr->name, name, sptr->nexttarget - now);
1302       }
1303       return 1;
1304     }
1305     else
1306     {
1307 #ifdef GODMODE
1308       sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT,
1309           me.name, sptr->name, name, (now - sptr->nexttarget) / TARGET_DELAY);
1310 #endif
1311       sptr->nexttarget += TARGET_DELAY;
1312       if (sptr->nexttarget < now - (TARGET_DELAY * (MAXTARGETS - 1)))
1313         sptr->nexttarget = now - (TARGET_DELAY * (MAXTARGETS - 1));
1314     }
1315   }
1316   memmove(&sptr->targets[1], &sptr->targets[0], MAXTARGETS - 1);
1317   sptr->targets[0] = hash;
1318   return 0;
1319 }
1320
1321 /*
1322  * m_message (used in m_private() and m_notice())
1323  *
1324  * The general function to deliver MSG's between users/channels
1325  *
1326  * parv[0] = sender prefix
1327  * parv[1] = receiver list
1328  * parv[parc-1] = message text
1329  *
1330  * massive cleanup
1331  * rev argv 6/91
1332  */
1333 static int m_message(aClient *cptr, aClient *sptr,
1334     int parc, char *parv[], int notice)
1335 {
1336   Reg1 aClient *acptr;
1337   Reg2 char *s;
1338   aChannel *chptr;
1339   char *nick, *server, *p, *cmd, *host;
1340
1341   sptr->flags &= ~FLAGS_TS8;
1342
1343   cmd = notice ? MSG_NOTICE : MSG_PRIVATE;
1344
1345   if (parc < 2 || *parv[1] == '\0')
1346   {
1347     sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], cmd);
1348     return -1;
1349   }
1350
1351   if (parc < 3 || *parv[parc - 1] == '\0')
1352   {
1353     sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
1354     return -1;
1355   }
1356
1357   if (MyUser(sptr))
1358     parv[1] = canonize(parv[1]);
1359   for (p = NULL, nick = strtoken(&p, parv[1], ","); nick;
1360       nick = strtoken(&p, NULL, ","))
1361   {
1362     /*
1363      * channel msg?
1364      */
1365     if (IsChannelName(nick))
1366     {
1367       if ((chptr = FindChannel(nick)))
1368       {
1369         if (can_send(sptr, chptr) == 0  /* This first: Almost never a server/service */
1370             || IsChannelService(sptr) || IsServer(sptr))
1371         {
1372           if (MyUser(sptr) && (chptr->mode.mode & MODE_NOPRIVMSGS) &&
1373               check_target_limit(sptr, chptr, chptr->chname, 0))
1374             continue;
1375           sendto_channel_butone(cptr, sptr, chptr,
1376               ":%s %s %s :%s", parv[0], cmd, chptr->chname, parv[parc - 1]);
1377         }
1378         else if (!notice)
1379           sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
1380               me.name, parv[0], chptr->chname);
1381         continue;
1382       }
1383     }
1384     else if (*nick != '$' && !strchr(nick, '@'))
1385     {
1386       /*
1387        * nickname addressed?
1388        */
1389       if (MyUser(sptr) || Protocol(cptr) < 10)
1390         acptr = FindUser(nick);
1391       else if ((acptr = findNUser(nick)) && !IsUser(acptr))
1392         acptr = NULL;
1393       if (acptr)
1394       {
1395         if (MyUser(sptr) && check_target_limit(sptr, acptr, acptr->name, 0))
1396           continue;
1397         if (!is_silenced(sptr, acptr))
1398         {
1399           if (!notice && MyConnect(sptr) && acptr->user && acptr->user->away)
1400             sendto_one(sptr, rpl_str(RPL_AWAY),
1401                 me.name, parv[0], acptr->name, acptr->user->away);
1402           if (MyUser(acptr) || Protocol(acptr->from) < 10)
1403           {
1404             if (MyUser(acptr))
1405               add_target(acptr, sptr);
1406             sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
1407                 parv[0], cmd, acptr->name, parv[parc - 1]);
1408           }
1409           else
1410             sendto_prefix_one(acptr, sptr, ":%s %s %s%s :%s",
1411                 parv[0], cmd, NumNick(acptr), parv[parc - 1]);
1412         }
1413       }
1414       else if (MyUser(sptr) || Protocol(cptr) < 10)
1415         sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
1416       else
1417         sendto_one(sptr,
1418             ":%s %d %s * :Target left UnderNet. Failed to deliver: [%.50s]",
1419             me.name, ERR_NOSUCHNICK, sptr->name, parv[parc - 1]);
1420       continue;
1421     }
1422     /*
1423      * The following two cases allow masks in NOTICEs
1424      * (for OPERs only)
1425      *
1426      * Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
1427      */
1428     if ((*nick == '$' || *nick == '#') && IsAnOper(sptr))
1429     {
1430       if (MyConnect(sptr))
1431       {
1432         if (!(s = strrchr(nick, '.')))
1433         {
1434           sendto_one(sptr, err_str(ERR_NOTOPLEVEL), me.name, parv[0], nick);
1435           continue;
1436         }
1437         while (*++s)
1438           if (*s == '.' || *s == '*' || *s == '?')
1439             break;
1440         if (*s == '*' || *s == '?')
1441         {
1442           sendto_one(sptr, err_str(ERR_WILDTOPLEVEL), me.name, parv[0], nick);
1443           continue;
1444         }
1445       }
1446       sendto_match_butone(IsServer(cptr) ? cptr : NULL,
1447           sptr, nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
1448           ":%s %s %s :%s", parv[0], cmd, nick, parv[parc - 1]);
1449       continue;
1450     }
1451     else if ((server = strchr(nick, '@')) && (acptr = FindServer(server + 1)))
1452     {
1453       /*
1454        * NICK[%host]@server addressed? See if <server> is me first
1455        */
1456       if (!IsMe(acptr))
1457       {
1458         sendto_one(acptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[parc - 1]);
1459         continue;
1460       }
1461
1462       /* Look for an user whose NICK is equal to <nick> and then
1463        * check if it's hostname matches <host> and if it's a local
1464        * user. */
1465       *server = '\0';
1466       if ((host = strchr(nick, '%')))
1467         *host++ = '\0';
1468
1469       if ((!(acptr = FindUser(nick))) ||
1470           (!(MyUser(acptr))) ||
1471           ((!(BadPtr(host))) && match(host, acptr->user->host)))
1472         acptr = NULL;
1473
1474       *server = '@';
1475       if (host)
1476         *--host = '%';
1477
1478       if (acptr)
1479       {
1480         if (!(is_silenced(sptr, acptr)))
1481           sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
1482               parv[0], cmd, nick, parv[parc - 1]);
1483         continue;
1484       }
1485     }
1486     if (IsChannelName(nick))
1487       sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], nick);
1488     else
1489       sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
1490   }
1491   return 0;
1492 }
1493
1494 /*
1495  * m_private
1496  *
1497  * parv[0] = sender prefix
1498  * parv[1] = receiver list
1499  * parv[parc-1] = message text
1500  */
1501 int m_private(aClient *cptr, aClient *sptr, int parc, char *parv[])
1502 {
1503   return m_message(cptr, sptr, parc, parv, 0);
1504 }
1505
1506 /*
1507  * m_notice
1508  *
1509  * parv[0] = sender prefix
1510  * parv[1] = receiver list
1511  * parv[parc-1] = notice text
1512  */
1513 int m_notice(aClient *cptr, aClient *sptr, int parc, char *parv[])
1514 {
1515   if (MyUser(sptr) && parv[1] && parv[1][0] == '@' &&
1516       IsChannelName(&parv[1][1]))
1517   {
1518     parv[1]++;                  /* Get rid of '@' */
1519     return m_wallchops(cptr, sptr, parc, parv);
1520   }
1521   return m_message(cptr, sptr, parc, parv, 1);
1522 }
1523
1524
1525 /*
1526  * whisper - called from m_cnotice and m_cprivmsg.
1527  *
1528  * parv[0] = sender prefix
1529  * parv[1] = nick
1530  * parv[2] = #channel
1531  * parv[3] = Private message text
1532  *
1533  * Added 971023 by Run.
1534  * Reason: Allows channel operators to sent an arbitrary number of private
1535  *   messages to users on their channel, avoiding the max.targets limit.
1536  *   Building this into m_private would use too much cpu because we'd have
1537  *   to a cross channel lookup for every private message!
1538  * Note that we can't allow non-chan ops to use this command, it would be
1539  *   abused by mass advertisers.
1540  */
1541 int whisper(aClient *sptr, int parc, char *parv[], int notice)
1542 {
1543   int s_is_member = 0, s_is_voiced = 0, t_is_member = 0;
1544   aClient *tcptr;
1545   aChannel *chptr;
1546   register Link *lp;
1547
1548   if (!MyUser(sptr))
1549     return 0;
1550   if (parc < 4 || BadPtr(parv[3]))
1551   {
1552     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
1553         me.name, parv[0], notice ? "CNOTICE" : "CPRIVMSG");
1554     return 0;
1555   }
1556   if (!(chptr = FindChannel(parv[2])))
1557   {
1558     sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[2]);
1559     return 0;
1560   }
1561   if (!(tcptr = FindUser(parv[1])))
1562   {
1563     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
1564     return 0;
1565   }
1566   for (lp = chptr->members; lp; lp = lp->next)
1567   {
1568     register aClient *mcptr = lp->value.cptr;
1569     if (mcptr == sptr)
1570     {
1571       s_is_member = 1;
1572       if ((lp->flags & (CHFL_CHANOP | CHFL_VOICE)))
1573         s_is_voiced = 1;
1574       else
1575         break;
1576       if (t_is_member)
1577         break;
1578     }
1579     if (mcptr == tcptr)
1580     {
1581       t_is_member = 1;
1582       if (s_is_voiced)
1583         break;
1584     }
1585   }
1586   if (!s_is_voiced)
1587   {
1588     sendto_one(sptr, err_str(s_is_member ? ERR_VOICENEEDED : ERR_NOTONCHANNEL),
1589         me.name, parv[0], chptr->chname);
1590     return 0;
1591   }
1592   if (!t_is_member)
1593   {
1594     sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
1595         me.name, parv[0], tcptr->name, chptr->chname);
1596     return 0;
1597   }
1598   if (is_silenced(sptr, tcptr))
1599     return 0;
1600
1601   if (tcptr->user && tcptr->user->away)
1602     sendto_one(sptr, rpl_str(RPL_AWAY),
1603         me.name, parv[0], tcptr->name, tcptr->user->away);
1604   if (MyUser(tcptr) || Protocol(tcptr->from) < 10)
1605     sendto_prefix_one(tcptr, sptr, ":%s %s %s :%s",
1606         parv[0], notice ? "NOTICE" : "PRIVMSG", tcptr->name, parv[3]);
1607   else
1608     sendto_prefix_one(tcptr, sptr, ":%s %s %s%s :%s",
1609         parv[0], notice ? "NOTICE" : "PRIVMSG", NumNick(tcptr), parv[3]);
1610
1611   return 0;
1612 }
1613
1614 int m_cnotice(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
1615 {
1616   return whisper(sptr, parc, parv, 1);
1617 }
1618
1619 int m_cprivmsg(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
1620 {
1621   return whisper(sptr, parc, parv, 0);
1622 }
1623
1624 /*
1625  * m_wallchops
1626  *
1627  * parv[0] = sender prefix
1628  * parv[1] = target channel
1629  * parv[parc - 1] = wallchops text
1630  */
1631 int m_wallchops(aClient *cptr, aClient *sptr, int parc, char *parv[])
1632 {
1633   aChannel *chptr;
1634
1635   sptr->flags &= ~FLAGS_TS8;
1636
1637   if (parc < 2 || *parv[1] == '\0')
1638   {
1639     sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], "WALLCHOPS");
1640     return -1;
1641   }
1642
1643   if (parc < 3 || *parv[parc - 1] == '\0')
1644   {
1645     sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
1646     return -1;
1647   }
1648
1649   if (MyUser(sptr))
1650     parv[1] = canonize(parv[1]);
1651
1652   if (IsChannelName(parv[1]))
1653   {
1654     if ((chptr = FindChannel(parv[1])))
1655     {
1656       if (can_send(sptr, chptr) == 0)
1657       {
1658         if (MyUser(sptr) && (chptr->mode.mode & MODE_NOPRIVMSGS) &&
1659             check_target_limit(sptr, chptr, chptr->chname, 0))
1660           return 0;
1661         /* Send to local clients: */
1662         sendto_lchanops_butone(cptr, sptr, chptr,
1663             ":%s NOTICE @%s :%s", parv[0], parv[1], parv[parc - 1]);
1664 #ifdef NO_PROTOCOL9
1665         /* And to other servers: */
1666         sendto_chanopsserv_butone(cptr, sptr, chptr,
1667             ":%s WC %s :%s", parv[0], parv[1], parv[parc - 1]);
1668 #else
1669         /*
1670          * WARNING: `sendto_chanopsserv_butone' is heavily hacked when
1671          * `NO_PROTOCOL9' is not defined ! Therefore this is the ONLY
1672          * place you may use `sendto_chanopsserv_butone', until all
1673          * servers are 2.10.
1674          */
1675         sendto_chanopsserv_butone(cptr, sptr, chptr,
1676             ":%s WC %s :%s", parv[0], parv[1], parv[parc - 1]);
1677 #endif
1678       }
1679       else
1680         sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
1681             me.name, parv[0], parv[1]);
1682     }
1683   }
1684   else
1685     sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
1686
1687   return 0;
1688 }
1689
1690 /*
1691  * m_user
1692  *
1693  * parv[0] = sender prefix
1694  * parv[1] = username (login name, account)
1695  * parv[2] = umode mask
1696  * parv[3] = server notice mask
1697  * parv[4] = users real name info
1698  */
1699 int m_user(aClient *cptr, aClient *sptr, int parc, char *parv[])
1700 {
1701 #define UFLAGS  (FLAGS_INVISIBLE|FLAGS_WALLOP|FLAGS_SERVNOTICE)
1702   char *username, *host, *server, *realname;
1703   anUser *user;
1704
1705   if (IsServer(cptr))
1706     return 0;
1707
1708   if (IsServerPort(cptr))
1709     return exit_client(cptr, cptr, &me, "Use a different port");
1710
1711   if (parc > 2 && (username = strchr(parv[1], '@')))
1712     *username = '\0';
1713   if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
1714       *parv[3] == '\0' || *parv[4] == '\0')
1715   {
1716     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USER");
1717     return 0;
1718   }
1719
1720   /* Copy parameters into better documenting variables */
1721
1722   username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
1723   host = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
1724   server = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];
1725   realname = (parc < 5 || BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
1726
1727   user = make_user(sptr);
1728
1729   if (!IsUnknown(sptr))
1730   {
1731     sendto_one(sptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
1732     return 0;
1733   }
1734
1735   if (!strchr(host, '.'))       /* Not an IP# as hostname ? */
1736     sptr->flags |= (UFLAGS & atoi(host));
1737   if ((sptr->flags & FLAGS_SERVNOTICE))
1738     set_snomask(sptr, (isDigit(*server) && !strchr(server, '.')) ?
1739         (atoi(server) & SNO_USER) : SNO_DEFAULT, SNO_SET);
1740   user->server = &me;
1741   strncpy(sptr->info, realname, sizeof(sptr->info) - 1);
1742   if (sptr->name[0] && sptr->cookie == COOKIE_VERIFIED)
1743     /* NICK and PONG already received, now we have USER... */
1744     return register_user(cptr, sptr, sptr->name, username);
1745   else
1746   {
1747     strncpy(sptr->user->username, username, USERLEN);
1748     strncpy(user->host, host, sizeof(user->host) - 1);
1749   }
1750   return 0;
1751 }
1752
1753 /*
1754  * m_quit
1755  *
1756  * parv[0] = sender prefix
1757  * parv[parc-1] = comment
1758  */
1759 int m_quit(aClient *cptr, aClient *sptr, int parc, char *parv[])
1760 {
1761   register char *comment = (parc > 1
1762       && parv[parc - 1]) ? parv[parc - 1] : cptr->name;
1763
1764   if (MyUser(sptr))
1765   {
1766     if (!strncmp("Local Kill", comment, 10) || !strncmp(comment, "Killed", 6))
1767       comment = parv[0];
1768     if (sptr->user)
1769     {
1770       Link *lp;
1771       for (lp = sptr->user->channel; lp; lp = lp->next)
1772         if (can_send(sptr, lp->value.chptr) != 0)
1773           return exit_client(cptr, sptr, sptr, "Signed off");
1774     }
1775   }
1776   if (strlen(comment) > (size_t)TOPICLEN)
1777     comment[TOPICLEN] = '\0';
1778   return IsServer(sptr) ? 0 : exit_client(cptr, sptr, sptr, comment);
1779 }
1780
1781 /*
1782  * m_kill
1783  *
1784  * parv[0] = sender prefix
1785  * parv[1] = kill victim
1786  * parv[parc-1] = kill path
1787  */
1788 int m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[])
1789 {
1790   aClient *acptr;
1791   char *inpath = get_client_name(cptr, FALSE);
1792   char *user, *path, *killer;
1793   int chasing = 0;
1794
1795   if (parc < 3 || *parv[1] == '\0')
1796   {
1797     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KILL");
1798     return 0;
1799   }
1800
1801   user = parv[1];
1802   path = parv[parc - 1];        /* Either defined or NULL (parc >= 3) */
1803
1804 #ifdef  OPER_KILL
1805   if (!IsPrivileged(cptr))
1806   {
1807     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1808     return 0;
1809   }
1810 #else
1811   if (!IsServer(cptr))
1812   {
1813     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1814     return 0;
1815   }
1816 #endif
1817   if (IsAnOper(cptr))
1818   {
1819     if (BadPtr(path))
1820     {
1821       sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KILL");
1822       return 0;
1823     }
1824     if (strlen(path) > (size_t)TOPICLEN)
1825       path[TOPICLEN] = '\0';
1826   }
1827
1828   if (MyUser(sptr) || Protocol(cptr) < 10)
1829   {
1830     if (!(acptr = FindClient(user)))
1831     {
1832       /*
1833        * If the user has recently changed nick, we automaticly
1834        * rewrite the KILL for this new nickname--this keeps
1835        * servers in synch when nick change and kill collide
1836        */
1837       if (!(acptr = get_history(user, (long)15)))
1838       {
1839         sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], user);
1840         return 0;
1841       }
1842       sendto_one(sptr, ":%s NOTICE %s :Changed KILL %s into %s",
1843           me.name, parv[0], user, acptr->name);
1844       chasing = 1;
1845     }
1846   }
1847   else if (!(acptr = findNUser(user)))
1848   {
1849     if (Protocol(cptr) < 10 && IsUser(sptr))
1850       sendto_one(sptr,
1851           ":%s NOTICE %s :KILL target disconnected before I got him :(",
1852           me.name, parv[0]);
1853     else if (IsUser(sptr))
1854       sendto_one(sptr,
1855           "%s NOTICE %s%s :KILL target disconnected before I got him :(",
1856           NumServ(&me), NumNick(sptr));
1857     return 0;
1858   }
1859   if (!MyConnect(acptr) && IsLocOp(cptr))
1860   {
1861     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1862     return 0;
1863   }
1864   if (IsServer(acptr) || IsMe(acptr))
1865   {
1866     sendto_one(sptr, err_str(ERR_CANTKILLSERVER), me.name, parv[0]);
1867     return 0;
1868   }
1869
1870   /* if the user is +k, prevent a kill from local user */
1871   if (IsChannelService(acptr) && MyUser(sptr))
1872   {
1873     sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
1874         parv[0], "KILL", acptr->name);
1875     return 0;
1876   }
1877
1878 #ifdef  LOCAL_KILL_ONLY
1879   if (MyConnect(sptr) && !MyConnect(acptr))
1880   {
1881     sendto_one(sptr, ":%s NOTICE %s :Nick %s isnt on your server",
1882         me.name, parv[0], acptr->name);
1883     return 0;
1884   }
1885 #endif
1886   if (!IsServer(cptr))
1887   {
1888     /*
1889      * The kill originates from this server, initialize path.
1890      * (In which case the 'path' may contain user suplied
1891      * explanation ...or some nasty comment, sigh... >;-)
1892      *
1893      * ...!operhost!oper
1894      * ...!operhost!oper (comment)
1895      */
1896     if (IsUnixSocket(cptr))     /* Don't use get_client_name syntax */
1897       inpath = me.sockhost;
1898     else
1899       inpath = cptr->sockhost;
1900     if (!BadPtr(path))
1901     {
1902       sprintf_irc(buf,
1903           "%s%s (%s)", cptr->name, IsOper(sptr) ? "" : "(L)", path);
1904       path = buf;
1905     }
1906     else
1907       path = cptr->name;
1908   }
1909   else if (BadPtr(path))
1910     path = "*no-path*";         /* Bogus server sending??? */
1911   /*
1912    * Notify all *local* opers about the KILL (this includes the one
1913    * originating the kill, if from this server--the special numeric
1914    * reply message is not generated anymore).
1915    *
1916    * Note: "acptr->name" is used instead of "user" because we may
1917    *       have changed the target because of the nickname change.
1918    */
1919   if (IsLocOp(sptr) && !MyConnect(acptr))
1920   {
1921     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1922     return 0;
1923   }
1924   sendto_op_mask(IsServer(sptr) ? SNO_SERVKILL : SNO_OPERKILL,
1925       "Received KILL message for %s. From %s Path: %s!%s",
1926       acptr->name, parv[0], inpath, path);
1927 #if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
1928   if (MyUser(acptr))
1929   {                             /* get more infos when your local
1930                                    clients are killed -- _dl */
1931     if (IsServer(sptr))
1932       syslog(LOG_DEBUG,
1933           "A local client %s!%s@%s KILLED from %s [%s] Path: %s!%s)",
1934           acptr->name, acptr->user->username, acptr->user->host,
1935           parv[0], sptr->name, inpath, path);
1936     else
1937       syslog(LOG_DEBUG,
1938           "A local client %s!%s@%s KILLED by %s [%s!%s@%s] (%s!%s)",
1939           acptr->name, acptr->user->username, acptr->user->host,
1940           parv[0], sptr->name, sptr->user->username, sptr->user->host,
1941           inpath, path);
1942   }
1943   else if (IsOper(sptr))
1944     syslog(LOG_DEBUG, "KILL From %s For %s Path %s!%s",
1945         parv[0], acptr->name, inpath, path);
1946 #endif
1947   /*
1948    * And pass on the message to other servers. Note, that if KILL
1949    * was changed, the message has to be sent to all links, also
1950    * back.
1951    * Suicide kills are NOT passed on --SRB
1952    */
1953   if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
1954   {
1955     sendto_lowprot_butone(cptr, 9, ":%s KILL %s :%s!%s",
1956         parv[0], acptr->name, inpath, path);
1957     sendto_highprot_butone(cptr, 10, ":%s KILL %s%s :%s!%s",
1958         parv[0], NumNick(acptr), inpath, path);
1959 #ifndef NO_PROTOCOL9
1960     if (chasing && IsServer(cptr))      /* Can be removed when all are Protocol 10 */
1961       sendto_one(cptr, ":%s KILL %s :%s!%s",
1962           me.name, acptr->name, inpath, path);
1963 #endif
1964     /* We *can* have crossed a NICK with this numeric... --Run */
1965     /* Note the following situation:
1966      *  KILL SAA -->       X
1967      *  <-- S NICK ... SAA | <-- SAA QUIT <-- S NICK ... SAA <-- SQUIT S
1968      * Where the KILL reaches point X before the QUIT does.
1969      * This would then *still* cause an orphan because the KILL doesn't reach S
1970      * (because of the SQUIT), the QUIT is ignored (because of the KILL)
1971      * and the second NICK ... SAA causes an orphan on the server at the
1972      * right (which then isn't removed when the SQUIT arrives).
1973      * Therefore we still need to detect numeric nick collisions too.
1974      */
1975     if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1976       sendto_one(cptr, "%s KILL %s%s :%s!%s (Ghost5)",
1977           NumServ(&me), NumNick(acptr), inpath, path);
1978     acptr->flags |= FLAGS_KILLED;
1979   }
1980
1981   /*
1982    * Tell the victim she/he has been zapped, but *only* if
1983    * the victim is on current server--no sense in sending the
1984    * notification chasing the above kill, it won't get far
1985    * anyway (as this user don't exist there any more either)
1986    */
1987   if (MyConnect(acptr))
1988     sendto_prefix_one(acptr, sptr, ":%s KILL %s :%s!%s",
1989         parv[0], acptr->name, inpath, path);
1990   /*
1991    * Set FLAGS_KILLED. This prevents exit_one_client from sending
1992    * the unnecessary QUIT for this. (This flag should never be
1993    * set in any other place)
1994    */
1995   if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))
1996     sprintf_irc(buf2, "Local kill by %s (%s)", sptr->name,
1997         BadPtr(parv[parc - 1]) ? sptr->name : parv[parc - 1]);
1998   else
1999   {
2000     if ((killer = strchr(path, ' ')))
2001     {
2002       while (*killer && *killer != '!')
2003         killer--;
2004       if (!*killer)
2005         killer = path;
2006       else
2007         killer++;
2008     }
2009     else
2010       killer = path;
2011     sprintf_irc(buf2, "Killed (%s)", killer);
2012   }
2013   return exit_client(cptr, acptr, sptr, buf2);
2014 }
2015
2016 /*
2017  * m_away                               - Added 14 Dec 1988 by jto.
2018  *
2019  * parv[0] = sender prefix
2020  * parv[1] = away message
2021  */
2022 int m_away(aClient *cptr, aClient *sptr, int parc, char *parv[])
2023 {
2024   Reg1 char *away, *awy2 = parv[1];
2025
2026   away = sptr->user->away;
2027
2028   if (parc < 2 || !*awy2)
2029   {
2030     /* Marking as not away */
2031     if (away)
2032     {
2033       RunFree(away);
2034       sptr->user->away = NULL;
2035     }
2036     sendto_serv_butone(cptr, ":%s AWAY", parv[0]);
2037     if (MyConnect(sptr))
2038       sendto_one(sptr, rpl_str(RPL_UNAWAY), me.name, parv[0]);
2039     return 0;
2040   }
2041
2042   /* Marking as away */
2043
2044   if (strlen(awy2) > (size_t)TOPICLEN)
2045     awy2[TOPICLEN] = '\0';
2046   sendto_serv_butone(cptr, ":%s AWAY :%s", parv[0], awy2);
2047
2048   if (away)
2049     away = (char *)RunRealloc(away, strlen(awy2) + 1);
2050   else
2051     away = (char *)RunMalloc(strlen(awy2) + 1);
2052
2053   sptr->user->away = away;
2054   strcpy(away, awy2);
2055   if (MyConnect(sptr))
2056     sendto_one(sptr, rpl_str(RPL_NOWAWAY), me.name, parv[0]);
2057   return 0;
2058 }
2059
2060 /*
2061  * m_ping
2062  *
2063  * parv[0] = sender prefix
2064  * parv[1] = origin
2065  * parv[2] = destination
2066  */
2067 int m_ping(aClient *cptr, aClient *sptr, int parc, char *parv[])
2068 {
2069   aClient *acptr;
2070   char *origin, *destination;
2071
2072   if (parc < 2 || *parv[1] == '\0')
2073   {
2074     sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
2075     return 0;
2076   }
2077   origin = parv[1];
2078   destination = parv[2];        /* Will get NULL or pointer (parc >= 2!!) */
2079
2080   acptr = FindClient(origin);
2081   if (acptr && acptr != sptr)
2082     origin = cptr->name;
2083
2084   if (!BadPtr(destination) && strCasediff(destination, me.name) != 0)
2085   {
2086     if ((acptr = FindServer(destination)))
2087       sendto_one(acptr, ":%s PING %s :%s", parv[0], origin, destination);
2088     else
2089     {
2090       sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
2091           me.name, parv[0], destination);
2092       return 0;
2093     }
2094   }
2095   else
2096     sendto_one(sptr, ":%s PONG %s :%s", me.name, me.name, origin);
2097   return 0;
2098 }
2099
2100 /*
2101  * m_pong
2102  *
2103  * parv[0] = sender prefix
2104  * parv[1] = origin
2105  * parv[2] = destination
2106  */
2107 int m_pong(aClient *cptr, aClient *sptr, int parc, char *parv[])
2108 {
2109   aClient *acptr;
2110   char *origin, *destination;
2111
2112   if (MyUser(sptr))
2113     return 0;
2114
2115   /* Check to see if this is a PONG :cookie reply from an
2116    * unregistered user.  If so, process it. -record       */
2117
2118   if ((!IsRegistered(sptr)) && (sptr->cookie != 0) &&
2119       (sptr->cookie != COOKIE_VERIFIED) && (parc > 1))
2120   {
2121     if (atol(parv[parc - 1]) == (long)sptr->cookie)
2122     {
2123       sptr->cookie = COOKIE_VERIFIED;
2124       if (sptr->user && *sptr->user->host && sptr->name[0])     /* NICK and
2125                                                                    USER OK */
2126         return register_user(cptr, sptr, sptr->name, sptr->user->username);
2127     }
2128     else
2129       sendto_one(sptr, ":%s %d %s :To connect, type /QUOTE PONG %u",
2130           me.name, ERR_BADPING, sptr->name, sptr->cookie);
2131
2132     return 0;
2133   }
2134
2135   if (parc < 2 || *parv[1] == '\0')
2136   {
2137     sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
2138     return 0;
2139   }
2140
2141   origin = parv[1];
2142   destination = parv[2];
2143   cptr->flags &= ~FLAGS_PINGSENT;
2144   sptr->flags &= ~FLAGS_PINGSENT;
2145
2146   if (!BadPtr(destination) && strCasediff(destination, me.name) != 0)
2147   {
2148     if ((acptr = FindClient(destination)))
2149       sendto_one(acptr, ":%s PONG %s %s", parv[0], origin, destination);
2150     else
2151     {
2152       sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
2153           me.name, parv[0], destination);
2154       return 0;
2155     }
2156   }
2157 #ifdef  DEBUGMODE
2158   else
2159     Debug((DEBUG_NOTICE, "PONG: %s %s",
2160         origin, destination ? destination : "*"));
2161 #endif
2162   return 0;
2163 }
2164
2165 static char umode_buf[2 * sizeof(user_modes) / sizeof(int)];
2166
2167 /*
2168  * added Sat Jul 25 07:30:42 EST 1992
2169  */
2170 static void send_umode_out(aClient *cptr, aClient *sptr, int old)
2171 {
2172   Reg1 int i;
2173   Reg2 aClient *acptr;
2174
2175   send_umode(NULL, sptr, old, SEND_UMODES);
2176
2177   for (i = highest_fd; i >= 0; i--)
2178     if ((acptr = loc_clients[i]) && IsServer(acptr) &&
2179         (acptr != cptr) && (acptr != sptr) && *umode_buf)
2180       sendto_one(acptr, ":%s MODE %s :%s", sptr->name, sptr->name, umode_buf);
2181
2182   if (cptr && MyUser(cptr))
2183     send_umode(cptr, sptr, old, ALL_UMODES);
2184 }
2185
2186 /*
2187  *  m_oper
2188  *    parv[0] = sender prefix
2189  *    parv[1] = oper name
2190  *    parv[2] = oper password
2191  */
2192 int m_oper(aClient *cptr, aClient *sptr, int parc, char *parv[])
2193 {
2194   aConfItem *aconf;
2195   char *name, *password, *encr;
2196 #ifdef CRYPT_OPER_PASSWORD
2197   char salt[3];
2198 #endif /* CRYPT_OPER_PASSWORD */
2199
2200   name = parc > 1 ? parv[1] : NULL;
2201   password = parc > 2 ? parv[2] : NULL;
2202
2203   if (!IsServer(cptr) && (BadPtr(name) || BadPtr(password)))
2204   {
2205     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "OPER");
2206     return 0;
2207   }
2208
2209   /* if message arrived from server, trust it, and set to oper */
2210
2211   if ((IsServer(cptr) || IsMe(cptr)) && !IsOper(sptr))
2212   {
2213     ++nrof.opers;
2214     sptr->flags |= FLAGS_OPER;
2215     sendto_serv_butone(cptr, ":%s MODE %s :+o", parv[0], parv[0]);
2216     if (IsMe(cptr))
2217       sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2218     return 0;
2219   }
2220   else if (IsAnOper(sptr))
2221   {
2222     if (MyConnect(sptr))
2223       sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2224     return 0;
2225   }
2226   if (!(aconf = find_conf_exact(name, sptr->username, sptr->sockhost,
2227       CONF_OPS)) && !(aconf = find_conf_exact(name, sptr->username,
2228       inetntoa(cptr->ip), CONF_OPS)))
2229   {
2230     sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
2231     sendto_realops("Failed OPER attempt by %s (%s@%s)",
2232         parv[0], sptr->user->username, sptr->sockhost);
2233     return 0;
2234   }
2235 #ifdef CRYPT_OPER_PASSWORD
2236   /* use first two chars of the password they send in as salt */
2237
2238   /* passwd may be NULL. Head it off at the pass... */
2239   salt[0] = '\0';
2240   if (password && aconf->passwd)
2241   {
2242     salt[0] = aconf->passwd[0];
2243     salt[1] = aconf->passwd[1];
2244     salt[2] = '\0';
2245     encr = crypt(password, salt);
2246   }
2247   else
2248     encr = "";
2249 #else
2250   encr = password;
2251 #endif /* CRYPT_OPER_PASSWORD */
2252
2253   if ((aconf->status & CONF_OPS) &&
2254       !strcmp(encr, aconf->passwd) && attach_conf(sptr, aconf) == ACR_OK)
2255   {
2256     int old = (sptr->flags & ALL_UMODES);
2257     char *s;
2258
2259     s = strchr(aconf->host, '@');
2260     *s++ = '\0';
2261 #ifdef  OPER_REMOTE
2262     if (aconf->status == CONF_LOCOP)
2263     {
2264 #else
2265     if ((match(s, me.sockhost) && !IsLocal(sptr)) ||
2266         aconf->status == CONF_LOCOP)
2267     {
2268 #endif
2269       ClearOper(sptr);
2270       SetLocOp(sptr);
2271     }
2272     else
2273     {
2274       /* prevent someone from being both oper and local oper */
2275       ClearLocOp(sptr);
2276       SetOper(sptr);
2277       ++nrof.opers;
2278     }
2279     *--s = '@';
2280     sendto_ops("%s (%s@%s) is now operator (%c)", parv[0],
2281         sptr->user->username, sptr->sockhost, IsOper(sptr) ? 'O' : 'o');
2282     sptr->flags |= (FLAGS_WALLOP | FLAGS_SERVNOTICE | FLAGS_DEBUG);
2283     set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
2284     send_umode_out(cptr, sptr, old);
2285     sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2286 #if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\
2287     (defined(USE_SYSLOG) && defined(SYSLOG_OPER)))
2288     encr = "";
2289 #endif
2290 #if defined(USE_SYSLOG) && defined(SYSLOG_OPER)
2291     syslog(LOG_INFO, "OPER (%s) (%s) by (%s!%s@%s)",
2292         name, encr, parv[0], sptr->user->username, sptr->sockhost);
2293 #endif
2294 #ifdef FNAME_OPERLOG
2295     if (IsUser(sptr))
2296       write_log(FNAME_OPERLOG,
2297           "%s OPER (%s) (%s) by (%s!%s@%s)\n", myctime(now), name,
2298           encr, parv[0], sptr->user->username, sptr->sockhost);
2299 #endif
2300   }
2301   else
2302   {
2303     detach_conf(sptr, aconf);
2304     sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
2305     sendto_realops("Failed OPER attempt by %s (%s@%s)",
2306         parv[0], sptr->user->username, sptr->sockhost);
2307   }
2308   return 0;
2309 }
2310
2311 /*
2312  * m_pass
2313  *
2314  * parv[0] = sender prefix
2315  * parv[1] = password
2316  */
2317 int m_pass(aClient *cptr, aClient *sptr, int parc, char *parv[])
2318 {
2319   char *password = parc > 1 ? parv[1] : NULL;
2320
2321   if (BadPtr(password))
2322   {
2323     sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PASS");
2324     return 0;
2325   }
2326   if (!MyConnect(sptr) || (!IsUnknown(cptr) && !IsHandshake(cptr)))
2327   {
2328     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
2329     return 0;
2330   }
2331   strncpy(cptr->passwd, password, sizeof(cptr->passwd) - 1);
2332   return 0;
2333 }
2334
2335 /*
2336  * m_userhost
2337  *
2338  * Added by Darren Reed 13/8/91 to aid clients and reduce the need for
2339  * complicated requests like WHOIS.
2340  *
2341  * Returns user/host information only (no spurious AWAY labels or channels).
2342  *
2343  * Rewritten to speed it up by Carlo Wood 3/8/97.
2344  */
2345 int m_userhost(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2346 {
2347   Reg1 char *s;
2348   Reg2 int i, j = 5;
2349   char *p = NULL, *sbuf;
2350   aClient *acptr;
2351
2352   if (parc < 2)
2353   {
2354     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERHOST");
2355     return 0;
2356   }
2357
2358   sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERHOST), me.name, parv[0]);
2359   for (i = j, s = strtoken(&p, parv[1], " "); i && s;
2360       s = strtoken(&p, (char *)NULL, " "), i--)
2361     if ((acptr = FindUser(s)))
2362     {
2363       if (i < j)
2364         *sbuf++ = ' ';
2365       sbuf = sprintf_irc(sbuf, "%s%s=%c%s@%s", acptr->name,
2366           IsAnOper(acptr) ? "*" : "", (acptr->user->away) ? '-' : '+',
2367           acptr->user->username, acptr->user->host);
2368     }
2369     else
2370     {
2371       if (i < j)
2372         sendbufto_one(sptr);
2373       sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], s);
2374       sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERHOST), me.name, parv[0]);
2375       j = i - 1;
2376     }
2377   if (j)
2378     sendbufto_one(sptr);
2379   return 0;
2380 }
2381
2382 /*
2383  * m_userip added by Carlo Wood 3/8/97.
2384  *
2385  * The same as USERHOST, but with the IP-number instead of the hostname.
2386  */
2387 int m_userip(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2388 {
2389   Reg1 char *s;
2390   Reg3 int i, j = 5;
2391   char *p = NULL, *sbuf;
2392   aClient *acptr;
2393
2394   if (parc < 2)
2395   {
2396     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERIP");
2397     return 0;
2398   }
2399
2400   sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERIP), me.name, parv[0]);
2401   for (i = j, s = strtoken(&p, parv[1], " "); i && s;
2402       s = strtoken(&p, (char *)NULL, " "), i--)
2403     if ((acptr = FindUser(s)))
2404     {
2405       if (i < j)
2406         *sbuf++ = ' ';
2407       sbuf = sprintf_irc(sbuf, "%s%s=%c%s@%s", acptr->name,
2408           IsAnOper(acptr) ? "*" : "", (acptr->user->away) ? '-' : '+',
2409           acptr->user->username, inetntoa(acptr->ip));
2410     }
2411     else
2412     {
2413       if (i < j)
2414         sendbufto_one(sptr);
2415       sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], s);
2416       sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERIP), me.name, parv[0]);
2417       j = i - 1;
2418     }
2419   if (i < j)
2420     sendbufto_one(sptr);
2421   return 0;
2422 }
2423
2424 /*
2425  * m_ison
2426  *
2427  * Added by Darren Reed 13/8/91 to act as an efficent user indicator
2428  * with respect to cpu/bandwidth used. Implemented for NOTIFY feature in
2429  * clients. Designed to reduce number of whois requests. Can process
2430  * nicknames in batches as long as the maximum buffer length.
2431  *
2432  * format:
2433  * ISON :nicklist
2434  */
2435
2436 int m_ison(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2437 {
2438   Reg1 aClient *acptr;
2439   Reg2 char *s, **pav = parv;
2440   Reg3 size_t len;
2441   char *p = NULL;
2442
2443   if (parc < 2)
2444   {
2445     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "ISON");
2446     return 0;
2447   }
2448
2449   sprintf_irc(buf, rpl_str(RPL_ISON), me.name, *parv);
2450   len = strlen(buf);
2451   buf[sizeof(buf) - 1] = 0;
2452
2453   for (s = strtoken(&p, *++pav, " "); s; s = strtoken(&p, NULL, " "))
2454     if ((acptr = FindUser(s)))
2455     {
2456       strncat(buf, acptr->name, sizeof(buf) - 1 - len);
2457       len += strlen(acptr->name);
2458       if (len >= sizeof(buf) - 1)
2459         break;
2460       strcat(buf, " ");
2461       len++;
2462     }
2463   sendto_one(sptr, "%s", buf);
2464   return 0;
2465 }
2466
2467 /*
2468  * m_umode() added 15/10/91 By Darren Reed.
2469  *
2470  * parv[0] - sender
2471  * parv[1] - username to change mode for
2472  * parv[2] - modes to change
2473  */
2474 int m_umode(aClient *cptr, aClient *sptr, int parc, char *parv[])
2475 {
2476   Reg1 int flag;
2477   Reg2 int *s;
2478   Reg3 char **p, *m;
2479   aClient *acptr;
2480   int what, setflags;
2481   snomask_t tmpmask = 0;
2482   int snomask_given = 0;
2483
2484   what = MODE_ADD;
2485
2486   if (parc < 2)
2487   {
2488     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
2489     return 0;
2490   }
2491
2492   if (!(acptr = FindUser(parv[1])))
2493   {
2494     if (MyConnect(sptr))
2495       sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
2496     return 0;
2497   }
2498
2499   if (IsServer(sptr) || sptr != acptr)
2500   {
2501     if (IsServer(cptr))
2502       sendto_ops_butone(NULL, &me, ":%s WALLOPS :MODE for User %s From %s!%s",
2503           me.name, parv[1], get_client_name(cptr, FALSE), sptr->name);
2504     else
2505       sendto_one(sptr, err_str(ERR_USERSDONTMATCH), me.name, parv[0]);
2506     return 0;
2507   }
2508
2509   if (parc < 3)
2510   {
2511     m = buf;
2512     *m++ = '+';
2513     for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4); s += 2)
2514       if (sptr->flags & flag)
2515         *m++ = (char)(*(s + 1));
2516     *m = '\0';
2517     sendto_one(sptr, rpl_str(RPL_UMODEIS), me.name, parv[0], buf);
2518     if ((sptr->flags & FLAGS_SERVNOTICE) && MyConnect(sptr)
2519         && sptr->snomask !=
2520         (unsigned int)(IsOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT))
2521       sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, parv[0], sptr->snomask,
2522           sptr->snomask);
2523     return 0;
2524   }
2525
2526   /* find flags already set for user */
2527   setflags = 0;
2528   for (s = user_modes; (flag = *s); s += 2)
2529     if (sptr->flags & flag)
2530       setflags |= flag;
2531   if (MyConnect(sptr))
2532     tmpmask = sptr->snomask;
2533
2534   /*
2535    * parse mode change string(s)
2536    */
2537   for (p = &parv[2]; *p; p++)   /* p is changed in loop too */
2538     for (m = *p; *m; m++)
2539       switch (*m)
2540       {
2541         case '+':
2542           what = MODE_ADD;
2543           break;
2544         case '-':
2545           what = MODE_DEL;
2546           break;
2547         case 's':
2548           if (*(p + 1) && is_snomask(*(p + 1)))
2549           {
2550             snomask_given = 1;
2551             tmpmask = umode_make_snomask(tmpmask, *++p, what);
2552             tmpmask &= (IsAnOper(sptr) ? SNO_ALL : SNO_USER);
2553           }
2554           else
2555             tmpmask = (what == MODE_ADD) ?
2556                 (IsAnOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT) : 0;
2557           if (tmpmask)
2558             sptr->flags |= FLAGS_SERVNOTICE;
2559           else
2560             sptr->flags &= ~FLAGS_SERVNOTICE;
2561           break;
2562           /*
2563            * We may not get these, but they shouldnt be in default:
2564            */
2565         case ' ':
2566         case '\n':
2567         case '\r':
2568         case '\t':
2569           break;
2570         default:
2571           for (s = user_modes; (flag = *s); s += 2)
2572             if (*m == (char)(*(s + 1)))
2573             {
2574               if (what == MODE_ADD)
2575                 sptr->flags |= flag;
2576               else if ((flag & (FLAGS_OPER | FLAGS_LOCOP)))
2577               {
2578                 sptr->flags &= ~(FLAGS_OPER | FLAGS_LOCOP);
2579                 if (MyConnect(sptr))
2580                   tmpmask = sptr->snomask & ~SNO_OPER;
2581               }
2582               /* allow either -o or -O to reset all operator status's... */
2583               else
2584                 sptr->flags &= ~flag;
2585               break;
2586             }
2587           if (flag == 0 && MyConnect(sptr))
2588             sendto_one(sptr, err_str(ERR_UMODEUNKNOWNFLAG), me.name, parv[0]);
2589           break;
2590       }
2591   /*
2592    * Stop users making themselves operators too easily:
2593    */
2594   if (!(setflags & FLAGS_OPER) && IsOper(sptr) && !IsServer(cptr))
2595     ClearOper(sptr);
2596   if (!(setflags & FLAGS_LOCOP) && IsLocOp(sptr) && !IsServer(cptr))
2597     sptr->flags &= ~FLAGS_LOCOP;
2598   if ((setflags & (FLAGS_OPER | FLAGS_LOCOP)) && !IsAnOper(sptr) &&
2599       MyConnect(sptr))
2600     det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
2601   /* new umode; servers can set it, local users cannot;
2602    * prevents users from /kick'ing or /mode -o'ing */
2603   if (!(setflags & FLAGS_CHSERV) && !IsServer(cptr))
2604     sptr->flags &= ~FLAGS_CHSERV;
2605   /*
2606    * Compare new flags with old flags and send string which
2607    * will cause servers to update correctly.
2608    */
2609   if ((setflags & FLAGS_OPER) && !IsOper(sptr))
2610     --nrof.opers;
2611   if (!(setflags & FLAGS_OPER) && IsOper(sptr))
2612     ++nrof.opers;
2613   if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
2614     --nrof.inv_clients;
2615   if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr))
2616     ++nrof.inv_clients;
2617   send_umode_out(cptr, sptr, setflags);
2618
2619   if (MyConnect(sptr))
2620   {
2621     if (tmpmask != sptr->snomask)
2622       set_snomask(sptr, tmpmask, SNO_SET);
2623     if (sptr->snomask && snomask_given)
2624       sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
2625           sptr->snomask, sptr->snomask);
2626   }
2627
2628   return 0;
2629 }
2630
2631 /*
2632  * Build umode string for BURST command
2633  * --Run
2634  */
2635 char *umode_str(aClient *cptr)
2636 {
2637   char *m = umode_buf;          /* Maximum string size: "owidg\0" */
2638   int *s, flag, c_flags;
2639
2640   c_flags = cptr->flags & SEND_UMODES;  /* cleaning up the original code */
2641
2642   for (s = user_modes; (flag = *s); s += 2)
2643     if ((c_flags & flag))
2644       *m++ = *(s + 1);
2645   *m = '\0';
2646
2647   return umode_buf;             /* Note: static buffer, gets
2648                                    overwritten by send_umode() */
2649 }
2650
2651 /*
2652  * Send the MODE string for user (user) to connection cptr
2653  * -avalon
2654  */
2655 void send_umode(aClient *cptr, aClient *sptr, int old, int sendmask)
2656 {
2657   Reg1 int *s, flag;
2658   Reg2 char *m;
2659   int what = MODE_NULL;
2660
2661   /*
2662    * Build a string in umode_buf to represent the change in the user's
2663    * mode between the new (sptr->flag) and 'old'.
2664    */
2665   m = umode_buf;
2666   *m = '\0';
2667   for (s = user_modes; (flag = *s); s += 2)
2668   {
2669     if (MyUser(sptr) && !(flag & sendmask))
2670       continue;
2671     if ((flag & old) && !(sptr->flags & flag))
2672     {
2673       if (what == MODE_DEL)
2674         *m++ = *(s + 1);
2675       else
2676       {
2677         what = MODE_DEL;
2678         *m++ = '-';
2679         *m++ = *(s + 1);
2680       }
2681     }
2682     else if (!(flag & old) && (sptr->flags & flag))
2683     {
2684       if (what == MODE_ADD)
2685         *m++ = *(s + 1);
2686       else
2687       {
2688         what = MODE_ADD;
2689         *m++ = '+';
2690         *m++ = *(s + 1);
2691       }
2692     }
2693   }
2694   *m = '\0';
2695   if (*umode_buf && cptr)
2696     sendto_one(cptr, ":%s MODE %s :%s", sptr->name, sptr->name, umode_buf);
2697 }
2698
2699 /*
2700  * Check to see if this resembles a sno_mask.  It is if 1) there is
2701  * at least one digit and 2) The first digit occurs before the first
2702  * alphabetic character.
2703  */
2704 int is_snomask(char *word)
2705 {
2706   if (word)
2707   {
2708     for (; *word; word++)
2709       if (isDigit(*word))
2710         return 1;
2711       else if (isAlpha(*word))
2712         return 0;
2713   }
2714   return 0;
2715 }
2716
2717 /*
2718  * If it begins with a +, count this as an additive mask instead of just
2719  * a replacement.  If what == MODE_DEL, "+" has no special effect.
2720  */
2721 snomask_t umode_make_snomask(snomask_t oldmask, char *arg, int what)
2722 {
2723   snomask_t sno_what;
2724   snomask_t newmask;
2725   if (*arg == '+')
2726   {
2727     arg++;
2728     if (what == MODE_ADD)
2729       sno_what = SNO_ADD;
2730     else
2731       sno_what = SNO_DEL;
2732   }
2733   else if (*arg == '-')
2734   {
2735     arg++;
2736     if (what == MODE_ADD)
2737       sno_what = SNO_DEL;
2738     else
2739       sno_what = SNO_ADD;
2740   }
2741   else
2742     sno_what = (what == MODE_ADD) ? SNO_SET : SNO_DEL;
2743   /* pity we don't have strtoul everywhere */
2744   newmask = (snomask_t)atoi(arg);
2745   if (sno_what == SNO_DEL)
2746     newmask = oldmask & ~newmask;
2747   else if (sno_what == SNO_ADD)
2748     newmask |= oldmask;
2749   return newmask;
2750 }
2751
2752 /*
2753  * This function sets a Client's server notices mask, according to
2754  * the parameter 'what'.  This could be even faster, but the code
2755  * gets mighty hard to read :)
2756  */
2757 void delfrom_list(aClient *, Link **);
2758 void set_snomask(aClient *cptr, snomask_t newmask, int what)
2759 {
2760   snomask_t oldmask, diffmask;  /* unsigned please */
2761   int i;
2762   Link *tmp;
2763
2764   oldmask = cptr->snomask;
2765
2766   if (what == SNO_ADD)
2767     newmask |= oldmask;
2768   else if (what == SNO_DEL)
2769     newmask = oldmask & ~newmask;
2770   else if (what != SNO_SET)     /* absolute set, no math needed */
2771     sendto_ops("setsnomask called with %d ?!", what);
2772
2773   newmask &= (IsAnOper(cptr) ? SNO_ALL : SNO_USER);
2774
2775   diffmask = oldmask ^ newmask;
2776
2777   for (i = 0; diffmask >> i; i++)
2778     if (((diffmask >> i) & 1))
2779     {
2780       if (((newmask >> i) & 1))
2781       {
2782         tmp = make_link();
2783         tmp->next = opsarray[i];
2784         tmp->value.cptr = cptr;
2785         opsarray[i] = tmp;
2786       }
2787       else
2788         /* not real portable :( */
2789         delfrom_list(cptr, &opsarray[i]);
2790     }
2791   cptr->snomask = newmask;
2792 }
2793
2794 void delfrom_list(aClient *cptr, Link **list)
2795 {
2796   Link *tmp, *prv = NULL;
2797   for (tmp = *list; tmp; tmp = tmp->next)
2798   {
2799     if (tmp->value.cptr == cptr)
2800     {
2801       if (prv)
2802         prv->next = tmp->next;
2803       else
2804         *list = tmp->next;
2805       free_link(tmp);
2806       break;
2807     }
2808     prv = tmp;
2809   }
2810 }
2811
2812 /*
2813  * is_silenced : Does the actual check wether sptr is allowed
2814  *               to send a message to acptr.
2815  *               Both must be registered persons.
2816  * If sptr is silenced by acptr, his message should not be propagated,
2817  * but more over, if this is detected on a server not local to sptr
2818  * the SILENCE mask is sent upstream.
2819  */
2820 int is_silenced(aClient *sptr, aClient *acptr)
2821 {
2822   Reg1 Link *lp;
2823   Reg2 anUser *user;
2824   static char sender[HOSTLEN + NICKLEN + USERLEN + 5];
2825   static char senderip[16 + NICKLEN + USERLEN + 5];
2826
2827   if (!(acptr->user) || !(lp = acptr->user->silence) || !(user = sptr->user))
2828     return 0;
2829   sprintf_irc(sender, "%s!%s@%s", sptr->name, user->username, user->host);
2830   sprintf_irc(senderip, "%s!%s@%s", sptr->name, user->username,
2831       inetntoa(sptr->ip));
2832   for (; lp; lp = lp->next)
2833   {
2834     if ((!(lp->flags & CHFL_SILENCE_IPMASK) && !match(lp->value.cp, sender)) ||
2835         ((lp->flags & CHFL_SILENCE_IPMASK) && !match(lp->value.cp, senderip)))
2836     {
2837       if (!MyConnect(sptr))
2838       {
2839         if (Protocol(sptr->from) < 10)
2840           sendto_one(sptr->from, ":%s SILENCE %s %s", acptr->name,
2841               sptr->name, lp->value.cp);
2842         else
2843           sendto_one(sptr->from, ":%s SILENCE %s%s %s", acptr->name,
2844               NumNick(sptr), lp->value.cp);
2845       }
2846       return 1;
2847     }
2848   }
2849   return 0;
2850 }
2851
2852 /*
2853  * del_silence
2854  *
2855  * Removes all silence masks from the list of sptr that fall within `mask'
2856  * Returns -1 if none where found, 0 otherwise.
2857  */
2858 int del_silence(aClient *sptr, char *mask)
2859 {
2860   Reg1 Link **lp;
2861   Reg2 Link *tmp;
2862   int ret = -1;
2863
2864   for (lp = &sptr->user->silence; *lp;)
2865     if (!mmatch(mask, (*lp)->value.cp))
2866     {
2867       tmp = *lp;
2868       *lp = tmp->next;
2869       RunFree(tmp->value.cp);
2870       free_link(tmp);
2871       ret = 0;
2872     }
2873     else
2874       lp = &(*lp)->next;
2875
2876   return ret;
2877 }
2878
2879 static int add_silence(aClient *sptr, char *mask)
2880 {
2881   Reg1 Link *lp, **lpp;
2882   Reg3 int cnt = 0, len = strlen(mask);
2883   char *ip_start;
2884
2885   for (lpp = &sptr->user->silence, lp = *lpp; lp;)
2886   {
2887     if (!strCasediff(mask, lp->value.cp))
2888       return -1;
2889     if (!mmatch(mask, lp->value.cp))
2890     {
2891       Link *tmp = lp;
2892       *lpp = lp = lp->next;
2893       RunFree(tmp->value.cp);
2894       free_link(tmp);
2895       continue;
2896     }
2897     if (MyUser(sptr))
2898     {
2899       len += strlen(lp->value.cp);
2900       if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
2901       {
2902         sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
2903         return -1;
2904       }
2905       else if (!mmatch(lp->value.cp, mask))
2906         return -1;
2907     }
2908     lpp = &lp->next;
2909     lp = *lpp;
2910   }
2911   lp = make_link();
2912   memset(lp, 0, sizeof(Link));
2913   lp->next = sptr->user->silence;
2914   lp->value.cp = (char *)RunMalloc(strlen(mask) + 1);
2915   strcpy(lp->value.cp, mask);
2916   if ((ip_start = strrchr(mask, '@')) && check_if_ipmask(ip_start + 1))
2917     lp->flags = CHFL_SILENCE_IPMASK;
2918   sptr->user->silence = lp;
2919   return 0;
2920 }
2921
2922 /*
2923  * m_silence() - Added 19 May 1994 by Run.
2924  *
2925  *   parv[0] = sender prefix
2926  * From local client:
2927  *   parv[1] = mask (NULL sends the list)
2928  * From remote client:
2929  *   parv[1] = Numeric nick that must be silenced
2930  *   parv[2] = mask
2931  */
2932 int m_silence(aClient *cptr, aClient *sptr, int parc, char *parv[])
2933 {
2934   Link *lp;
2935   aClient *acptr;
2936   char c, *cp;
2937
2938   if (MyUser(sptr))
2939   {
2940     acptr = sptr;
2941     if (parc < 2 || *parv[1] == '\0' || (acptr = FindUser(parv[1])))
2942     {
2943       if (!(acptr->user))
2944         return 0;
2945       for (lp = acptr->user->silence; lp; lp = lp->next)
2946         sendto_one(sptr, rpl_str(RPL_SILELIST), me.name,
2947             sptr->name, acptr->name, lp->value.cp);
2948       sendto_one(sptr, rpl_str(RPL_ENDOFSILELIST), me.name, sptr->name,
2949           acptr->name);
2950       return 0;
2951     }
2952     cp = parv[1];
2953     c = *cp;
2954     if (c == '-' || c == '+')
2955       cp++;
2956     else if (!(strchr(cp, '@') || strchr(cp, '.') ||
2957         strchr(cp, '!') || strchr(cp, '*')))
2958     {
2959       sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
2960       return -1;
2961     }
2962     else
2963       c = '+';
2964     cp = pretty_mask(cp);
2965     if ((c == '-' && !del_silence(sptr, cp)) ||
2966         (c != '-' && !add_silence(sptr, cp)))
2967     {
2968       sendto_prefix_one(sptr, sptr, ":%s SILENCE %c%s", parv[0], c, cp);
2969       if (c == '-')
2970         sendto_serv_butone(NULL, ":%s SILENCE * -%s", sptr->name, cp);
2971     }
2972   }
2973   else if (parc < 3 || *parv[2] == '\0')
2974   {
2975     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SILENCE");
2976     return -1;
2977   }
2978   else
2979   {
2980     if (Protocol(cptr) < 10)
2981       acptr = FindClient(parv[1]);      /* In case of NOTE notice, parv[1] */
2982     else if (parv[1][1])        /* can be a server */
2983       acptr = findNUser(parv[1]);
2984     else
2985       acptr = FindNServer(parv[1]);
2986
2987     if (*parv[2] == '-')
2988     {
2989       if (!del_silence(sptr, parv[2] + 1))
2990         sendto_serv_butone(cptr, ":%s SILENCE * %s", parv[0], parv[2]);
2991     }
2992     else
2993     {
2994       add_silence(sptr, parv[2]);
2995       if (acptr && IsServer(acptr->from))
2996       {
2997         if (Protocol(acptr->from) < 10)
2998           sendto_one(acptr, ":%s SILENCE %s %s", parv[0], acptr->name, parv[2]);
2999         else if (IsServer(acptr))
3000           sendto_one(acptr, ":%s SILENCE %s %s",
3001               parv[0], NumServ(acptr), parv[2]);
3002         else
3003           sendto_one(acptr, ":%s SILENCE %s%s %s",
3004               parv[0], NumNick(acptr), parv[2]);
3005       }
3006     }
3007   }
3008   return 0;
3009 }