1 /*
2  *   Unreal Internet Relay Chat Daemon, src/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 CLEAN_COMPILE
26 static char sccsid[] =
27     "@(#)send.c	2.32 2/28/94 (C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen";
28 #endif
29 
30 #include "struct.h"
31 #include "numeric.h"
32 #include "common.h"
33 #include "sys.h"
34 #include "h.h"
35 #include "msg.h"
36 #include <stdarg.h>
37 #include <stdio.h>
38 #ifdef _WIN32
39 #include <io.h>
40 #endif
41 #include <string.h>
42 
43 void vsendto_one(aClient *to, char *pattern, va_list vl);
44 void sendbufto_one(aClient *to, char *msg, unsigned int quick);
45 int vmakebuf_local_withprefix(char *buf, struct Client *from, const char *pattern, va_list vl);
46 
47 #define ADD_CRLF(buf, len) { if (len > 510) len = 510; \
48                              buf[len++] = '\r'; buf[len++] = '\n'; buf[len] = '\0'; } while(0)
49 
50 #ifndef NO_FDLIST
51 extern fdlist serv_fdlist;
52 extern fdlist oper_fdlist;
53 #endif
54 
55 #define NEWLINE	"\r\n"
56 
57 static char sendbuf[2048];
58 static char tcmd[2048];
59 static char ccmd[2048];
60 static char xcmd[2048];
61 static char wcmd[2048];
62 
63 /* this array is used to ensure we send a msg only once to a remote
64 ** server.  like, when we are sending a message to all channel members
65 ** send the message to those that are directly connected to us and once
66 ** to each server that has these members.  the servers then forward the
67 ** message to other servers and to those channel members that are directly
68 ** connected to them
69 */
70 static int sentalong[MAXCONNECTIONS];
71 
72 void vsendto_prefix_one(struct Client *to, struct Client *from,
73     const char *pattern, va_list vl);
74 
75 MODVAR int  sentalong_marker;
76 MODVAR int  sendanyways = 0;
77 /*
78 ** dead_link
79 **	An error has been detected. The link *must* be closed,
80 **	but *cannot* call ExitClient (m_bye) from here.
81 **	Instead, mark it with FLAGS_DEADSOCKET. This should
82 **	generate ExitClient from the main loop.
83 **
84 **	notice will be the quit message. notice will also be
85 **	sent to failops in case 'to' is a server.
86 */
dead_link(aClient * to,char * notice)87 static int dead_link(aClient *to, char *notice)
88 {
89 
90 	to->flags |= FLAGS_DEADSOCKET;
91 	/*
92 	 * If because of BUFFERPOOL problem then clean dbuf's now so that
93 	 * notices don't hurt operators below.
94 	 */
95 	DBufClear(&to->recvQ);
96 	DBufClear(&to->sendQ);
97 
98 	if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
99 		(void)sendto_failops_whoare_opers("Closing link: %s - %s",
100 			notice, get_client_name(to, FALSE));
101 	Debug((DEBUG_ERROR, "dead_link: %s - %s", notice, get_client_name(to, FALSE)));
102 	to->error_str = strdup(notice);
103 	return -1;
104 }
105 
106 /*
107 ** flush_connections
108 **	Used to empty all output buffers for all connections. Should only
109 **	be called once per scan of connections. There should be a select in
110 **	here perhaps but that means either forcing a timeout or doing a poll.
111 **	When flushing, all we do is empty the obuffer array for each local
112 **	client and try to send it. if we cant send it, it goes into the sendQ
113 **	-avalon
114 */
flush_connections(aClient * cptr)115 void flush_connections(aClient* cptr)
116 {
117 	int  i;
118 	aClient *acptr;
119 
120 	if (&me == cptr)
121 	{
122 		for (i = LastSlot; i >= 0; i--)
123 			if ((acptr = local[i]) && !(acptr->flags & FLAGS_BLOCKED)
124 			    && ((DBufLength(&acptr->sendQ) > 0)
125 #ifdef ZIP_LINKS
126 				|| (IsZipped(acptr) && acptr->zip->outcount)
127 #endif /* ZIP_LINKS */
128 				) )
129 				send_queued(acptr);
130 	}
131 	else if (cptr->fd >= 0 && !(cptr->flags & FLAGS_BLOCKED)
132 	    && ((DBufLength(&cptr->sendQ) > 0)
133 #ifdef ZIP_LINKS
134 		|| (IsZipped(cptr) && cptr->zip->outcount)
135 #endif /* ZIP_LINKS */
136 		) )
137 		send_queued(cptr);
138 
139 }
140 /* flush an fdlist intelligently */
141 #ifndef NO_FDLIST
flush_fdlist_connections(fdlist * listp)142 void flush_fdlist_connections(fdlist * listp)
143 {
144 	int  i, fd;
145 	aClient *cptr;
146 
147 	for (fd = listp->entry[i = 1]; i <= listp->last_entry;
148 	    fd = listp->entry[++i])
149 		if ((cptr = local[fd]) && !(cptr->flags & FLAGS_BLOCKED)
150 		    && DBufLength(&cptr->sendQ) > 0)
151 			send_queued(cptr);
152 }
153 #endif
154 
155 /*
156 ** send_queued
157 **	This function is called from the main select-loop (or whatever)
158 **	when there is a chance the some output would be possible. This
159 **	attempts to empty the send queue as far as possible...
160 */
send_queued(aClient * to)161 int  send_queued(aClient *to)
162 {
163 	char *msg;
164 	int  len, rlen;
165 #ifdef ZIP_LINKS
166 	int more = 0;
167 #endif
168 	if (IsBlocked(to))
169 		return -1;		/* Can't write to already blocked socket */
170 
171 	/*
172 	   ** Once socket is marked dead, we cannot start writing to it,
173 	   ** even if the error is removed...
174 	 */
175 	if (IsDead(to))
176 	{
177 		/*
178 		   ** Actually, we should *NEVER* get here--something is
179 		   ** not working correct if send_queued is called for a
180 		   ** dead socket... --msa
181 		 */
182 		return -1;
183 	}
184 #ifdef ZIP_LINKS
185 	/*
186 	** Here, we must make sure than nothing will be left in to->zip->outbuf
187 	** This buffer needs to be compressed and sent if all the sendQ is sent
188 	*/
189 	if ((IsZipped(to)) && to->zip->outcount) {
190 		if (DBufLength(&to->sendQ) > 0) {
191 			more = 1;
192 		} else {
193 			msg = zip_buffer(to, NULL, &len, 1);
194 			if (len == -1)
195 				return dead_link(to, "fatal error in zip_buffer()");
196 			if (!dbuf_put(&to->sendQ, msg, len))
197 				return dead_link(to, "Buffer allocation error");
198 		}
199 	}
200 #endif
201 	while (DBufLength(&to->sendQ) > 0)
202 	{
203 		msg = dbuf_map(&to->sendQ, &len);
204 		/* Returns always len > 0 */
205 		if ((rlen = deliver_it(to, msg, len)) < 0)
206 		{
207 			char buf[256];
208 			snprintf(buf, 256, "Write error: %s", STRERROR(ERRNO));
209 			return dead_link(to, buf);
210 		}
211 		(void)dbuf_delete(&to->sendQ, rlen);
212 		to->lastsq = DBufLength(&to->sendQ) / 1024;
213 		if (rlen < len)
214 		{
215 			/* If we can't write full message, mark the socket
216 			 * as "blocking" and stop trying. -Donwulff */
217 			SetBlocked(to);
218 			break;
219 		}
220 #ifdef ZIP_LINKS
221 		if (DBufLength(&to->sendQ) == 0 && more) {
222 			/*
223 			** The sendQ is now empty, compress what's left
224 			** uncompressed and try to send it too
225 			*/
226 			more = 0;
227 			msg = zip_buffer(to, NULL, &len, 1);
228 			if (len == -1)
229 				return dead_link(to, "fatal error in zip_buffer()");
230 			if (!dbuf_put(&to->sendQ, msg, len))
231 				return dead_link(to, "Buffer allocation error");
232 		}
233 #endif
234 	}
235 
236 	return (IsDead(to)) ? -1 : 0;
237 }
238 
239 /*
240  *  send message to single client
241  */
sendto_one(aClient * to,char * pattern,...)242 void sendto_one(aClient *to, char *pattern, ...)
243 {
244 	va_list vl;
245 	va_start(vl, pattern);
246 	vsendto_one(to, pattern, vl);
247 	va_end(vl);
248 }
249 
vsendto_one(aClient * to,char * pattern,va_list vl)250 void vsendto_one(aClient *to, char *pattern, va_list vl)
251 {
252 	ircvsprintf(sendbuf, pattern, vl);
253 	sendbufto_one(to, sendbuf, 0);
254 }
255 
256 
257 /* sendbufto_one:
258  * to: the client to which the buffer should be send
259  * msg: the message
260  * quick: normally set to 0, see later.
261  * NOTES:
262  * - neither to or msg can be NULL
263  * - if quick is set to 0, the length is calculated, the string is cutoff
264  *   at 510 bytes if needed, and \r\n is added if needed.
265  *   if quick is >0 it is assumed the message has \r\n and 'quick' is used
266  *   as length. Of course you should be very careful with that.
267  */
sendbufto_one(aClient * to,char * msg,unsigned int quick)268 void sendbufto_one(aClient *to, char *msg, unsigned int quick)
269 {
270 	int  len;
271 	Hook *h;
272 
273 	Debug((DEBUG_ERROR, "Sending [%s] to %s", msg, to->name));
274 
275 	if (to->from)
276 		to = to->from;
277 	if (IsDead(to))
278 		return;		/* This socket has already
279 				   been marked as dead */
280 	if (to->fd < 0)
281 	{
282 		/* This is normal when 'to' was being closed (via exit_client
283 		 *  and close_connection) --Run
284 		 * Print the debug message anyway...
285 		 */
286 		Debug((DEBUG_ERROR,
287 		    "Local socket %s with negative fd %d... AARGH!", to->name,
288 		    to->fd));
289 		return;
290 	}
291 
292 	if (!quick)
293 	{
294 		len = strlen(msg);
295 		if (!len || (msg[len - 1] != '\n'))
296 		{
297 			if (len > 510)
298 				len = 510;
299 			msg[len++] = '\r';
300 			msg[len++] = '\n';
301 			msg[len] = '\0';
302 		}
303 	} else
304 		len = quick;
305 
306 	if (len > 512)
307 	{
308 		ircd_log(LOG_ERROR, "sendbufto_one: len=%u, quick=%u", len, quick);
309 		abort();
310 	}
311 
312 	if (IsMe(to))
313 	{
314 		char tmp_msg[500], *p;
315 
316 		p = strchr(msg, '\r');
317 		if (p) *p = '\0';
318 		snprintf(tmp_msg, 500, "Trying to send data to myself! '%s'", msg);
319 		ircd_log(LOG_ERROR, "%s", tmp_msg);
320 		sendto_ops("%s", tmp_msg); /* recursion? */
321 		return;
322 	}
323         for(h = Hooks[HOOKTYPE_PACKET]; h; h = h->next) {
324 		(*(h->func.intfunc))(&me, to, &msg, &len);
325 		if(!msg) return;
326 	}
327 	if (DBufLength(&to->sendQ) > get_sendq(to))
328 	{
329 		if (IsServer(to))
330 			sendto_ops("Max SendQ limit exceeded for %s: %u > %d",
331 			    get_client_name(to, FALSE), DBufLength(&to->sendQ),
332 			    get_sendq(to));
333 		dead_link(to, "Max SendQ exceeded");
334 		return;
335 	}
336 
337 #ifdef ZIP_LINKS
338 	/*
339 	** data is first stored in to->zip->outbuf until
340 	** it's big enough to be compressed and stored in the sendq.
341 	** send_queued is then responsible to never let the sendQ
342 	** be empty and to->zip->outbuf not empty.
343 	*/
344 	if (IsZipped(to))
345 		msg = zip_buffer(to, msg, &len, 0);
346 
347 	if (len && !dbuf_put(&to->sendQ, msg, len))
348 #else
349 	if (!dbuf_put(&to->sendQ, msg, len))
350 #endif
351 	{
352 		dead_link(to, "Buffer allocation error");
353 		return;
354 	}
355 	/*
356 	 * Update statistics. The following is slightly incorrect
357 	 * because it counts messages even if queued, but bytes
358 	 * only really sent. Queued bytes get updated in SendQueued.
359 	 */
360 	to->sendM += 1;
361 	me.sendM += 1;
362 	if (to->listener != &me)
363 		to->listener->sendM += 1;
364 	/*
365 	 * This little bit is to stop the sendQ from growing too large when
366 	 * there is no need for it to. Thus we call send_queued() every time
367 	 * 2k has been added to the queue since the last non-fatal write.
368 	 * Also stops us from deliberately building a large sendQ and then
369 	 * trying to flood that link with data (possible during the net
370 	 * relinking done by servers with a large load).
371 	 */
372 	if (DBufLength(&to->sendQ) / 1024 > to->lastsq)
373 		send_queued(to);
374 }
375 
sendto_channel_butone(aClient * one,aClient * from,aChannel * chptr,char * pattern,...)376 void sendto_channel_butone(aClient *one, aClient *from, aChannel *chptr,
377     char *pattern, ...)
378 {
379 	va_list vl;
380 	Member *lp;
381 	aClient *acptr;
382 	int  i;
383 
384 	va_start(vl, pattern);
385 
386 	++sentalong_marker;
387 	for (lp = chptr->members; lp; lp = lp->next)
388 	{
389 		acptr = lp->cptr;
390 		/* skip the one and deaf clients (unless sendanyways is set) */
391 		if (acptr->from == one || (IsDeaf(acptr) && !(sendanyways == 1)))
392 			continue;
393 		if (MyConnect(acptr))	/* (It is always a client) */
394 			vsendto_prefix_one(acptr, from, pattern, vl);
395 		else if (sentalong[(i = acptr->from->slot)] != sentalong_marker)
396 		{
397 			sentalong[i] = sentalong_marker;
398 			/*
399 			 * Burst messages comes here..
400 			 */
401 			va_start(vl, pattern);
402 			vsendto_prefix_one(acptr, from, pattern, vl);
403 			va_end(vl);
404 		}
405 	}
406 	va_end(vl);
407 }
408 
sendto_channelprefix_butone(aClient * one,aClient * from,aChannel * chptr,int prefix,char * pattern,...)409 void sendto_channelprefix_butone(aClient *one, aClient *from, aChannel *chptr,
410 	int	prefix,
411     char *pattern, ...)
412 {
413 	va_list vl;
414 	Member *lp;
415 	aClient *acptr;
416 	int  i;
417 
418 	va_start(vl, pattern);
419 
420 	++sentalong_marker;
421 	for (lp = chptr->members; lp; lp = lp->next)
422 	{
423 		acptr = lp->cptr;
424 		if (acptr->from == one)
425 			continue;	/* ...was the one I should skip
426 					   or user not not a channel op */
427 	        if ((prefix & PREFIX_HALFOP) && (lp->flags & CHFL_HALFOP))
428 			goto good;
429 		if ((prefix & PREFIX_VOICE) && (lp->flags & CHFL_VOICE))
430 			goto good;
431 		if ((prefix & PREFIX_OP) && (lp->flags & CHFL_CHANOP))
432 			goto good;
433 #ifdef PREFIX_AQ
434 		if ((prefix & PREFIX_ADMIN) && (lp->flags & CHFL_CHANPROT))
435 			goto good;
436 		if ((prefix & PREFIX_OWNER) && (lp->flags & CHFL_CHANOWNER))
437 			goto good;
438 #endif
439 		continue;
440 
441 		good:
442 		i = acptr->from->slot;
443 		if (MyConnect(acptr) && IsRegisteredUser(acptr))
444 		{
445 #ifdef SECURECHANMSGSONLYGOTOSECURE
446 			if (chptr->mode.mode & MODE_ONLYSECURE)
447 				if (!IsSecure(acptr))
448 					continue;
449 #endif
450 			va_start(vl, pattern);
451 			vsendto_prefix_one(acptr, from, pattern, vl);
452 			va_end(vl);
453 			sentalong[i] = sentalong_marker;
454 		}
455 		else
456 		{
457 			/* Now check whether a message has been sent to this
458 			 * remote link already */
459 			if (sentalong[i] != sentalong_marker)
460 			{
461 #ifdef SECURECHANMSGSONLYGOTOSECURE
462 				if (chptr->mode.mode & MODE_ONLYSECURE)
463 					if (!IsSecure(acptr->from))
464 						continue;
465 #endif
466 				va_start(vl, pattern);
467 				vsendto_prefix_one(acptr, from, pattern, vl);
468 				va_end(vl);
469 				sentalong[i] = sentalong_marker;
470 			}
471 		}
472 		va_end(vl);
473 	}
474 	va_end(vl);
475 	return;
476 }
477 
sendto_channelprefix_butone_tok(aClient * one,aClient * from,aChannel * chptr,int prefix,char * cmd,char * tok,char * nick,char * text,char do_send_check)478 void sendto_channelprefix_butone_tok(aClient *one, aClient *from, aChannel *chptr,
479 	int	prefix,
480     char *cmd, char *tok, char *nick, char *text, char do_send_check)
481 {
482 	Member *lp;
483 	aClient *acptr;
484 	int  i;
485 	char is_ctcp = 0;
486 	unsigned int tlen, clen, xlen, wlen = 0;
487 	char *p;
488 
489 	/* For servers with token capability */
490 	p = ircsprintf(tcmd, ":%s %s %s :%s", from->name, tok, nick, text);
491 	tlen = (int)(p - tcmd);
492 	ADD_CRLF(tcmd, tlen);
493 
494 	/* For dumb servers without tokens */
495 	p = ircsprintf(ccmd, ":%s %s %s :%s", from->name, cmd, nick, text);
496 	clen = (int)(p - ccmd);
497 	ADD_CRLF(ccmd, clen);
498 
499 	/* For our users... */
500 	if (IsPerson(from))
501 		p = ircsprintf(xcmd, ":%s!%s@%s %s %s :%s",
502 			from->name, from->user->username, GetHost(from), cmd, nick, text);
503 	else
504 		p = ircsprintf(xcmd, ":%s %s %s :%s", from->name, cmd, nick, text);
505 	xlen = (int)(p - xcmd);
506 	ADD_CRLF(xcmd, xlen);
507 
508 	/* For our webtv friends... */
509 	if (!strcmp(cmd, "NOTICE"))
510 	{
511 		char *chan = strchr(nick, '#'); /* impossible to become NULL? */
512 		if (IsPerson(from))
513 			p = ircsprintf(wcmd, ":%s!%s@%s %s %s :%s",
514 				from->name, from->user->username, GetHost(from), MSG_PRIVATE, chan, text);
515 		else
516 			p = ircsprintf(wcmd, ":%s %s %s :%s", from->name, MSG_PRIVATE, chan, text);
517 		wlen = (int)(p - wcmd);
518 		ADD_CRLF(wcmd, wlen);
519 	}
520 
521 	if (do_send_check && *text == 1 && myncmp(text+1,"ACTION ",7) && myncmp(text+1,"DCC ",4))
522 		is_ctcp = 1;
523 
524 
525 	++sentalong_marker;
526 	for (lp = chptr->members; lp; lp = lp->next)
527 	{
528 		acptr = lp->cptr;
529 		if (acptr->from == one)
530 			continue;	/* ...was the one I should skip
531 					   or user not not a channel op */
532         if (prefix == PREFIX_ALL)
533            	goto good;
534         if ((prefix & PREFIX_HALFOP) && (lp->flags & CHFL_HALFOP))
535 			goto good;
536 		if ((prefix & PREFIX_VOICE) && (lp->flags & CHFL_VOICE))
537 			goto good;
538 		if ((prefix & PREFIX_OP) && (lp->flags & CHFL_CHANOP))
539 			goto good;
540 #ifdef PREFIX_AQ
541 		if ((prefix & PREFIX_ADMIN) && (lp->flags & CHFL_CHANPROT))
542 			goto good;
543 		if ((prefix & PREFIX_OWNER) && (lp->flags & CHFL_CHANOWNER))
544 			goto good;
545 #endif
546 		continue;
547 
548 		good:
549 		i = acptr->from->slot;
550 		if (IsDeaf(acptr) && !sendanyways)
551 			continue;
552 		if (MyConnect(acptr) && IsRegisteredUser(acptr))
553 		{
554 			if (IsNoCTCP(acptr) && !IsOper(from) && is_ctcp)
555 				continue;
556 
557 			if (IsWebTV(acptr) && wlen)
558 				sendbufto_one(acptr, wcmd, wlen);
559 			else
560 				sendbufto_one(acptr, xcmd, xlen);
561 			sentalong[i] = sentalong_marker;
562 		}
563 		else
564 		{
565 			/* Now check whether a message has been sent to this
566 			 * remote link already */
567 			if (sentalong[i] != sentalong_marker)
568 			{
569 				if (IsToken(acptr->from))
570 					sendbufto_one(acptr, tcmd, tlen);
571 				else
572 					sendbufto_one(acptr, ccmd, clen);
573 				sentalong[i] = sentalong_marker;
574 			}
575 		}
576 	}
577 	return;
578 }
579 
580 /* weird channelmode +mu crap:
581  * - local: deliver msgs to chanops (and higher) like <IRC> SrcNick: hi all
582  * - remote: deliver msgs to every server once (if needed) with real sourcenick.
583  * The problem is we can't send to remote servers with sourcenick (prefix) 'IRC'
584  * because that's a virtual user... Fun... -- Syzop.
585  */
sendto_chmodemucrap(aClient * from,aChannel * chptr,char * text)586 void sendto_chmodemucrap(aClient *from, aChannel *chptr, char *text)
587 {
588 	Member *lp;
589 	aClient *acptr;
590 	int  i;
591 	int remote = MyClient(from) ? 0 : 1;
592 
593 	sprintf(tcmd, ":%s %s %s :%s", from->name, TOK_PRIVATE, chptr->chname, text); /* token */
594 	sprintf(ccmd, ":%s %s %s :%s", from->name, MSG_PRIVATE, chptr->chname, text); /* msg */
595 	sprintf(xcmd, ":IRC!IRC@%s PRIVMSG %s :%s: %s", me.name, chptr->chname, from->name, text); /* local */
596 
597 	++sentalong_marker;
598 	for (lp = chptr->members; lp; lp = lp->next)
599 	{
600 		acptr = lp->cptr;
601 
602 		if (IsDeaf(acptr) && !sendanyways)
603 			continue;
604 		if (!(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT)))
605 			continue;
606 		if (remote && (acptr->from == from->from)) /* don't send it back to where it came from */
607 			continue;
608 		i = acptr->from->slot;
609 		if (MyConnect(acptr) && IsRegisteredUser(acptr))
610 		{
611 			sendto_one(acptr, "%s", xcmd);
612 			sentalong[i] = sentalong_marker;
613 		}
614 		else
615 		{
616 			/* Now check whether a message has been sent to this
617 			 * remote link already */
618 			if (sentalong[i] != sentalong_marker)
619 			{
620 				if (IsToken(acptr->from))
621 					sendto_one(acptr, "%s", tcmd);
622 				else
623 					sendto_one(acptr, "%s", ccmd);
624 				sentalong[i] = sentalong_marker;
625 			}
626 		}
627 	}
628 	return;
629 }
630 
631 
632 /*
633    sendto_chanops_butone -Stskeeps
634 */
635 
sendto_chanops_butone(aClient * one,aChannel * chptr,char * pattern,...)636 void sendto_chanops_butone(aClient *one, aChannel *chptr, char *pattern, ...)
637 {
638 	va_list vl;
639 	Member *lp;
640 	aClient *acptr;
641 
642 	va_start(vl, pattern);
643 	for (lp = chptr->members; lp; lp = lp->next)
644 	{
645 		acptr = lp->cptr;
646 		if (acptr == one || !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT)))
647 			continue;	/* ...was the one I should skip
648 					   or user not not a channel op */
649 		if (MyConnect(acptr) && IsRegisteredUser(acptr))
650 		{
651 			va_start(vl, pattern);
652 			vsendto_one(acptr, pattern, vl);
653 			va_end(vl);
654 		}
655 	}
656 	va_end(vl);
657 }
658 
659 /*
660  * sendto_server_butone
661  *
662  * Send a message to all connected servers except the client 'one'.
663  */
sendto_serv_butone(aClient * one,char * pattern,...)664 void sendto_serv_butone(aClient *one, char *pattern, ...)
665 {
666 	va_list vl;
667 	int  i;
668 	aClient *cptr;
669 #ifndef NO_FDLIST
670 	int  j;
671 #endif
672 
673 	va_start(vl, pattern);
674 #ifdef NO_FDLIST
675 	for (i = 0; i <= LastSlot; i++)
676 #else
677 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
678 #endif
679 	{
680 		if (!(cptr = local[i]) || (one && cptr == one->from))
681 			continue;
682 		va_start(vl, pattern);
683 
684 #ifdef NO_FDLIST
685 		if (IsServer(cptr))
686 #endif
687 			vsendto_one(cptr, pattern, vl);
688 		va_end(vl);
689 	}
690 	va_end(vl);
691 	return;
692 }
693 
694 /*
695  * sendto_server_butone_token
696  *
697  * Send a message to all connected servers except the client 'one'.
698  * with capab to tokenize
699  */
700 
sendto_serv_butone_token(aClient * one,char * prefix,char * command,char * token,char * pattern,...)701 void sendto_serv_butone_token(aClient *one, char *prefix, char *command,
702     char *token, char *pattern, ...)
703 {
704 	va_list vl;
705 	int  i;
706 	aClient *cptr;
707 	aClient *acptr;
708 #ifndef NO_FDLIST
709 	int  j;
710 #endif
711 	static char buff[2048];
712 	static char pref[100];
713 	va_start(vl, pattern);
714 
715 	pref[0] = '\0';
716 	if (strchr(prefix, '.'))
717 	{
718 		acptr = (aClient *) find_server_quick(prefix);
719 		if (acptr->serv->numeric)
720 		{
721 			strcpy(pref, base64enc(acptr->serv->numeric));
722 		}
723 	}
724 	strcpy(tcmd, token);
725 	strcpy(ccmd, command);
726 	strcat(tcmd, " ");
727 	strcat(ccmd, " ");
728 	ircvsprintf(buff, pattern, vl);
729 	strcat(tcmd, buff);
730 	strcat(ccmd, buff);
731 
732 #ifdef NO_FDLIST
733 	for (i = 0; i <= LastSlot; i++)
734 #else
735 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
736 #endif
737 	{
738 		if (!(cptr = local[i]) || (one && cptr == one->from))
739 			continue;
740 #ifdef NO_FDLIST
741 		if (IsServer(cptr))
742 #endif
743 			if (IsToken(cptr))
744 			{
745 				if (SupportNS(cptr) && pref[0])
746 				{
747 					sendto_one(cptr, "@%s %s",
748 						pref, tcmd);
749 				}
750 					else
751 				{
752 					sendto_one(cptr, ":%s %s",
753 						prefix, tcmd);
754 				}
755 			}
756 			else
757 			{
758 				if (SupportNS(cptr) && pref[0])
759 				{
760 					sendto_one(cptr, "@%s %s",
761 						pref, ccmd);
762 				}
763 				else
764 				{
765 					sendto_one(cptr, ":%s %s", prefix,
766 					    ccmd);
767 				}
768 			}
769 	}
770 	va_end(vl);
771 	return;
772 }
773 
774 /*
775  * sendto_server_butone_token_opt
776  *
777  * Send a message to all connected servers except the client 'one'.
778  * with capab to tokenize, opt
779  */
780 
sendto_serv_butone_token_opt(aClient * one,int opt,char * prefix,char * command,char * token,char * pattern,...)781 void sendto_serv_butone_token_opt(aClient *one, int opt, char *prefix, char *command,
782     char *token, char *pattern, ...)
783 {
784 	va_list vl;
785 	int  i;
786 	aClient *cptr;
787 	aClient *acptr;
788 #ifndef NO_FDLIST
789 	int  j;
790 #endif
791 	static char tcmd[2048];
792 	static char ccmd[2048];
793 	static char buff[2048];
794 	static char pref[100];
795 
796 	va_start(vl, pattern);
797 
798 	pref[0] = '\0';
799 	if (strchr(prefix, '.'))
800 	{
801 		acptr = (aClient *) find_server_quick(prefix);
802 		if (acptr && acptr->serv)
803 			if (acptr->serv->numeric)
804 			{
805 				strcpy(pref, base64enc(acptr->serv->numeric));
806 			}
807 	}
808 
809 	strcpy(tcmd, token);
810 	strcpy(ccmd, command);
811 	strcat(tcmd, " ");
812 	strcat(ccmd, " ");
813 	ircvsprintf(buff, pattern, vl);
814 	strcat(tcmd, buff);
815 	strcat(ccmd, buff);
816 
817 #ifdef NO_FDLIST
818 	for (i = 0; i <= LastSlot; i++)
819 #else
820 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
821 #endif
822 	{
823 		if (!(cptr = local[i]) || (one && cptr == one->from))
824 			continue;
825 #ifdef NO_FDLIST
826 		if (IsServer(cptr))
827 #endif
828 
829 		if ((opt & OPT_NOT_SJOIN) && SupportSJOIN(cptr))
830 			continue;
831 		if ((opt & OPT_NOT_NICKv2) && SupportNICKv2(cptr))
832 			continue;
833 		if ((opt & OPT_NOT_SJOIN2) && SupportSJOIN2(cptr))
834 			continue;
835 		if ((opt & OPT_NOT_UMODE2) && SupportUMODE2(cptr))
836 			continue;
837 		if ((opt & OPT_NOT_SJ3) && SupportSJ3(cptr))
838 			continue;
839 		if ((opt & OPT_NICKv2) && !SupportNICKv2(cptr))
840 			continue;
841 		if ((opt & OPT_SJOIN) && !SupportSJOIN(cptr))
842 			continue;
843 		if ((opt & OPT_SJOIN2) && !SupportSJOIN2(cptr))
844 			continue;
845 		if ((opt & OPT_UMODE2) && !SupportUMODE2(cptr))
846 			continue;
847 		if ((opt & OPT_SJ3) && !SupportSJ3(cptr))
848 			continue;
849 		if ((opt & OPT_SJB64) && !(cptr->proto & PROTO_SJB64))
850 			continue;
851 		if ((opt & OPT_NOT_SJB64) && (cptr->proto & PROTO_SJB64))
852 			continue;
853 		if ((opt & OPT_VHP) && !(cptr->proto & PROTO_VHP))
854 			continue;
855 		if ((opt & OPT_NOT_VHP) && (cptr->proto & PROTO_VHP))
856 			continue;
857 		if ((opt & OPT_TKLEXT) && !(cptr->proto & PROTO_TKLEXT))
858 			continue;
859 		if ((opt & OPT_NOT_TKLEXT) && (cptr->proto & PROTO_TKLEXT))
860 			continue;
861 		if ((opt & OPT_NICKIP) && !(cptr->proto & PROTO_TKLEXT))
862 			continue;
863 		if ((opt & OPT_NOT_NICKIP) && (cptr->proto & PROTO_NICKIP))
864 			continue;
865 
866 		if (IsToken(cptr))
867 		{
868 			if (SupportNS(cptr) && pref[0])
869 			{
870 				sendto_one(cptr, "@%s %s",
871 					pref, tcmd);
872 			}
873 				else
874 			{
875 				sendto_one(cptr, ":%s %s",
876 					prefix, tcmd);
877 			}
878 		}
879 		else
880 		{
881 			if (SupportNS(cptr) && pref[0])
882 			{
883 				sendto_one(cptr, "@%s %s",
884 					pref, ccmd);
885 			}
886 			else
887 			{
888 				sendto_one(cptr, ":%s %s", prefix,
889 				    ccmd);
890 			}
891 		}
892 	}
893 	va_end(vl);
894 	return;
895 }
896 
897 /*
898  * sendto_serv_butone_quit
899  *
900  * Send a message to all connected servers except the client 'one'.
901  * BUT, don't send to NOQUIT servers.
902  */
sendto_serv_butone_quit(aClient * one,char * pattern,...)903 void sendto_serv_butone_quit(aClient *one, char *pattern, ...)
904 {
905 	va_list vl;
906 	int  i;
907 	aClient *cptr;
908 #ifndef NO_FDLIST
909 	int  j;
910 #endif
911 	va_start(vl, pattern);
912 
913 #ifdef NO_FDLIST
914 	for (i = 0; i <= LastSlot; i++)
915 #else
916 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
917 #endif
918 	{
919 		if (!(cptr = local[i]) || (one && cptr == one->from))
920 			continue;
921 		va_start(vl, pattern);
922 
923 #ifdef NO_FDLIST
924 		if (IsServer(cptr) && !DontSendQuit(cptr))
925 #else
926 		if (!DontSendQuit(cptr))
927 #endif
928 			vsendto_one(cptr, pattern, vl);
929 		va_end(vl);
930 	}
931 	va_end(vl);
932 	return;
933 }
934 
935 /*
936  * sendto_serv_butone_sjoin
937  *
938  * Send a message to all connected servers except the client 'one'.
939  * BUT, don't send to SJOIN servers.
940  */
sendto_serv_butone_sjoin(aClient * one,char * pattern,...)941 void sendto_serv_butone_sjoin(aClient *one, char *pattern, ...)
942 {
943 	va_list vl;
944 	int  i;
945 	aClient *cptr;
946 #ifndef NO_FDLIST
947 	int  j;
948 #endif
949 	va_start(vl, pattern);
950 #ifdef NO_FDLIST
951 	for (i = 0; i <= LastSlot; i++)
952 #else
953 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
954 #endif
955 	{
956 		if (!(cptr = local[i]) || (one && cptr == one->from))
957 			continue;
958 		va_start(vl, pattern);
959 
960 #ifdef NO_FDLIST
961 		if (IsServer(cptr) && !SupportSJOIN(cptr))
962 #else
963 		if (!SupportSJOIN(cptr))
964 #endif
965 			vsendto_one(cptr, pattern, vl);
966 		va_end(vl);
967 	}
968 	va_end(vl);
969 	return;
970 }
971 
972 /*
973  * sendto_serv_sjoin
974  *
975  * Send a message to all connected servers except the client 'one'.
976  * BUT only send to SJOIN servers.
977  */
sendto_serv_sjoin(aClient * one,char * pattern,...)978 void sendto_serv_sjoin(aClient *one, char *pattern, ...)
979 {
980 	va_list vl;
981 	int  i;
982 	aClient *cptr;
983 #ifndef NO_FDLIST
984 	int  j;
985 #endif
986 	va_start(vl, pattern);
987 
988 #ifdef NO_FDLIST
989 	for (i = 0; i <= LastSlot; i++)
990 #else
991 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
992 #endif
993 	{
994 		if (!(cptr = local[i]) || (one && cptr == one->from))
995 			continue;
996 		va_start(vl, pattern);
997 
998 #ifdef NO_FDLIST
999 		if (IsServer(cptr) && SupportSJOIN(cptr))
1000 #else
1001 		if (SupportSJOIN(cptr))
1002 #endif
1003 			vsendto_one(cptr, pattern, vl);
1004 		va_end(vl);
1005 	}
1006 	va_end(vl);
1007 	return;
1008 }
1009 
1010 /*
1011  * sendto_serv_butone_nickv2
1012  *
1013  * Send a message to all connected servers except the client 'one'.
1014  * BUT, don't send to NICKv2 servers.
1015  */
sendto_serv_butone_nickv2(aClient * one,char * pattern,...)1016 void sendto_serv_butone_nickv2(aClient *one, char *pattern, ...)
1017 {
1018 	va_list vl;
1019 	int  i;
1020 	aClient *cptr;
1021 #ifndef NO_FDLIST
1022 	int  j;
1023 #endif
1024 	va_start(vl, pattern);
1025 
1026 #ifdef NO_FDLIST
1027 	for (i = 0; i <= LastSlot; i++)
1028 #else
1029 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1030 #endif
1031 	{
1032 		if (!(cptr = local[i]) || (one && cptr == one->from))
1033 			continue;
1034 		va_start(vl, pattern);
1035 
1036 #ifdef NO_FDLIST
1037 		if (IsServer(cptr) && !SupportNICKv2(cptr))
1038 #else
1039 		if (!SupportNICKv2(cptr))
1040 #endif
1041 			vsendto_one(cptr, pattern, vl);
1042 		va_end(vl);
1043 	}
1044 	va_end(vl);
1045 	return;
1046 }
1047 
1048 /*
1049  * sendto_serv_nickv2
1050  *
1051  * Send a message to all connected servers except the client 'one'.
1052  * BUT only send to NICKv2 servers.
1053  */
sendto_serv_nickv2(aClient * one,char * pattern,...)1054 void sendto_serv_nickv2(aClient *one, char *pattern, ...)
1055 {
1056 	va_list vl;
1057 	int  i;
1058 	aClient *cptr;
1059 #ifndef NO_FDLIST
1060 	int  j;
1061 #endif
1062 	va_start(vl, pattern);
1063 
1064 #ifdef NO_FDLIST
1065 	for (i = 0; i <= LastSlot; i++)
1066 #else
1067 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1068 #endif
1069 	{
1070 		if (!(cptr = local[i]) || (one && cptr == one->from))
1071 			continue;
1072 		va_start(vl, pattern);
1073 
1074 #ifdef NO_FDLIST
1075 		if (IsServer(cptr) && SupportNICKv2(cptr))
1076 #else
1077 		if (SupportNICKv2(cptr))
1078 #endif
1079 			vsendto_one(cptr, pattern, vl);
1080 		va_end(vl);
1081 	}
1082 	va_end(vl);
1083 	return;
1084 }
1085 
1086 
1087 /*
1088  * sendto_serv_nickv2_token
1089  *
1090  * Send a message to all connected servers except the client 'one'.
1091  * BUT only send to NICKv2 servers. As of Unreal3.1 it uses two patterns now
1092  * one for non token and one for tokens */
sendto_serv_nickv2_token(aClient * one,char * pattern,char * tokpattern,...)1093 void sendto_serv_nickv2_token(aClient *one, char *pattern, char *tokpattern,
1094     ...)
1095 {
1096 	va_list vl;
1097 	int  i;
1098 	aClient *cptr;
1099 #ifndef NO_FDLIST
1100 	int  j;
1101 #endif
1102 	va_start(vl, tokpattern);
1103 
1104 #ifdef NO_FDLIST
1105 	for (i = 0; i <= LastSlot; i++)
1106 #else
1107 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1108 #endif
1109 	{
1110 		if (!(cptr = local[i]) || (one && cptr == one->from))
1111 			continue;
1112 		va_start(vl, tokpattern);
1113 
1114 #ifdef NO_FDLIST
1115 		if (IsServer(cptr) && SupportNICKv2(cptr) && !IsToken(cptr))
1116 #else
1117 		if (SupportNICKv2(cptr) && !IsToken(cptr))
1118 #endif
1119 			vsendto_one(cptr, pattern, vl);
1120 		else
1121 #ifdef NO_FDLIST
1122 		if (IsServer(cptr) && SupportNICKv2(cptr) && IsToken(cptr))
1123 #else
1124 		if (SupportNICKv2(cptr) && IsToken(cptr))
1125 #endif
1126 			vsendto_one(cptr, tokpattern, vl);
1127 		va_end(vl);
1128 	}
1129 	va_end(vl);
1130 	return;
1131 }
1132 
1133 /*
1134  * sendto_common_channels()
1135  *
1136  * Sends a message to all people (including user) on local server who are
1137  * in same channel with user.
1138  */
sendto_common_channels(aClient * user,char * pattern,...)1139 void sendto_common_channels(aClient *user, char *pattern, ...)
1140 {
1141 	va_list vl;
1142 
1143 	Membership *channels;
1144 	Member *users;
1145 	aClient *cptr;
1146 	int sendlen;
1147 
1148 	/* We now create the buffer _before_ we send it to the clients. -- Syzop */
1149 	*sendbuf = '\0';
1150 	va_start(vl, pattern);
1151 	sendlen = vmakebuf_local_withprefix(sendbuf, user, pattern, vl);
1152 	va_end(vl);
1153 
1154 	++sentalong_marker;
1155 	if (user->fd >= 0)
1156 		sentalong[user->slot] = sentalong_marker;
1157 	if (user->user)
1158 		for (channels = user->user->channel; channels; channels = channels->next)
1159 			for (users = channels->chptr->members; users; users = users->next)
1160 			{
1161 				cptr = users->cptr;
1162 				if (!MyConnect(cptr) || (cptr->slot < 0) || (sentalong[cptr->slot] == sentalong_marker))
1163 					continue;
1164 				if ((channels->chptr->mode.mode & MODE_AUDITORIUM) &&
1165 				    !(is_chanownprotop(user, channels->chptr) || is_chanownprotop(cptr, channels->chptr)))
1166 					continue;
1167 				sentalong[cptr->slot] = sentalong_marker;
1168 				sendbufto_one(cptr, sendbuf, sendlen);
1169 			}
1170 
1171 	if (MyConnect(user))
1172 		sendbufto_one(user, sendbuf, sendlen);
1173 
1174 	return;
1175 }
1176 
1177 /*
1178  * sendto_common_channels_local_butone()
1179  *
1180  * Sends a message to all people on local server who are
1181  * in same channel with user and have the specified capability.
1182  */
sendto_common_channels_local_butone(aClient * user,int cap,char * pattern,...)1183 void sendto_common_channels_local_butone(aClient *user, int cap, char *pattern, ...)
1184 {
1185 	va_list vl;
1186 
1187 	Membership *channels;
1188 	Member *users;
1189 	aClient *cptr;
1190 	int sendlen;
1191 
1192 	/* We now create the buffer _before_ we send it to the clients. -- Syzop */
1193 	*sendbuf = '\0';
1194 	va_start(vl, pattern);
1195 	sendlen = vmakebuf_local_withprefix(sendbuf, user, pattern, vl);
1196 	va_end(vl);
1197 
1198 	++sentalong_marker;
1199 	if (user->fd >= 0)
1200 		sentalong[user->slot] = sentalong_marker;
1201 	if (user->user)
1202 	{
1203 		for (channels = user->user->channel; channels; channels = channels->next)
1204 			for (users = channels->chptr->members; users; users = users->next)
1205 			{
1206 				cptr = users->cptr;
1207 				if (!MyConnect(cptr) || (cptr->slot < 0) || (sentalong[cptr->slot] == sentalong_marker) ||
1208 				    !CHECKPROTO(cptr, cap))
1209 					continue;
1210 				if ((channels->chptr->mode.mode & MODE_AUDITORIUM) &&
1211 				    !(is_chanownprotop(user, channels->chptr) || is_chanownprotop(cptr, channels->chptr)))
1212 					continue;
1213 				sentalong[cptr->slot] = sentalong_marker;
1214 				sendbufto_one(cptr, sendbuf, sendlen);
1215 			}
1216 	}
1217 
1218 	return;
1219 }
1220 
1221 /*
1222  * sendto_channel_butserv
1223  *
1224  * Send a message to all members of a channel that are connected to this
1225  * server.
1226  */
1227 
sendto_channel_butserv(aChannel * chptr,aClient * from,char * pattern,...)1228 void sendto_channel_butserv(aChannel *chptr, aClient *from, char *pattern, ...)
1229 {
1230 	va_list vl;
1231 	Member *lp;
1232 	aClient *acptr;
1233 	int sendlen;
1234 
1235 	/* We now create the buffer _before_ we send it to the clients. Rather than
1236 	 * rebuilding the buffer 1000 times for a 1000 local-users channel. -- Syzop
1237 	 */
1238 	*sendbuf = '\0';
1239 	va_start(vl, pattern);
1240 	sendlen = vmakebuf_local_withprefix(sendbuf, from, pattern, vl);
1241 	va_end(vl);
1242 
1243 	for (lp = chptr->members; lp; lp = lp->next)
1244 		if (MyConnect(acptr = lp->cptr))
1245 			sendbufto_one(acptr, sendbuf, sendlen);
1246 
1247 	return;
1248 }
1249 
sendto_channel_butserv_butone(aChannel * chptr,aClient * from,aClient * one,char * pattern,...)1250 void sendto_channel_butserv_butone(aChannel *chptr, aClient *from, aClient *one, char *pattern, ...)
1251 {
1252 	va_list vl;
1253 	Member *lp;
1254 	aClient *acptr;
1255 
1256 	for (va_start(vl, pattern), lp = chptr->members; lp; lp = lp->next)
1257 	{
1258 		if (lp->cptr == one)
1259 			continue;
1260 		if (MyConnect(acptr = lp->cptr))
1261 		{
1262 			va_start(vl, pattern);
1263 			vsendto_prefix_one(acptr, from, pattern, vl);
1264 			va_end(vl);
1265 		}
1266 	}
1267 	va_end(vl);
1268 	return;
1269 }
1270 
1271 /*
1272 ** send a msg to all ppl on servers/hosts that match a specified mask
1273 ** (used for enhanced PRIVMSGs)
1274 **
1275 ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
1276 */
1277 
match_it(one,mask,what)1278 static int match_it(one, mask, what)
1279 	aClient *one;
1280 	char *mask;
1281 	int  what;
1282 {
1283 	switch (what)
1284 	{
1285 	  case MATCH_HOST:
1286 		  return (match(mask, one->user->realhost) == 0);
1287 	  case MATCH_SERVER:
1288 	  default:
1289 		  return (match(mask, one->user->server) == 0);
1290 	}
1291 }
1292 
1293 /*
1294  * sendto_match_servs
1295  *
1296  * send to all servers which match the mask at the end of a channel name
1297  * (if there is a mask present) or to all if no mask.
1298  */
sendto_match_servs(aChannel * chptr,aClient * from,char * format,...)1299 void sendto_match_servs(aChannel *chptr, aClient *from, char *format, ...)
1300 {
1301 	va_list vl;
1302 	int  i;
1303 	aClient *cptr;
1304 	char *mask;
1305 
1306 	va_start(vl, format);
1307 
1308 	if (chptr)
1309 	{
1310 		if (*chptr->chname == '&')
1311 			return;
1312 		if ((mask = (char *)rindex(chptr->chname, ':')))
1313 			mask++;
1314 	}
1315 	else
1316 		mask = (char *)NULL;
1317 
1318 	for (i = 0; i <= LastSlot; i++)
1319 	{
1320 		if (!(cptr = local[i]))
1321 			continue;
1322 		if ((cptr == from) || !IsServer(cptr))
1323 			continue;
1324 		if (!BadPtr(mask) && IsServer(cptr) && match(mask, cptr->name))
1325 			continue;
1326 		va_start(vl, format);
1327 		vsendto_one(cptr, format, vl);
1328 		va_end(vl);
1329 	}
1330 	va_end(vl);
1331 }
1332 
1333 /*
1334  * sendto_match_butone
1335  *
1336  * Send to all clients which match the mask in a way defined on 'what';
1337  * either by user hostname or user servername.
1338  */
sendto_match_butone(aClient * one,aClient * from,char * mask,int what,char * pattern,...)1339 void sendto_match_butone(aClient *one, aClient *from, char *mask, int what,
1340     char *pattern, ...)
1341 {
1342 	va_list vl;
1343 	int  i;
1344 	aClient *cptr, *acptr;
1345 	char cansendlocal, cansendglobal;
1346 
1347 	va_start(vl, pattern);
1348 	if (MyConnect(from))
1349 	{
1350 		cansendlocal = (OPCanLNotice(from)) ? 1 : 0;
1351 		cansendglobal = (OPCanGNotice(from)) ? 1 : 0;
1352 	}
1353 	else
1354 		cansendlocal = cansendglobal = 1;
1355 
1356 	for (i = 0; i <= LastSlot; i++)
1357 	{
1358 		if (!(cptr = local[i]))
1359 			continue;	/* that clients are not mine */
1360 		if (cptr == one)	/* must skip the origin !! */
1361 			continue;
1362 		if (IsServer(cptr))
1363 		{
1364 			if (!cansendglobal)
1365 				continue;
1366 			for (acptr = client; acptr; acptr = acptr->next)
1367 				if (IsRegisteredUser(acptr)
1368 				    && match_it(acptr, mask, what)
1369 				    && acptr->from == cptr)
1370 					break;
1371 			/* a person on that server matches the mask, so we
1372 			   ** send *one* msg to that server ...
1373 			 */
1374 			if (acptr == NULL)
1375 				continue;
1376 			/* ... but only if there *IS* a matching person */
1377 		}
1378 		/* my client, does he match ? */
1379 		else if (!cansendlocal || (!(IsRegisteredUser(cptr) &&
1380 		    match_it(cptr, mask, what))))
1381 			continue;
1382 		va_start(vl, pattern);
1383 		vsendto_prefix_one(cptr, from, pattern, vl);
1384 		va_end(vl);
1385 	}
1386 	va_end(vl);
1387 	return;
1388 }
1389 
1390 /*
1391  * sendto_all_butone.
1392  *
1393  * Send a message to all connections except 'one'. The basic wall type
1394  * message generator.
1395  */
1396 
sendto_all_butone(aClient * one,aClient * from,char * pattern,...)1397 void sendto_all_butone(aClient *one, aClient *from, char *pattern, ...)
1398 {
1399 	va_list vl;
1400 	int  i;
1401 	aClient *cptr;
1402 
1403 	for (va_start(vl, pattern), i = 0; i <= LastSlot; i++)
1404 		if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
1405 		{
1406 			va_start(vl, pattern);
1407 			vsendto_prefix_one(cptr, from, pattern, vl);
1408 			va_end(vl);
1409 		}
1410 	va_end(vl);
1411 	return;
1412 }
1413 
1414 /*
1415  * sendto_ops
1416  *
1417  *	Send to *local* ops only.
1418  */
sendto_ops(char * pattern,...)1419 void sendto_ops(char *pattern, ...)
1420 {
1421 	va_list vl;
1422 	aClient *cptr;
1423 	int  i;
1424 	char nbuf[1024];
1425 
1426 	va_start(vl, pattern);
1427 	for (i = 0; i <= LastSlot; i++)
1428 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) && SendServNotice(cptr))
1429 		{
1430 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** Notice -- ", me.name, cptr->name);
1431 			(void)strncat(nbuf, pattern, sizeof(nbuf) - strlen(nbuf));
1432 			va_start(vl, pattern);
1433 			vsendto_one(cptr, nbuf, vl);
1434 			va_end(vl);
1435 		}
1436 	va_end(vl);
1437 	return;
1438 }
1439 
1440 /*
1441  * sendto_failops
1442  *
1443  *      Send to *local* mode +g ops only.
1444  */
sendto_failops(char * pattern,...)1445 void sendto_failops(char *pattern, ...)
1446 {
1447 	va_list vl;
1448 	aClient *cptr;
1449 	int  i;
1450 	char nbuf[1024];
1451 
1452 	va_start(vl, pattern);
1453 	for (i = 0; i <= LastSlot; i++)
1454 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1455 		    SendFailops(cptr))
1456 		{
1457 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
1458 			    me.name, cptr->name);
1459 			(void)strncat(nbuf, pattern,
1460 			    sizeof(nbuf) - strlen(nbuf));
1461 			va_start(vl, pattern);
1462 			vsendto_one(cptr, nbuf, vl);
1463 			va_end(vl);
1464 		}
1465 	va_end(vl);
1466 	return;
1467 }
1468 
1469 /*
1470  * sendto_umode
1471  *
1472  *  Send to specified umode
1473  */
sendto_umode(int umodes,char * pattern,...)1474 void sendto_umode(int umodes, char *pattern, ...)
1475 {
1476 	va_list vl;
1477 	aClient *cptr;
1478 	int  i;
1479 	char nbuf[1024];
1480 	va_start(vl, pattern);
1481 	for (i = 0; i <= LastSlot; i++)
1482 		if ((cptr = local[i]) && IsPerson(cptr) && (cptr->umodes & umodes) == umodes)
1483 		{
1484 			(void)ircsprintf(nbuf, ":%s NOTICE %s :",
1485 			    me.name, cptr->name);
1486 			(void)strncat(nbuf, pattern,
1487 			    sizeof(nbuf) - strlen(nbuf));
1488 			va_start(vl, pattern);
1489 			vsendto_one(cptr, nbuf, vl);
1490 			va_end(vl);
1491 		}
1492 	va_end(vl);
1493 	return;
1494 }
1495 
1496 /*
1497  * sendto_umode_raw
1498  *
1499  *  Send to specified umode , raw, not a notice
1500  */
sendto_umode_raw(int umodes,char * pattern,...)1501 void sendto_umode_raw(int umodes, char *pattern, ...)
1502 {
1503 	va_list vl;
1504 	aClient *cptr;
1505 	int  i;
1506 	va_start(vl, pattern);
1507 	for (i = 0; i <= LastSlot; i++)
1508 		if ((cptr = local[i]) && IsPerson(cptr) && (cptr->umodes & umodes) == umodes)
1509 		{
1510 			va_start(vl, pattern);
1511 			vsendto_one(cptr, pattern, vl);
1512 			va_end(vl);
1513 		}
1514 	va_end(vl);
1515 	return;
1516 }
1517 /** Send to specified snomask - local / operonly.
1518  * @param snomask Snomask to send to (can be a bitmask [AND])
1519  * @param pattern printf-style pattern, followed by parameters.
1520  * This function does not send snomasks to non-opers.
1521  */
sendto_snomask(int snomask,char * pattern,...)1522 void sendto_snomask(int snomask, char *pattern, ...)
1523 {
1524 	va_list vl;
1525 	aClient *cptr;
1526 	int  i, j;
1527 	char nbuf[2048];
1528 
1529 	va_start(vl, pattern);
1530 	ircvsprintf(nbuf, pattern, vl);
1531 	va_end(vl);
1532 
1533 	for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1534 		if (((cptr = local[i])) && (cptr->user->snomask & snomask))
1535 			sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1536 }
1537 
1538 /** Send to specified snomask - global / operonly.
1539  * @param snomask Snomask to send to (can be a bitmask [AND])
1540  * @param pattern printf-style pattern, followed by parameters
1541  * This function does not send snomasks to non-opers.
1542  */
sendto_snomask_global(int snomask,char * pattern,...)1543 void sendto_snomask_global(int snomask, char *pattern, ...)
1544 {
1545 	va_list vl;
1546 	aClient *cptr;
1547 	int  i, j;
1548 	char nbuf[2048], snobuf[32], *p;
1549 
1550 	va_start(vl, pattern);
1551 	ircvsprintf(nbuf, pattern, vl);
1552 	va_end(vl);
1553 
1554 	for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1555 		if (((cptr = local[i])) && (cptr->user->snomask & snomask))
1556 			sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1557 
1558 	/* Build snomasks-to-send-to buffer */
1559 	snobuf[0] = '\0';
1560 	for (i = 0, p=snobuf; i<= Snomask_highest; i++)
1561 		if (snomask & Snomask_Table[i].mode)
1562 			*p++ = Snomask_Table[i].flag;
1563 	*p = '\0';
1564 
1565 	sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO,
1566 		"%s :%s", snobuf, nbuf);
1567 }
1568 
1569 /** Send to specified snomask - local.
1570  * @param snomask Snomask to send to (can be a bitmask [AND])
1571  * @param pattern printf-style pattern, followed by parameters.
1572  * This function also delivers to non-opers w/the snomask if needed.
1573  */
sendto_snomask_normal(int snomask,char * pattern,...)1574 void sendto_snomask_normal(int snomask, char *pattern, ...)
1575 {
1576 	va_list vl;
1577 	aClient *cptr;
1578 	int  i;
1579 	char nbuf[2048];
1580 
1581 	va_start(vl, pattern);
1582 	ircvsprintf(nbuf, pattern, vl);
1583 	va_end(vl);
1584 
1585 	for (i = LastSlot; i >= 0; i--)
1586 		if ((cptr = local[i]) && IsPerson(cptr) && (cptr->user->snomask & snomask))
1587 			sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1588 }
1589 
1590 /** Send to specified snomask - global.
1591  * @param snomask Snomask to send to (can be a bitmask [AND])
1592  * @param pattern printf-style pattern, followed by parameters
1593  * This function also delivers to non-opers w/the snomask if needed.
1594  */
sendto_snomask_normal_global(int snomask,char * pattern,...)1595 void sendto_snomask_normal_global(int snomask, char *pattern, ...)
1596 {
1597 	va_list vl;
1598 	aClient *cptr;
1599 	int  i;
1600 	char nbuf[2048], snobuf[32], *p;
1601 
1602 	va_start(vl, pattern);
1603 	ircvsprintf(nbuf, pattern, vl);
1604 	va_end(vl);
1605 
1606 	for (i = LastSlot; i >= 0; i--)
1607 		if ((cptr = local[i]) && IsPerson(cptr) && (cptr->user->snomask & snomask))
1608 			sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1609 
1610 	/* Build snomasks-to-send-to buffer */
1611 	snobuf[0] = '\0';
1612 	for (i = 0, p=snobuf; i<= Snomask_highest; i++)
1613 		if (snomask & Snomask_Table[i].mode)
1614 			*p++ = Snomask_Table[i].flag;
1615 	*p = '\0';
1616 
1617 	sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO,
1618 		"%s :%s", snobuf, nbuf);
1619 }
1620 
1621 
1622 /*
1623  * sendto_failops_whoare_opers
1624  *
1625  *      Send to *local* mode +g ops only who are also +o.
1626  */
sendto_failops_whoare_opers(char * pattern,...)1627 void sendto_failops_whoare_opers(char *pattern, ...)
1628 {
1629 	va_list vl;
1630 	aClient *cptr;
1631 	int  i;
1632 	char nbuf[1024];
1633 
1634 	va_start(vl, pattern);
1635 	for (i = 0; i <= LastSlot; i++)
1636 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1637 		    SendFailops(cptr) && IsAnOper(cptr))
1638 		{
1639 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
1640 			    me.name, cptr->name);
1641 			(void)strncat(nbuf, pattern,
1642 			    sizeof(nbuf) - strlen(nbuf));
1643 			va_start(vl, pattern);
1644 			vsendto_one(cptr, nbuf, vl);
1645 			va_end(vl);
1646 		}
1647 	va_end(vl);
1648 	return;
1649 }
1650 /*
1651  * sendto_locfailops
1652  *
1653  *      Send to *local* mode +g ops only who are also +o.
1654  */
sendto_locfailops(char * pattern,...)1655 void sendto_locfailops(char *pattern, ...)
1656 {
1657 	va_list vl;
1658 	aClient *cptr;
1659 	int  i;
1660 	char nbuf[1024];
1661 
1662 	va_start(vl, pattern);
1663 	for (i = 0; i <= LastSlot; i++)
1664 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1665 		    SendFailops(cptr) && IsAnOper(cptr))
1666 		{
1667 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** LocOps -- ",
1668 			    me.name, cptr->name);
1669 			(void)strncat(nbuf, pattern,
1670 			    sizeof(nbuf) - strlen(nbuf));
1671 			va_start(vl, pattern);
1672 			vsendto_one(cptr, nbuf, vl);
1673 			va_end(vl);
1674 		}
1675 	va_end(vl);
1676 	return;
1677 }
1678 /*
1679  * sendto_opers
1680  *
1681  *	Send to *local* ops only. (all +O or +o people)
1682  */
sendto_opers(char * pattern,...)1683 void sendto_opers(char *pattern, ...)
1684 {
1685 	va_list vl;
1686 	aClient *cptr;
1687 	int  i;
1688 	char nbuf[1024];
1689 
1690 	va_start(vl, pattern);
1691 	for (i = 0; i <= LastSlot; i++)
1692 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1693 		    IsAnOper(cptr))
1694 		{
1695 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** Oper -- ",
1696 			    me.name, cptr->name);
1697 			(void)strncat(nbuf, pattern,
1698 			    sizeof(nbuf) - strlen(nbuf));
1699 			va_start(vl, pattern);
1700 			vsendto_one(cptr, nbuf, vl);
1701 			va_end(vl);
1702 		}
1703 	va_end(vl);
1704 	return;
1705 }
1706 
1707 /* ** sendto_ops_butone
1708 **	Send message to all operators.
1709 ** one - client not to send message to
1710 ** from- client which message is from *NEVER* NULL!!
1711 */
sendto_ops_butone(aClient * one,aClient * from,char * pattern,...)1712 void sendto_ops_butone(aClient *one, aClient *from, char *pattern, ...)
1713 {
1714 	va_list vl;
1715 	int  i;
1716 	aClient *cptr;
1717 
1718 	va_start(vl, pattern);
1719 
1720 	++sentalong_marker;
1721 	for (cptr = client; cptr; cptr = cptr->next)
1722 	{
1723 		if (!SendWallops(cptr))
1724 			continue;
1725 		i = cptr->from->slot;	/* find connection oper is on */
1726 		if (sentalong[i] == sentalong_marker)	/* sent message along it already ? */
1727 			continue;
1728 		if (cptr->from == one)
1729 			continue;	/* ...was the one I should skip */
1730 		sentalong[i] = sentalong_marker;
1731 		va_start(vl, pattern);
1732 		vsendto_prefix_one(cptr->from, from, pattern, vl);
1733 		va_end(vl);
1734 	}
1735 	va_end(vl);
1736 	return;
1737 }
1738 
1739 /*
1740 ** sendto_ops_butone
1741 **	Send message to all operators regardless of whether they are +w or
1742 **	not..
1743 ** one - client not to send message to
1744 ** from- client which message is from *NEVER* NULL!!
1745 */
sendto_opers_butone(aClient * one,aClient * from,char * pattern,...)1746 void sendto_opers_butone(aClient *one, aClient *from, char *pattern, ...)
1747 {
1748 	va_list vl;
1749 	int  i;
1750 	aClient *cptr;
1751 
1752 	va_start(vl, pattern);
1753 
1754 	++sentalong_marker;
1755 	for (cptr = client; cptr; cptr = cptr->next)
1756 	{
1757 		if (!IsAnOper(cptr))
1758 			continue;
1759 		i = cptr->from->slot;	/* find connection oper is on */
1760 		if (sentalong[i] == sentalong_marker)	/* sent message along it already ? */
1761 			continue;
1762 		if (cptr->from == one)
1763 			continue;	/* ...was the one I should skip */
1764 		sentalong[i] = sentalong_marker;
1765 		va_start(vl, pattern);
1766 		vsendto_prefix_one(cptr->from, from, pattern, vl);
1767 		va_end(vl);
1768 	}
1769 	va_end(vl);
1770 	return;
1771 }
1772 /*
1773 ** sendto_ops_butme
1774 **	Send message to all operators except local ones
1775 ** from- client which message is from *NEVER* NULL!!
1776 */
sendto_ops_butme(aClient * from,char * pattern,...)1777 void sendto_ops_butme(aClient *from, char *pattern, ...)
1778 {
1779 	va_list vl;
1780 	int  i;
1781 	aClient *cptr;
1782 
1783 	va_start(vl, pattern);
1784 
1785 	++sentalong_marker;
1786 	for (cptr = client; cptr; cptr = cptr->next)
1787 	{
1788 		if (!SendWallops(cptr))
1789 			continue;
1790 		i = cptr->from->slot;	/* find connection oper is on */
1791 		if (sentalong[i] == sentalong_marker)	/* sent message along it already ? */
1792 			continue;
1793 		if (!strcmp(cptr->user->server, me.name))	/* a locop */
1794 			continue;
1795 		sentalong[i] = sentalong_marker;
1796 		va_start(vl, pattern);
1797 		vsendto_prefix_one(cptr->from, from, pattern, vl);
1798 		va_end(vl);
1799 	}
1800 	va_end(vl);
1801 	return;
1802 }
1803 
1804 /* Prepare buffer based on format string and 'from' for LOCAL delivery.
1805  * The prefix (:<something>) will be expanded to :nick!user@host if 'from'
1806  * is a person, taking into account the rules for hidden/cloaked host.
1807  * NOTE: Do not send this prepared buffer to remote clients or servers,
1808  *       they do not want or need the expanded prefix. In that case, simply
1809  *       use ircvsprintf() directly.
1810  */
vmakebuf_local_withprefix(char * buf,struct Client * from,const char * pattern,va_list vl)1811 int vmakebuf_local_withprefix(char *buf, struct Client *from, const char *pattern, va_list vl)
1812 {
1813 int len;
1814 
1815 	if (from && from->user)
1816 	{
1817 		char *par;
1818 
1819 		par = va_arg(vl, char *); /* eat first parameter */
1820 
1821 		*buf = ':';
1822 		strcpy(buf+1, from->name);
1823 
1824 		if (IsPerson(from))
1825 		{
1826 			char *username = from->user->username;
1827 			char *host = GetHost(from);
1828 
1829 			if (*username)
1830 			{
1831 				strcat(buf, "!");
1832 				strcat(buf, username);
1833 			}
1834 			if (*host)
1835 			{
1836 				strcat(buf, "@");
1837 				strcat(buf, host);
1838 			}
1839 		}
1840 
1841 		/* Assuming 'pattern' always starts with ":%s ..." */
1842 		if (!strcmp(&pattern[3], "%s"))
1843 			strcpy(buf + strlen(buf), va_arg(vl, char *)); /* This can speed things up by 30% -- Syzop */
1844 		else
1845 			ircvsprintf(buf + strlen(buf), &pattern[3], vl);
1846 	}
1847 	else
1848 		ircvsprintf(buf, pattern, vl);
1849 
1850 	len = strlen(buf);
1851 	ADD_CRLF(buf, len);
1852 	return len;
1853 }
1854 
vsendto_prefix_one(struct Client * to,struct Client * from,const char * pattern,va_list vl)1855 void vsendto_prefix_one(struct Client *to, struct Client *from,
1856     const char *pattern, va_list vl)
1857 {
1858 	if (to && from && MyClient(to) && from->user)
1859 		vmakebuf_local_withprefix(sendbuf, from, pattern, vl);
1860 	else
1861 		ircvsprintf(sendbuf, pattern, vl);
1862 
1863 	sendbufto_one(to, sendbuf, 0);
1864 }
1865 
1866 /*
1867  * sendto_prefix_one
1868  *
1869  * to - destination client
1870  * from - client which message is from
1871  *
1872  * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
1873  * -avalon
1874  */
1875 
sendto_prefix_one(aClient * to,aClient * from,const char * pattern,...)1876 void sendto_prefix_one(aClient *to, aClient *from, const char *pattern, ...)
1877 {
1878 	va_list vl;
1879 	va_start(vl, pattern);
1880 	vsendto_prefix_one(to, from, pattern, vl);
1881 	va_end(vl);
1882 }
1883 
1884 /*
1885  * sendto_realops
1886  *
1887  *	Send to *local* ops only but NOT +s nonopers.
1888  */
sendto_realops(char * pattern,...)1889 void sendto_realops(char *pattern, ...)
1890 {
1891 	va_list vl;
1892 	aClient *cptr;
1893 	int  i;
1894 #ifndef NO_FDLIST
1895 	int  j;
1896 #endif
1897 	char nbuf[1024];
1898 
1899 	va_start(vl, pattern);
1900 #ifdef NO_FDLIST
1901 	for (i = 0; i <= LastSlot; i++)
1902 #else
1903 	for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1904 #endif
1905 #ifdef NO_FDLIST
1906 		if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1907 		    IsOper(cptr))
1908 #else
1909 		if ((cptr = local[i]))
1910 #endif
1911 		{
1912 			(void)ircsprintf(nbuf, ":%s NOTICE %s :*** Notice -- ",
1913 			    me.name, cptr->name);
1914 			(void)strncat(nbuf, pattern,
1915 			    sizeof(nbuf) - strlen(nbuf));
1916 			va_start(vl, pattern);
1917 			vsendto_one(cptr, nbuf, vl);
1918 			va_end(vl);
1919 		}
1920 	va_end(vl);
1921 	return;
1922 }
1923 
sendto_connectnotice(char * nick,anUser * user,aClient * sptr,int disconnect,char * comment)1924 void sendto_connectnotice(char *nick, anUser *user, aClient *sptr, int disconnect, char *comment)
1925 {
1926 	aClient *cptr;
1927 	int  i, j;
1928 	char connectd[1024];
1929 	char connecth[1024];
1930 
1931 	if (!disconnect)
1932 	{
1933 		RunHook(HOOKTYPE_LOCAL_CONNECT, sptr);
1934 		ircsprintf(connectd,
1935 		    "*** Notice -- Client connecting on port %d: %s (%s@%s) [%s] %s%s%s",
1936 		    sptr->listener->port, nick, user->username, user->realhost,
1937 		    sptr->class ? sptr->class->name : "",
1938 #ifdef USE_SSL
1939 		IsSecure(sptr) ? "[secure " : "",
1940 		IsSecure(sptr) ? SSL_get_cipher((SSL *)sptr->ssl) : "",
1941 		IsSecure(sptr) ? "]" : "");
1942 #else
1943 		"", "", "");
1944 #endif
1945 		ircsprintf(connecth,
1946 		    "*** Notice -- Client connecting: %s (%s@%s) [%s] {%s}", nick,
1947 		    user->username, user->realhost, Inet_ia2p(&sptr->ip),
1948 		    sptr->class ? sptr->class->name : "0");
1949 	}
1950 	else
1951 	{
1952 		ircsprintf(connectd, "*** Notice -- Client exiting: %s (%s@%s) [%s]",
1953 			nick, user->username, user->realhost, comment);
1954 		ircsprintf(connecth, "*** Notice -- Client exiting: %s (%s@%s) [%s] [%s]",
1955 			nick, user->username, user->realhost, comment, Inet_ia2p(&sptr->ip));
1956 	}
1957 
1958 	for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1959 		if (((cptr = local[i])) && (cptr->user->snomask & SNO_CLIENT))
1960 		{
1961 			if (IsHybNotice(cptr))
1962 				sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
1963 				    cptr->name, connecth);
1964 			else
1965 				sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
1966 				    cptr->name, connectd);
1967 
1968 		}
1969 }
1970 
sendto_fconnectnotice(char * nick,anUser * user,aClient * sptr,int disconnect,char * comment)1971 void sendto_fconnectnotice(char *nick, anUser *user, aClient *sptr, int disconnect, char *comment)
1972 {
1973 	aClient *cptr;
1974 	int  i, j;
1975 	char connectd[1024];
1976 	char connecth[1024];
1977 
1978 	if (!disconnect)
1979 	{
1980 		ircsprintf(connectd, "*** Notice -- Client connecting at %s: %s (%s@%s)",
1981 			    user->server, nick, user->username, user->realhost);
1982 		ircsprintf(connecth,
1983 		    "*** Notice -- Client connecting at %s: %s (%s@%s) [%s] {0}", user->server, nick,
1984 		    user->username, user->realhost, user->ip_str ? user->ip_str : "0");
1985 	}
1986 	else
1987 	{
1988 		ircsprintf(connectd, "*** Notice -- Client exiting at %s: %s!%s@%s (%s)",
1989 			   user->server, nick, user->username, user->realhost, comment);
1990 		ircsprintf(connecth, "*** Notice -- Client exiting at %s: %s (%s@%s) [%s] [%s]",
1991 			user->server, nick, user->username, user->realhost, comment,
1992 			user->ip_str ? user->ip_str : "0");
1993 	}
1994 
1995 	for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1996 		if (((cptr = local[i])) && (cptr->user->snomask & SNO_FCLIENT))
1997 		{
1998 			if (IsHybNotice(cptr))
1999 				sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
2000 				    cptr->name, connecth);
2001 			else
2002 				sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
2003 				    cptr->name, connectd);
2004 
2005 		}
2006 }
2007 
2008 /*
2009  * sendto_server_butone_nickcmd
2010  *
2011  * Send a message to all connected servers except the client 'one'.
2012  */
sendto_serv_butone_nickcmd(aClient * one,aClient * sptr,char * nick,int hopcount,long lastnick,char * username,char * realhost,char * server,char * svid,char * info,char * umodes,char * virthost)2013 void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr,
2014 			char *nick, int hopcount,
2015     long lastnick, char *username, char *realhost, char *server,
2016     char *svid, char *info, char *umodes, char *virthost)
2017 {
2018 	int  i;
2019 	aClient *cptr;
2020 #ifndef NO_FDLIST
2021 	int  j;
2022 #endif
2023 
2024 #ifdef NO_FDLIST
2025 	for (i = 0; i <= LastSlot; i++)
2026 #else
2027 	for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
2028 #endif
2029 	{
2030 		if (!(cptr = local[i]) || (one && cptr == one->from))
2031 			continue;
2032 #ifdef NO_FDLIST
2033 		if (IsServer(cptr))
2034 #endif
2035 		{
2036 			char *vhost;
2037 			if (SupportVHP(cptr))
2038 			{
2039 				if (IsHidden(sptr))
2040 					vhost = sptr->user->virthost;
2041 				else
2042 					vhost = sptr->user->realhost;
2043 			}
2044 			else
2045 			{
2046 				if (IsHidden(sptr) && sptr->umodes & UMODE_SETHOST)
2047 					vhost = sptr->user->virthost;
2048 				else
2049 					vhost = "*";
2050 			}
2051 
2052 			if (SupportNICKv2(cptr))
2053 			{
2054 				if (sptr->srvptr->serv->numeric && SupportNS(cptr))
2055 					sendto_one(cptr,
2056 						(cptr->proto & PROTO_SJB64) ?
2057 					    /* Ugly double %s to prevent excessive spaces */
2058 					    "%s %s %d %B %s %s %b %s %s %s %s%s%s%s:%s"
2059 					    :
2060 					    "%s %s %d %lu %s %s %b %s %s %s %s%s%s%s:%s"
2061 					    ,
2062 					    (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick,
2063 					    hopcount, (long)lastnick, username, realhost,
2064 					    (long)(sptr->srvptr->serv->numeric),
2065 					    svid, umodes, vhost,
2066 					    SupportCLK(cptr) ? getcloak(sptr) : "",
2067 					    SupportCLK(cptr) ? " " : "",
2068 					    SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2069 					    SupportNICKIP(cptr) ? " " : "",
2070 					    info);
2071 				else
2072 					sendto_one(cptr,
2073 					    "%s %s %d %d %s %s %s %s %s %s %s%s%s%s:%s",
2074 					    (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick,
2075 					    hopcount, lastnick, username, realhost,
2076 					    SupportNS(cptr) && sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric) : server,
2077 					    svid, umodes, vhost,
2078 					    SupportCLK(cptr) ? getcloak(sptr) : "",
2079 					    SupportCLK(cptr) ? " " : "",
2080 					    SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2081 					    SupportNICKIP(cptr) ? " " : "",
2082 					    info);
2083 
2084 			}
2085 			else
2086 			{
2087 				sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s",
2088 				    (IsToken(cptr) ? TOK_NICK : MSG_NICK),
2089 				    nick, hopcount, lastnick, username,
2090 				    realhost,
2091 				    server, svid, info);
2092 				if (strcmp(umodes, "+"))
2093 				{
2094 					sendto_one(cptr, ":%s %s %s :%s",
2095 					    nick,
2096 					    (IsToken(cptr) ? TOK_MODE :
2097 					    MSG_MODE), nick, umodes);
2098 				}
2099 				if (IsHidden(sptr) && (sptr->umodes & UMODE_SETHOST))
2100 				{
2101 					sendto_one(cptr, ":%s %s %s",
2102 					    nick,
2103 					    (IsToken(cptr) ? TOK_SETHOST :
2104 					    MSG_SETHOST), virthost);
2105 				}
2106 				else if (SupportVHP(cptr))
2107 				{
2108 					sendto_one(cptr, ":%s %s %s",
2109 					    nick,
2110 					    (IsToken(cptr) ? TOK_SETHOST :
2111 					     MSG_SETHOST), (IsHidden(sptr) ? virthost :
2112 					     realhost));
2113 				}
2114 			}
2115 		}
2116 	}
2117 	return;
2118 }
2119 
2120 /*
2121  * sendto_one_nickcmd
2122  *
2123  */
sendto_one_nickcmd(aClient * cptr,aClient * sptr,char * umodes)2124 void sendto_one_nickcmd(aClient *cptr, aClient *sptr, char *umodes)
2125 {
2126 	if (SupportNICKv2(cptr))
2127 	{
2128 		char *vhost;
2129 		if (SupportVHP(cptr))
2130 		{
2131 			if (IsHidden(sptr))
2132 				vhost = sptr->user->virthost;
2133 			else
2134 				vhost = sptr->user->realhost;
2135 		}
2136 		else
2137 		{
2138 			if (IsHidden(sptr) && sptr->umodes & UMODE_SETHOST)
2139 				vhost = sptr->user->virthost;
2140 			else
2141 				vhost = "*";
2142 		}
2143 		if (sptr->srvptr->serv->numeric && SupportNS(cptr))
2144 			sendto_one(cptr,
2145 				(cptr->proto & PROTO_SJB64) ?
2146 			    /* Ugly double %s to prevent excessive spaces */
2147 			    "%s %s %d %B %s %s %b %s %s %s %s%s:%s"
2148 			    :
2149 			    "%s %s %d %lu %s %s %b %s %s %s %s%s:%s"
2150 			    ,
2151 			    (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name,
2152 			    sptr->hopcount+1, (long)sptr->lastnick, sptr->user->username,
2153 			    sptr->user->realhost, (long)(sptr->srvptr->serv->numeric),
2154 			    sptr->user->svid, umodes, vhost,
2155 			    SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2156 			    SupportNICKIP(cptr) ? " " : "", sptr->info);
2157 		else
2158 			sendto_one(cptr,
2159 			    "%s %s %d %d %s %s %s %lu %s %s %s%s:%s",
2160 			    (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name,
2161 			    sptr->hopcount+1, sptr->lastnick, sptr->user->username,
2162 			    sptr->user->realhost, SupportNS(cptr) &&
2163 			    sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric)
2164 			    : sptr->user->server, sptr->user->svid, umodes, vhost,
2165 			    SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2166 			    SupportNICKIP(cptr) ? " " : "", sptr->info);
2167 	}
2168 	else
2169 	{
2170 		sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s",
2171 		    (IsToken(cptr) ? TOK_NICK : MSG_NICK),
2172 		    sptr->name, sptr->hopcount+1, sptr->lastnick, sptr->user->username,
2173 		    sptr->user->realhost, sptr->user->server, sptr->user->svid,
2174 		    sptr->info);
2175 		if (strcmp(umodes, "+"))
2176 		{
2177 			sendto_one(cptr, ":%s %s %s :%s",
2178 			    sptr->name, (IsToken(cptr) ? TOK_MODE :
2179 			    MSG_MODE), sptr->name, umodes);
2180 		}
2181 		if (IsHidden(sptr) && (sptr->umodes & UMODE_SETHOST))
2182 		{
2183 			sendto_one(cptr, ":%s %s %s",
2184 			    sptr->name, (IsToken(cptr) ? TOK_SETHOST :
2185 			    MSG_SETHOST), sptr->user->virthost);
2186 		}
2187 		else if (SupportVHP(cptr))
2188 		{
2189 			sendto_one(cptr, ":%s %s %s", sptr->name,
2190 			    (IsToken(cptr) ? TOK_SETHOST : MSG_SETHOST),
2191 			    (IsHidden(sptr) ? sptr->user->virthost :
2192 			    sptr->user->realhost));
2193 		}
2194 	}
2195 	return;
2196 }
2197 
sendto_message_one(aClient * to,aClient * from,char * sender,char * cmd,char * nick,char * msg)2198 void	sendto_message_one(aClient *to, aClient *from, char *sender,
2199 			char *cmd, char *nick, char *msg)
2200 {
2201         if(IsServer(to->from) && IsToken(to->from)) {
2202           if(*cmd == 'P') cmd = TOK_PRIVATE;
2203           if(*cmd == 'N') cmd = TOK_NOTICE;
2204         }
2205         sendto_prefix_one(to, from, ":%s %s %s :%s",
2206                          sender, cmd, nick, msg);
2207 }
2208 
2209 /* sidenote: sendnotice() and sendtxtnumeric() assume no client or server
2210  * has a % in their nick, which is a safe assumption since % is illegal.
2211  */
2212 
sendnotice(aClient * to,char * pattern,...)2213 void sendnotice(aClient *to, char *pattern, ...)
2214 {
2215 static char realpattern[1024];
2216 va_list vl;
2217 char *name = *to->name ? to->name : "*";
2218 
2219 	if (!IsWebTV(to))
2220 		ircsprintf(realpattern, ":%s NOTICE %s :%s", me.name, name, pattern);
2221 	else
2222 		ircsprintf(realpattern, ":%s PRIVMSG %s :%s", me.name, name, pattern);
2223 
2224 	va_start(vl, pattern);
2225 	vsendto_one(to, realpattern, vl);
2226 	va_end(vl);
2227 }
2228 
sendtxtnumeric(aClient * to,char * pattern,...)2229 void sendtxtnumeric(aClient *to, char *pattern, ...)
2230 {
2231 static char realpattern[1024];
2232 va_list vl;
2233 
2234 	if (!IsWebTV(to))
2235 		ircsprintf(realpattern, ":%s %d %s :%s", me.name, RPL_TEXT, to->name, pattern);
2236 	else
2237 		ircsprintf(realpattern, ":%s PRIVMSG %s :%s", me.name, to->name, pattern);
2238 
2239 	va_start(vl, pattern);
2240 	vsendto_one(to, realpattern, vl);
2241 	va_end(vl);
2242 }
2243