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