]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-write.c
- JOIN: Invite- und Ban-Lists werden nun beachtet.
[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.5 2002/05/30 16:52:21 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
25 #include "conn.h"
26 #include "client.h"
27 #include "channel.h"
28 #include "defines.h"
29
30 #include "exp.h"
31 #include "irc-write.h"
32
33
34 LOCAL CHAR *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
35
36
37 #ifdef PROTOTYPES
38 GLOBAL BOOLEAN
39 IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
40 #else
41 GLOBAL BOOLEAN
42 IRC_WriteStrClient( Client, Format, va_alist )
43 CLIENT *Client;
44 CHAR *Format;
45 va_dcl
46 #endif
47 {
48         CHAR buffer[1000];
49         BOOLEAN ok = CONNECTED;
50         va_list ap;
51
52         assert( Client != NULL );
53         assert( Format != NULL );
54
55 #ifdef PROTOTYPES
56         va_start( ap, Format );
57 #else
58         va_start( ap );
59 #endif
60         vsnprintf( buffer, 1000, Format, ap );
61         va_end( ap );
62
63         /* an den Client selber */
64         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
65
66         return ok;
67 } /* IRC_WriteStrClient */
68
69
70 #ifdef PROTOTYPES
71 GLOBAL BOOLEAN
72 IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
73 #else
74 GLOBAL BOOLEAN
75 IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
76 CLIENT *Client;
77 CLIENT *Prefix;
78 CHAR *Format;
79 va_dcl
80 #endif
81 {
82         /* Text an Clients, lokal bzw. remote, senden. */
83
84         CHAR buffer[1000];
85         va_list ap;
86
87         assert( Client != NULL );
88         assert( Format != NULL );
89         assert( Prefix != NULL );
90
91 #ifdef PROTOTYPES
92         va_start( ap, Format );
93 #else
94         va_start( ap );
95 #endif
96         vsnprintf( buffer, 1000, Format, ap );
97         va_end( ap );
98
99         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
100 } /* IRC_WriteStrClientPrefix */
101
102
103 #ifdef PROTOTYPES
104 GLOBAL BOOLEAN
105 IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
106 #else
107 GLOBAL BOOLEAN
108 IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
109 CLIENT *Client;
110 CHANNEL *Chan;
111 BOOLEAN Remote;
112 CHAR *Format;
113 va_dcl
114 #endif
115 {
116         CHAR buffer[1000];
117         va_list ap;
118
119         assert( Client != NULL );
120         assert( Format != NULL );
121
122 #ifdef PROTOTYPES
123         va_start( ap, Format );
124 #else
125         va_start( ap );
126 #endif
127         vsnprintf( buffer, 1000, Format, ap );
128         va_end( ap );
129
130         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
131 } /* IRC_WriteStrChannel */
132
133
134 #ifdef PROTOTYPES
135 GLOBAL BOOLEAN
136 IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
137 #else
138 GLOBAL BOOLEAN
139 IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
140 CLIENT *Client;
141 CHANNEL *Chan;
142 CLIENT *Prefix;
143 BOOLEAN Remote;
144 CHAR *Format;
145 va_dcl
146 #endif
147 {
148         BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
149         CHAR buffer[1000];
150         CL2CHAN *cl2chan;
151         CLIENT *c;
152         INT s, i;
153         va_list ap;
154
155         assert( Client != NULL );
156         assert( Chan != NULL );
157         assert( Prefix != NULL );
158         assert( Format != NULL );
159
160 #ifdef PROTOTYPES
161         va_start( ap, Format );
162 #else
163         va_start( ap  );
164 #endif
165         vsnprintf( buffer, 1000, Format, ap );
166         va_end( ap );
167
168         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
169
170         /* An alle Clients, die in den selben Channels sind.
171          * Dabei aber nur einmal je Remote-Server */
172         cl2chan = Channel_FirstMember( Chan );
173         while( cl2chan )
174         {
175                 c = Channel_GetClient( cl2chan );
176                 if( ! Remote )
177                 {
178                         if( Client_Conn( c ) <= NONE ) c = NULL;
179                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
180                 }
181                 if( c ) c = Client_NextHop( c );
182                         
183                 if( c && ( c != Client ))
184                 {
185                         /* Ok, anderer Client */
186                         s = Client_Conn( c );
187                         assert( s >= 0 );
188                         assert( s < MAX_CONNECTIONS );
189                         sock[s] = TRUE;
190                         if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
191                         else is_server[s] = FALSE;
192                 }
193                 cl2chan = Channel_NextMember( Chan, cl2chan );
194         }
195
196         /* Senden ... */
197         for( i = 0; i < MAX_CONNECTIONS; i++ )
198         {
199                 if( sock[i] )
200                 {
201                         if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
202                         else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
203                         if( ! ok ) break;
204                 }
205         }
206         return ok;
207 } /* IRC_WriteStrChannelPrefix */
208
209
210 #ifdef PROTOTYPES
211 GLOBAL VOID
212 IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
213 #else
214 GLOBAL VOID
215 IRC_WriteStrServers( ExceptOf, Format, va_alist )
216 CLIENT *ExceptOf;
217 CHAR *Format;
218 va_dcl
219 #endif
220 {
221         CHAR buffer[1000];
222         va_list ap;
223
224         assert( Format != NULL );
225
226 #ifdef PROTOTYPES
227         va_start( ap, Format );
228 #else
229         va_start( ap );
230 #endif
231         vsnprintf( buffer, 1000, Format, ap );
232         va_end( ap );
233
234         /* an den Client selber */
235         IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
236 } /* IRC_WriteStrServers */
237
238
239 #ifdef PROTOTYPES
240 GLOBAL VOID
241 IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
242 #else
243 GLOBAL VOID
244 IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
245 CLIENT *ExceptOf;
246 CLIENT *Prefix;
247 CHAR *Format;
248 va_dcl
249 #endif
250 {
251         CHAR buffer[1000];
252         CLIENT *c;
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         c = Client_First( );
267         while( c )
268         {
269                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
270                 {
271                         /* Ziel-Server gefunden */
272                         IRC_WriteStrClientPrefix( c, Prefix, buffer );
273                 }
274                 c = Client_Next( c );
275         }
276 } /* IRC_WriteStrServersPrefix */
277
278
279 #ifdef PROTOTYPES
280 GLOBAL BOOLEAN
281 IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
282 #else
283 GLOBAL BOOLEAN
284 IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
285 CLIENT *Client;
286 CLIENT *Prefix;
287 BOOLEAN Remote;
288 CHAR *Format;
289 va_dcl
290 #endif
291 {
292         BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
293         CL2CHAN *chan_cl2chan, *cl2chan;
294         CHAR buffer[1000];
295         CHANNEL *chan;
296         va_list ap;
297         CLIENT *c;
298         INT i, s;
299
300         assert( Client != NULL );
301         assert( Prefix != NULL );
302         assert( Format != NULL );
303
304 #ifdef PROTOTYPES
305         va_start( ap, Format );
306 #else
307         va_start( ap );
308 #endif
309         vsnprintf( buffer, 1000, Format, ap );
310         va_end( ap );
311
312         /* initialisieren */
313         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
314
315         /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
316          * den Text schicken. An Remote-Server aber jeweils nur einmal. */
317         chan_cl2chan = Channel_FirstChannelOf( Client );
318         while( chan_cl2chan )
319         {
320                 /* Channel des Users durchsuchen */
321                 chan = Channel_GetChannel( chan_cl2chan );
322                 cl2chan = Channel_FirstMember( chan );
323                 while( cl2chan )
324                 {
325                         c = Channel_GetClient( cl2chan );
326                         if( ! Remote )
327                         {
328                                 if( Client_Conn( c ) <= NONE ) c = NULL;
329                                 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
330                         }
331                         if( c ) c = Client_NextHop( c );
332
333                         if( c && ( c != Client ))
334                         {
335                                 /* Ok, anderer Client */
336                                 s = Client_Conn( c );
337                                 assert( s >= 0 );
338                                 assert( s < MAX_CONNECTIONS );
339                                 sock[s] = TRUE;
340                                 if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
341                                 else is_server[s] = FALSE;
342                         }
343                         cl2chan = Channel_NextMember( chan, cl2chan );
344                 }
345                 
346                 /* naechsten Channel */
347                 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
348         }
349
350         /* Senden ... */
351         for( i = 0; i < MAX_CONNECTIONS; i++ )
352         {
353                 if( sock[i] )
354                 {
355                         if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
356                         else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
357                         if( ! ok ) break;
358                 }
359         }
360         return ok;
361 } /* IRC_WriteStrRelatedPrefix */
362
363
364 LOCAL CHAR *
365 Get_Prefix( CLIENT *Target, CLIENT *Client )
366 {
367         assert( Target != NULL );
368         assert( Client != NULL );
369
370         if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
371         else return Client_Mask( Client );
372 } /* Get_Prefix */
373
374
375 /* -eof- */