home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / other / irc / common / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  20.4 KB  |  906 lines

  1. /************************************************************************
  2.  *   IRC - Internet Relay Chat, common/send.c
  3.  *   Copyright (C) 1990 Jarkko Oikarinen and
  4.  *              University of Oulu, Computing Center
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation; either version 1, or (at your option)
  9.  *   any later version.
  10.  *
  11.  *   This program is distributed in the hope that it will be useful,
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *   GNU General Public License for more details.
  15.  *
  16.  *   You should have received a copy of the GNU General Public License
  17.  *   along with this program; if not, write to the Free Software
  18.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* -- Jto -- 16 Jun 1990
  22.  * Added Armin's PRIVMSG patches...
  23.  */
  24.  
  25. #ifndef lint
  26. static  char sccsid[] = "@(#)send.c    2.32 2/28/94 (C) 1988 University of Oulu, \
  27. Computing Center and Jarkko Oikarinen";
  28. #endif
  29.  
  30. #include "struct.h"
  31. #include "common.h"
  32. #include "sys.h"
  33. #include "h.h"
  34. #include <stdio.h>
  35.  
  36. #ifdef    IRCII_KLUDGE
  37. #define    NEWLINE    "\n"
  38. #else
  39. #define NEWLINE    "\r\n"
  40. #endif
  41.  
  42. static    char    sendbuf[16384];
  43. static    int    send_message PROTO((aClient *, char *, int));
  44.  
  45. #ifndef CLIENT_COMPILE
  46. static    int    sentalong[MAXCONNECTIONS];
  47. #endif
  48.  
  49. /*
  50. ** dead_link
  51. **    An error has been detected. The link *must* be closed,
  52. **    but *cannot* call ExitClient (m_bye) from here.
  53. **    Instead, mark it with FLAGS_DEADSOCKET. This should
  54. **    generate ExitClient from the main loop.
  55. **
  56. **    If 'notice' is not NULL, it is assumed to be a format
  57. **    for a message to local opers. I can contain only one
  58. **    '%s', which will be replaced by the sockhost field of
  59. **    the failing link.
  60. **
  61. **    Also, the notice is skipped for "uninteresting" cases,
  62. **    like Persons and yet unknown connections...
  63. */
  64. static    int    dead_link(to, notice)
  65. aClient *to;
  66. char    *notice;
  67. {
  68.     to->flags |= FLAGS_DEADSOCKET;
  69.     /*
  70.      * If because of BUFFERPOOL problem then clean dbuf's now so that
  71.      * notices don't hurt operators below.
  72.      */
  73.     DBufClear(&to->recvQ);
  74.     DBufClear(&to->sendQ);
  75. #ifndef CLIENT_COMPILE
  76.     if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
  77.         sendto_ops(notice, get_client_name(to, FALSE));
  78.     Debug((DEBUG_ERROR, notice, get_client_name(to, FALSE)));
  79. #endif
  80.     return -1;
  81. }
  82.  
  83. #ifndef CLIENT_COMPILE
  84. /*
  85. ** flush_connections
  86. **    Used to empty all output buffers for all connections. Should only
  87. **    be called once per scan of connections. There should be a select in
  88. **    here perhaps but that means either forcing a timeout or doing a poll.
  89. **    When flushing, all we do is empty the obuffer array for each local
  90. **    client and try to send it. if we cant send it, it goes into the sendQ
  91. **    -avalon
  92. */
  93. void    flush_connections(fd)
  94. int    fd;
  95. {
  96. #ifdef SENDQ_ALWAYS
  97.     Reg1    int    i;
  98.     Reg2    aClient *cptr;
  99.  
  100.     if (fd == me.fd)
  101.         {
  102.         for (i = highest_fd; i >= 0; i--)
  103.             if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
  104.                 (void)send_queued(cptr);
  105.         }
  106.     else if (fd >= 0 && (cptr = local[fd]) && DBufLength(&cptr->sendQ) > 0)
  107.         (void)send_queued(cptr);
  108. #endif
  109. }
  110. #endif
  111.  
  112. /*
  113. ** send_message
  114. **    Internal utility which delivers one message buffer to the
  115. **    socket. Takes care of the error handling and buffering, if
  116. **    needed.
  117. */
  118. static    int    send_message(to, msg, len)
  119. aClient    *to;
  120. char    *msg;    /* if msg is a null pointer, we are flushing connection */
  121. int    len;
  122. #ifdef SENDQ_ALWAYS
  123. {
  124.     if (IsDead(to))
  125.         return 0; /* This socket has already been marked as dead */
  126. # ifdef    CLIENT_COMPILE
  127.     if (DBufLength(&to->sendQ) > MAXSENDQLENGTH)
  128.         return dead_link(to,"Max SendQ limit exceeded for %s");
  129. # else
  130.     if (DBufLength(&to->sendQ) > get_sendq(to))
  131.         {
  132.         if (IsServer(to))
  133.             sendto_ops("Max SendQ limit exceeded for %s: %d > %d",
  134.                    get_client_name(to, FALSE),
  135.                 DBufLength(&to->sendQ), get_sendq(to));
  136.         return dead_link(to, "Max Sendq exceeded");
  137.         }
  138. # endif
  139.     else if (dbuf_put(&to->sendQ, msg, len) < 0)
  140.         return dead_link(to, "Buffer allocation error for %s");
  141.     /*
  142.     ** Update statistics. The following is slightly incorrect
  143.     ** because it counts messages even if queued, but bytes
  144.     ** only really sent. Queued bytes get updated in SendQueued.
  145.     */
  146.     to->sendM += 1;
  147.     me.sendM += 1;
  148.     if (to->acpt != &me)
  149.         to->acpt->sendM += 1;
  150.     /*
  151.     ** This little bit is to stop the sendQ from growing too large when
  152.     ** there is no need for it to. Thus we call send_queued() every time
  153.     ** 2k has been added to the queue since the last non-fatal write.
  154.     ** Also stops us from deliberately building a large sendQ and then
  155.     ** trying to flood that link with data (possible during the net
  156.     ** relinking done by servers with a large load).
  157.     */
  158.     if (DBufLength(&to->sendQ)/1024 > to->lastsq)
  159.         send_queued(to);
  160.     return 0;
  161. }
  162. #else
  163. {
  164.     int    rlen = 0;
  165.  
  166.     if (IsDead(to))
  167.         return 0; /* This socket has already been marked as dead */
  168.  
  169.     /*
  170.     ** DeliverIt can be called only if SendQ is empty...
  171.     */
  172.     if ((DBufLength(&to->sendQ) == 0) &&
  173.         (rlen = deliver_it(to, msg, len)) < 0)
  174.         return dead_link(to,"Write error to %s, closing link");
  175.     else if (rlen < len)
  176.         {
  177.         /*
  178.         ** Was unable to transfer all of the requested data. Queue
  179.         ** up the remainder for some later time...
  180.         */
  181. # ifdef    CLIENT_COMPILE
  182.         if (DBufLength(&to->sendQ) > MAXSENDQLENGTH)
  183.             return dead_link(to,"Max SendQ limit exceeded for %s");
  184. # else
  185.         if (DBufLength(&to->sendQ) > get_sendq(to))
  186.             {
  187.             sendto_ops("Max SendQ limit exceeded for %s : %d > %d",
  188.                    get_client_name(to, FALSE),
  189.                    DBufLength(&to->sendQ), get_sendq(to));
  190.             return dead_link(to, "Max Sendq exceeded");
  191.             }
  192. # endif
  193.         else if (dbuf_put(&to->sendQ,msg+rlen,len-rlen) < 0)
  194.             return dead_link(to,"Buffer allocation error for %s");
  195.         }
  196.     /*
  197.     ** Update statistics. The following is slightly incorrect
  198.     ** because it counts messages even if queued, but bytes
  199.     ** only really sent. Queued bytes get updated in SendQueued.
  200.     */
  201.     to->sendM += 1;
  202.     me.sendM += 1;
  203.     if (to->acpt != &me)
  204.         to->acpt->sendM += 1;
  205.     return 0;
  206. }
  207. #endif
  208.  
  209. /*
  210. ** send_queued
  211. **    This function is called from the main select-loop (or whatever)
  212. **    when there is a chance the some output would be possible. This
  213. **    attempts to empty the send queue as far as possible...
  214. */
  215. int    send_queued(to)
  216. aClient *to;
  217. {
  218.     char    *msg;
  219.     int    len, rlen;
  220.  
  221.     /*
  222.     ** Once socket is marked dead, we cannot start writing to it,
  223.     ** even if the error is removed...
  224.     */
  225.     if (IsDead(to))
  226.         {
  227.         /*
  228.         ** Actually, we should *NEVER* get here--something is
  229.         ** not working correct if send_queued is called for a
  230.         ** dead socket... --msa
  231.         */
  232. #ifndef SENDQ_ALWAYS
  233.         return dead_link(to, "send_queued called for a DEADSOCKET:%s");
  234. #else
  235.         return -1;
  236. #endif
  237.         }
  238.     while (DBufLength(&to->sendQ) > 0)
  239.         {
  240.         msg = dbuf_map(&to->sendQ, &len);
  241.                     /* Returns always len > 0 */
  242.         if ((rlen = deliver_it(to, msg, len)) < 0)
  243.             return dead_link(to,"Write error to %s, closing link");
  244.         (void)dbuf_delete(&to->sendQ, rlen);
  245.         to->lastsq = DBufLength(&to->sendQ)/1024;
  246.         if (rlen < len) /* ..or should I continue until rlen==0? */
  247.             break;
  248.         }
  249.  
  250.     return (IsDead(to)) ? -1 : 0;
  251. }
  252.  
  253. /*
  254. ** send message to single client
  255. */
  256. #ifndef    USE_VARARGS
  257. /*VARARGS*/
  258. void    sendto_one(to, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
  259. aClient *to;
  260. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11;
  261. {
  262. #else
  263. void    sendto_one(to, pattern, va_alist)
  264. aClient    *to;
  265. char    *pattern;
  266. va_dcl
  267. {
  268.     va_list    vl;
  269. #endif
  270.  
  271. /*
  272. # ifdef NPATH
  273.         check_command((long)1, pattern, p1, p2, p3);
  274. # endif
  275. */
  276.  
  277. #ifdef VMS
  278.     extern int goodbye;
  279.     
  280.     if (StrEq("QUIT", pattern)) 
  281.         goodbye = 1;
  282. #endif
  283.  
  284. #ifdef    USE_VARARGS
  285.     va_start(vl);
  286.     (void)vsprintf(sendbuf, pattern, vl);
  287.     va_end(vl);
  288. #else
  289.     (void)sprintf(sendbuf, pattern, p1, p2, p3, p4, p5, p6,
  290.         p7, p8, p9, p10, p11);
  291. #endif
  292.     Debug((DEBUG_SEND,"Sending [%s] to %s", sendbuf,to->name));
  293.  
  294.     if (to->from)
  295.         to = to->from;
  296.     if (to->fd < 0)
  297.         {
  298.         Debug((DEBUG_ERROR,
  299.               "Local socket %s with negative fd... AARGH!",
  300.               to->name));
  301.         }
  302. #ifndef    CLIENT_COMPILE
  303.     else if (IsMe(to))
  304.         {
  305.         sendto_ops("Trying to send [%s] to myself!", sendbuf);
  306.         return;
  307.         }
  308. #endif
  309.     (void)strcat(sendbuf, NEWLINE);
  310. #ifndef    IRCII_KLUDGE
  311.     sendbuf[IRC_SUCKS_LINE_LENGTH] = '\r';
  312. #endif
  313.     sendbuf[IRC_SUCKS_LINE_LENGTH+1] = '\n';
  314.     sendbuf[IRC_SUCKS_LINE_LENGTH+2] = '\0';
  315.     (void)send_message(to, sendbuf, strlen(sendbuf));
  316. }
  317.  
  318. #ifndef CLIENT_COMPILE
  319. # ifndef    USE_VARARGS
  320. /*VARARGS*/
  321. void    sendto_channel_butone(one, from, chptr, pattern,
  322.                   p1, p2, p3, p4, p5, p6, p7, p8)
  323. aClient *one, *from;
  324. aChannel *chptr;
  325. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  326. {
  327. # else
  328. void    sendto_channel_butone(one, from, chptr, pattern, va_alist)
  329. aClient    *one, *from;
  330. aChannel *chptr;
  331. char    *pattern;
  332. va_dcl
  333. {
  334.     va_list    vl;
  335. # endif
  336.     Reg1    Link    *lp;
  337.     Reg2    aClient *acptr;
  338.     Reg3    int    i;
  339.  
  340. # ifdef    USE_VARARGS
  341.     va_start(vl);
  342. # endif
  343.     for (i = 0; i < MAXCONNECTIONS; i++)
  344.         sentalong[i] = 0;
  345.     for (lp = chptr->members; lp; lp = lp->next)
  346.         {
  347.         acptr = lp->value.cptr;
  348.         if (acptr->from == one)
  349.             continue;    /* ...was the one I should skip */
  350.         i = acptr->from->fd;
  351.         if (MyConnect(acptr) && IsRegisteredUser(acptr))
  352.             {
  353. # ifdef    USE_VARARGS
  354.             sendto_prefix_one(acptr, from, pattern, vl);
  355. # else
  356.             sendto_prefix_one(acptr, from, pattern, p1, p2,
  357.                       p3, p4, p5, p6, p7, p8);
  358. # endif
  359.             sentalong[i] = 1;
  360.             }
  361.         else
  362.             {
  363.         /* Now check whether a message has been sent to this
  364.          * remote link already */
  365.             if (sentalong[i] == 0)
  366.                 {
  367. # ifdef    USE_VARARGS
  368.                   sendto_prefix_one(acptr, from, pattern, vl);
  369. # else
  370.                   sendto_prefix_one(acptr, from, pattern,
  371.                           p1, p2, p3, p4,
  372.                           p5, p6, p7, p8);
  373. # endif
  374.                 sentalong[i] = 1;
  375.                 }
  376.             }
  377.         }
  378. # ifdef    USE_VARARGS
  379.     va_end(vl);
  380. # endif
  381.     return;
  382. }
  383.  
  384. /*
  385.  * sendto_server_butone
  386.  *
  387.  * Send a message to all connected servers except the client 'one'.
  388.  */
  389. # ifndef    USE_VARARGS
  390. /*VARARGS*/
  391. void    sendto_serv_butone(one, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
  392. aClient *one;
  393. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  394. {
  395. # else
  396. void    sendto_serv_butone(one, pattern, va_alist)
  397. aClient    *one;
  398. char    *pattern;
  399. va_dcl
  400. {
  401.     va_list    vl;
  402. # endif
  403.     Reg1    int    i;
  404.     Reg2    aClient *cptr;
  405.  
  406. # ifdef    USE_VARARGS
  407.     va_start(vl);
  408. # endif
  409.  
  410. # ifdef NPATH
  411.         check_command((long)2, pattern, p1, p2, p3);
  412. # endif
  413.  
  414.     for (i = 0; i <= highest_fd; i++)
  415.         {
  416.         if (!(cptr = local[i]) || (one && cptr == one->from))
  417.             continue;
  418.         if (IsServer(cptr))
  419. # ifdef    USE_VARARGS
  420.             sendto_one(cptr, pattern, vl);
  421.         }
  422.     va_end(vl);
  423. # else
  424.             sendto_one(cptr, pattern, p1, p2, p3, p4,
  425.                    p5, p6, p7, p8);
  426.         }
  427. # endif
  428.     return;
  429. }
  430.  
  431. /*
  432.  * sendto_common_channels()
  433.  *
  434.  * Sends a message to all people (inclusing user) on local server who are
  435.  * in same channel with user.
  436.  */
  437. # ifndef    USE_VARARGS
  438. /*VARARGS*/
  439. void    sendto_common_channels(user, pattern, p1, p2, p3, p4,
  440.                 p5, p6, p7, p8)
  441. aClient *user;
  442. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  443. {
  444. # else
  445. void    sendto_common_channels(user, pattern, va_alist)
  446. aClient    *user;
  447. char    *pattern;
  448. va_dcl
  449. {
  450.     va_list    vl;
  451. # endif
  452.     Reg1    int    i;
  453.     Reg2    aClient *cptr;
  454.     Reg3    Link    *lp;
  455.  
  456. # ifdef    USE_VARARGS
  457.     va_start(vl);
  458. # endif
  459.     for (i = 0; i <= highest_fd; i++)
  460.         {
  461.         if (!(cptr = local[i]) || IsServer(cptr) ||
  462.             user == cptr || !user->user)
  463.             continue;
  464.         for (lp = user->user->channel; lp; lp = lp->next)
  465.             if (IsMember(cptr, lp->value.chptr))
  466.                 {
  467. # ifdef    USE_VARARGS
  468.                 sendto_prefix_one(cptr, user, pattern, vl);
  469. # else
  470.                 sendto_prefix_one(cptr, user, pattern,
  471.                           p1, p2, p3, p4,
  472.                           p5, p6, p7, p8);
  473. # endif
  474.                 break;
  475.                 }
  476.         }
  477.     if (MyConnect(user))
  478. # ifdef    USE_VARARGS
  479.         sendto_prefix_one(user, user, pattern, vl);
  480.     va_end(vl);
  481. # else
  482.         sendto_prefix_one(user, user, pattern, p1, p2, p3, p4,
  483.                     p5, p6, p7, p8);
  484. # endif
  485.     return;
  486. }
  487. #endif /* CLIENT_COMPILE */
  488.  
  489. /*
  490.  * sendto_channel_butserv
  491.  *
  492.  * Send a message to all members of a channel that are connected to this
  493.  * server.
  494.  */
  495. #ifndef    USE_VARARGS
  496. /*VARARGS*/
  497. void    sendto_channel_butserv(chptr, from, pattern, p1, p2, p3,
  498.                    p4, p5, p6, p7, p8)
  499. aChannel *chptr;
  500. aClient *from;
  501. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  502. {
  503. #else
  504. void    sendto_channel_butserv(chptr, from, pattern, va_alist)
  505. aChannel *chptr;
  506. aClient *from;
  507. char    *pattern;
  508. va_dcl
  509. {
  510.     va_list    vl;
  511. #endif
  512.     Reg1    Link    *lp;
  513.     Reg2    aClient    *acptr;
  514.  
  515. #ifdef    USE_VARARGS
  516.     for (va_start(vl), lp = chptr->members; lp; lp = lp->next)
  517.         if (MyConnect(acptr = lp->value.cptr))
  518.             sendto_prefix_one(acptr, from, pattern, vl);
  519.     va_end(vl);
  520. #else
  521.     for (lp = chptr->members; lp; lp = lp->next)
  522.         if (MyConnect(acptr = lp->value.cptr))
  523.             sendto_prefix_one(acptr, from, pattern,
  524.                       p1, p2, p3, p4,
  525.                       p5, p6, p7, p8);
  526. #endif
  527.  
  528.     return;
  529. }
  530.  
  531. /*
  532. ** send a msg to all ppl on servers/hosts that match a specified mask
  533. ** (used for enhanced PRIVMSGs)
  534. **
  535. ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
  536. */
  537.  
  538. static    int    match_it(one, mask, what)
  539. aClient *one;
  540. char    *mask;
  541. int    what;
  542. {
  543.     switch (what)
  544.     {
  545.     case MATCH_HOST:
  546.         return (matches(mask, one->user->host)==0);
  547.     case MATCH_SERVER:
  548.     default:
  549.         return (matches(mask, one->user->server)==0);
  550.     }
  551. }
  552.  
  553. #ifndef CLIENT_COMPILE
  554. /*
  555.  * sendto_match_servs
  556.  *
  557.  * send to all servers which match the mask at the end of a channel name
  558.  * (if there is a mask present) or to all if no mask.
  559.  */
  560. #ifndef    USE_VARARGS
  561. /*VARARGS*/
  562. void    sendto_match_servs(chptr, from, format, p1,p2,p3,p4,p5,p6,p7,p8,p9)
  563. aChannel *chptr;
  564. aClient    *from;
  565. char    *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
  566. {
  567. #else
  568. void    sendto_match_servs(chptr, from, format, va_alist)
  569. aChannel *chptr;
  570. aClient    *from;
  571. char    *format;
  572. va_dcl
  573. {
  574.     va_list    vl;
  575. #endif
  576.     Reg1    int    i;
  577.     Reg2    aClient    *cptr;
  578.     char    *mask;
  579.  
  580. #ifdef    USE_VARARGS
  581.     va_start(vl);
  582. #endif
  583.  
  584. # ifdef NPATH
  585.         check_command((long)3, format, p1, p2, p3);
  586. # endif
  587.     if (chptr)
  588.         {
  589.         if (*chptr->chname == '&')
  590.             return;
  591.         if (mask = (char *)rindex(chptr->chname, ':'))
  592.             mask++;
  593.         }
  594.     else
  595.         mask = (char *)NULL;
  596.  
  597.     for (i = 0; i <= highest_fd; i++)
  598.         {
  599.         if (!(cptr = local[i]))
  600.             continue;
  601.         if ((cptr == from) || !IsServer(cptr))
  602.             continue;
  603.         if (!BadPtr(mask) && IsServer(cptr) &&
  604.             matches(mask, cptr->name))
  605.             continue;
  606. #ifdef    USE_VARARGS
  607.         sendto_one(cptr, format, vl);
  608.         }
  609.     va_end(vl);
  610. #else
  611.         sendto_one(cptr, format, p1, p2, p3, p4, p5, p6, p7, p8, p9);
  612.         }
  613. #endif
  614. }
  615.  
  616. /*
  617.  * sendto_match_butone
  618.  *
  619.  * Send to all clients which match the mask in a way defined on 'what';
  620.  * either by user hostname or user servername.
  621.  */
  622. #ifndef    USE_VARARGS
  623. /*VARARGS*/
  624. void    sendto_match_butone(one, from, mask, what, pattern,
  625.                 p1, p2, p3, p4, p5, p6, p7, p8)
  626. aClient *one, *from;
  627. int    what;
  628. char    *mask, *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  629. {
  630. #else
  631. void    sendto_match_butone(one, from, mask, what, pattern, va_alist)
  632. aClient *one, *from;
  633. int    what;
  634. char    *mask, *pattern;
  635. va_dcl
  636. {
  637.     va_list    vl;
  638. #endif
  639.     Reg1    int    i;
  640.     Reg2    aClient *cptr, *acptr;
  641.   
  642. #ifdef    USE_VARARGS
  643.     va_start(vl);
  644. #endif
  645.     for (i = 0; i <= highest_fd; i++)
  646.         {
  647.         if (!(cptr = local[i]))
  648.             continue;       /* that clients are not mine */
  649.          if (cptr == one)    /* must skip the origin !! */
  650.             continue;
  651.         if (IsServer(cptr))
  652.             {
  653.             for (acptr = client; acptr; acptr = acptr->next)
  654.                 if (IsRegisteredUser(acptr)
  655.                     && match_it(acptr, mask, what)
  656.                     && acptr->from == cptr)
  657.                     break;
  658.             /* a person on that server matches the mask, so we
  659.             ** send *one* msg to that server ...
  660.             */
  661.             if (acptr == NULL)
  662.                 continue;
  663.             /* ... but only if there *IS* a matching person */
  664.             }
  665.         /* my client, does he match ? */
  666.         else if (!(IsRegisteredUser(cptr) &&
  667.              match_it(cptr, mask, what)))
  668.             continue;
  669. #ifdef    USE_VARARGS
  670.         sendto_prefix_one(cptr, from, pattern, vl);
  671.         }
  672.     va_end(vl);
  673. #else
  674.         sendto_prefix_one(cptr, from, pattern,
  675.                   p1, p2, p3, p4, p5, p6, p7, p8);
  676.         }
  677. #endif
  678.     return;
  679. }
  680.  
  681. /*
  682.  * sendto_all_butone.
  683.  *
  684.  * Send a message to all connections except 'one'. The basic wall type
  685.  * message generator.
  686.  */
  687. #ifndef    USE_VARARGS
  688. /*VARARGS*/
  689. void    sendto_all_butone(one, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
  690. aClient *one, *from;
  691. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  692. {
  693. #else
  694. void    sendto_all_butone(one, from, pattern, va_alist)
  695. aClient *one, *from;
  696. char    *pattern;
  697. va_dcl
  698. {
  699.     va_list    vl;
  700. #endif
  701.     Reg1    int    i;
  702.     Reg2    aClient *cptr;
  703.  
  704. #ifdef    USE_VARARGS
  705.     for (va_start(vl), i = 0; i <= highest_fd; i++)
  706.         if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
  707.             sendto_prefix_one(cptr, from, pattern, vl);
  708.     va_end(vl);
  709. #else
  710.     for (i = 0; i <= highest_fd; i++)
  711.         if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
  712.             sendto_prefix_one(cptr, from, pattern,
  713.                       p1, p2, p3, p4, p5, p6, p7, p8);
  714. #endif
  715.  
  716.     return;
  717. }
  718.  
  719. /*
  720.  * sendto_ops
  721.  *
  722.  *    Send to *local* ops only.
  723.  */
  724. #ifndef    USE_VARARGS
  725. /*VARARGS*/
  726. void    sendto_ops(pattern, p1, p2, p3, p4, p5, p6, p7, p8)
  727. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  728. {
  729. #else
  730. void    sendto_ops(pattern, va_alist)
  731. char    *pattern;
  732. va_dcl
  733. {
  734.     va_list    vl;
  735. #endif
  736.     Reg1    aClient *cptr;
  737.     Reg2    int    i;
  738.     char    nbuf[1024];
  739.  
  740. #ifdef    USE_VARARGS
  741.     va_start(vl);
  742. #endif
  743.     for (i = 0; i <= highest_fd; i++)
  744.         if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
  745.             SendServNotice(cptr))
  746.             {
  747.             (void)sprintf(nbuf, ":%s NOTICE %s :*** Notice -- ",
  748.                     me.name, cptr->name);
  749.             (void)strncat(nbuf, pattern,
  750.                     sizeof(nbuf) - strlen(nbuf));
  751. #ifdef    USE_VARARGS
  752.             sendto_one(cptr, nbuf, va_alist);
  753. #else
  754.             sendto_one(cptr, nbuf, p1, p2, p3, p4, p5, p6, p7, p8);
  755. #endif
  756.             }
  757. #ifdef    USE_SERVICES
  758.         else if (cptr && IsService(cptr) &&
  759.              (cptr->service->wanted & SERVICE_WANT_SERVNOTE))
  760.             {
  761.             (void)sprintf(nbuf, "NOTICE %s :*** Notice -- ",
  762.                     cptr->name);
  763.             (void)strncat(nbuf, pattern,
  764.                     sizeof(nbuf) - strlen(nbuf));
  765. # ifdef    USE_VARARGS
  766.             sendto_one(cptr, nbuf, vl);
  767.             }
  768.     va_end(vl);
  769. # else
  770.             sendto_one(cptr, nbuf, p1, p2, p3, p4, p5, p6, p7, p8);
  771.             }
  772. # endif
  773. #endif
  774.     return;
  775. }
  776.  
  777. /*
  778. ** sendto_ops_butone
  779. **    Send message to all operators.
  780. ** one - client not to send message to
  781. ** from- client which message is from *NEVER* NULL!!
  782. */
  783. #ifndef    USE_VARARGS
  784. /*VARARGS*/
  785. void    sendto_ops_butone(one, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
  786. aClient *one, *from;
  787. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  788. {
  789. #else
  790. void    sendto_ops_butone(one, from, pattern, va_alist)
  791. aClient *one, *from;
  792. char    *pattern;
  793. va_dcl
  794. {
  795.     va_list    vl;
  796. #endif
  797.     Reg1    int    i;
  798.     Reg2    aClient *cptr;
  799.  
  800. #ifdef    USE_VARARGS
  801.     va_start(vl);
  802. #endif
  803.     for (i=0; i <= highest_fd; i++)
  804.         sentalong[i] = 0;
  805.     for (cptr = client; cptr; cptr = cptr->next)
  806.         {
  807.         if (!SendWallops(cptr))
  808.             continue;
  809.         if (MyClient(cptr) && !(IsServer(from) || IsMe(from)))
  810.             continue;
  811.         i = cptr->from->fd;    /* find connection oper is on */
  812.         if (sentalong[i])    /* sent message along it already ? */
  813.             continue;
  814.         if (cptr->from == one)
  815.             continue;    /* ...was the one I should skip */
  816.         sentalong[i] = 1;
  817. # ifdef    USE_VARARGS
  818.               sendto_prefix_one(cptr->from, from, pattern, vl);
  819.         }
  820.     va_end(vl);
  821. # else
  822.               sendto_prefix_one(cptr->from, from, pattern,
  823.                   p1, p2, p3, p4, p5, p6, p7, p8);
  824.         }
  825. # endif
  826.     return;
  827. }
  828. #endif
  829.  
  830. /*
  831.  * to - destination client
  832.  * from - client which message is from
  833.  *
  834.  * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
  835.  * -avalon
  836.  */
  837. #ifndef    USE_VARARGS
  838. /*VARARGS*/
  839. void    sendto_prefix_one(to, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
  840. Reg1    aClient *to;
  841. Reg2    aClient *from;
  842. char    *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
  843. {
  844. #else
  845. void    sendto_prefix_one(to, from, pattern, va_alist)
  846. Reg1    aClient *to;
  847. Reg2    aClient *from;
  848. char    *pattern;
  849. va_dcl
  850. {
  851.     va_list    vl;
  852. #endif
  853.     static    char    sender[HOSTLEN+NICKLEN+USERLEN+5];
  854.     Reg3    anUser    *user;
  855.     char    *par;
  856.     int    flag = 0;
  857.  
  858. #ifdef    USE_VARARGS
  859.     va_start(vl);
  860.     par = va_arg(vl, char *);
  861. #else
  862.     par = p1;
  863. #endif
  864.     if (to && from && MyClient(to) && IsPerson(from) &&
  865.         !mycmp(par, from->name))
  866.         {
  867.         user = from->user;
  868.         (void)strcpy(sender, from->name);
  869.         if (user)
  870.             {
  871.             if (*user->username)
  872.                 {
  873.                 (void)strcat(sender, "!");
  874.                 (void)strcat(sender, user->username);
  875.                 }
  876.             if (*user->host && !MyConnect(from))
  877.                 {
  878.                 (void)strcat(sender, "@");
  879.                 (void)strcat(sender, user->host);
  880.                 flag = 1;
  881.                 }
  882.             }
  883.         /*
  884.         ** flag is used instead of index(sender, '@') for speed and
  885.         ** also since username/nick may have had a '@' in them. -avalon
  886.         */
  887.         if (!flag && MyConnect(from) && *user->host)
  888.             {
  889.             (void)strcat(sender, "@");
  890.             if (IsUnixSocket(from))
  891.                 (void)strcat(sender, user->host);
  892.             else
  893.                 (void)strcat(sender, from->sockhost);
  894.             }
  895. #ifdef    USE_VARARGS
  896.         par = sender;
  897.         }
  898.     sendto_one(to, pattern, par, vl);
  899.     va_end(vl);
  900. #else
  901.         par = sender;
  902.         }
  903.     sendto_one(to, pattern, par, p2, p3, p4, p5, p6, p7, p8);
  904. #endif
  905. }
  906.