1 /************************************************************************
2 * IRC - Internet Relay Chat, ircd/s_numeric.c
3 * Copyright (C) 1990 Jarkko Oikarinen
4 *
5 * Numerous fixes by Markku Savela
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 1, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifndef lint
23 static const volatile char rcsid[] = "@(#)$Id: s_numeric.c,v 1.8 2005/01/30 17:56:31 chopin Exp $";
24 #endif
25
26 #include "os.h"
27 #include "s_defines.h"
28 #define S_NUMERIC_C
29 #include "s_externs.h"
30 #undef S_NUMERIC_C
31
32 static char buffer[1024];
33
34 /*
35 ** DoNumeric (replacement for the old do_numeric)
36 **
37 ** parc number of arguments ('sender' counted as one!)
38 ** parv[0] pointer to 'sender' (may point to empty string) (not used)
39 ** parv[1]..parv[parc-1]
40 ** pointers to additional parameters, this is a NULL
41 ** terminated list (parv[parc] == NULL).
42 **
43 ** *WARNING*
44 ** Numerics are mostly error reports. If there is something
45 ** wrong with the message, just *DROP* it! Don't even think of
46 ** sending back a neat error message -- big danger of creating
47 ** a ping pong error message...
48 */
do_numeric(int numeric,aClient * cptr,aClient * sptr,int parc,char * parv[])49 int do_numeric(int numeric, aClient *cptr, aClient *sptr, int parc,
50 char *parv[])
51 {
52 aClient *acptr = NULL;
53 aChannel *chptr;
54 char *nick, *p;
55 int i;
56
57 if (parc < 1 || !IsServer(sptr))
58 return 1;
59 /* Remap low number numerics. */
60 if (numeric < 100)
61 numeric += 100;
62 /*
63 ** Prepare the parameter portion of the message into 'buffer'.
64 ** (Because the buffer is twice as large as the message buffer
65 ** for the socket, no overflow can occur here... ...on current
66 ** assumptions--bets are off, if these are changed --msa)
67 ** Note: if buffer is non-empty, it will begin with SPACE.
68 */
69 buffer[0] = '\0';
70 if (parc > 1)
71 {
72 for (i = 2; i < (parc - 1); i++)
73 {
74 (void)strcat(buffer, " ");
75 (void)strcat(buffer, parv[i]);
76 }
77 (void)strcat(buffer, " :");
78 (void)strcat(buffer, parv[parc-1]);
79 }
80 for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL)
81 {
82 acptr = find_target(nick, cptr);
83 if (acptr)
84 {
85 /*
86 ** Drop to bit bucket if for me...
87 ** ...one might consider sendto_ops
88 ** here... --msa
89 ** And so it was done. -avalon
90 ** And regretted. Don't do it that way. Make sure
91 ** it goes only to non-servers. -avalon
92 ** Check added to make sure servers don't try to loop
93 ** with numerics which can happen with nick collisions.
94 ** - Avalon
95 */
96 if (IsMe(acptr) || acptr->from == cptr)
97 sendto_flag(SCH_NUM,
98 "From %s for %s: %s %d %s %s.",
99 get_client_name(cptr, TRUE),
100 acptr->name, sptr->name,
101 numeric, nick, buffer);
102 else if (IsPerson(acptr) || IsServer(acptr) ||
103 IsService(acptr))
104 sendto_prefix_one(acptr, sptr,":%s %d %s%s",
105 parv[0], numeric, nick, buffer);
106 }
107 /* any reason why no cptr == acptr->from checks here? -krys */
108 /* because these are not used.. -Vesa
109 else if ((acptr = find_service(nick, (aClient *)NULL)))
110 sendto_prefix_one(acptr, sptr,":%s %d %s%s",
111 parv[0], numeric, nick, buffer);
112 else if ((acptr = find_server(nick, (aClient *)NULL)))
113 {
114 if (!IsMe(acptr) && acptr->from != cptr)
115 sendto_prefix_one(acptr, sptr,":%s %d %s%s",
116 parv[0], numeric, nick, buffer);
117 }
118 ..nuke them */
119 else if ((chptr = find_channel(nick, (aChannel *)NULL)))
120 sendto_channel_butone(cptr,sptr,chptr,":%s %d %s%s",
121 parv[0],
122 numeric, chptr->chname, buffer);
123 }
124 return 1;
125 }
126
127