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