]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-write.c
Don't #include client.h when conn.h/conn-func.h is already included
[ngircd-alex.git] / src / ngircd / irc-write.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  *
11  * Sending IRC commands over the network
12  */
13
14
15 #include "portab.h"
16
17 #include "imp.h"
18 #include <assert.h>
19 #ifdef PROTOTYPES
20 #       include <stdarg.h>
21 #else
22 #       include <varargs.h>
23 #endif
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "defines.h"
28 #include "conn-func.h"
29 #include "channel.h"
30
31 #include "exp.h"
32 #include "irc-write.h"
33
34
35 #define SEND_TO_USER 1
36 #define SEND_TO_SERVER 2
37
38
39 static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
40 static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
41                                          CLIENT *Prefix, void *Buffer));
42
43
44 #ifdef PROTOTYPES
45 GLOBAL bool
46 IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
47 #else
48 GLOBAL bool
49 IRC_WriteStrClient( Client, Format, va_alist )
50 CLIENT *Client;
51 const char *Format;
52 va_dcl
53 #endif
54 {
55         char buffer[1000];
56         bool ok = CONNECTED;
57         va_list ap;
58
59         assert( Client != NULL );
60         assert( Format != NULL );
61
62 #ifdef PROTOTYPES
63         va_start( ap, Format );
64 #else
65         va_start( ap );
66 #endif
67         vsnprintf( buffer, 1000, Format, ap );
68         va_end( ap );
69
70         /* to the client itself */
71         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
72
73         return ok;
74 } /* IRC_WriteStrClient */
75
76
77 #ifdef PROTOTYPES
78 GLOBAL bool
79 IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
80 #else
81 GLOBAL bool
82 IRC_WriteStrClientPrefix(Client, Prefix, Format, va_alist)
83 CLIENT *Client;
84 CLIENT *Prefix;
85 const char *Format;
86 va_dcl
87 #endif
88 {
89         /* send text to local and remote clients */
90
91         char buffer[1000];
92         va_list ap;
93
94         assert( Client != NULL );
95         assert( Format != NULL );
96         assert( Prefix != NULL );
97
98 #ifdef PROTOTYPES
99         va_start( ap, Format );
100 #else
101         va_start( ap );
102 #endif
103         vsnprintf( buffer, 1000, Format, ap );
104         va_end( ap );
105
106         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
107 } /* IRC_WriteStrClientPrefix */
108
109
110 #ifdef PROTOTYPES
111 GLOBAL bool
112 IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
113                     const char *Format, ...)
114 #else
115 GLOBAL bool
116 IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
117 CLIENT *Client;
118 CHANNEL *Chan;
119 bool Remote;
120 const char *Format;
121 va_dcl
122 #endif
123 {
124         char buffer[1000];
125         va_list ap;
126
127         assert( Client != NULL );
128         assert( Format != NULL );
129
130 #ifdef PROTOTYPES
131         va_start( ap, Format );
132 #else
133         va_start( ap );
134 #endif
135         vsnprintf( buffer, 1000, Format, ap );
136         va_end( ap );
137
138         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
139 } /* IRC_WriteStrChannel */
140
141
142
143 /**
144  * send message to all clients in the same channel, but only send message
145  * once per remote server.
146  */
147 #ifdef PROTOTYPES
148 GLOBAL bool
149 IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
150                           bool Remote, const char *Format, ...)
151 #else
152 GLOBAL bool
153 IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
154 CLIENT *Client;
155 CHANNEL *Chan;
156 CLIENT *Prefix;
157 bool Remote;
158 const char *Format;
159 va_dcl
160 #endif
161 {
162         bool ok = CONNECTED;
163         char buffer[1000];
164         CL2CHAN *cl2chan;
165         CONN_ID conn;
166         CLIENT *c;
167         va_list ap;
168
169         assert( Client != NULL );
170         assert( Chan != NULL );
171         assert( Prefix != NULL );
172         assert( Format != NULL );
173
174 #ifdef PROTOTYPES
175         va_start( ap, Format );
176 #else
177         va_start( ap  );
178 #endif
179         vsnprintf( buffer, 1000, Format, ap );
180         va_end( ap );
181
182         Conn_ClearFlags( );
183
184         cl2chan = Channel_FirstMember( Chan );
185         while( cl2chan )
186         {
187                 c = Channel_GetClient( cl2chan );
188                 if( ! Remote )
189                 {
190                         if( Client_Conn( c ) <= NONE ) c = NULL;
191                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
192                 }
193                 if( c ) c = Client_NextHop( c );
194
195                 if( c && ( c != Client ))
196                 {
197                         /* Ok, another Client */
198                         conn = Client_Conn( c );
199                         if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
200                         else Conn_SetFlag( conn, SEND_TO_USER );
201                 }
202                 cl2chan = Channel_NextMember( Chan, cl2chan );
203         }
204
205         conn = Conn_First( );
206         while( conn != NONE )
207         {
208                 /* do we need to send data via this connection? */
209                 if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
210                 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
211                 if( ! ok ) break;
212
213                 conn = Conn_Next( conn );
214         }
215
216         return ok;
217 } /* IRC_WriteStrChannelPrefix */
218
219
220 #ifdef PROTOTYPES
221 GLOBAL void
222 IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
223 #else
224 GLOBAL void
225 IRC_WriteStrServers(ExceptOf, Format, va_alist)
226 CLIENT *ExceptOf;
227 const char *Format;
228 va_dcl
229 #endif
230 {
231         char buffer[1000];
232         va_list ap;
233
234         assert( Format != NULL );
235
236 #ifdef PROTOTYPES
237         va_start( ap, Format );
238 #else
239         va_start( ap );
240 #endif
241         vsnprintf( buffer, 1000, Format, ap );
242         va_end( ap );
243
244         IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
245 } /* IRC_WriteStrServers */
246
247
248 #ifdef PROTOTYPES
249 GLOBAL void
250 IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
251                           const char *Format, ...)
252 #else
253 GLOBAL void
254 IRC_WriteStrServersPrefix(ExceptOf, Prefix, Format, va_alist)
255 CLIENT *ExceptOf;
256 CLIENT *Prefix;
257 const char *Format;
258 va_dcl
259 #endif
260 {
261         char buffer[1000];
262         va_list ap;
263
264         assert( Format != NULL );
265         assert( Prefix != NULL );
266
267 #ifdef PROTOTYPES
268         va_start( ap, Format );
269 #else
270         va_start( ap );
271 #endif
272         vsnprintf( buffer, 1000, Format, ap );
273         va_end( ap );
274
275         IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
276 } /* IRC_WriteStrServersPrefix */
277
278
279 #ifdef PROTOTYPES
280 GLOBAL void
281 IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
282                               const char *Format, ...)
283 #else
284 GLOBAL void
285 IRC_WriteStrServersPrefixFlag(ExceptOf, Prefix, Flag, Format, va_alist)
286 CLIENT *ExceptOf;
287 CLIENT *Prefix;
288 char Flag;
289 const char *Format;
290 va_dcl
291 #endif
292 {
293         char buffer[1000];
294         va_list ap;
295
296         assert( Format != NULL );
297         assert( Prefix != NULL );
298
299 #ifdef PROTOTYPES
300         va_start( ap, Format );
301 #else
302         va_start( ap );
303 #endif
304         vsnprintf( buffer, 1000, Format, ap );
305         va_end( ap );
306
307         IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
308                                          cb_writeStrServersPrefixFlag, buffer);
309 } /* IRC_WriteStrServersPrefixFlag */
310
311
312 GLOBAL void
313 IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
314                 void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
315 {
316         CLIENT *c;
317
318         c = Client_First();
319         while(c) {
320                 if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
321                     c != Client_ThisServer() && c != ExceptOf) {
322                         /* Found a target server, do the flags match? */
323                         if (Flag == '\0' || strchr(Client_Flags(c), Flag))
324                                 callback(c, Prefix, cb_data);
325                 }
326                 c = Client_Next(c);
327         }
328 } /* IRC_WriteStrServersPrefixFlag */
329
330
331 /**
332  * send message to all clients that are in the same channels as the client sending this message.
333  * only send message once per reote server.
334  */
335 #ifdef PROTOTYPES
336 GLOBAL bool
337 IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
338                           const char *Format, ...)
339 #else
340 GLOBAL bool
341 IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
342 CLIENT *Client;
343 CLIENT *Prefix;
344 bool Remote;
345 const char *Format;
346 va_dcl
347 #endif
348 {
349         bool ok = CONNECTED;
350         CL2CHAN *chan_cl2chan, *cl2chan;
351         char buffer[1000];
352         CHANNEL *chan;
353         CONN_ID conn;
354         va_list ap;
355         CLIENT *c;
356
357         assert( Client != NULL );
358         assert( Prefix != NULL );
359         assert( Format != NULL );
360
361 #ifdef PROTOTYPES
362         va_start( ap, Format );
363 #else
364         va_start( ap );
365 #endif
366         vsnprintf( buffer, 1000, Format, ap );
367         va_end( ap );
368
369         Conn_ClearFlags( );
370
371         chan_cl2chan = Channel_FirstChannelOf( Client );
372         while( chan_cl2chan )
373         {
374                 chan = Channel_GetChannel( chan_cl2chan );
375                 cl2chan = Channel_FirstMember( chan );
376                 while( cl2chan )
377                 {
378                         c = Channel_GetClient( cl2chan );
379                         if( ! Remote )
380                         {
381                                 if( Client_Conn( c ) <= NONE ) c = NULL;
382                                 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
383                         }
384                         if( c ) c = Client_NextHop( c );
385
386                         if( c && ( c != Client ))
387                         {
388                                 conn = Client_Conn( c );
389                                 if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
390                                 else Conn_SetFlag( conn, SEND_TO_USER );
391                         }
392                         cl2chan = Channel_NextMember( chan, cl2chan );
393                 }
394
395                 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
396         }
397
398         conn = Conn_First( );
399         while( conn != NONE )
400         {
401                 /* send data via this connection? */
402                 if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
403                 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
404                 if( ! ok ) break;
405
406                 conn = Conn_Next( conn );
407         }
408         return ok;
409 } /* IRC_WriteStrRelatedPrefix */
410
411
412 /**
413  * Send WALLOPS message.
414  */
415 #ifdef PROTOTYPES
416 GLOBAL void
417 IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
418 #else
419 GLOBAL void
420 IRC_SendWallops(Client, From, Format, va_alist )
421 CLIENT *Client;
422 CLIENT *From;
423 const char *Format;
424 va_dcl
425 #endif
426 {
427         va_list ap;
428         char msg[1000];
429         CLIENT *to;
430
431 #ifdef PROTOTYPES
432         va_start(ap, Format);
433 #else
434         va_start(ap);
435 #endif
436         vsnprintf(msg, 1000, Format, ap);
437         va_end(ap);
438
439         for (to=Client_First(); to != NULL; to=Client_Next(to)) {
440                 if (Client_Conn(to) == NONE) /* no local connection */
441                         continue;
442
443                 switch (Client_Type(to)) {
444                 case CLIENT_USER:
445                         if (Client_HasMode(to, 'w'))
446                                 IRC_WriteStrClientPrefix(to, From,
447                                                          "WALLOPS :%s", msg);
448                                 break;
449                 case CLIENT_SERVER:
450                         if (to != Client)
451                                 IRC_WriteStrClientPrefix(to, From,
452                                                          "WALLOPS :%s", msg);
453                                 break;
454                 }
455         }
456 } /* IRC_SendWallops */
457
458
459 GLOBAL void
460 IRC_SetPenalty( CLIENT *Client, time_t Seconds )
461 {
462         CONN_ID c;
463
464         assert( Client != NULL );
465         assert( Seconds > 0 );
466
467         if( Client_Type( Client ) == CLIENT_SERVER ) return;
468
469         c = Client_Conn( Client );
470         if (c > NONE)
471                 Conn_SetPenalty(c, Seconds);
472 } /* IRC_SetPenalty */
473
474
475 static const char *
476 Get_Prefix( CLIENT *Target, CLIENT *Client )
477 {
478         assert( Target != NULL );
479         assert( Client != NULL );
480
481         if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
482         else return Client_Mask( Client );
483 } /* Get_Prefix */
484
485
486 static void
487 cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
488 {
489         IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
490 } /* cb_writeStrServersPrefixFlag */
491
492
493 /* -eof- */