02f691d85b6b086539c7532f74ac0f34230f07c3
[ngircd-alex.git] / src / ngircd / irc-write.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
5  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: irc-write.c,v 1.7 2002/09/16 09:19:23 alex Exp $
13  *
14  * irc-write.c: IRC-Texte und Befehle ueber Netzwerk versenden
15  */
16
17
18 #include "portab.h"
19
20 #include "imp.h"
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "conn.h"
27 #include "client.h"
28 #include "channel.h"
29 #include "defines.h"
30
31 #include "exp.h"
32 #include "irc-write.h"
33
34
35 LOCAL CHAR *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
36
37
38 #ifdef PROTOTYPES
39 GLOBAL BOOLEAN
40 IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
41 #else
42 GLOBAL BOOLEAN
43 IRC_WriteStrClient( Client, Format, va_alist )
44 CLIENT *Client;
45 CHAR *Format;
46 va_dcl
47 #endif
48 {
49         CHAR buffer[1000];
50         BOOLEAN ok = CONNECTED;
51         va_list ap;
52
53         assert( Client != NULL );
54         assert( Format != NULL );
55
56 #ifdef PROTOTYPES
57         va_start( ap, Format );
58 #else
59         va_start( ap );
60 #endif
61         vsnprintf( buffer, 1000, Format, ap );
62         va_end( ap );
63
64         /* an den Client selber */
65         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
66
67         return ok;
68 } /* IRC_WriteStrClient */
69
70
71 #ifdef PROTOTYPES
72 GLOBAL BOOLEAN
73 IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
74 #else
75 GLOBAL BOOLEAN
76 IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
77 CLIENT *Client;
78 CLIENT *Prefix;
79 CHAR *Format;
80 va_dcl
81 #endif
82 {
83         /* Text an Clients, lokal bzw. remote, senden. */
84
85         CHAR buffer[1000];
86         va_list ap;
87
88         assert( Client != NULL );
89         assert( Format != NULL );
90         assert( Prefix != NULL );
91
92 #ifdef PROTOTYPES
93         va_start( ap, Format );
94 #else
95         va_start( ap );
96 #endif
97         vsnprintf( buffer, 1000, Format, ap );
98         va_end( ap );
99
100         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
101 } /* IRC_WriteStrClientPrefix */
102
103
104 #ifdef PROTOTYPES
105 GLOBAL BOOLEAN
106 IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
107 #else
108 GLOBAL BOOLEAN
109 IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
110 CLIENT *Client;
111 CHANNEL *Chan;
112 BOOLEAN Remote;
113 CHAR *Format;
114 va_dcl
115 #endif
116 {
117         CHAR buffer[1000];
118         va_list ap;
119
120         assert( Client != NULL );
121         assert( Format != NULL );
122
123 #ifdef PROTOTYPES
124         va_start( ap, Format );
125 #else
126         va_start( ap );
127 #endif
128         vsnprintf( buffer, 1000, Format, ap );
129         va_end( ap );
130
131         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
132 } /* IRC_WriteStrChannel */
133
134
135 #ifdef PROTOTYPES
136 GLOBAL BOOLEAN
137 IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
138 #else
139 GLOBAL BOOLEAN
140 IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
141 CLIENT *Client;
142 CHANNEL *Chan;
143 CLIENT *Prefix;
144 BOOLEAN Remote;
145 CHAR *Format;
146 va_dcl
147 #endif
148 {
149         BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
150         CHAR buffer[1000];
151         CL2CHAN *cl2chan;
152         CLIENT *c;
153         INT s, i;
154         va_list ap;
155
156         assert( Client != NULL );
157         assert( Chan != NULL );
158         assert( Prefix != NULL );
159         assert( Format != NULL );
160
161 #ifdef PROTOTYPES
162         va_start( ap, Format );
163 #else
164         va_start( ap  );
165 #endif
166         vsnprintf( buffer, 1000, Format, ap );
167         va_end( ap );
168
169         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
170
171         /* An alle Clients, die in den selben Channels sind.
172          * Dabei aber nur einmal je Remote-Server */
173         cl2chan = Channel_FirstMember( Chan );
174         while( cl2chan )
175         {
176                 c = Channel_GetClient( cl2chan );
177                 if( ! Remote )
178                 {
179                         if( Client_Conn( c ) <= NONE ) c = NULL;
180                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
181                 }
182                 if( c ) c = Client_NextHop( c );
183                         
184                 if( c && ( c != Client ))
185                 {
186                         /* Ok, anderer Client */
187                         s = Client_Conn( c );
188                         assert( s >= 0 );
189                         assert( s < MAX_CONNECTIONS );
190                         sock[s] = TRUE;
191                         if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
192                         else is_server[s] = FALSE;
193                 }
194                 cl2chan = Channel_NextMember( Chan, cl2chan );
195         }
196
197         /* Senden ... */
198         for( i = 0; i < MAX_CONNECTIONS; i++ )
199         {
200                 if( sock[i] )
201                 {
202                         if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
203                         else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
204                         if( ! ok ) break;
205                 }
206         }
207         return ok;
208 } /* IRC_WriteStrChannelPrefix */
209
210
211 #ifdef PROTOTYPES
212 GLOBAL VOID
213 IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
214 #else
215 GLOBAL VOID
216 IRC_WriteStrServers( ExceptOf, Format, va_alist )
217 CLIENT *ExceptOf;
218 CHAR *Format;
219 va_dcl
220 #endif
221 {
222         CHAR buffer[1000];
223         va_list ap;
224
225         assert( Format != NULL );
226
227 #ifdef PROTOTYPES
228         va_start( ap, Format );
229 #else
230         va_start( ap );
231 #endif
232         vsnprintf( buffer, 1000, Format, ap );
233         va_end( ap );
234
235         /* an den Client selber */
236         IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
237 } /* IRC_WriteStrServers */
238
239
240 #ifdef PROTOTYPES
241 GLOBAL VOID
242 IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
243 #else
244 GLOBAL VOID
245 IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
246 CLIENT *ExceptOf;
247 CLIENT *Prefix;
248 CHAR *Format;
249 va_dcl
250 #endif
251 {
252         CHAR buffer[1000];
253         va_list ap;
254
255         assert( Format != NULL );
256         assert( Prefix != NULL );
257
258 #ifdef PROTOTYPES
259         va_start( ap, Format );
260 #else
261         va_start( ap );
262 #endif
263         vsnprintf( buffer, 1000, Format, ap );
264         va_end( ap );
265
266         return;
267 } /* IRC_WriteStrServersPrefix */
268         
269
270 #ifdef PROTOTYPES
271 GLOBAL VOID
272 IRC_WriteStrServersPrefixFlag( CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... )
273 #else
274 GLOBAL VOID
275 IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, Flag, Format, va_alist )
276 CLIENT *ExceptOf;
277 CLIENT *Prefix;
278 CHAR Flag;
279 CHAR *Format;
280 va_dcl
281 #endif
282 {
283         CHAR buffer[1000];
284         CLIENT *c;
285         va_list ap;
286         
287         assert( Format != NULL );
288         assert( Prefix != NULL );
289
290 #ifdef PROTOTYPES
291         va_start( ap, Format );
292 #else
293         va_start( ap );
294 #endif
295         vsnprintf( buffer, 1000, Format, ap );
296         va_end( ap );
297         
298         c = Client_First( );
299         while( c )
300         {
301                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
302                 {
303                         /* Ziel-Server gefunden. Nun noch pruefen, ob Flags stimmen */
304                         if(( Flag == '\0' ) || ( strchr( Client_Flags( c ), Flag ) != NULL )) IRC_WriteStrClientPrefix( c, Prefix, buffer );
305                 }
306                 c = Client_Next( c );
307         }
308 } /* IRC_WriteStrServersPrefixFlag */
309
310
311 #ifdef PROTOTYPES
312 GLOBAL BOOLEAN
313 IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
314 #else
315 GLOBAL BOOLEAN
316 IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
317 CLIENT *Client;
318 CLIENT *Prefix;
319 BOOLEAN Remote;
320 CHAR *Format;
321 va_dcl
322 #endif
323 {
324         BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
325         CL2CHAN *chan_cl2chan, *cl2chan;
326         CHAR buffer[1000];
327         CHANNEL *chan;
328         va_list ap;
329         CLIENT *c;
330         INT i, s;
331
332         assert( Client != NULL );
333         assert( Prefix != NULL );
334         assert( Format != NULL );
335
336 #ifdef PROTOTYPES
337         va_start( ap, Format );
338 #else
339         va_start( ap );
340 #endif
341         vsnprintf( buffer, 1000, Format, ap );
342         va_end( ap );
343
344         /* initialisieren */
345         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
346
347         /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
348          * den Text schicken. An Remote-Server aber jeweils nur einmal. */
349         chan_cl2chan = Channel_FirstChannelOf( Client );
350         while( chan_cl2chan )
351         {
352                 /* Channel des Users durchsuchen */
353                 chan = Channel_GetChannel( chan_cl2chan );
354                 cl2chan = Channel_FirstMember( chan );
355                 while( cl2chan )
356                 {
357                         c = Channel_GetClient( cl2chan );
358                         if( ! Remote )
359                         {
360                                 if( Client_Conn( c ) <= NONE ) c = NULL;
361                                 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
362                         }
363                         if( c ) c = Client_NextHop( c );
364
365                         if( c && ( c != Client ))
366                         {
367                                 /* Ok, anderer Client */
368                                 s = Client_Conn( c );
369                                 assert( s >= 0 );
370                                 assert( s < MAX_CONNECTIONS );
371                                 sock[s] = TRUE;
372                                 if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
373                                 else is_server[s] = FALSE;
374                         }
375                         cl2chan = Channel_NextMember( chan, cl2chan );
376                 }
377                 
378                 /* naechsten Channel */
379                 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
380         }
381
382         /* Senden ... */
383         for( i = 0; i < MAX_CONNECTIONS; i++ )
384         {
385                 if( sock[i] )
386                 {
387                         if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
388                         else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
389                         if( ! ok ) break;
390                 }
391         }
392         return ok;
393 } /* IRC_WriteStrRelatedPrefix */
394
395
396 LOCAL CHAR *
397 Get_Prefix( CLIENT *Target, CLIENT *Client )
398 {
399         assert( Target != NULL );
400         assert( Client != NULL );
401
402         if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
403         else return Client_Mask( Client );
404 } /* Get_Prefix */
405
406
407 /* -eof- */