home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / ircd4652.zip / ircd-df-4.6.5-os2 / src / s_user.c < prev    next >
C/C++ Source or Header  |  1998-06-06  |  99KB  |  3,408 lines

  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. #ifndef lint
  25. static  char sccsid[] = "@(#)s_user.c    2.74 2/8/94 (C) 1988 University of Oulu, \
  26. Computing Center and Jarkko Oikarinen";
  27. #endif
  28.  
  29. #include "struct.h"
  30. #include "common.h"
  31. #include "sys.h"
  32. #include "numeric.h"
  33. #include "msg.h"
  34. #include "channel.h"
  35. #include "userload.h"
  36. #include <sys/stat.h>
  37. #if !defined _WIN32 && !defined __EMX__
  38. #include <utmp.h>
  39. #else
  40. #include <io.h>
  41. #endif
  42. #include <fcntl.h>
  43. #include "h.h"
  44.  
  45. void    send_umode_out PROTO((aClient*, aClient *, int));
  46. void    send_svsmode_out PROTO((aClient*, aClient *, aClient *, int));
  47. void    send_umode PROTO((aClient *, aClient *, int, int, char *));
  48. static    is_silenced PROTO((aClient *, aClient *));
  49. /* static  Link    *is_banned PROTO((aClient *, aChannel *)); */
  50.  
  51. static char buf[BUFSIZE], buf2[BUFSIZE];
  52.  
  53. /*
  54. ** m_functions execute protocol messages on this server:
  55. **
  56. **    cptr    is always NON-NULL, pointing to a *LOCAL* client
  57. **        structure (with an open socket connected!). This
  58. **        identifies the physical socket where the message
  59. **        originated (or which caused the m_function to be
  60. **        executed--some m_functions may call others...).
  61. **
  62. **    sptr    is the source of the message, defined by the
  63. **        prefix part of the message if present. If not
  64. **        or prefix not found, then sptr==cptr.
  65. **
  66. **        (!IsServer(cptr)) => (cptr == sptr), because
  67. **        prefixes are taken *only* from servers...
  68. **
  69. **        (IsServer(cptr))
  70. **            (sptr == cptr) => the message didn't
  71. **            have the prefix.
  72. **
  73. **            (sptr != cptr && IsServer(sptr) means
  74. **            the prefix specified servername. (?)
  75. **
  76. **            (sptr != cptr && !IsServer(sptr) means
  77. **            that message originated from a remote
  78. **            user (not local).
  79. **
  80. **        combining
  81. **
  82. **        (!IsServer(sptr)) means that, sptr can safely
  83. **        taken as defining the target structure of the
  84. **        message in this server.
  85. **
  86. **    *Always* true (if 'parse' and others are working correct):
  87. **
  88. **    1)    sptr->from == cptr  (note: cptr->from == cptr)
  89. **
  90. **    2)    MyConnect(sptr) <=> sptr == cptr (e.g. sptr
  91. **        *cannot* be a local connection, unless it's
  92. **        actually cptr!). [MyConnect(x) should probably
  93. **        be defined as (x == x->from) --msa ]
  94. **
  95. **    parc    number of variable parameter strings (if zero,
  96. **        parv is allowed to be NULL)
  97. **
  98. **    parv    a NULL terminated list of parameter pointers,
  99. **
  100. **            parv[0], sender (prefix string), if not present
  101. **                this points to an empty string.
  102. **            parv[1]...parv[parc-1]
  103. **                pointers to additional parameters
  104. **            parv[parc] == NULL, *always*
  105. **
  106. **        note:    it is guaranteed that parv[0]..parv[parc-1] are all
  107. **            non-NULL pointers.
  108. */
  109.  
  110. /*
  111. ** next_client
  112. **    Local function to find the next matching client. The search
  113. **    can be continued from the specified client entry. Normal
  114. **    usage loop is:
  115. **
  116. **    for (x = client; x = next_client(x,mask); x = x->next)
  117. **        HandleMatchingClient;
  118. **          
  119. */
  120. aClient *next_client(next, ch)
  121. Reg1    aClient *next;    /* First client to check */
  122. Reg2    char    *ch;    /* search string (may include wilds) */
  123. {
  124.     Reg3    aClient    *tmp = next;
  125.  
  126.     next = find_client(ch, tmp);
  127.     if (tmp && tmp->prev == next)
  128.         return NULL;
  129.     if (next != tmp)
  130.         return next;
  131.     for ( ; next; next = next->next)
  132.         {
  133.         if (IsService(next))
  134.             continue;
  135.         if (!match(ch, next->name) || !match(next->name, ch))
  136.             break;
  137.         }
  138.     return next;
  139. }
  140.  
  141. /*
  142. ** hunt_server
  143. **
  144. **    Do the basic thing in delivering the message (command)
  145. **    across the relays to the specific server (server) for
  146. **    actions.
  147. **
  148. **    Note:    The command is a format string and *MUST* be
  149. **        of prefixed style (e.g. ":%s COMMAND %s ...").
  150. **        Command can have only max 8 parameters.
  151. **
  152. **    server    parv[server] is the parameter identifying the
  153. **        target server.
  154. **
  155. **    *WARNING*
  156. **        parv[server] is replaced with the pointer to the
  157. **        real servername from the matched client (I'm lazy
  158. **        now --msa).
  159. **
  160. **    returns: (see #defines)
  161. */
  162. int    hunt_server(cptr, sptr, command, server, parc, parv)
  163. aClient    *cptr, *sptr;
  164. char    *command, *parv[];
  165. int    server, parc;
  166.     {
  167.     aClient *acptr;
  168.  
  169.     /*
  170.     ** Assume it's me, if no server
  171.     */
  172.     if (parc <= server || BadPtr(parv[server]) ||
  173.         match(me.name, parv[server]) == 0 ||
  174.         match(parv[server], me.name) == 0)
  175.         return (HUNTED_ISME);
  176.     /*
  177.     ** These are to pickup matches that would cause the following
  178.     ** message to go in the wrong direction while doing quick fast
  179.     ** non-matching lookups.
  180.     */
  181.     if ((acptr = find_client(parv[server], NULL)))
  182.         if (acptr->from == sptr->from && !MyConnect(acptr))
  183.             acptr = NULL;
  184.     if (!acptr && (acptr = find_server(parv[server], NULL)))
  185.         if (acptr->from == sptr->from && !MyConnect(acptr))
  186.             acptr = NULL;
  187.     if (!acptr)
  188.         for (acptr = client, (void)collapse(parv[server]);
  189.              (acptr = next_client(acptr, parv[server]));
  190.              acptr = acptr->next)
  191.             {
  192.             if (acptr->from == sptr->from && !MyConnect(acptr))
  193.                 continue;
  194.             /*
  195.              * Fix to prevent looping in case the parameter for
  196.              * some reason happens to match someone from the from
  197.              * link --jto
  198.              */
  199.             if (IsRegistered(acptr) && (acptr != cptr))
  200.                 break;
  201.             }
  202.      if (acptr)
  203.         {
  204.         if (IsMe(acptr) || MyClient(acptr))
  205.             return HUNTED_ISME;
  206.         if (match(acptr->name, parv[server]))
  207.             parv[server] = acptr->name;
  208.         sendto_one(acptr, command, parv[0],
  209.                parv[1], parv[2], parv[3], parv[4],
  210.                parv[5], parv[6], parv[7], parv[8]);
  211.         return(HUNTED_PASS);
  212.         } 
  213.     sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name,
  214.            parv[0], parv[server]);
  215.     return(HUNTED_NOSUCH);
  216.     }
  217.  
  218. /*
  219. ** check_for_target_limit
  220. **
  221. ** Return Values:
  222. ** True(1) == too many targets are addressed
  223. ** False(0) == ok to send message
  224. **
  225. */
  226. int check_for_target_limit(aClient *sptr, void *target, const char *name)
  227. {
  228.     register u_char *p;
  229.     register u_int tmp = ((u_int)target & 0xffff00) >> 8;
  230.  
  231.     u_char hash = (tmp * tmp) >> 12;
  232.  
  233.     if(IsAnOper(sptr))
  234.         return 0;
  235.     if (sptr->targets[0] == hash)
  236.         return 0;
  237.  
  238.     for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
  239.         if (*++p == hash) {
  240.             memmove(&sptr->targets[1], &sptr->targets[0], p - sptr->targets);
  241.             sptr->targets[0] = hash;
  242.             return 0;
  243.         }
  244.  
  245.     if (now < sptr->nexttarget) {
  246.         if (sptr->nexttarget - now < TARGET_DELAY + 8) {
  247.             sptr->nexttarget += 2;
  248.             sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
  249.                 me.name, sptr->name, name, sptr->nexttarget - now);
  250.         }
  251.     return 1;
  252.     } else {
  253.         sptr->nexttarget += TARGET_DELAY;
  254.         if (sptr->nexttarget < now - (TARGET_DELAY * (MAXTARGETS - 1)))
  255.             sptr->nexttarget = now - (TARGET_DELAY * (MAXTARGETS - 1));
  256.     }
  257.     memmove(&sptr->targets[1], &sptr->targets[0], MAXTARGETS - 1);
  258.     sptr->targets[0] = hash;   
  259.     return 0;
  260. }
  261.  
  262.  
  263.     
  264.  
  265. /*
  266. ** 'do_nick_name' ensures that the given parameter (nick) is
  267. ** really a proper string for a nickname (note, the 'nick'
  268. ** may be modified in the process...)
  269. **
  270. **    RETURNS the length of the final NICKNAME (0, if
  271. **    nickname is illegal)
  272. **
  273. **  Nickname characters are in range
  274. **    'A'..'}', '_', '-', '0'..'9'
  275. **  anything outside the above set will terminate nickname.
  276. **  In addition, the first character cannot be '-'
  277. **  or a Digit.
  278. **
  279. **  Note:
  280. **    '~'-character should be allowed, but
  281. **    a change should be global, some confusion would
  282. **    result if only few servers allowed it...
  283. */
  284.  
  285. int    do_nick_name(nick)
  286. char    *nick;
  287. {
  288.     Reg1 char *ch;
  289.  
  290.     if (*nick == '-' || isdigit(*nick)) /* first character in [0..9-] */
  291.         return 0;
  292.  
  293.     for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++)
  294.         if (!isvalid(*ch) || isspace(*ch))
  295.             break;
  296.  
  297.     *ch = '\0';
  298.  
  299.     return (ch - nick);
  300. }
  301.  
  302.  
  303. /*
  304. ** canonize
  305. **
  306. ** reduce a string of duplicate list entries to contain only the unique
  307. ** items.  Unavoidably O(n^2).
  308. */
  309. char    *canonize(buffer)
  310. char    *buffer;
  311. {
  312.     static    char    cbuf[BUFSIZ];
  313.     register char    *s, *t, *cp = cbuf;
  314.     register int    l = 0;
  315.     char    *p = NULL, *p2;
  316.  
  317.     *cp = '\0';
  318.  
  319.     for (s = strtoken(&p, buffer, ","); s; s = strtoken(&p, NULL, ","))
  320.         {
  321.         if (l)
  322.             {
  323.             for (p2 = NULL, t = strtoken(&p2, cbuf, ","); t;
  324.                  t = strtoken(&p2, NULL, ","))
  325.                 if (!mycmp(s, t))
  326.                     break;
  327.                 else if (p2)
  328.                     p2[-1] = ',';
  329.             }
  330.         else
  331.             t = NULL;
  332.         if (!t)
  333.             {
  334.             if (l)
  335.                 *(cp-1) = ',';
  336.             else
  337.                 l = 1;
  338.             (void)strcpy(cp, s);
  339.             if (p)
  340.                 cp += (p - s);
  341.             }
  342.         else if (p2)
  343.             p2[-1] = ',';
  344.         }
  345.     return cbuf;
  346. }
  347.  
  348.  
  349. /*
  350. ** register_user
  351. **    This function is called when both NICK and USER messages
  352. **    have been accepted for the client, in whatever order. Only
  353. **    after this the USER message is propagated.
  354. **
  355. **    NICK's must be propagated at once when received, although
  356. **    it would be better to delay them too until full info is
  357. **    available. Doing it is not so simple though, would have
  358. **    to implement the following:
  359. **
  360. **    1) user telnets in and gives only "NICK foobar" and waits
  361. **    2) another user far away logs in normally with the nick
  362. **       "foobar" (quite legal, as this server didn't propagate
  363. **       it).
  364. **    3) now this server gets nick "foobar" from outside, but
  365. **       has already the same defined locally. Current server
  366. **       would just issue "KILL foobar" to clean out dups. But,
  367. **       this is not fair. It should actually request another
  368. **       nick from local user or kill him/her...
  369. */
  370.  
  371. static    int    register_user(cptr, sptr, nick, username)
  372. aClient    *cptr;
  373. aClient    *sptr;
  374. char    *nick, *username;
  375. {
  376.     Reg1    aConfItem *aconf;
  377.         char        *parv[3], *tmpstr, c;
  378. #ifdef HOSTILENAME
  379.     char    stripuser[USERLEN+1], *u1=stripuser, *u2, olduser[USERLEN+1],
  380.         userbad[USERLEN*2+1], *ubad=userbad, noident=0;
  381. #endif
  382.         short   oldstatus = sptr->status, upper = 0, lower = 0, special = 0;
  383.     anUser    *user = sptr->user;
  384.     aClient *nsptr;
  385.     int    i;
  386.  
  387.     user->last = time(NULL);
  388.     parv[0] = sptr->name;
  389.     parv[1] = parv[2] = NULL;
  390.  
  391.     if (MyConnect(sptr))
  392.         {
  393.         if ((i = check_client(sptr)))
  394.             {
  395.             sendto_umode(UMODE_OPER|UMODE_CLIENT,
  396.                    "*** Notice -- %s from %s.",
  397.                    i == -3 ? "Too many connections" :
  398.                          "Unauthorized connection",
  399.                    get_client_host(sptr));
  400.             ircstp->is_ref++;
  401.             return exit_client(cptr, sptr, &me, i == -3 ?
  402.                "This server is full.  Please try irc.dal.net" :
  403.                "You are not authorized to connect to this server");
  404.               } 
  405.         if (IsUnixSocket(sptr))
  406.             strncpyzt(user->host, me.sockhost, sizeof(user->host));
  407.         else if (sptr->hostp) {
  408.             /* No control-chars or ip-like dns replies... I cheat :)
  409.                -- OnyxDragon */
  410.             for (tmpstr = sptr->sockhost; *tmpstr > ' ' &&
  411.                 *tmpstr < 127; tmpstr++);
  412.             if (*tmpstr || !*user->host || isdigit(*(tmpstr-1)))
  413.                 strncpyzt(sptr->sockhost, (char *)inetntoa((char *)&sptr->ip), sizeof(sptr->sockhost)); /* Fix the sockhost for debug jic */
  414.             strncpyzt(user->host, sptr->sockhost, sizeof(sptr->sockhost));
  415.         }
  416.         else /* Failsafe point, don't let the user define their
  417.                 own hostname via the USER command --Cabal95 */
  418.             strncpyzt(user->host, sptr->sockhost, HOSTLEN+1);
  419.         aconf = sptr->confs->value.aconf;
  420.         /*
  421.          * I do not consider *, ~ or ! 'hostile' in usernames,
  422.          * as it is easy to differentiate them (Use \*, \? and \\)
  423.          * with the possible?
  424.          * exception of !. With mIRC etc. ident is easy to fake
  425.          * to contain @ though, so if that is found use non-ident
  426.          * username. -Donwulff
  427.          *
  428.          * I do, We only allow a-z A-Z 0-9 _ - and . now so the
  429.          * !strchr(sptr->username, '@') check is out of date. -Cabal95
  430.          *
  431.          * Moved the noident stuff here. -OnyxDragon
  432.          */
  433.         if (!(sptr->flags & FLAGS_DOID))
  434.             strncpyzt(user->username, username, USERLEN+1);
  435.         else if (sptr->flags & FLAGS_GOTID)
  436.             strncpyzt(user->username, sptr->username, USERLEN+1);
  437.         else
  438.             {
  439.             /* because username may point to user->username */
  440.             char    temp[USERLEN+1];
  441.  
  442.             strncpyzt(temp, username, USERLEN+1);
  443.             *user->username = '~';
  444.             (void)strncpy(&user->username[1], temp, USERLEN);
  445.             user->username[USERLEN] = '\0';
  446. #ifdef HOSTILENAME
  447.             noident = 1;
  448. #endif
  449.             }
  450. #ifdef HOSTILENAME
  451.         /*
  452.          * Limit usernames to just 0-9 a-z A-Z _ - and .
  453.          * It strips the "bad" chars out, and if nothing is left
  454.          * changes the username to the first 8 characters of their
  455.          * nickname. After the MOTD is displayed it sends numeric
  456.          * 455 to the user telling them what(if anything) happened.
  457.          * -Cabal95
  458.          *
  459.          * Moved the noident thing to the right place - see above
  460.          * -OnyxDragon
  461.          */
  462.         for (u2 = user->username+noident; *u2; u2++)
  463.             {
  464.             if (isallowed(*u2))
  465.                 *u1++ = *u2;
  466.             else if (*u2 < 32)
  467.                 {
  468.                 /*
  469.                  * Make sure they can read what control
  470.                  * characters were in their username.
  471.                  */
  472.                 *ubad++ = '^';
  473.                 *ubad++ = *u2+'@';
  474.                 }
  475.             else
  476.                 *ubad++ = *u2;
  477.             }
  478.         *u1 = '\0';
  479.         *ubad = '\0';
  480.         if (strlen(stripuser) != strlen(user->username+noident))
  481.             {
  482.             if (stripuser[0] == '\0')
  483.                 {
  484.                 strncpy(stripuser, cptr->name, 8);
  485.                 stripuser[8] = '\0';
  486.                 }
  487.  
  488.             strcpy(olduser, user->username+noident);
  489.             strncpy(user->username+1, stripuser, USERLEN-1);
  490.             user->username[0] = '~';
  491.             user->username[USERLEN] = '\0';
  492.             }
  493.         else
  494.             u1 = NULL;
  495. #endif
  496.  
  497.         if (!BadPtr(aconf->passwd)) {
  498.             if (!StrEq(sptr->passwd, aconf->passwd)) {
  499.                 ircstp->is_ref++;
  500.                 sendto_one(sptr, err_str(ERR_PASSWDMISMATCH),
  501.                        me.name, parv[0]);
  502.                 return exit_client(cptr, sptr, &me, "Bad Password");
  503.             }
  504.             /* .. Else password check was successful, clear the pass
  505.              * so it doesn't get sent to NickServ.
  506.              * - Wizzu
  507.              */
  508.             else sptr->passwd[0] = '\0';
  509.         }
  510.  
  511.         /*
  512.          * following block for the benefit of time-dependent K:-lines
  513.          */
  514.         if (find_kill(sptr))
  515.             {
  516.             ircstp->is_ref++;
  517.             return exit_client(cptr, sptr, &me, "K-lined");
  518.             }
  519. #ifdef R_LINES
  520.         if (find_restrict(sptr))
  521.             {
  522.             ircstp->is_ref++;
  523.             return exit_client(cptr, sptr, &me , "R-lined");
  524.             }
  525. #endif
  526.  
  527. #ifdef                DISALLOW_MIXED_CASE
  528. /* check for mixed case usernames, meaning probably hacked   Jon2 3-94
  529. */
  530. #ifdef        IGNORE_CASE_FIRST_CHAR
  531.               tmpstr = (username[0] == '~' ? &username[2] : &username[1]);
  532. #else
  533.               tmpstr = (username[0] == '~' ? &username[1] : username);
  534. #endif        /* IGNORE_CASE_FIRST_CHAR */
  535.              while (*tmpstr && !(lower && upper || special)) {
  536.                c = *tmpstr;
  537.                tmpstr++;
  538.                if (islower(c)) {
  539.                  lower++;
  540.                  continue; /* bypass rest of tests */
  541.                }
  542.                if (isupper(c)) {
  543.                  upper++;
  544.                  continue;
  545.                }
  546.                if (c == '-' || c == '_' || c == '.' || isdigit(c))
  547.                  continue;
  548.                special++;
  549.              }
  550.              if (lower && upper || special) {
  551.                    sendto_ops("Invalid username: %s",
  552.                               get_client_name(sptr,FALSE));
  553.                    ircstp->is_ref++;
  554.                    return exit_client(cptr, sptr, sptr , "Invalid username");
  555.              }
  556.  
  557. #endif                /* DISALLOW_MIXED_CASE */
  558.  
  559.         if (oldstatus == STAT_MASTER && MyConnect(sptr))
  560.             (void)m_oper(&me, sptr, 1, parv);
  561.         }
  562.     else
  563.         strncpyzt(user->username, username, USERLEN+1);
  564.     SetClient(sptr);
  565.     if (MyConnect(sptr))
  566.         {
  567.         sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, nick,
  568.                user->username, user->host);
  569.         /* This is a duplicate of the NOTICE but see below...*/
  570.         sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
  571.                get_client_name(&me, FALSE), version);
  572. #ifdef    IRCII_KLUDGE
  573.         /*
  574.         ** Don't mess with this one - IRCII needs it! -Avalon
  575.         */
  576.         sendto_one(sptr,
  577.             "NOTICE %s :*** Your host is %s, running version %s",
  578.             nick, get_client_name(&me, FALSE), version);
  579. #endif
  580.         sendto_one(sptr, rpl_str(RPL_CREATED),me.name,nick,creation);
  581.         sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0],
  582.                me.name, version);
  583.         sendto_one(sptr, rpl_str(RPL_PROTOCTL), me.name, parv[0],
  584.                PROTOCTL_SUPPORTED);
  585.         (void)m_lusers(sptr, sptr, 1, parv);
  586.         update_load();
  587.         (void)m_motd(sptr, sptr, 1, parv);
  588. #ifdef HOSTILENAME
  589.         /*
  590.          * Now send a numeric to the user telling them what, if
  591.          * anything, happened.
  592.          */
  593.         if (u1)
  594.             sendto_one(sptr, err_str(ERR_HOSTILENAME), me.name,
  595.                    sptr->name, olduser, userbad, stripuser);
  596. #endif
  597.         nextping = time(NULL);
  598.         sendto_umode(UMODE_OPER|UMODE_CLIENT,"*** Notice -- Client connecting on port %d: %s (%s@%s)", 
  599.                    sptr->acpt->port, nick, user->username,
  600.                    user->host);
  601.         }
  602.     else if (IsServer(cptr))
  603.         {
  604.         aClient    *acptr;
  605.  
  606.         if (!(acptr = find_server(user->server, NULL)))
  607.         {
  608.           sendto_ops("Bad USER [%s] :%s USER %s %s : No such server",
  609.               cptr->name, nick, user->username, user->server);
  610.           sendto_one(cptr, ":%s KILL %s :%s (No such server: %s)",
  611.               me.name, sptr->name, me.name, user->server);
  612.           sptr->flags |= FLAGS_KILLED;
  613.           return exit_client(sptr, sptr, &me,
  614.               "USER without prefix(2.8) or wrong prefix");
  615.          }
  616.          else if (acptr->from != sptr->from)
  617.            {
  618.             sendto_ops("Bad User [%s] :%s USER %s %s, != %s[%s]",
  619.                 cptr->name, nick, user->username, user->server,
  620.                 acptr->name, acptr->from->name);
  621.             sendto_one(cptr, ":%s KILL %s :%s (%s != %s[%s])",
  622.                    me.name, sptr->name, me.name, user->server,
  623.                    acptr->from->name, acptr->from->sockhost);
  624.             sptr->flags |= FLAGS_KILLED;
  625.             return exit_client(sptr, sptr, &me,
  626.                        "USER server wrong direction");
  627.            }
  628.         else sptr->flags|=(acptr->flags & FLAGS_TS8);
  629.         /* *FINALL* this gets in ircd... -- Barubary */
  630.         if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD)
  631.             || (sptr->user && find_conf_host(cptr->confs,
  632.             sptr->user->server, CONF_UWORLD)))
  633.             sptr->flags |= FLAGS_ULINE;
  634.         }
  635.  
  636.     hash_check_notify(sptr, RPL_LOGON);    /* Uglier hack */
  637.     sendto_serv_butone(cptr, "NICK %s %d %d %s %s %s %lu :%s", nick,
  638.       sptr->hopcount+1, sptr->lastnick, user->username, user->host,
  639.       user->server, sptr->user->servicestamp, sptr->info);
  640.  
  641.     /* Send password from sptr->passwd to NickServ for identification,
  642.      * if passwd given and if NickServ is online.
  643.      * - by taz, modified by Wizzu
  644.      */
  645.     if (MyConnect(sptr)) {
  646.         send_umode_out(cptr, sptr, 0);
  647.         if (sptr->passwd[0] && (nsptr = find_person(NickServ, NULL)))
  648.         sendto_one(nsptr,":%s PRIVMSG %s@%s :SIDENTIFY %s",
  649.           sptr->name, NickServ, SERVICES_NAME, sptr->passwd);
  650.     }
  651.  
  652. #ifdef    USE_SERVICES
  653.     check_services_butone(SERVICE_WANT_NICK, sptr,
  654.       "NICK %s %d %d %s %s %s %lu :%s", nick, sptr->hopcount,
  655.       sptr->lastnick, user->username, user->host, user->server,
  656.       sptr->user->servicestamp, sptr->info);
  657.     check_services_butone(SERVICE_WANT_USER, sptr, ":%s USER %s %s %s :%s",
  658.       nick, user->username, user->host, user->server, sptr->info);
  659. #endif
  660.     if(MyConnect(sptr) && !BadPtr(sptr->passwd))
  661.         bzero(sptr->passwd, sizeof(sptr->passwd));
  662.  
  663.     return 0;
  664.     }
  665.  
  666. /*
  667. ** m_svsnick
  668. **    parv[0] = sender
  669. **    parv[1] = old nickname
  670. **    parv[2] = new nickname
  671. **    parv[3] = timestamp
  672. */
  673. int    m_svsnick(cptr, sptr, parc, parv)
  674. aClient *cptr, *sptr;
  675. int    parc;
  676. char    *parv[];
  677. {
  678.     aClient *acptr;
  679.     char    nick[NICKLEN+2], *s;
  680.     time_t    lastnick = (time_t)0;
  681.  
  682.     if (!IsULine(cptr, sptr) || parc < 4 || (strlen(parv[2]) > NICKLEN))
  683.         return;
  684.  
  685.     if (!hunt_server(cptr, sptr, ":%s SVSNICK %s %s :%s", 1, parc, parv) != HUNTED_ISME) {
  686.         if ((acptr = find_person(parv[1], NULL))) {
  687.             acptr->umodes &= ~UMODE_REGNICK;
  688.             acptr->lastnick = atoi(parv[3]);
  689.             sendto_common_channels(acptr, ":%s NICK :%s", parv[1], parv[2]);
  690.             if (IsPerson(acptr))
  691.                 add_history(acptr);
  692.             sendto_serv_butone(NULL, ":%s NICK %s :%i", parv[1], parv[2], atoi(parv[3]));
  693.             if(acptr->name[0])
  694.                 (void)del_from_client_hash_table(acptr->name, acptr);
  695.             (void)strcpy(acptr->name, parv[2]);
  696.             (void)add_to_client_hash_table(parv[2], acptr);
  697.         }
  698.     }
  699. }
  700.  
  701. /*
  702. ** m_nick
  703. **    parv[0] = sender prefix
  704. **    parv[1] = nickname
  705. **  if from new client  -taz
  706. **    parv[2] = nick password
  707. **  if from server:
  708. **      parv[2] = hopcount
  709. **      parv[3] = timestamp
  710. **      parv[4] = username
  711. **      parv[5] = hostname
  712. **      parv[6] = servername
  713. **      parv[7] = servicestamp
  714. **    parv[8] = info
  715. */
  716. int    m_nick(cptr, sptr, parc, parv)
  717. aClient *cptr, *sptr;
  718. int    parc;
  719. char    *parv[];
  720. {
  721.     aConfItem *aconf;
  722.     aSqlineItem *asqline;
  723.     aClient *acptr, *serv;
  724.     char    nick[NICKLEN+2], *s;
  725.     Link    *lp;
  726.     time_t    lastnick = (time_t)0;
  727.     int    differ = 1;
  728.  
  729.         static int firstnsrun=0;
  730.     u_int32_t     md5data[16];
  731.     static u_int32_t     md5hash[4];
  732.  
  733.     /*
  734.      * If the user didn't specify a nickname, complain
  735.      */
  736.     if (parc < 2) {
  737.       sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
  738.              me.name, parv[0]);
  739.       return 0;
  740.     }
  741.  
  742.     if (MyConnect(sptr) && (s = (char *)index(parv[1], '~')))
  743.       *s = '\0';
  744.  
  745.     strncpyzt(nick, parv[1], NICKLEN+1);
  746.     /*
  747.      * if do_nick_name() returns a null name OR if the server sent a nick
  748.      * name and do_nick_name() changed it in some way (due to rules of nick
  749.      * creation) then reject it. If from a server and we reject it,
  750.      * and KILL it. -avalon 4/4/92
  751.      */
  752.     if (do_nick_name(nick) == 0 ||
  753.         (IsServer(cptr) && strcmp(nick, parv[1]))) {
  754.         sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
  755.                me.name, parv[0], parv[1], "Illegal characters");
  756.  
  757.         if (IsServer(cptr)) {
  758.             ircstp->is_kill++;
  759.             sendto_ops("Bad Nick: %s From: %s %s",
  760.                    parv[1], parv[0],
  761.                    get_client_name(cptr, FALSE));
  762.             sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
  763.                    me.name, parv[1], me.name, parv[1],
  764.                    nick, cptr->name);
  765.             if (sptr != cptr) { /* bad nick change */
  766.                 sendto_serv_butone(cptr,
  767.                     ":%s KILL %s :%s (%s <- %s!%s@%s)",
  768.                     me.name, parv[0], me.name,
  769.                     get_client_name(cptr, FALSE),
  770.                     parv[0],
  771.                     sptr->user ? sptr->username : "",
  772.                     sptr->user ? sptr->user->server :
  773.                              cptr->name);
  774.                 sptr->flags |= FLAGS_KILLED;
  775.                 return exit_client(cptr,sptr,&me,"BadNick");
  776.                 }
  777.             }
  778.         return 0;
  779.         }
  780.  
  781.     /*
  782.     ** Protocol 4 doesn't send the server as prefix, so it is possible
  783.     ** the server doesn't exist (a lagged net.burst), in which case
  784.     ** we simply need to ignore the NICK. Also when we got that server
  785.     ** name (again) but from another direction. --Run
  786.     */
  787.     /* 
  788.     ** We should really only deal with this for msgs from servers.
  789.     ** -- Aeto
  790.     */
  791.     if (IsServer(cptr) && 
  792.         (parc > 7 && (!(serv = find_server(parv[6], NULL)) ||
  793.               serv->from != cptr->from)))
  794.       return 0;
  795.  
  796.     /*
  797.     ** Check against nick name collisions.
  798.     **
  799.     ** Put this 'if' here so that the nesting goes nicely on the screen :)
  800.     ** We check against server name list before determining if the nickname
  801.     ** is present in the nicklist (due to the way the below for loop is
  802.     ** constructed). -avalon
  803.     */
  804.     if ((acptr = find_server(nick, NULL))) {
  805.         if (MyConnect(sptr))
  806.             {
  807.             sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
  808.                    BadPtr(parv[0]) ? "*" : parv[0], nick);
  809.             return 0; /* NICK message ignored */
  810.             }
  811.     }
  812.  
  813.     /*
  814.     ** Check for a Q-lined nickname. If we find it, and it's our
  815.     ** client, just reject it. -Lefler
  816.     ** Allow opers to use Q-lined nicknames. -Russell
  817.     */
  818.  
  819.     if ((aconf = find_conf_name(nick, CONF_QUARANTINED_NICK)) || 
  820.         (asqline = find_sqline_match(nick))) {
  821.       sendto_realops ("Q-lined nick %s from %s on %s.", nick,
  822.               (*sptr->name!=0 && !IsServer(sptr)) ? sptr->name :
  823.                "<unregistered>",
  824.               (sptr->user==NULL) ? ((IsServer(sptr)) ? parv[6] : me.name) :
  825.                        sptr->user->server);
  826.       if ((!IsServer(cptr)) && (!IsOper(cptr))) {
  827.  
  828.         if(aconf)
  829.         sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
  830.                BadPtr(parv[0]) ? "*" : parv[0], nick,
  831.                BadPtr(aconf->passwd) ? "reason unspecified" :
  832.                aconf->passwd);
  833.         else if(asqline)
  834.         sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
  835.                BadPtr(parv[0]) ? "*" : parv[0], nick,
  836.                BadPtr(asqline->reason) ? "reason unspecified" :
  837.                asqline->reason);
  838.  
  839.         sendto_realops("Forbidding Q-lined nick %s from %s.",
  840.             nick, get_client_name(cptr, FALSE));
  841.         return 0; /* NICK message ignored */
  842.       }
  843.     }
  844.  
  845.     /*
  846.     ** acptr already has result from previous find_server()
  847.     */
  848.     if (acptr)
  849.         {
  850.         /*
  851.         ** We have a nickname trying to use the same name as
  852.         ** a server. Send out a nick collision KILL to remove
  853.         ** the nickname. As long as only a KILL is sent out,
  854.         ** there is no danger of the server being disconnected.
  855.         ** Ultimate way to jupiter a nick ? >;-). -avalon
  856.         */
  857.         sendto_ops("Nick collision on %s(%s <- %s)",
  858.                sptr->name, acptr->from->name,
  859.                get_client_name(cptr, FALSE));
  860.         ircstp->is_kill++;
  861.         sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
  862.                me.name, sptr->name, me.name, acptr->from->name,
  863.                /* NOTE: Cannot use get_client_name
  864.                ** twice here, it returns static
  865.                ** string pointer--the other info
  866.                ** would be lost
  867.                */
  868.                get_client_name(cptr, FALSE));
  869.         sptr->flags |= FLAGS_KILLED;
  870.         return exit_client(cptr, sptr, &me, "Nick/Server collision");
  871.         }
  872.     if (MyClient(cptr) && !IsOper(cptr))
  873.         cptr->since += 3; /* Nick-flood prot. -Donwulff */
  874.  
  875.     if (!(acptr = find_client(nick, NULL)))
  876.         goto nickkilldone;  /* No collisions, all clear... */
  877.     /*
  878.     ** If the older one is "non-person", the new entry is just
  879.     ** allowed to overwrite it. Just silently drop non-person,
  880.     ** and proceed with the nick. This should take care of the
  881.     ** "dormant nick" way of generating collisions...
  882.     */
  883.     /* Moved before Lost User Field to fix some bugs... -- Barubary */
  884.     if (IsUnknown(acptr) && MyConnect(acptr))
  885.         {
  886.         /* This may help - copying code below */
  887.         if (acptr == cptr)
  888.             return 0;
  889.         acptr->flags |= FLAGS_KILLED;
  890.         exit_client(NULL, acptr, &me, "Overridden");
  891.         goto nickkilldone;
  892.         }
  893.     /* A sanity check in the user field... */
  894.     if (acptr->user == NULL) {
  895.       /* This is a Bad Thing */
  896.       sendto_ops("Lost user field for %s in change from %s",
  897.              acptr->name, get_client_name(cptr,FALSE));
  898.       ircstp->is_kill++;
  899.       sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)",
  900.              me.name, acptr->name, me.name);
  901.       acptr->flags |= FLAGS_KILLED;
  902.       /* Here's the previous versions' desynch.  If the old one is
  903.          messed up, trash the old one and accept the new one.
  904.          Remember - at this point there is a new nick coming in!
  905.          Handle appropriately. -- Barubary */
  906.       exit_client (NULL, acptr, &me, "Lost user field");
  907.       goto nickkilldone;
  908.     }
  909.     /*
  910.     ** If acptr == sptr, then we have a client doing a nick
  911.     ** change between *equivalent* nicknames as far as server
  912.     ** is concerned (user is changing the case of his/her
  913.     ** nickname or somesuch)
  914.     */
  915.     if (acptr == sptr)
  916.       if (strcmp(acptr->name, nick) != 0)
  917.         /*
  918.         ** Allows change of case in his/her nick
  919.         */
  920.         goto nickkilldone; /* -- go and process change */
  921.       else
  922.         /*
  923.         ** This is just ':old NICK old' type thing.
  924.         ** Just forget the whole thing here. There is
  925.         ** no point forwarding it to anywhere,
  926.         ** especially since servers prior to this
  927.         ** version would treat it as nick collision.
  928.         */
  929.         return 0; /* NICK Message ignored */
  930.     /*
  931.     ** Note: From this point forward it can be assumed that
  932.     ** acptr != sptr (point to different client structures).
  933.     */
  934.     /*
  935.     ** Decide, we really have a nick collision and deal with it
  936.     */
  937.     if (!IsServer(cptr))
  938.         {
  939.         /*
  940.         ** NICK is coming from local client connection. Just
  941.         ** send error reply and ignore the command.
  942.         */
  943.         sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
  944.                /* parv[0] is empty when connecting */
  945.                me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
  946.         return 0; /* NICK message ignored */
  947.         }
  948.     /*
  949.     ** NICK was coming from a server connection.
  950.     ** This means we have a race condition (two users signing on
  951.     ** at the same time), or two net fragments reconnecting with
  952.     ** the same nick.
  953.     ** The latter can happen because two different users connected
  954.     ** or because one and the same user switched server during a
  955.     ** net break.
  956.     ** If we have the old protocol (no TimeStamp and no user@host)
  957.     ** or if the TimeStamps are equal, we kill both (or only 'new'
  958.     ** if it was a "NICK new"). Otherwise we kill the youngest
  959.     ** when user@host differ, or the oldest when they are the same.
  960.     ** --Run
  961.     ** 
  962.     */
  963.     if (IsServer(sptr))
  964.     {
  965. #ifdef USE_CASETABLES
  966.       /* OK.  Here's what we know now...  (1) acptr points to
  967.       ** someone or something using the nick we want to add,
  968.       ** (2) we are getting the nick request from a server, not
  969.       ** a local client.  What we need to figure out is whether
  970.       ** this is a user changing the case on its nick or a server
  971.       ** with a different set of case tables trying to introduce
  972.       ** a nick it thinks is unique, but we don't.  What we are going
  973.       ** to do is see if the acptr == find_client(parv[0]).
  974.       **    -Aeto 
  975.       */
  976.       /* Have to make sure it's not a server else we go back to the old
  977.          "kill both" situation.  Removed for now. -- Barubary */
  978.       if ((find_client(parv[0],NULL) != acptr) && !IsServer(find_client(
  979.         parv[0],NULL)))
  980.       {
  981.         sendto_one(sptr, ":%s KILL %s :%s (%s Self collision)",
  982.                me.name, nick, me.name,
  983.                /* NOTE: Cannot use get_client_name
  984.                ** twice here, it returns static
  985.                ** string pointer--the other info
  986.                ** would be lost
  987.                */
  988.                get_client_name(cptr, FALSE));
  989.         return 0;
  990.       }
  991. #endif
  992.       /*
  993.         ** A new NICK being introduced by a neighbouring
  994.         ** server (e.g. message type "NICK new" received)
  995.         */
  996.         if (parc > 3)
  997.         { lastnick = atoi(parv[3]);
  998.           if (parc > 5)
  999.         differ = (mycmp(acptr->user->username, parv[4]) ||
  1000.             mycmp(acptr->user->host, parv[5])); }
  1001.         sendto_failops("Nick collision on %s (%s %d <- %s %d)",
  1002.             acptr->name, acptr->from->name, acptr->lastnick, 
  1003.             get_client_name(cptr, FALSE), lastnick);
  1004.     }
  1005.     else
  1006.     {
  1007.         /*
  1008.         ** A NICK change has collided (e.g. message type ":old NICK new").
  1009.         */
  1010.         if (parc > 2)
  1011.             lastnick = atoi(parv[2]);
  1012.         differ = (mycmp(acptr->user->username, sptr->user->username) ||
  1013.         mycmp(acptr->user->host, sptr->user->host));
  1014.         sendto_ops("Nick change collision from %s to %s (%s %d <- %s %d)",
  1015.             sptr->name, acptr->name, acptr->from->name,
  1016.             acptr->lastnick, get_client_name(cptr, FALSE), lastnick);
  1017.     }
  1018.     /*
  1019.     ** Now remove (kill) the nick on our side if it is the youngest.
  1020.     ** If no timestamp was received, we ignore the incoming nick
  1021.     ** (and expect a KILL for our legit nick soon ):
  1022.     ** When the timestamps are equal we kill both nicks. --Run
  1023.     ** acptr->from != cptr should *always* be true (?).
  1024.     */
  1025.     if (acptr->from != cptr) {
  1026.       if (!lastnick || differ && lastnick >= acptr->lastnick ||
  1027.           !differ && lastnick <= acptr->lastnick) {
  1028.         if (!IsServer(sptr)) {
  1029.           ircstp->is_kill++;
  1030.           sendto_serv_butone(cptr, /* Kill old from outgoing servers */
  1031.                  ":%s KILL %s :%s (%s <- %s)",
  1032.                  me.name, sptr->name, me.name,
  1033.                  acptr->from->name,
  1034.                  get_client_name(cptr, FALSE));
  1035.           sptr->flags |= FLAGS_KILLED;
  1036.           (void)exit_client(NULL, sptr, &me,
  1037.                 "Nick collision (you're a ghost)");
  1038.         }
  1039.         if (lastnick && lastnick != acptr->lastnick)
  1040.           return 0; /* Ignore the NICK */
  1041.       }
  1042.       sendto_one(acptr, err_str(ERR_NICKCOLLISION),
  1043.              me.name, acptr->name, nick); }
  1044.     ircstp->is_kill++;
  1045.     sendto_serv_butone(cptr, /* Kill our old from outgoing servers */
  1046.                ":%s KILL %s :%s (%s <- %s)",
  1047.                me.name, acptr->name, me.name,
  1048.                acptr->from->name, get_client_name(cptr, FALSE));
  1049.     acptr->flags |= FLAGS_KILLED;
  1050.     (void)exit_client(NULL, acptr, &me,
  1051.               "Nick collision (older nick overruled)");
  1052.  
  1053.     if (lastnick == acptr->lastnick)
  1054.       return 0;
  1055.     
  1056. nickkilldone:
  1057.     if (IsServer(sptr)) {
  1058.       /* A server introducing a new client, change source */
  1059.  
  1060.       sptr = make_client(cptr, serv);
  1061.       add_client_to_list(sptr);
  1062.       if (parc > 2)
  1063.         sptr->hopcount = atoi(parv[2]);
  1064.       if (parc > 3)
  1065.         sptr->lastnick = atoi(parv[3]);
  1066.       else /* Little bit better, as long as not all upgraded */
  1067.         sptr->lastnick = time(NULL);
  1068.     } else if (sptr->name[0]&&IsPerson(sptr)) {
  1069.       /*
  1070.       ** If the client belongs to me, then check to see
  1071.       ** if client is currently on any channels where it
  1072.       ** is currently banned.  If so, do not allow the nick
  1073.       ** change to occur.
  1074.       ** Also set 'lastnick' to current time, if changed.
  1075.       */
  1076.       if (MyClient(sptr))
  1077.         for (lp = cptr->user->channel; lp; lp = lp->next)
  1078.           if (is_banned(cptr, lp->value.chptr)) {
  1079.         sendto_one(cptr,
  1080.                err_str(ERR_BANNICKCHANGE),
  1081.                me.name, parv[0],
  1082.                lp->value.chptr->chname);
  1083.         return 0;
  1084.           }
  1085.       
  1086.       /*
  1087.        * Client just changing his/her nick. If he/she is
  1088.        * on a channel, send note of change to all clients
  1089.        * on that channel. Propagate notice to other servers.
  1090.        */
  1091.       if (mycmp(parv[0], nick) ||
  1092.           /* Next line can be removed when all upgraded  --Run */
  1093.           !MyClient(sptr) && parc>2 && atoi(parv[2])<sptr->lastnick)
  1094.         sptr->lastnick = (MyClient(sptr) || parc < 3) ?
  1095.           time(NULL):atoi(parv[2]);
  1096.       SetRegNick(sptr);
  1097.       add_history(sptr);
  1098.       sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
  1099.       sendto_serv_butone(cptr, ":%s NICK %s :%d",
  1100.                  parv[0], nick, sptr->lastnick);
  1101.     } else if(!sptr->name[0]) {
  1102. #ifdef NOSPOOF
  1103.       /*
  1104.        * Client setting NICK the first time.
  1105.        *
  1106.        * Generate a random string for them to pong with.
  1107.        *
  1108.        * The first two are server specific.  The intent is to randomize
  1109.        * things well.
  1110.        *
  1111.        * We use lots of junk here, but only "low cost" things.
  1112.        */
  1113.       md5data[0] = NOSPOOF_SEED01;
  1114.       md5data[1] = NOSPOOF_SEED02;
  1115.       md5data[2] = time(NULL);
  1116.       md5data[3] = me.sendM;
  1117.       md5data[4] = me.receiveM;
  1118.       md5data[5] = 0;
  1119.       md5data[6] = getpid();
  1120.       md5data[7] = sptr->ip.s_addr;
  1121.       md5data[8] = sptr->fd;
  1122.       md5data[9] = 0;
  1123.       md5data[10] = 0;
  1124.       md5data[11] = 0;
  1125.       md5data[12] = md5hash[0];  /* previous runs... */
  1126.       md5data[13] = md5hash[1];
  1127.       md5data[14] = md5hash[2];
  1128.       md5data[15] = md5hash[3];
  1129.       
  1130.       /*
  1131.        * initialize the md5 buffer to known values
  1132.        */
  1133.       MD5Init(md5hash);
  1134.  
  1135.       /*
  1136.        * transform the above information into gibberish
  1137.        */
  1138.       MD5Transform(md5hash, md5data);
  1139.  
  1140.       /*
  1141.        * Never release any internal state of our generator.  Instead,
  1142.        * use two parts of the returned hash and xor them to hide
  1143.        * both values.
  1144.        */
  1145.       sptr->nospoof = (md5hash[0] ^ md5hash[1]);
  1146.  
  1147.       /*
  1148.        * If on the odd chance it comes out zero, make it something
  1149.        * non-zero.
  1150.        */
  1151.       if (sptr->nospoof == 0)
  1152.         sptr->nospoof = 0xdeadbeef;
  1153.       sendto_one(sptr, "NOTICE %s :*** If you are having problems"
  1154.              " connecting due to ping timeouts, please"
  1155.              " type /notice %X nospoof now.",
  1156.              nick, sptr->nospoof, sptr->nospoof);
  1157.       sendto_one(sptr, "PING :%X", sptr->nospoof);
  1158. #endif /* NOSPOOF */
  1159.       
  1160. #ifdef CONTACT_EMAIL
  1161.       sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with a"
  1162.              " connection problem, please email " CONTACT_EMAIL
  1163.              " with the name and version of the client you are"
  1164.              " using, and the server you tried to connect to: %s",
  1165.              me.name, nick, me.name);
  1166. #endif /* CONTACT_EMAIL */
  1167. #ifdef CONTACT_URL
  1168.       sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with"
  1169.              " connecting to this server, %s, please refer to: "
  1170.              CONTACT_URL, me.name, nick, me.name);
  1171. #endif /* CONTACT_URL */
  1172.       
  1173.       /* Copy password to the passwd field if it's given after NICK
  1174.        * - originally by taz, modified by Wizzu
  1175.        */
  1176.       if((parc > 2) && (strlen(parv[2]) < sizeof(sptr->passwd)))
  1177.        (void)strcpy(sptr->passwd,parv[2]);
  1178.  
  1179.       /* This had to be copied here to avoid problems.. */
  1180.       (void)strcpy(sptr->name, nick);
  1181.       if (sptr->user && IsNotSpoof(sptr)) {
  1182.         /*
  1183.         ** USER already received, now we have NICK.
  1184.         ** *NOTE* For servers "NICK" *must* precede the
  1185.         ** user message (giving USER before NICK is possible
  1186.         ** only for local client connection!). register_user
  1187.         ** may reject the client and call exit_client for it
  1188.         ** --must test this and exit m_nick too!!!
  1189.         */
  1190.         sptr->lastnick = time(NULL); /* Always local client */
  1191.         if (register_user(cptr, sptr, nick,
  1192.                   sptr->user->username)
  1193.         == FLUSH_BUFFER)
  1194.           return FLUSH_BUFFER; }
  1195.     }
  1196.     /*
  1197.      *  Finally set new nick name.
  1198.      */
  1199.     if (sptr->name[0]) {
  1200.       (void)del_from_client_hash_table(sptr->name, sptr);
  1201.       if (IsPerson(sptr))
  1202.         hash_check_notify(sptr, RPL_LOGOFF);
  1203.     }
  1204.     (void)strcpy(sptr->name, nick);
  1205.     (void)add_to_client_hash_table(nick, sptr);
  1206.     if (IsServer(cptr) && parc>7) {
  1207.       parv[3]=nick;
  1208.       return m_user(cptr, sptr, parc-3, &parv[3]); }
  1209.     else if (IsPerson(sptr))
  1210.       hash_check_notify(sptr, RPL_LOGON);
  1211.  
  1212.     return 0;
  1213. }
  1214.  
  1215. /*
  1216. ** m_message (used in m_private() and m_notice())
  1217. ** the general function to deliver MSG's between users/channels
  1218. **
  1219. **    parv[0] = sender prefix
  1220. **    parv[1] = receiver list
  1221. **    parv[2] = message text
  1222. **
  1223. ** massive cleanup
  1224. ** rev argv 6/91
  1225. **
  1226. */
  1227.  
  1228. static    int    m_message(cptr, sptr, parc, parv, notice)
  1229. aClient *cptr, *sptr;
  1230. int    parc;
  1231. char    *parv[];
  1232. int    notice;
  1233. {
  1234.     Reg1    aClient    *acptr;
  1235.     Reg2    char    *s;
  1236.     aChannel *chptr;
  1237.     char    *nick, *server, *p, *cmd, *host;
  1238.  
  1239.     if (notice)
  1240.         {
  1241.         if (check_registered(sptr))
  1242.             return 0;
  1243.         }
  1244.     else if (check_registered_user(sptr))
  1245.         return 0;
  1246.  
  1247.     sptr->flags&=~FLAGS_TS8;
  1248.  
  1249.     cmd = notice ? MSG_NOTICE : MSG_PRIVATE;
  1250.  
  1251.     if (parc < 2 || *parv[1] == '\0')
  1252.         {
  1253.         sendto_one(sptr, err_str(ERR_NORECIPIENT),
  1254.                me.name, parv[0], cmd);
  1255.         return -1;
  1256.         }
  1257.  
  1258.     if (parc < 3 || *parv[2] == '\0')
  1259.         {
  1260.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1261.         return -1;
  1262.         }
  1263.  
  1264.     if (MyConnect(sptr))
  1265.         parv[1] = canonize(parv[1]);
  1266.     for (p = NULL, nick = strtoken(&p, parv[1], ","); nick;
  1267.          nick = strtoken(&p, NULL, ","))
  1268.         {
  1269.         /*
  1270.         ** nickname addressed?
  1271.         */
  1272.         if ((acptr = find_person(nick, NULL)))
  1273.         {
  1274.             if (MyClient(sptr) && check_for_target_limit(sptr, acptr, acptr->name))
  1275.             continue;
  1276.  
  1277.         if (!is_silenced(sptr, acptr))
  1278.             {
  1279.             if (!notice && MyConnect(sptr) &&
  1280.                 acptr->user && acptr->user->away)
  1281.                 sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
  1282.                        parv[0], acptr->name,
  1283.                        acptr->user->away);
  1284.             sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
  1285.                       parv[0], cmd, nick, parv[2]);
  1286.             }
  1287.             continue;
  1288.                 }
  1289.  
  1290.                 if (nick[0] == '@')
  1291.                     {
  1292.  
  1293.         /*   
  1294.          * If its a message for all Channel OPs call the function
  1295.          * sendto_channelops_butone() to handle it.  -Cabal95
  1296.          */
  1297.             if ( nick[1] == '#' )
  1298.                 {
  1299.                                 if(chptr = find_channel(nick+1, NullChn))
  1300.                                     {
  1301.                                   if (can_send(sptr, chptr) == 0 || IsULine(cptr,sptr))
  1302.                             sendto_channelops_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]);
  1303.                                else if (!notice)
  1304.                             sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick+1);
  1305.                                     }
  1306.                                 else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick+1);
  1307.                     }
  1308.  
  1309.             /*   
  1310.              * If its a message for all Channel ops and voices call the function
  1311.               * sendto_channelvoice_butone() to handle it.  -DuffJ
  1312.              */
  1313.             else if ( nick[1] == '+' && nick[2] == '#' )
  1314.                       {
  1315.                                 if (chptr = find_channel(nick+2, NullChn))
  1316.                                     {
  1317.                         if (can_send(sptr, chptr) == 0 || IsULine(cptr,sptr))
  1318.                             sendto_channelvoice_butone(cptr, sptr, chptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[2]);
  1319.                         else if (!notice)
  1320.                             sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], nick+2);
  1321.                                     }
  1322.                     else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick+2);
  1323.                 }
  1324.             continue;
  1325.                     }
  1326.         /*
  1327.         ** channel msg?
  1328.         ** Now allows U-lined users to send to channel no problemo
  1329.         ** -- Barubary
  1330.         */
  1331.         if ((chptr = find_channel(nick, NullChn)))
  1332.             {
  1333.             if (can_send(sptr, chptr) == 0) {
  1334.                 if(MyClient(sptr) && check_for_target_limit(sptr, chptr, chptr->chname))
  1335.                     continue;
  1336.                 sendto_channel_butone(cptr, sptr, chptr,
  1337.                               ":%s %s %s :%s",
  1338.                               parv[0], cmd, nick,
  1339.                               parv[2]);
  1340.             }
  1341.             else if (!notice)
  1342.                 sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
  1343.                        me.name, parv[0], nick);
  1344.             continue;
  1345.             }
  1346.     
  1347.         /*
  1348.         ** the following two cases allow masks in NOTICEs
  1349.         ** (for OPERs only)
  1350.         **
  1351.         ** Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
  1352.         */
  1353.         if ((*nick == '$' || *nick == '#') && IsAnOper(sptr))
  1354.             {
  1355.             if (!(s = (char *)rindex(nick, '.')))
  1356.                 {
  1357.                 sendto_one(sptr, err_str(ERR_NOTOPLEVEL),
  1358.                        me.name, parv[0], nick);
  1359.                 continue;
  1360.                 }
  1361.             while (*++s)
  1362.                 if (*s == '.' || *s == '*' || *s == '?')
  1363.                     break;
  1364.             if (*s == '*' || *s == '?')
  1365.                 {
  1366.                 sendto_one(sptr, err_str(ERR_WILDTOPLEVEL),
  1367.                        me.name, parv[0], nick);
  1368.                 continue;
  1369.                 }
  1370.             sendto_match_butone(IsServer(cptr) ? cptr : NULL, 
  1371.                         sptr, nick + 1,
  1372.                         (*nick == '#') ? MATCH_HOST :
  1373.                                  MATCH_SERVER,
  1374.                         ":%s %s %s :%s", parv[0],
  1375.                         cmd, nick, parv[2]);
  1376.             continue;
  1377.             }
  1378.     
  1379.         /*
  1380.         ** user[%host]@server addressed?
  1381.         */
  1382.         if ((server = (char *)index(nick, '@')) &&
  1383.             (acptr = find_server(server + 1, NULL)))
  1384.             {
  1385.             /*
  1386.             ** Not destined for a user on me :-(
  1387.             */
  1388.             if (!IsMe(acptr))
  1389.                 {
  1390.                 sendto_one(acptr,":%s %s %s :%s", parv[0],
  1391.                        cmd, nick, parv[2]);
  1392.                 continue;
  1393.                 }
  1394.  
  1395.             /*
  1396.             ** Find the nick@server using hash.
  1397.             */
  1398.             acptr = find_nickserv(nick, (aClient *)NULL);
  1399.             if (acptr) {
  1400.                 sendto_prefix_one(acptr, sptr,
  1401.                           ":%s %s %s :%s",
  1402.                            parv[0], cmd,
  1403.                           acptr->name,
  1404.                           parv[2]);
  1405.                 continue;
  1406.             }
  1407.             }
  1408.         if (server && strncasecmp(server+1, SERVICES_NAME, 
  1409.             strlen(SERVICES_NAME))==0)
  1410.             sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, 
  1411.                 parv[0], nick);
  1412.         else 
  1413.             sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
  1414.                 parv[0], nick);
  1415.             }
  1416.     return 0;
  1417. }
  1418.  
  1419. /*
  1420. ** m_private
  1421. **    parv[0] = sender prefix
  1422. **    parv[1] = receiver list
  1423. **    parv[2] = message text
  1424. */
  1425.  
  1426. int    m_private(cptr, sptr, parc, parv)
  1427. aClient *cptr, *sptr;
  1428. int    parc;
  1429. char    *parv[];
  1430. {
  1431.     return m_message(cptr, sptr, parc, parv, 0);
  1432. }
  1433.  
  1434. /*
  1435.  * Built in services aliasing for ChanServ, Memoserv, NickServ and
  1436.  * OperServ. This not only is an alias, but is also a security measure,
  1437.  * because PRIVMSG's arent sent to 'ChanServ' they are now sent to
  1438.  * 'ChanServ@services.dal.net' so nobody can snoop /cs commands :) -taz
  1439.  */
  1440.  
  1441. int    m_chanserv(cptr, sptr, parc, parv)
  1442. aClient *cptr, *sptr;
  1443. int    parc;
  1444. char    *parv[];
  1445. {
  1446.     aClient *acptr;
  1447.  
  1448.     if (check_registered_user(sptr))
  1449.         return 0;
  1450.  
  1451.     if (parc < 2 || *parv[1] == '\0') {
  1452.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1453.         return -1;
  1454.     }
  1455.  
  1456.     if ((acptr = find_person(ChanServ, NULL)))
  1457.         sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0], 
  1458.             ChanServ, SERVICES_NAME, parv[1]);
  1459.     else
  1460.         sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1461.             parv[0], ChanServ);
  1462. }
  1463.  
  1464. int    m_memoserv(cptr, sptr, parc, parv)
  1465. aClient *cptr, *sptr;
  1466. int    parc;
  1467. char    *parv[];
  1468. {
  1469.     aClient *acptr;
  1470.  
  1471.     if (check_registered_user(sptr))
  1472.         return 0;
  1473.  
  1474.     if (parc < 2 || *parv[1] == '\0') {
  1475.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1476.         return -1;
  1477.     }
  1478.  
  1479.     if ((acptr = find_person(MemoServ, NULL)))
  1480.         sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0], 
  1481.             MemoServ, SERVICES_NAME, parv[1]);
  1482.     else
  1483.         sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1484.             parv[0], MemoServ);
  1485. }
  1486.  
  1487. int    m_nickserv(cptr, sptr, parc, parv)
  1488. aClient *cptr, *sptr;
  1489. int    parc;
  1490. char    *parv[];
  1491. {
  1492.     aClient *acptr;
  1493.  
  1494.     if (check_registered_user(sptr))
  1495.         return 0;
  1496.  
  1497.     if (parc < 2 || *parv[1] == '\0') {
  1498.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1499.         return -1;
  1500.     }
  1501.  
  1502.     if ((acptr = find_person(NickServ, NULL)))
  1503.         sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0], 
  1504.             NickServ, SERVICES_NAME, parv[1]);
  1505.     else
  1506.         sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1507.             parv[0], NickServ);
  1508. }
  1509.  
  1510. int    m_operserv(cptr, sptr, parc, parv)
  1511. aClient *cptr, *sptr;
  1512. int    parc;
  1513. char    *parv[];
  1514. {
  1515.     aClient *acptr;
  1516.  
  1517.     if (check_registered_user(sptr))
  1518.         return 0;
  1519.  
  1520.     if (parc < 2 || *parv[1] == '\0') {
  1521.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1522.         return -1;
  1523.     }
  1524.  
  1525.     if ((acptr = find_person(OperServ, NULL)))
  1526.         sendto_one(acptr,":%s PRIVMSG %s@%s :%s", parv[0], 
  1527.             OperServ, SERVICES_NAME, parv[1]);
  1528.     else
  1529.         sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1530.             parv[0], OperServ);
  1531. }
  1532.  
  1533. /* 
  1534.  * Automatic NickServ/ChanServ direction for the identify command
  1535.  * -taz
  1536.  */
  1537. int    m_identify(cptr, sptr, parc, parv)
  1538. aClient *cptr, *sptr;
  1539. int    parc;
  1540. char    *parv[];
  1541. {
  1542.     aClient *acptr;
  1543.  
  1544.     if (check_registered_user(sptr))
  1545.         return 0;
  1546.  
  1547.     if (parc < 2 || *parv[1] == '\0') {
  1548.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1549.         return -1;
  1550.     }
  1551.  
  1552.     if (*parv[1]) {
  1553.         if((*parv[1] == '#') && ((char *)index(parv[1], ' '))) {
  1554.             if ((acptr = find_person(ChanServ, NULL)))
  1555.                 sendto_one(acptr,":%s PRIVMSG %s@%s :IDENTIFY %s", parv[0], 
  1556.                     ChanServ, SERVICES_NAME, parv[1]);
  1557.             else
  1558.                 sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1559.                     parv[0], ChanServ);
  1560.         } else {
  1561.             if ((acptr = find_person(NickServ, NULL)))
  1562.                 sendto_one(acptr,":%s PRIVMSG %s@%s :IDENTIFY %s", parv[0],
  1563.                     NickServ, SERVICES_NAME, parv[1]);
  1564.             else
  1565.                 sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
  1566.                     parv[0], NickServ);
  1567.         }
  1568.     }
  1569. }
  1570.  
  1571. /*
  1572.  * Automatic NickServ/ChanServ parsing. If the second word of parv[1]
  1573.  * starts with a '#' this message goes to ChanServ. If it starts with 
  1574.  * anything else, it goes to NickServ. If there is no second word in 
  1575.  * parv[1], the message defaultly goes to NickServ. If parv[1] == 'help'
  1576.  * the user in instructed to /cs, /ns or /ms HELP for the help they need.
  1577.  * -taz
  1578.  */
  1579.  
  1580. int    m_services(cptr, sptr, parc, parv)
  1581. aClient *cptr, *sptr;
  1582. int    parc;
  1583. char    *parv[];
  1584. {
  1585.     aClient *acptr;
  1586.     char *tmps;
  1587.  
  1588.     if (check_registered_user(sptr))
  1589.         return 0;
  1590.  
  1591.     if (parc < 2 || *parv[1] == '\0') {
  1592.         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
  1593.         return -1;
  1594.     }
  1595.  
  1596.     if ((strlen(parv[1])>=4) && (!strncmp(parv[1], "help", 4))) {
  1597.         sendto_one(sptr, ":services!service@%s NOTICE %s :For ChanServ help use: /chanserv help", SERVICES_NAME, sptr->name);
  1598.         sendto_one(sptr, ":services!service@%s NOTICE %s :For NickServ help use: /nickserv help", SERVICES_NAME, sptr->name);
  1599.         sendto_one(sptr, ":services!service@%s NOTICE %s :For MemoServ help use: /memoserv help", SERVICES_NAME, sptr->name);
  1600.         return;
  1601.     }
  1602.  
  1603.     if ((tmps = (char *)index(parv[1], ' '))) {
  1604.         tmps++;
  1605.         if(*tmps == '#')
  1606.             return m_chanserv(cptr, sptr, parc, parv);
  1607.         else
  1608.             return m_nickserv(cptr, sptr, parc, parv);
  1609.     }
  1610.  
  1611.     return m_nickserv(cptr, sptr, parc, parv);
  1612.  
  1613. }
  1614.  
  1615. /*
  1616. ** m_notice
  1617. **    parv[0] = sender prefix
  1618. **    parv[1] = receiver list
  1619. **    parv[2] = notice text
  1620. */
  1621.  
  1622. int    m_notice(cptr, sptr, parc, parv)
  1623. aClient *cptr, *sptr;
  1624. int    parc;
  1625. char    *parv[];
  1626. {
  1627.     if (!IsRegistered(cptr) && (cptr->name[0]) && !IsNotSpoof(cptr))
  1628.     {
  1629.         if (BadPtr(parv[1])) return 0;
  1630. #ifdef NOSPOOF
  1631.         if (strtoul(parv[1], NULL, 16) != cptr->nospoof)
  1632.             goto temp;
  1633.         sptr->nospoof = 0;
  1634. #endif
  1635.         if (sptr->user && sptr->name[0])
  1636.             return register_user(cptr, sptr, sptr->name,
  1637.                 sptr->user->username);
  1638.         return 0;
  1639.     }
  1640.     temp:
  1641.     return m_message(cptr, sptr, parc, parv, 1);
  1642. }
  1643.  
  1644. static    void    do_who(sptr, acptr, repchan)
  1645. aClient *sptr, *acptr;
  1646. aChannel *repchan;
  1647. {
  1648.     char    status[5];
  1649.     int    i = 0;
  1650.  
  1651.     if (acptr->user->away)
  1652.         status[i++] = 'G';
  1653.     else
  1654.         status[i++] = 'H';
  1655.     if (IsAnOper(acptr))
  1656.         status[i++] = '*';
  1657.     else if (IsInvisible(acptr) && sptr != acptr && IsAnOper(sptr))
  1658.         status[i++] = '%';
  1659.     if (repchan && is_chan_op(acptr, repchan))
  1660.         status[i++] = '@';
  1661.     else if (repchan && has_voice(acptr, repchan))
  1662.         status[i++] = '+';
  1663.     else if (repchan && is_zombie(acptr, repchan))
  1664.         status[i++] = '!';
  1665.     status[i] = '\0';
  1666.     sendto_one(sptr, rpl_str(RPL_WHOREPLY), me.name, sptr->name,
  1667.            (repchan) ? (repchan->chname) : "*", acptr->user->username,
  1668.            acptr->user->host, acptr->user->server, acptr->name,
  1669.            status, acptr->hopcount, acptr->info);
  1670. }
  1671.  
  1672.  
  1673. /*
  1674. ** m_who
  1675. **    parv[0] = sender prefix
  1676. **    parv[1] = nickname mask list
  1677. **    parv[2] = additional selection flag, only 'o' for now.
  1678. */
  1679. int    m_who(cptr, sptr, parc, parv)
  1680. aClient *cptr, *sptr;
  1681. int    parc;
  1682. char    *parv[];
  1683. {
  1684.     Reg1    aClient *acptr;
  1685.     Reg2    char    *mask = parc > 1 ? parv[1] : NULL;
  1686.     Reg3    Link    *lp;
  1687.     aChannel *chptr;
  1688.     aChannel *mychannel;
  1689.     char    *channame = NULL, *s;
  1690.     int    oper = parc > 2 ? (*parv[2] == 'o' ): 0; /* Show OPERS only */
  1691.     int    member;
  1692.  
  1693.     if (check_registered_user(sptr))
  1694.         return 0;
  1695.  
  1696.     if (!BadPtr(mask))
  1697.         {
  1698.         if ((s = (char *)index(mask, ',')))
  1699.             {
  1700.             parv[1] = ++s;
  1701.             (void)m_who(cptr, sptr, parc, parv);
  1702.             }
  1703.         clean_channelname(mask);
  1704.         }
  1705.  
  1706.     mychannel = NullChn;
  1707.     if (sptr->user)
  1708.         if ((lp = sptr->user->channel))
  1709.             mychannel = lp->value.chptr;
  1710.  
  1711.     /* Allow use of m_who without registering */
  1712.     
  1713.     /*
  1714.     **  Following code is some ugly hacking to preserve the
  1715.     **  functions of the old implementation. (Also, people
  1716.     **  will complain when they try to use masks like "12tes*"
  1717.     **  and get people on channel 12 ;) --msa
  1718.     */
  1719.     if (!mask || *mask == '\0')
  1720.         mask = NULL;
  1721.     else if (mask[1] == '\0' && mask[0] == '*')
  1722.         {
  1723.         mask = NULL;
  1724.         if (mychannel)
  1725.             channame = mychannel->chname;
  1726.         }
  1727.     else if (mask[1] == '\0' && mask[0] == '0') /* "WHO 0" for irc.el */
  1728.         mask = NULL;
  1729.     else
  1730.         channame = mask;
  1731.     (void)collapse(mask);
  1732.  
  1733.     if (IsChannelName(channame))
  1734.         {
  1735.         /*
  1736.          * List all users on a given channel
  1737.          */
  1738.         chptr = find_channel(channame, NULL);
  1739.         if (chptr)
  1740.           {
  1741.             member = IsMember(sptr, chptr);
  1742.             if (member || !SecretChannel(chptr))
  1743.             for (lp = chptr->members; lp; lp = lp->next)
  1744.                 {
  1745.                 if (oper && !IsAnOper(lp->value.cptr))
  1746.                     continue;
  1747.                 if (lp->value.cptr!=sptr &&
  1748.                     (lp->flags & CHFL_ZOMBIE))
  1749.                     continue;
  1750.                 if (lp->value.cptr!=sptr && IsInvisible(lp->value.cptr) && !member)
  1751.                     continue;
  1752.                 do_who(sptr, lp->value.cptr, chptr);
  1753.                 }
  1754.           }
  1755.         }
  1756.     else for (acptr = client; acptr; acptr = acptr->next)
  1757.         {
  1758.         aChannel *ch2ptr = NULL;
  1759.         int    showperson, isinvis;
  1760.  
  1761.         if (!IsPerson(acptr))
  1762.             continue;
  1763.         if (oper && !IsAnOper(acptr))
  1764.             continue;
  1765.         showperson = 0;
  1766.         /*
  1767.          * Show user if they are on the same channel, or not
  1768.          * invisible and on a non secret channel (if any).
  1769.          * Do this before brute force match on all relevant fields
  1770.          * since these are less cpu intensive (I hope :-) and should
  1771.          * provide better/more shortcuts - avalon
  1772.          */
  1773.         isinvis = acptr!=sptr && IsInvisible(acptr) && !IsAnOper(sptr);
  1774.         for (lp = acptr->user->channel; lp; lp = lp->next)
  1775.             {
  1776.             chptr = lp->value.chptr;
  1777.             member = IsMember(sptr, chptr);
  1778.             if (isinvis && !member)
  1779.                 continue;
  1780.             if (is_zombie(acptr, chptr))
  1781.                 continue;
  1782.             if (IsAnOper(sptr)) showperson = 1;
  1783.             if (member || (!isinvis && 
  1784.                 ShowChannel(sptr, chptr)))
  1785.                 {
  1786.                 ch2ptr = chptr;
  1787.                 showperson = 1;
  1788.                 break;
  1789.                 }
  1790.             if (HiddenChannel(chptr) && !SecretChannel(chptr) &&
  1791.                 !isinvis)
  1792.                 showperson = 1;
  1793.             }
  1794.         if (!acptr->user->channel && !isinvis)
  1795.             showperson = 1;
  1796.         /*
  1797.         ** This is brute force solution, not efficient...? ;( 
  1798.         ** Show entry, if no mask or any of the fields match
  1799.         ** the mask. --msa
  1800.         */
  1801.         if (showperson &&
  1802.             (!mask ||
  1803.              match(mask, acptr->name) == 0 ||
  1804.              match(mask, acptr->user->username) == 0 ||
  1805.              match(mask, acptr->user->host) == 0 ||
  1806.              match(mask, acptr->user->server) == 0 ||
  1807.              match(mask, acptr->info) == 0))
  1808.             do_who(sptr, acptr, ch2ptr);
  1809.         }
  1810.     sendto_one(sptr, rpl_str(RPL_ENDOFWHO), me.name, parv[0],
  1811.            BadPtr(mask) ?  "*" : mask);
  1812.     return 0;
  1813. }
  1814.  
  1815. /*
  1816. ** m_whois
  1817. **    parv[0] = sender prefix
  1818. **    parv[1] = nickname masklist
  1819. */
  1820. int    m_whois(cptr, sptr, parc, parv)
  1821. aClient *cptr, *sptr;
  1822. int    parc;
  1823. char    *parv[];
  1824. {
  1825.     static anUser UnknownUser =
  1826.         {
  1827.         NULL,    /* nextu */
  1828.         NULL,    /* channel */
  1829.         NULL,   /* invited */
  1830.         NULL,    /* silence */
  1831.         NULL,    /* away */
  1832.         0,    /* last */
  1833.         0,    /* servicestamp */
  1834.         1,      /* refcount */
  1835.         0,    /* joined */
  1836.         "<Unknown>",    /* username */
  1837.         "<Unknown>",    /* host */
  1838.         "<Unknown>"    /* server */
  1839.         };
  1840.     Reg2    Link    *lp;
  1841.     Reg3    anUser    *user;
  1842.     aClient *acptr, *a2cptr;
  1843.     aChannel *chptr;
  1844.     char    *nick, *tmp, *name, *temp;
  1845.     char    *p = NULL;
  1846.     int    found, len, mlen, t;
  1847.  
  1848.  
  1849.     if (check_registered_user(sptr))
  1850.         return 0;
  1851.  
  1852.         if (parc < 2)
  1853.         {
  1854.         sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
  1855.                me.name, parv[0]);
  1856.         return 0;
  1857.         }
  1858.  
  1859.     if (parc > 2)
  1860.         {
  1861.         if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) !=
  1862.             HUNTED_ISME)
  1863.             return 0;
  1864.         parv[1] = parv[2];
  1865.         }
  1866.  
  1867.     for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL)
  1868.         {
  1869.         int    invis, showperson, member, wilds;
  1870.  
  1871.         found = 0;
  1872.         (void)collapse(nick);
  1873.         wilds = (index(nick, '?') || index(nick, '*'));
  1874.         if (wilds && IsServer(cptr)) continue;
  1875.         for (acptr = client; (acptr = next_client(acptr, nick));
  1876.              acptr = acptr->next)
  1877.             {
  1878.             if (IsServer(acptr))
  1879.                 continue;
  1880.             /*
  1881.              * I'm always last :-) and acptr->next == NULL!!
  1882.              */
  1883.             if (IsMe(acptr))
  1884.                 break;
  1885.             /*
  1886.              * 'Rules' established for sending a WHOIS reply:
  1887.              *
  1888.              * - only allow a remote client to get replies for
  1889.              *   local clients if wildcards are being used;
  1890.              *
  1891.              * - if wildcards are being used dont send a reply if
  1892.              *   the querier isnt any common channels and the
  1893.              *   client in question is invisible and wildcards are
  1894.              *   in use (allow exact matches only);
  1895.              *
  1896.              * - only send replies about common or public channels
  1897.              *   the target user(s) are on;
  1898.              */
  1899.             if (!MyConnect(sptr) && !MyConnect(acptr) && wilds)
  1900.                 continue;
  1901.             user = acptr->user ? acptr->user : &UnknownUser;
  1902.             name = (!*acptr->name) ? "?" : acptr->name;
  1903.  
  1904.             invis = acptr!=sptr && IsInvisible(acptr);
  1905.             member = (user->channel) ? 1 : 0;
  1906.             showperson = (wilds && !invis && !member) || !wilds;
  1907.             for (lp = user->channel; lp; lp = lp->next)
  1908.                 {
  1909.                 chptr = lp->value.chptr;
  1910.                 member = IsMember(sptr, chptr);
  1911.                 if (invis && !member)
  1912.                     continue;
  1913.                 if (is_zombie(acptr, chptr))
  1914.                     continue;
  1915.                 if (member || (!invis && PubChannel(chptr)))
  1916.                     {
  1917.                     showperson = 1;
  1918.                     break;
  1919.                     }
  1920.                 if (!invis && HiddenChannel(chptr) &&
  1921.                     !SecretChannel(chptr))
  1922.                     showperson = 1;
  1923.                 }
  1924.             if (!showperson)
  1925.                 continue;
  1926.  
  1927.             a2cptr = find_server(user->server, NULL);
  1928.  
  1929.             sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name,
  1930.                    parv[0], name,
  1931.                    user->username, user->host, acptr->info);
  1932.             if (IsARegNick(acptr))
  1933.                 sendto_one(sptr, rpl_str(RPL_WHOISREGNICK),
  1934.                        me.name, parv[0], name);
  1935.             found = 1;
  1936.             mlen = strlen(me.name) + strlen(parv[0]) + 6 +
  1937.                 strlen(name);
  1938.             for (len = 0, *buf = '\0', lp = user->channel; lp;
  1939.                  lp = lp->next)
  1940.                 {
  1941.                 chptr = lp->value.chptr;
  1942.                 if (ShowChannel(sptr, chptr) &&
  1943.                     (acptr==sptr || !is_zombie(acptr, chptr)))
  1944.                     {
  1945.                     if (len + strlen(chptr->chname)
  1946.                                             > (size_t) BUFSIZE - 4 - mlen)
  1947.                         {
  1948.                         sendto_one(sptr,
  1949.                                ":%s %d %s %s :%s",
  1950.                                me.name,
  1951.                                RPL_WHOISCHANNELS,
  1952.                                parv[0], name, buf);
  1953.                         *buf = '\0';
  1954.                         len = 0;
  1955.                         }
  1956.                     if (is_chan_op(acptr, chptr))
  1957.                         *(buf + len++) = '@';
  1958.                     else if (has_voice(acptr, chptr))
  1959.                         *(buf + len++) = '+';
  1960.                      else if (is_zombie(acptr, chptr))
  1961.                         *(buf + len++) = '!';
  1962.                     if (len)
  1963.                         *(buf + len) = '\0';
  1964.                     (void)strcpy(buf + len, chptr->chname);
  1965.                     len += strlen(chptr->chname);
  1966.                     (void)strcat(buf + len, " ");
  1967.                     len++;
  1968.                     }
  1969.                 }
  1970.             if (buf[0] != '\0')
  1971.                 sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS),
  1972.                        me.name, parv[0], name, buf);
  1973.  
  1974.             sendto_one(sptr, rpl_str(RPL_WHOISSERVER),
  1975.                    me.name, parv[0], name, user->server,
  1976.                    a2cptr?a2cptr->info:"*Not On This Net*");
  1977.  
  1978.             if (user->away)
  1979.                 sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
  1980.                        parv[0], name, user->away);
  1981.  
  1982.             /* The following includes admin/Sadmin
  1983.              * status in the WHOISOPERATOR reply.
  1984.                          * -DuffJ
  1985.              */
  1986.             buf[0]='\0';
  1987.                   if (IsAnOper(acptr))
  1988.                 strcat(buf, "an IRC Operator");
  1989.                   if (IsAdmin(acptr))
  1990.                 strcat(buf, " - Server Administrator");
  1991.                   else if (IsSAdmin(acptr))
  1992.                 strcat(buf, " - Services Administrator");
  1993.  
  1994.             if(buf[0])
  1995.              sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR),
  1996.                 me.name, parv[0], name, buf);
  1997.  
  1998.                         if (IsHelpOp(acptr))
  1999.                          sendto_one(sptr, rpl_str(RPL_WHOISHELPOP),
  2000.                 me.name, parv[0], name);
  2001.  
  2002.             if (acptr->user && MyConnect(acptr))
  2003.                 sendto_one(sptr, rpl_str(RPL_WHOISIDLE),
  2004.                        me.name, parv[0], name,
  2005.                        time(NULL) - user->last,
  2006.                        acptr->firsttime);
  2007.             }
  2008.         if (!found)
  2009.             sendto_one(sptr, err_str(ERR_NOSUCHNICK),
  2010.                    me.name, parv[0], nick);
  2011.         if (p)
  2012.             p[-1] = ',';
  2013.         }
  2014.     sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], parv[1]);
  2015.  
  2016.     return 0;
  2017. }
  2018.  
  2019. /*
  2020. ** m_user
  2021. **    parv[0] = sender prefix
  2022. **    parv[1] = username (login name, account)
  2023. **    parv[2] = client host name (used only from other servers)
  2024. **    parv[3] = server host name (used only from other servers)
  2025. **    parv[4] = users real name info
  2026. */
  2027. int    m_user(cptr, sptr, parc, parv)
  2028. aClient    *cptr, *sptr;
  2029. int    parc;
  2030. char    *parv[];
  2031. {
  2032. #define    UFLAGS    (UMODE_INVISIBLE|UMODE_WALLOP|UMODE_SERVNOTICE)
  2033.     char    *username, *host, *server, *realname;
  2034.     u_int32_t sstamp = 0;
  2035.     anUser    *user;
  2036.  
  2037.     if (IsServer(cptr) && !IsUnknown(sptr))
  2038.         return 0;
  2039.  
  2040.     if (parc > 2 && (username = (char *)index(parv[1],'@')))
  2041.         *username = '\0'; 
  2042.     if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
  2043.         *parv[3] == '\0' || *parv[4] == '\0')
  2044.         {
  2045.         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2046.                    me.name, parv[0], "USER");
  2047.         if (IsServer(cptr))
  2048.             sendto_ops("bad USER param count for %s from %s",
  2049.                    parv[0], get_client_name(cptr, FALSE));
  2050.         else
  2051.             return 0;
  2052.         }
  2053.  
  2054.     /* Copy parameters into better documenting variables */
  2055.  
  2056.     username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
  2057.     host     = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
  2058.     server   = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];
  2059.  
  2060.     /* This we can remove as soon as all servers have upgraded. */
  2061.  
  2062.     if (parc == 6 && IsServer(cptr)) {
  2063.         if (isdigit(*parv[4]))
  2064.              sstamp = atol(parv[4]);
  2065.         realname = (BadPtr(parv[5])) ? "<bad-realname>" : parv[5];
  2066.     } else
  2067.         realname = (BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
  2068.  
  2069.      user = make_user(sptr);
  2070.  
  2071.     if (!MyConnect(sptr))
  2072.         {
  2073.         if (sptr->srvptr == NULL)
  2074.             sendto_ops("WARNING, User %s introduced as being "
  2075.                 "on non-existant server %s.", sptr->name,
  2076.                 server);
  2077.         strncpyzt(user->server, server, sizeof(user->server));
  2078.         strncpyzt(user->host, host, sizeof(user->host));
  2079.         goto user_finish;
  2080.         }
  2081.  
  2082.     if (!IsUnknown(sptr))
  2083.         {
  2084.         sendto_one(sptr, err_str(ERR_ALREADYREGISTRED),
  2085.                me.name, parv[0]);
  2086.         return 0;
  2087.         }
  2088. #ifndef    NO_DEFAULT_INVISIBLE
  2089.     sptr->umodes |= UMODE_INVISIBLE;
  2090. #endif
  2091.     sptr->umodes |= (UFLAGS & atoi(host));
  2092.     strncpyzt(user->host, host, sizeof(user->host));
  2093.     strncpyzt(user->server, me.name, sizeof(user->server));
  2094. user_finish:
  2095.     user->servicestamp = sstamp;
  2096.     strncpyzt(sptr->info, realname, sizeof(sptr->info));
  2097.     if (sptr->name[0] && (IsServer(cptr) ? 1 : IsNotSpoof(sptr)))
  2098.     /* NICK and no-spoof already received, now we have USER... */
  2099.         return register_user(cptr, sptr, sptr->name, username);
  2100.     else
  2101.         strncpyzt(sptr->user->username, username, USERLEN+1);
  2102.     return 0;
  2103. }
  2104.  
  2105. /*
  2106. ** m_quit
  2107. **    parv[0] = sender prefix
  2108. **    parv[1] = comment
  2109. */
  2110. int    m_quit(cptr, sptr, parc, parv)
  2111. aClient *cptr, *sptr;
  2112. int    parc;
  2113. char    *parv[];
  2114.     {
  2115.     char *ocomment = (parc > 1 && parv[1]) ? parv[1] : parv[0];
  2116.     static char comment[TOPICLEN];
  2117.  
  2118.     if (!IsServer(cptr)) {
  2119.         strcat(comment, "Quit: ");
  2120.         strncpy(comment+6,ocomment,TOPICLEN-7);
  2121.         comment[TOPICLEN] = '\0';
  2122.         return exit_client(cptr, sptr, sptr, comment);
  2123.     } else
  2124.         return exit_client(cptr, sptr, sptr, ocomment);
  2125.     }
  2126.  
  2127. /*
  2128. ** m_kill
  2129. **    parv[0] = sender prefix
  2130. **    parv[1] = kill victim(s) - comma separated list
  2131. **    parv[2] = kill path
  2132. */
  2133. int    m_kill(cptr, sptr, parc, parv)
  2134. aClient *cptr, *sptr;
  2135. int    parc;
  2136. char    *parv[];
  2137. {
  2138.     static anUser UnknownUser =
  2139.         {
  2140.         NULL,    /* nextu */
  2141.         NULL,    /* channel */
  2142.         NULL,   /* invited */
  2143.         NULL,    /* silence */
  2144.         NULL,    /* away */
  2145.         0,    /* last */
  2146.         0,    /* servicestamp */
  2147.         1,      /* refcount */
  2148.         0,    /* joined */
  2149.         "<Unknown>",    /* username */
  2150.         "<Unknown>",    /* host */
  2151.         "<Unknown>"    /* server */
  2152.         };
  2153.     aClient *acptr;
  2154.     anUser     *auser;
  2155.     char    inpath[HOSTLEN * 2 + USERLEN + 5];
  2156.     char    *oinpath = get_client_name(cptr,FALSE);
  2157.     char    *user, *path, *killer, *nick, *p, *s;
  2158.     int    chasing = 0, kcount = 0;
  2159.  
  2160.  
  2161.         if (check_registered(sptr))
  2162.                 return 0;
  2163.  
  2164.     if (parc < 2 || *parv[1] == '\0')
  2165.         {
  2166.         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2167.                me.name, parv[0], "KILL");
  2168.         return 0;
  2169.         }
  2170.  
  2171.     user = parv[1];
  2172.     path = parv[2]; /* Either defined or NULL (parc >= 2!!) */
  2173.     strcpy(inpath, oinpath);
  2174.     if (IsServer(cptr) && (s = (char *)index(inpath, '.')) != NULL)
  2175.         *s = '\0';    /* Truncate at first "." */
  2176.     if (!IsPrivileged(cptr))
  2177.         {
  2178.         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  2179.         return 0;
  2180.         }
  2181.     if (IsAnOper(cptr))
  2182.         {
  2183.         if (BadPtr(path))
  2184.             {
  2185.             sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2186.                    me.name, parv[0], "KILL");
  2187.             return 0;
  2188.             }
  2189.         if (strlen(path) > (size_t) TOPICLEN)
  2190.             path[TOPICLEN] = '\0';
  2191.         }
  2192.     if (MyClient(sptr))
  2193.         user = canonize(user);
  2194.     for (p = NULL, nick = strtoken(&p, user, ","); nick;
  2195.         nick = strtoken(&p, NULL, ","))
  2196.     {
  2197.     chasing = 0;
  2198.     if (!(acptr = find_client(nick, NULL)))
  2199.         {
  2200.         /*
  2201.         ** If the user has recently changed nick, we automaticly
  2202.         ** rewrite the KILL for this new nickname--this keeps
  2203.         ** servers in synch when nick change and kill collide
  2204.         */
  2205.         if (!(acptr = get_history(nick, (long)KILLCHASETIMELIMIT)))
  2206.             {
  2207.             sendto_one(sptr, err_str(ERR_NOSUCHNICK),
  2208.                    me.name, parv[0], nick);
  2209.             continue;
  2210.             }
  2211.         sendto_one(sptr,":%s NOTICE %s :KILL changed from %s to %s",
  2212.                me.name, parv[0], nick, acptr->name);
  2213.         chasing = 1;
  2214.         }
  2215.     if ((!MyConnect(acptr) && MyClient(cptr) && !OPCanGKill(cptr)) ||
  2216.         (MyConnect(acptr) && MyClient(cptr) && !OPCanLKill(cptr)))
  2217.         {
  2218.         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  2219.         continue;
  2220.         }
  2221.     if (IsServer(acptr) || IsMe(acptr))
  2222.         {
  2223.         sendto_one(sptr, err_str(ERR_CANTKILLSERVER),
  2224.                me.name, parv[0]);
  2225.         continue;
  2226.         }
  2227.     /* From here on, the kill is probably going to be successful. */
  2228.     kcount++;
  2229.     if (!IsServer(sptr) && (kcount > MAXKILLS))
  2230.     {
  2231.       sendto_one(sptr,":%s NOTICE %s :Too many targets, kill list was truncated. Maximum is %d.",me.name, parv[0], MAXKILLS);
  2232.       break;
  2233.     }
  2234.     if (!IsServer(cptr))
  2235.         {
  2236.         /*
  2237.         ** The kill originates from this server, initialize path.
  2238.         ** (In which case the 'path' may contain user suplied
  2239.         ** explanation ...or some nasty comment, sigh... >;-)
  2240.         **
  2241.         **    ...!operhost!oper
  2242.         **    ...!operhost!oper (comment)
  2243.         */
  2244.         if (IsUnixSocket(cptr)) /* Don't use get_client_name syntax */
  2245.             strcpy(inpath, me.sockhost);
  2246.         else
  2247.             strcpy(inpath, cptr->sockhost);
  2248.         if (kcount < 2) /* Only check the path the first time 
  2249.                    around, or it gets appended to itself. */
  2250.          if (!BadPtr(path))
  2251.             {
  2252.             (void)sprintf(buf, "%s%s (%s)",
  2253.                 cptr->name, IsOper(sptr) ? "" : "(L)", path);
  2254.             path = buf;
  2255.             }
  2256.          else
  2257.             path = cptr->name;
  2258.         }
  2259.     else if (BadPtr(path))
  2260.          path = "*no-path*"; /* Bogus server sending??? */
  2261.     /*
  2262.     ** Notify all *local* opers about the KILL (this includes the one
  2263.     ** originating the kill, if from this server--the special numeric
  2264.     ** reply message is not generated anymore).
  2265.     **
  2266.     ** Note: "acptr->name" is used instead of "user" because we may
  2267.     **     have changed the target because of the nickname change.
  2268.     */
  2269.     auser = acptr->user ? acptr->user : &UnknownUser;
  2270.     if (index(parv[0], '.'))
  2271.         sendto_umode(UMODE_KILLS, "*** Notice -- Received KILL message for %s!%s@%s from %s Path: %s!%s",
  2272.             acptr->name, auser->username, auser->host,
  2273.             parv[0], inpath, path);
  2274.     else
  2275.         sendto_ops("Received KILL message for %s!%s@%s from %s Path: %s!%s",
  2276.             acptr->name, auser->username, auser->host,
  2277.             parv[0], inpath, path);
  2278. #if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
  2279.     if (IsOper(sptr))
  2280.         syslog(LOG_DEBUG,"KILL From %s For %s Path %s!%s",
  2281.             parv[0], acptr->name, inpath, path);
  2282. #endif
  2283.     /*
  2284.     ** And pass on the message to other servers. Note, that if KILL
  2285.     ** was changed, the message has to be sent to all links, also
  2286.     ** back.
  2287.     ** Suicide kills are NOT passed on --SRB
  2288.     */
  2289.     if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
  2290.         {
  2291.         sendto_serv_butone(cptr, ":%s KILL %s :%s!%s",
  2292.                    parv[0], acptr->name, inpath, path);
  2293.         if (chasing && IsServer(cptr))
  2294.             sendto_one(cptr, ":%s KILL %s :%s!%s",
  2295.                    me.name, acptr->name, inpath, path);
  2296.         acptr->flags |= FLAGS_KILLED;
  2297.         }
  2298. #ifdef    USE_SERVICES
  2299.     check_services_butone(SERVICE_WANT_KILL, sptr, ":%s KILL %s :%s!%s",
  2300.                 parv[0], acptr->name, inpath, path);
  2301. #endif
  2302.     /*
  2303.     ** Tell the victim she/he has been zapped, but *only* if
  2304.     ** the victim is on current server--no sense in sending the
  2305.     ** notification chasing the above kill, it won't get far
  2306.     ** anyway (as this user don't exist there any more either)
  2307.     */
  2308.     if (MyConnect(acptr))
  2309.         sendto_prefix_one(acptr, sptr,":%s KILL %s :%s!%s",
  2310.                   parv[0], acptr->name, inpath, path);
  2311.     /*
  2312.     ** Set FLAGS_KILLED. This prevents exit_one_client from sending
  2313.     ** the unnecessary QUIT for this. (This flag should never be
  2314.     ** set in any other place)
  2315.     */
  2316.     if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))
  2317.         (void)sprintf(buf2, "Local kill by %s (%s)", sptr->name,
  2318.             BadPtr(parv[2]) ? sptr->name : parv[2]);
  2319.     else
  2320.         {
  2321.         if ((killer = index(path, ' ')))
  2322.             {
  2323.             while (*killer && *killer != '!')
  2324.                 killer--;
  2325.             if (!*killer)
  2326.                 killer = path;
  2327.             else
  2328.                 killer++;
  2329.             }
  2330.         else
  2331.             killer = path;
  2332.         (void)sprintf(buf2, "Killed (%s)", killer);
  2333.         }
  2334.         if(exit_client(cptr, acptr, sptr, buf2) == FLUSH_BUFFER)
  2335.         return FLUSH_BUFFER;
  2336.     }
  2337.     return 0;
  2338. }
  2339. /***********************************************************************
  2340.  * m_away() - Added 14 Dec 1988 by jto. 
  2341.  *            Not currently really working, I don't like this
  2342.  *            call at all...
  2343.  *
  2344.  *            ...trying to make it work. I don't like it either,
  2345.  *          but perhaps it's worth the load it causes to net.
  2346.  *          This requires flooding of the whole net like NICK,
  2347.  *          USER, MODE, etc messages...  --msa
  2348.  ***********************************************************************/
  2349. /*
  2350. ** m_away
  2351. **    parv[0] = sender prefix
  2352. **    parv[1] = away message
  2353. */
  2354. int    m_away(cptr, sptr, parc, parv)
  2355. aClient *cptr, *sptr;
  2356. int    parc;
  2357. char    *parv[];
  2358. {
  2359.     Reg1    char    *away, *awy2 = parv[1];
  2360.     if (check_registered_user(sptr))
  2361.         return 0;
  2362.     away = sptr->user->away;
  2363.     if (parc < 2 || !*awy2)
  2364.         {
  2365.         /* Marking as not away */
  2366.         if (away)
  2367.             {
  2368.             MyFree(away);
  2369.             sptr->user->away = NULL;
  2370.             }
  2371.         sendto_serv_butone(cptr, ":%s AWAY", parv[0]);
  2372.         if (MyConnect(sptr))
  2373.             sendto_one(sptr, rpl_str(RPL_UNAWAY),
  2374.                    me.name, parv[0]);
  2375. #ifdef    USE_SERVICES
  2376.         check_services_butonee(SERVICE_WANT_AWAY, ":%s AWAY", parv[0]);
  2377. #endif
  2378.         return 0;
  2379.         }
  2380.     /* Marking as away */
  2381.     if (strlen(awy2) > (size_t) TOPICLEN)
  2382.         awy2[TOPICLEN] = '\0';
  2383.     sendto_serv_butone(cptr, ":%s AWAY :%s", parv[0], awy2);
  2384. #ifdef    USE_SERVICES
  2385.     check_services_butonee(SERVICE_WANT_AWAY, ":%s AWAY :%s",
  2386.                 parv[0], parv[1]);
  2387. #endif
  2388.     if (away)
  2389.         away = (char *)MyRealloc(away, strlen(awy2)+1);
  2390.     else
  2391.         away = (char *)MyMalloc(strlen(awy2)+1);
  2392.     sptr->user->away = away;
  2393.     (void)strcpy(away, awy2);
  2394.     if (MyConnect(sptr))
  2395.         sendto_one(sptr, rpl_str(RPL_NOWAWAY), me.name, parv[0]);
  2396.     return 0;
  2397. }
  2398. /*
  2399. ** m_ping
  2400. **    parv[0] = sender prefix
  2401. **    parv[1] = origin
  2402. **    parv[2] = destination
  2403. */
  2404. int    m_ping(cptr, sptr, parc, parv)
  2405. aClient *cptr, *sptr;
  2406. int    parc;
  2407. char    *parv[];
  2408. {
  2409.     aClient *acptr;
  2410.     char    *origin, *destination;
  2411.         if (check_registered(sptr))
  2412.                 return 0;
  2413.  
  2414.      if (parc < 2 || *parv[1] == '\0')
  2415.         {
  2416.         sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
  2417.         return 0;
  2418.         }
  2419.     origin = parv[1];
  2420.     destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */
  2421.     acptr = find_client(origin, NULL);
  2422.     if (!acptr)
  2423.         acptr = find_server(origin, NULL);
  2424.     if (acptr && acptr != sptr)
  2425.         origin = cptr->name;
  2426.     if (!BadPtr(destination) && mycmp(destination, me.name) != 0)
  2427.         {
  2428.         if ((acptr = find_server(destination, NULL)))
  2429.             sendto_one(acptr,":%s PING %s :%s", parv[0],
  2430.                    origin, destination);
  2431.             else
  2432.             {
  2433.             sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
  2434.                    me.name, parv[0], destination);
  2435.             return 0;
  2436.             }
  2437.         }
  2438.     else
  2439.         sendto_one(sptr,":%s PONG %s :%s", me.name,
  2440.                (destination) ? destination : me.name, origin);
  2441.     return 0;
  2442.     }
  2443. #ifdef NOSPOOF
  2444. /*
  2445. ** m_nospoof - allows clients to respond to no spoofing patch
  2446. **    parv[0] = prefix
  2447. **    parv[1] = code
  2448. */
  2449. int    m_nospoof(cptr, sptr, parc, parv)
  2450. aClient *cptr, *sptr;
  2451. int    parc;
  2452. char    *parv[];
  2453. {
  2454. unsigned long result;
  2455.     if (IsNotSpoof(cptr)) return 0;
  2456.     if (IsRegistered(cptr)) return 0;
  2457.     if (!*sptr->name) return 0;
  2458.     if (BadPtr(parv[1])) goto temp;
  2459.     result = strtoul(parv[1], NULL, 16);
  2460.     /* Accept code in second parameter (ircserv) */
  2461.     if (result != sptr->nospoof)
  2462.     {
  2463.         if (BadPtr(parv[2])) goto temp;
  2464.         result = strtoul(parv[2], NULL, 16);
  2465.         if (result != sptr->nospoof) goto temp;
  2466.     }
  2467.     sptr->nospoof = 0;
  2468.     if (sptr->user && sptr->name[0])
  2469.         return register_user(cptr, sptr, sptr->name,
  2470.             sptr->user->username);
  2471.     return 0;
  2472.     temp:
  2473.     /* Homer compatibility */
  2474.     sendto_one(cptr, ":%X!nospoof@%s PRIVMSG %s :%cVERSION%c",
  2475.         cptr->nospoof, me.name, cptr->name, (char) 1, (char) 1);
  2476.     return 0;
  2477. }
  2478. #endif /* NOSPOOF */
  2479. /*
  2480. ** m_pong
  2481. **    parv[0] = sender prefix
  2482. **    parv[1] = origin
  2483. **    parv[2] = destination
  2484. */
  2485. int    m_pong(cptr, sptr, parc, parv)
  2486. aClient *cptr, *sptr;
  2487. int    parc;
  2488. char    *parv[];
  2489. {
  2490.     aClient *acptr;
  2491.     char    *origin, *destination;
  2492. #ifdef NOSPOOF
  2493.     if (!IsRegistered(cptr))
  2494.         return m_nospoof(cptr, sptr, parc, parv);
  2495. #endif
  2496.     if (parc < 2 || *parv[1] == '\0')
  2497.         {
  2498.         sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
  2499.         return 0;
  2500.         }
  2501.     origin = parv[1];
  2502.     destination = parv[2];
  2503.     cptr->flags &= ~FLAGS_PINGSENT;
  2504.     sptr->flags &= ~FLAGS_PINGSENT;
  2505.     if (!BadPtr(destination) && mycmp(destination, me.name) != 0)
  2506.         {
  2507.         if ((acptr = find_client(destination, NULL)) ||
  2508.             (acptr = find_server(destination, NULL)))
  2509.         {
  2510.             if (!IsServer(cptr) && !IsServer(acptr))
  2511.             {
  2512.                 sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
  2513.                     me.name, parv[0], destination);
  2514.                 return 0;
  2515.             }
  2516.             else
  2517.             sendto_one(acptr,":%s PONG %s %s",
  2518.                    parv[0], origin, destination);
  2519.         }
  2520.         else
  2521.             {
  2522.             sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
  2523.                    me.name, parv[0], destination);
  2524.             return 0;
  2525.             }
  2526.         }
  2527. #ifdef    DEBUGMODE
  2528.     else
  2529.         Debug((DEBUG_NOTICE, "PONG: %s %s", origin,
  2530.               destination ? destination : "*"));
  2531. #endif
  2532.     return 0;
  2533.     }
  2534. /*
  2535. ** m_oper
  2536. **    parv[0] = sender prefix
  2537. **    parv[1] = oper name
  2538. **    parv[2] = oper password
  2539. */
  2540. int    m_oper(cptr, sptr, parc, parv)
  2541. aClient *cptr, *sptr;
  2542. int    parc;
  2543. char    *parv[];
  2544.     {
  2545.     aConfItem *aconf;
  2546.     char    *name, *password, *encr;
  2547. #ifdef CRYPT_OPER_PASSWORD
  2548.     char    salt[3];
  2549.     extern    char *crypt();
  2550. #endif /* CRYPT_OPER_PASSWORD */
  2551.     if (check_registered_user(sptr))
  2552.         return 0;
  2553.     name = parc > 1 ? parv[1] : NULL;
  2554.     password = parc > 2 ? parv[2] : NULL;
  2555.     if (!IsServer(cptr) && (BadPtr(name) || BadPtr(password)))
  2556.         {
  2557.         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2558.                me.name, parv[0], "OPER");
  2559.         return 0;
  2560.         }
  2561.     
  2562.     /* if message arrived from server, trust it, and set to oper */
  2563.         
  2564.     if ((IsServer(cptr) || IsMe(cptr)) && !IsOper(sptr))
  2565.         {
  2566.         sptr->umodes |= UMODE_OPER;
  2567.         sendto_serv_butone(cptr, ":%s MODE %s :+o", parv[0], parv[0]);
  2568.         if (IsMe(cptr))
  2569.             sendto_one(sptr, rpl_str(RPL_YOUREOPER),
  2570.                    me.name, parv[0]);
  2571. #ifdef    USE_SERVICES
  2572.         check_services_butone(SERVICE_WANT_OPER, sptr,
  2573.                       ":%s MODE %s :+o", parv[0], parv[0]);
  2574. #endif
  2575.         return 0;
  2576.         }
  2577.     else if (IsOper(sptr))
  2578.         {
  2579.         if (MyConnect(sptr))
  2580.             sendto_one(sptr, rpl_str(RPL_YOUREOPER),
  2581.                    me.name, parv[0]);
  2582.         return 0;
  2583.         }
  2584.     if (!(aconf = find_conf_exact(name, sptr->username, sptr->sockhost,
  2585.                       CONF_OPS)) &&
  2586.         !(aconf = find_conf_exact(name, sptr->username,
  2587.                       inetntoa((char *)&cptr->ip), CONF_OPS)))
  2588.         {
  2589.         sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
  2590.                 sendto_realops("Failed OPER attempt by %s (%s@%s)",
  2591.                   parv[0], sptr->user->username, sptr->sockhost);
  2592.         sptr->since += 7;
  2593.         return 0;
  2594.         }
  2595. #ifdef CRYPT_OPER_PASSWORD
  2596.         /* use first two chars of the password they send in as salt */
  2597.         /* passwd may be NULL. Head it off at the pass... */
  2598.         salt[0] = '\0';
  2599.         if (password && aconf->passwd && aconf->passwd[0] && aconf->passwd[1])
  2600.         {
  2601.             salt[0] = aconf->passwd[0];
  2602.         salt[1] = aconf->passwd[1];
  2603.         salt[2] = '\0';
  2604.         encr = crypt(password, salt);
  2605.         }
  2606.     else
  2607.         encr = "";
  2608. #else
  2609.     encr = password;
  2610. #endif  /* CRYPT_OPER_PASSWORD */
  2611.     if ((aconf->status & CONF_OPS) &&
  2612.         StrEq(encr, aconf->passwd) && !attach_conf(sptr, aconf))
  2613.         {
  2614.         int old = (sptr->umodes & ALL_UMODES);
  2615.         char *s;
  2616.         s = index(aconf->host, '@');
  2617.         *s++ = '\0';
  2618.         if (!(aconf->port & OFLAG_ISGLOBAL))
  2619.             SetLocOp(sptr);
  2620.         else
  2621.             SetOper(sptr);
  2622.         sptr->oflag = aconf->port;
  2623.         *--s =  '@';
  2624.         sendto_ops("%s (%s!%s@%s) is now operator (%c)", parv[1],
  2625.                parv[0], sptr->user->username,
  2626.                sptr->user->host, IsOper(sptr) ? 'O' : 'o');
  2627. /*                sendto_serv_butone("%s (%s@%s) is now 
  2628.                operator (%c)", parv[0],
  2629.                            sptr->user->username, sptr->user->host,
  2630.                            IsOper(sptr) ? 'O' : 'o');*/
  2631.         sptr->umodes |=
  2632.         (UMODE_SERVNOTICE|UMODE_WALLOP|UMODE_FAILOP|UMODE_FLOOD);
  2633.         send_umode_out(cptr, sptr, old);
  2634.          sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
  2635. #if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\
  2636.     (defined(USE_SYSLOG) && defined(SYSLOG_OPER)))
  2637.         encr = "";
  2638. #endif
  2639. #if defined(USE_SYSLOG) && defined(SYSLOG_OPER)
  2640.         syslog(LOG_INFO, "OPER (%s) (%s) by (%s!%s@%s)",
  2641.             name, encr,
  2642.             parv[0], sptr->user->username, sptr->sockhost);
  2643. #endif
  2644. #ifdef FNAME_OPERLOG
  2645.           {
  2646.                 int     logfile;
  2647.                 /*
  2648.                  * This conditional makes the logfile active only after
  2649.                  * it's been created - thus logging can be turned off by
  2650.                  * removing the file.
  2651.                  *
  2652.                  * stop NFS hangs...most systems should be able to open a
  2653.                  * file in 3 seconds. -avalon (curtesy of wumpus)
  2654.                  */
  2655.                 if (IsPerson(sptr) &&
  2656.                     (logfile = open(FNAME_OPERLOG, O_WRONLY|O_APPEND)) != -1)
  2657.         {
  2658.                         (void)sprintf(buf, "%s OPER (%s) (%s) by (%s!%s@%s)\n",
  2659.                       myctime(time(NULL)), name, encr,
  2660.                       parv[0], sptr->user->username,
  2661.                       sptr->sockhost);
  2662.           (void)write(logfile, buf, strlen(buf));
  2663.           (void)close(logfile);
  2664.         }
  2665.                 /* Modification by pjg */
  2666.           }
  2667. #endif
  2668. #ifdef    USE_SERVICES
  2669.         check_services_butone(SERVICE_WANT_OPER, sptr,
  2670.                       ":%s MODE %s :+o", parv[0], parv[0]);
  2671. #endif
  2672.         }
  2673.     else
  2674.         {
  2675.         (void)detach_conf(sptr, aconf);
  2676.         sendto_one(sptr,err_str(ERR_PASSWDMISMATCH),me.name, parv[0]);
  2677. #ifndef    SHOW_PASSWORD
  2678. #ifdef  FAILOPER_WARN
  2679.         sendto_one(sptr,":%s NOTICE :Your attempt has been logged.",me.name);
  2680. #endif
  2681.                   sendto_realops("Failed OPER attempt by %s (%s@%s) using UID %s [NOPASSWORD]",
  2682.                    parv[0], sptr->user->username, sptr->sockhost, name);
  2683. #else
  2684.           sendto_realops("Failed OPER attempt by %s (%s@%s) [%s]",
  2685.            parv[0], sptr->user->username, sptr->sockhost,password);
  2686. #endif
  2687.           sendto_serv_butone(&me, ":%s GLOBOPS :Failed OPER attempt by %s (%s@%s) using UID %s [---]",
  2688.             me.name, parv[0], sptr->user->username, sptr->sockhost, name);
  2689.         sptr->since += 7;
  2690. #ifdef FNAME_OPERLOG
  2691.               {
  2692.                 int     logfile;
  2693.                 /*
  2694.                  * This conditional makes the logfile active only after
  2695.                  * it's been created - thus logging can be turned off by
  2696.                  * removing the file.
  2697.                  *
  2698.                  * stop NFS hangs...most systems should be able to open a
  2699.                  * file in 3 seconds. -avalon (curtesy of wumpus)
  2700.                  */
  2701.                 if (IsPerson(sptr) &&
  2702.                     (logfile = open(FNAME_OPERLOG, O_WRONLY|O_APPEND)) != -1)
  2703.                 {
  2704.                         (void)sprintf(buf, "%s FAILED OPER (%s) (%s) by (%s!%s@%s)\n PASSWORD %s",
  2705.                                       myctime(time(NULL)), name, encr,
  2706.                                       parv[0], sptr->user->username,
  2707.                                       sptr->sockhost, password);
  2708.                   (void)write(logfile, buf, strlen(buf));
  2709.                   (void)close(logfile);
  2710.                 }
  2711.                 /* Modification by pjg */
  2712.               }
  2713. #endif
  2714.         }
  2715.     return 0;
  2716.     }
  2717. /***************************************************************************
  2718.  * m_pass() - Added Sat, 4 March 1989
  2719.  ***************************************************************************/
  2720. /*
  2721. ** m_pass
  2722. **    parv[0] = sender prefix
  2723. **    parv[1] = password
  2724. */
  2725. int    m_pass(cptr, sptr, parc, parv)
  2726. aClient *cptr, *sptr;
  2727. int    parc;
  2728. char    *parv[];
  2729.     {
  2730.     char *password = parc > 1 ? parv[1] : NULL;
  2731.     if (BadPtr(password))
  2732.         {
  2733.         sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS),
  2734.                me.name, parv[0], "PASS");
  2735.         return 0;
  2736.         }
  2737.     if (!MyConnect(sptr) || (!IsUnknown(cptr) && !IsHandshake(cptr)))
  2738.         {
  2739.         sendto_one(cptr, err_str(ERR_ALREADYREGISTRED),
  2740.                me.name, parv[0]);
  2741.         return 0;
  2742.         }
  2743.     strncpyzt(cptr->passwd, password, sizeof(cptr->passwd));
  2744.     return 0;
  2745.     }
  2746. /*
  2747.  * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce
  2748.  * the need for complicated requests like WHOIS. It returns user/host
  2749.  * information only (no spurious AWAY labels or channels).
  2750.  */
  2751. int    m_userhost(cptr, sptr, parc, parv)
  2752. aClient *cptr, *sptr;
  2753. int    parc;
  2754. char    *parv[];
  2755. {
  2756.         int catsize;
  2757.     char    *p = NULL;
  2758.     aClient    *acptr;
  2759.     char    *s;
  2760.     char    *curpos;
  2761.     int    resid;
  2762.     if (check_registered(sptr))
  2763.         return 0;
  2764.     if (parc > 2)
  2765.         (void)m_userhost(cptr, sptr, parc-1, parv+1);
  2766.     if (parc < 2)
  2767.         {
  2768.         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2769.                me.name, parv[0], "USERHOST");
  2770.         return 0;
  2771.         }
  2772.     /*
  2773.      * use curpos to keep track of where we are in the output buffer,
  2774.      * and use resid to keep track of the remaining space in the
  2775.      * buffer
  2776.      */
  2777.     curpos = buf;
  2778.     curpos += sprintf(curpos, rpl_str(RPL_USERHOST), me.name, parv[0]);
  2779.     resid = sizeof(buf) - (curpos - buf) - 1;  /* remaining space */
  2780.     /*
  2781.      * for each user found, print an entry if it fits.
  2782.      */
  2783.     for (s = strtoken(&p, parv[1], " "); s;
  2784.          s = strtoken(&p, (char *)NULL, " "))
  2785.       if ((acptr = find_person(s, NULL))) {
  2786.         catsize = strlen(acptr->name)
  2787.           + (IsAnOper(acptr) ? 1 : 0)
  2788.           + 3 + strlen(acptr->user->username)
  2789.           + strlen(acptr->user->host) + 1;
  2790.         if (catsize <= resid) {
  2791.           curpos += sprintf(curpos, "%s%s=%c%s@%s ",
  2792.                 acptr->name,
  2793.                 IsAnOper(acptr) ? "*" : "",
  2794.                 (acptr->user->away) ? '-' : '+',
  2795.                 acptr->user->username,
  2796.                 acptr->user->host);
  2797.           resid -= catsize;
  2798.         }
  2799.       }
  2800.     
  2801.     /*
  2802.      * because of some trickery here, we might have the string end in
  2803.      * "...:" or "foo " (note the trailing space)
  2804.      * If we have a trailing space, nuke it here.
  2805.      */
  2806.     curpos--;
  2807.     if (*curpos != ':')
  2808.       *curpos = '\0';
  2809.     sendto_one(sptr, "%s", buf);
  2810.     return 0;
  2811. }
  2812. /*
  2813.  * m_ison added by Darren Reed 13/8/91 to act as an efficent user indicator
  2814.  * with respect to cpu/bandwidth used. Implemented for NOTIFY feature in
  2815.  * clients. Designed to reduce number of whois requests. Can process
  2816.  * nicknames in batches as long as the maximum buffer length.
  2817.  *
  2818.  * format:
  2819.  * ISON :nicklist
  2820.  */
  2821. int     m_ison(cptr, sptr, parc, parv)
  2822. aClient *cptr, *sptr;
  2823. int     parc;
  2824. char    *parv[];
  2825. {
  2826.         char    namebuf[USERLEN+HOSTLEN+4];
  2827.         Reg1    aClient *acptr;
  2828.         Reg2    char    *s, **pav = parv, *user;
  2829.         Reg3    int     len;
  2830.         char    *p = NULL;
  2831.  
  2832.         if (check_registered(sptr))
  2833.                 return 0;
  2834.  
  2835.         if (parc < 2)
  2836.       {
  2837.                 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2838.                            me.name, parv[0], "ISON");
  2839.                 return 0;
  2840.       }
  2841.  
  2842.         (void)sprintf(buf, rpl_str(RPL_ISON), me.name, *parv);
  2843.         len = strlen(buf);
  2844.  
  2845.         for (s = strtoken(&p, *++pav, " "); s; s = strtoken(&p, NULL, " "))
  2846.       {
  2847.                 if(user=index(s, '!')) *user++='\0';
  2848.                 if ((acptr = find_person(s, NULL)))
  2849.           {
  2850.             if (user) {
  2851.                                 strcpy(namebuf, acptr->user->username);
  2852.                                 strcat(namebuf, "@");
  2853.                                 strcat(namebuf, acptr->user->host);
  2854.                                 if(match(user, namebuf))
  2855.                                         continue;
  2856.                                 *--user='!';
  2857.             }
  2858.  
  2859.                         (void)strncat(buf, s, sizeof(buf) - len);
  2860.                         len += strlen(s);
  2861.                         (void)strncat(buf, " ", sizeof(buf) - len);
  2862.                         len++;
  2863.           }
  2864.       }
  2865.         sendto_one(sptr, "%s", buf);
  2866.         return 0;
  2867. }
  2868.  
  2869.  
  2870. static int user_modes[]         = { UMODE_OPER, 'o',
  2871.                  UMODE_LOCOP, 'O',
  2872.                  UMODE_INVISIBLE, 'i',
  2873.                  UMODE_WALLOP, 'w',
  2874.                  UMODE_FAILOP, 'g',
  2875.                  UMODE_HELPOP, 'h',
  2876.                  UMODE_SERVNOTICE, 's',
  2877.                  UMODE_KILLS, 'k',
  2878.                  UMODE_SADMIN, 'a',
  2879.                  UMODE_ADMIN, 'A',
  2880.                  UMODE_CLIENT, 'c',
  2881.                  UMODE_FLOOD, 'f',
  2882.                  UMODE_REGNICK, 'r',
  2883. #ifdef CHATOPS
  2884.                  UMODE_CHATOP, 'b',
  2885. #endif
  2886.                  0, 0 };
  2887. /*
  2888.  * m_umode() added 15/10/91 By Darren Reed.
  2889.  * parv[0] - sender
  2890.  * parv[1] - username to change mode for
  2891.  * parv[2] - modes to change
  2892.  */
  2893. int    m_umode(cptr, sptr, parc, parv)
  2894. aClient *cptr, *sptr;
  2895. int    parc;
  2896. char    *parv[];
  2897. {
  2898.     Reg1    int    flag;
  2899.     Reg2    int    *s;
  2900.     Reg3    char    **p, *m;
  2901.     aClient    *acptr;
  2902.     int    what, setflags;
  2903.     if (check_registered_user(sptr))
  2904.         return 0;
  2905.     what = MODE_ADD;
  2906.     if (parc < 2)
  2907.         {
  2908.         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
  2909.                me.name, parv[0], "MODE");
  2910.         return 0;
  2911.         }
  2912.     if (!(acptr = find_person(parv[1], NULL)))
  2913.         {
  2914.         if (MyConnect(sptr))
  2915.             sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
  2916.                    me.name, parv[0], parv[1]);
  2917.         return 0;
  2918.         }
  2919.     if (IsServer(sptr) || sptr != acptr)
  2920.         {
  2921.         if (IsServer(cptr))
  2922.             sendto_ops_butone(NULL, &me,
  2923.                   ":%s WALLOPS :MODE for User %s From %s!%s",
  2924.                   me.name, parv[1],
  2925.                   get_client_name(cptr, FALSE), sptr->name);
  2926.         else
  2927.             sendto_one(sptr, err_str(ERR_USERSDONTMATCH),
  2928.                    me.name, parv[0]);
  2929.             return 0;
  2930.         }
  2931.  
  2932.     if (parc < 3)
  2933.         {
  2934.         m = buf;
  2935.         *m++ = '+';
  2936.         for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4);
  2937.              s += 2)
  2938.             if ((sptr->umodes & flag))
  2939.                 *m++ = (char)(*(s+1));
  2940.         *m = '\0';
  2941.         sendto_one(sptr, rpl_str(RPL_UMODEIS),
  2942.                me.name, parv[0], buf);
  2943.         return 0;
  2944.         }
  2945.     /* find flags already set for user */
  2946.     setflags = 0;
  2947.     for (s = user_modes; (flag = *s); s += 2)
  2948.         if ((sptr->umodes & flag))
  2949.             setflags |= flag;
  2950.     /*
  2951.      * parse mode change string(s)
  2952.      */
  2953.     for (p = &parv[2]; p && *p; p++ )
  2954.         for (m = *p; *m; m++)
  2955.             switch(*m)
  2956.             {
  2957.             case '+' :
  2958.                 what = MODE_ADD;
  2959.                 break;
  2960.             case '-' :
  2961.                 what = MODE_DEL;
  2962.                 break;    
  2963.             /* we may not get these,
  2964.              * but they shouldnt be in default
  2965.              */
  2966.             case ' ' :
  2967.             case '\n' :
  2968.             case '\r' :
  2969.             case '\t' :
  2970.             case 'r'  :
  2971.                 break;
  2972.                         case 'A'  :
  2973.                 /* set auto +a if user is setting +A */
  2974.                                 if (MyClient(sptr) && (what == MODE_ADD))
  2975.                                         sptr->umodes |= UMODE_SADMIN;
  2976.             default :
  2977.                 for (s = user_modes; (flag = *s); s += 2)
  2978.                     if (*m == (char)(*(s+1)))
  2979.                     {
  2980.                     if (what == MODE_ADD)
  2981.                         sptr->umodes |= flag;
  2982.                     else
  2983.                         sptr->umodes &= ~flag;    
  2984.                     break;
  2985.                     }
  2986.                 if (flag == 0 && MyConnect(sptr))
  2987.                     sendto_one(sptr,
  2988.                         err_str(ERR_UMODEUNKNOWNFLAG),
  2989.                         me.name, parv[0]);
  2990.                 break;
  2991.             }
  2992.     /*
  2993.      * stop users making themselves operators too easily
  2994.      */
  2995.     if (!(setflags & UMODE_OPER) && IsOper(sptr) && !IsServer(cptr))
  2996.         ClearOper(sptr);
  2997.     if (!(setflags & UMODE_LOCOP) && IsLocOp(sptr) && !IsServer(cptr))
  2998.         sptr->umodes &= ~UMODE_LOCOP;
  2999. #ifdef    USE_SERVICES
  3000.     if (IsOper(sptr) && !(setflags & UMODE_OPER))
  3001.         check_services_butone(SERVICE_WANT_OPER, sptr,
  3002.                       ":%s MODE %s :+o", parv[0], parv[0]);
  3003.     else if (!IsOper(sptr) && (setflags & UMODE_OPER))
  3004.         check_services_butone(SERVICE_WANT_OPER, sptr,
  3005.                       ":%s MODE %s :-o", parv[0], parv[0]);
  3006. #endif
  3007.     /*
  3008.      *  Let only operators set HelpOp
  3009.      * Helpops get all /quote help <mess> globals -Donwulff
  3010.      */
  3011.     if (MyClient(sptr) && IsHelpOp(sptr) && !OPCanHelpOp(sptr))
  3012.         ClearHelpOp(sptr);
  3013. #ifdef CHATOPS
  3014.     /*
  3015.      *  Only let operators set +b
  3016.      *  +b users can send and recieve chatops
  3017.      *  +b is preserved after a -o    - darkrot
  3018.      */
  3019.     if (MyClient(sptr) && SendChatops(sptr) && !IsAnOper(sptr)
  3020.         && !(setflags & (UMODE_OPER|UMODE_LOCOP)))
  3021.         ClearChatops(sptr);
  3022. #endif
  3023.  
  3024.     /*
  3025.      * Let only operators set FloodF, ClientF; also
  3026.      * remove those flags if they've gone -o/-O.
  3027.      *  FloodF sends notices about possible flooding -Cabal95
  3028.      *  ClientF sends notices about clients connecting or exiting
  3029.      *  Admin is for server admins
  3030.      *  SAdmin is for services admins (mode changers)
  3031.      */
  3032.     if (!IsAnOper(sptr) && !IsServer(cptr))
  3033.         {
  3034.         if (IsClientF(sptr))
  3035.             ClearClientF(sptr);
  3036.         if (IsFloodF(sptr))
  3037.             ClearFloodF(sptr);
  3038.         if (IsAdmin(sptr))
  3039.             ClearAdmin(sptr);
  3040.         if (IsSAdmin(sptr))
  3041.             ClearSAdmin(sptr);
  3042.         }
  3043.     /*
  3044.      * New oper access flags - Only let them set certian usermodes on
  3045.      * themselves IF they have access to set that specific mode in their
  3046.      * O:Line.
  3047.      */
  3048.     if (MyClient(sptr) && IsAnOper(sptr))
  3049.         {
  3050.             if (IsClientF(sptr) && !OPCanUModeC(sptr))
  3051.                     ClearClientF(sptr);
  3052.             if (IsFloodF(sptr) && !OPCanUModeF(sptr))
  3053.                     ClearFloodF(sptr);  
  3054.         if (IsAdmin(sptr) && !OPIsAdmin(sptr))
  3055.             ClearAdmin(sptr);
  3056.         if (IsSAdmin(sptr) && !OPIsSAdmin(sptr))
  3057.             ClearSAdmin(sptr);
  3058.         }
  3059.     /*
  3060.      * If I understand what this code is doing correctly...
  3061.      *   If the user WAS an operator and has now set themselves -o/-O
  3062.      *   then remove their access, d'oh!
  3063.      * In order to allow opers to do stuff like go +o, +h, -o and
  3064.      * remain +h, I moved this code below those checks. It should be
  3065.      * O.K. The above code just does normal access flag checks. This
  3066.      * only changes the operflag access level.  -Cabal95
  3067.      */
  3068.     if ((setflags & (UMODE_OPER|UMODE_LOCOP)) && !IsAnOper(sptr) &&
  3069.         MyConnect(sptr))
  3070.         {
  3071.         det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
  3072.         sptr->oflag = 0;
  3073.         }
  3074.     /*
  3075.      * compare new flags with old flags and send string which
  3076.      * will cause servers to update correctly.
  3077.      */
  3078.     send_umode_out(cptr, sptr, setflags);
  3079.     return 0;
  3080. }
  3081. /*
  3082.  * m_svsmode() added by taz
  3083.  * parv[0] - sender
  3084.  * parv[1] - username to change mode for
  3085.  * parv[2] - modes to change
  3086.  * parv[3] - Service Stamp (if mode == d)
  3087.  */
  3088. int    m_svsmode(cptr, sptr, parc, parv)
  3089. aClient *cptr, *sptr;
  3090. int    parc;
  3091. char    *parv[];
  3092. {
  3093.     Reg1    int    flag;
  3094.     Reg2    int    *s;
  3095.     Reg3    char    **p, *m;
  3096.     aClient    *acptr;
  3097.     int    what, setflags;
  3098.     if (!IsULine(cptr, sptr))
  3099.         return 0;
  3100.     what = MODE_ADD;
  3101.     if (parc < 3)
  3102.         return 0;
  3103.     if (!(acptr = find_person(parv[1], NULL)))
  3104.         return 0;
  3105.     setflags = 0;
  3106.     for (s = user_modes; (flag = *s); s += 2)
  3107.         if (acptr->umodes & flag)
  3108.             setflags |= flag;
  3109.     /*
  3110.      * parse mode change string(s)
  3111.      */
  3112.     for (p = &parv[2]; p && *p; p++ )
  3113.         for (m = *p; *m; m++)
  3114.             switch(*m)
  3115.             {
  3116.             case '+' :
  3117.                 what = MODE_ADD;
  3118.                 break;
  3119.             case '-' :
  3120.                 what = MODE_DEL;
  3121.                 break;    
  3122.             /* we may not get these,
  3123.              * but they shouldnt be in default
  3124.              */
  3125.             case ' ' :
  3126.             case '\n' :
  3127.             case '\r' :
  3128.             case '\t' :
  3129.                 break;
  3130.             case 'l' :
  3131.                 if(parv[3] && isdigit(*parv[3]))
  3132.                     max_global_count = atoi(parv[3]);
  3133.                 break;
  3134.             case 'd' :
  3135.                 if(parv[3] && isdigit(*parv[3]))
  3136.                     acptr->user->servicestamp = atol(parv[3]);
  3137.                 break;
  3138.             default :
  3139.                 for (s = user_modes; (flag = *s); s += 2)
  3140.                     if (*m == (char)(*(s+1)))
  3141.                     {
  3142.                     if (what == MODE_ADD)
  3143.                         acptr->umodes |= flag;
  3144.                     else
  3145.                         acptr->umodes &= ~flag;    
  3146.                     break;
  3147.                     }
  3148.                 break;
  3149.             }
  3150.     if(parc > 3)
  3151.         sendto_serv_butone(cptr, ":%s SVSMODE %s %s %s",
  3152.             parv[0], parv[1], parv[2], parv[3]);
  3153.     else
  3154.         sendto_serv_butone(cptr, ":%s SVSMODE %s %s", parv[0],
  3155.             parv[1], parv[2]);
  3156.     return 0;
  3157. }
  3158.     
  3159. /*
  3160.  * send the MODE string for user (user) to connection cptr
  3161.  * -avalon
  3162.  */
  3163. void    send_umode(cptr, sptr, old, sendmask, umode_buf)
  3164. aClient *cptr, *sptr;
  3165. int    old, sendmask;
  3166. char    *umode_buf;
  3167. {
  3168.     Reg1    int    *s, flag;
  3169.     Reg2    char    *m;
  3170.     int    what = MODE_NULL;
  3171.     /*
  3172.      * build a string in umode_buf to represent the change in the user's
  3173.      * mode between the new (sptr->flag) and 'old'.
  3174.      */
  3175.     m = umode_buf;
  3176.     *m = '\0';
  3177.     for (s = user_modes; (flag = *s); s += 2)
  3178.         {
  3179.         if (MyClient(sptr) && !(flag & sendmask))
  3180.             continue;
  3181.         if ((flag & old) && !(sptr->umodes & flag))
  3182.             {
  3183.             if (what == MODE_DEL)
  3184.                 *m++ = *(s+1);
  3185.             else
  3186.                 {
  3187.                 what = MODE_DEL;
  3188.                 *m++ = '-';
  3189.                 *m++ = *(s+1);
  3190.                 }
  3191.             }
  3192.         else if (!(flag & old) && (sptr->umodes & flag))
  3193.             {
  3194.             if (what == MODE_ADD)
  3195.                 *m++ = *(s+1);
  3196.             else
  3197.                 {
  3198.                 what = MODE_ADD;
  3199.                 *m++ = '+';
  3200.                 *m++ = *(s+1);
  3201.                 }
  3202.             }
  3203.         }
  3204.     *m = '\0';
  3205.     if (*umode_buf && cptr)
  3206.         sendto_one(cptr, ":%s %s %s :%s", sptr->name,
  3207.                (IsToken(cptr)?TOK_MODE:MSG_MODE),
  3208.                sptr->name, umode_buf);
  3209. }
  3210. /*
  3211.  * added Sat Jul 25 07:30:42 EST 1992
  3212.  */
  3213. void    send_umode_out(cptr, sptr, old)
  3214. aClient *cptr, *sptr;
  3215. int    old;
  3216. {
  3217.     Reg1    int     i;
  3218.     Reg2    aClient *acptr;
  3219.     send_umode(NULL, sptr, old, SEND_UMODES, buf);
  3220. # ifdef NPATH
  3221.         check_command((long)4, ":%s MODE %s :%s", sptr->name, sptr->name, buf);
  3222. # endif
  3223.     for (i = highest_fd; i >= 0; i--)
  3224.         if ((acptr = local[i]) && IsServer(acptr) &&
  3225.             (acptr != cptr) && (acptr != sptr) && *buf)
  3226.             sendto_one(acptr, ":%s MODE %s :%s",
  3227.                    sptr->name, sptr->name, buf);
  3228.     if (cptr && MyClient(cptr))
  3229.         send_umode(cptr, sptr, old, ALL_UMODES, buf);
  3230. }
  3231. /*
  3232.  * added by taz
  3233.  */
  3234. void    send_svsmode_out(cptr, sptr, bsptr, old)
  3235. aClient *cptr, *sptr, *bsptr;
  3236. int    old;
  3237. {
  3238.     Reg1    int     i;
  3239.     Reg2    aClient *acptr;
  3240.     send_umode(NULL, sptr, old, SEND_UMODES, buf);
  3241.     sendto_serv_butone(acptr, ":%s SVSMODE %s :%s",
  3242.                    bsptr->name, sptr->name, buf);
  3243. /*    if (cptr && MyClient(cptr))
  3244.         send_umode(cptr, sptr, old, ALL_UMODES, buf);
  3245. */
  3246. }
  3247. /***********************************************************************
  3248.  * m_silence() - Added 19 May 1994 by Run. 
  3249.  *
  3250.  ***********************************************************************/
  3251. /*
  3252.  * is_silenced : Does the actual check wether sptr is allowed
  3253.  *               to send a message to acptr.
  3254.  *               Both must be registered persons.
  3255.  * If sptr is silenced by acptr, his message should not be propagated,
  3256.  * but more over, if this is detected on a server not local to sptr
  3257.  * the SILENCE mask is sent upstream.
  3258.  */
  3259. static int is_silenced(sptr, acptr)
  3260. aClient *sptr;
  3261. aClient *acptr;
  3262. { Reg1 Link *lp;
  3263.   Reg2 anUser *user;
  3264.   static char sender[HOSTLEN+NICKLEN+USERLEN+5];
  3265.   if (!(acptr->user) || !(lp = acptr->user->silence) ||
  3266.       !(user = sptr->user)) return 0;
  3267.   sprintf(sender,"%s!%s@%s",sptr->name,user->username,user->host);
  3268.   for (; lp; lp = lp->next)
  3269.   { if (!match(lp->value.cp, sender))
  3270.     { if (!MyConnect(sptr))
  3271.       { sendto_one(sptr->from, ":%s SILENCE %s :%s",acptr->name,
  3272.             sptr->name, lp->value.cp);
  3273.         lp->flags=1; }
  3274.       return 1; } }
  3275.   return 0;
  3276. }
  3277. int del_silence(sptr, mask)
  3278. aClient *sptr;
  3279. char *mask;
  3280. { Reg1 Link **lp;
  3281.   Reg2 Link *tmp;
  3282.   for (lp = &(sptr->user->silence); *lp; lp = &((*lp)->next))
  3283.     if (mycmp(mask, (*lp)->value.cp)==0)
  3284.     { tmp = *lp;
  3285.       *lp = tmp->next;
  3286.       MyFree(tmp->value.cp);
  3287.       free_link(tmp);
  3288.       return 0; }
  3289.   return -1;
  3290. }
  3291. static int add_silence(sptr, mask)
  3292. aClient *sptr;
  3293. char *mask;
  3294. { Reg1 Link *lp;
  3295.   Reg2 int cnt = 0, len = 0;
  3296.   for (lp = sptr->user->silence; lp; lp = lp->next)
  3297.   { len += strlen(lp->value.cp);
  3298.     if (MyClient(sptr))
  3299.       if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
  3300.       { sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
  3301.     return -1; }
  3302.       else
  3303.       { if (!match(lp->value.cp, mask))
  3304.       return -1; }
  3305.     else if (!mycmp(lp->value.cp, mask))
  3306.       return -1;
  3307.   }
  3308.   lp = make_link();
  3309.   bzero((char *)lp, sizeof(Link));
  3310.   lp->next = sptr->user->silence;
  3311.   lp->value.cp = (char *)MyMalloc(strlen(mask)+1);
  3312.   (void)strcpy(lp->value.cp, mask);
  3313.   sptr->user->silence = lp;
  3314.   return 0;
  3315. }
  3316. /*
  3317. ** m_silence
  3318. **    parv[0] = sender prefix
  3319. ** From local client:
  3320. **    parv[1] = mask (NULL sends the list)
  3321. ** From remote client:
  3322. **    parv[1] = nick that must be silenced
  3323. **      parv[2] = mask
  3324. */
  3325. int m_silence(cptr, sptr, parc, parv)
  3326. aClient    *cptr, *sptr;
  3327. int    parc;
  3328. char    *parv[];
  3329. {
  3330.   Link *lp;
  3331.   aClient *acptr;
  3332.   char c, *cp, *user, *host;
  3333.   if (check_registered_user(sptr)) return 0;
  3334.   if (MyClient(sptr))
  3335.   {
  3336.     acptr = sptr;
  3337.     if (parc < 2 || *parv[1]=='\0' || (acptr = find_person(parv[1], NULL)))
  3338.     { if (!(acptr->user)) return 0;
  3339.       for (lp = acptr->user->silence; lp; lp = lp->next)
  3340.     sendto_one(sptr, rpl_str(RPL_SILELIST), me.name,
  3341.         sptr->name, acptr->name, lp->value.cp);
  3342.       sendto_one(sptr, rpl_str(RPL_ENDOFSILELIST), me.name, acptr->name);
  3343.       return 0; }
  3344.     cp = parv[1];
  3345.     c = *cp;
  3346.     if (c=='-' || c=='+') cp++;
  3347.     else if (!(index(cp, '@') || index(cp, '.') ||
  3348.     index(cp, '!') || index(cp, '*')))
  3349.     { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
  3350.       return -1; }
  3351.     else c = '+';
  3352.     cp = pretty_mask(cp);
  3353.     if ((c=='-' && !del_silence(sptr,cp)) ||
  3354.         (c!='-' && !add_silence(sptr,cp)))
  3355.     { sendto_prefix_one(sptr, sptr, ":%s SILENCE %c%s", parv[0], c, cp);
  3356.       if (c=='-')
  3357.     sendto_serv_butone(NULL, ":%s SILENCE * -%s", sptr->name, cp);
  3358.     }
  3359.   }
  3360.   else if (parc < 3 || *parv[2]=='\0')
  3361.   {
  3362.     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SILENCE");
  3363.     return -1;
  3364.   }
  3365.   else if ((c = *parv[2])=='-' || (acptr = find_person(parv[1], NULL)))
  3366.   {
  3367.     if (c=='-')
  3368.     { if (!del_silence(sptr,parv[2]+1))
  3369.     sendto_serv_butone(cptr, ":%s SILENCE %s :%s",
  3370.         parv[0], parv[1], parv[2]); }
  3371.     else
  3372.     { (void)add_silence(sptr,parv[2]);
  3373.       if (!MyClient(acptr))
  3374.         sendto_one(acptr, ":%s SILENCE %s :%s",
  3375.             parv[0], parv[1], parv[2]); }
  3376.   }
  3377.   else
  3378.   {
  3379.     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
  3380.     return -1;
  3381.   }
  3382.   return 0;
  3383. }
  3384. int m_noshortn(cptr, sptr, parc, parv)
  3385. aClient    *cptr, *sptr;
  3386. int    parc;
  3387. char    *parv[];
  3388. {    sendto_one(sptr, "NOTICE %s :*** Please use /nickserv for that command",sptr->name);
  3389. }
  3390. int m_noshortc(cptr, sptr, parc, parv)
  3391. aClient    *cptr, *sptr;
  3392. int    parc;
  3393. char    *parv[];
  3394. {    sendto_one(sptr, "NOTICE %s :*** Please use /chanserv for that command",sptr->name);
  3395. }
  3396. int m_noshortm(cptr, sptr, parc, parv)
  3397. aClient    *cptr, *sptr;
  3398. int    parc;
  3399. char    *parv[];
  3400. {    sendto_one(sptr, "NOTICE %s :*** Please use /memoserv for that command",sptr->name);
  3401. }
  3402. int m_noshorto(cptr, sptr, parc, parv)
  3403. aClient    *cptr, *sptr;
  3404. int    parc;
  3405. char    *parv[];
  3406. {    sendto_one(sptr, "NOTICE %s :*** Please use /operserv for that command",sptr->name);
  3407. }
  3408.