Blob


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.12 2002/11/04 13:26:00 alex Exp $
13 *
14 * irc-write.c: IRC-Texte und Befehle ueber Netzwerk versenden
15 */
18 #include "portab.h"
20 #include "imp.h"
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "conn.h"
27 #include "client.h"
28 #include "channel.h"
29 #include "defines.h"
31 #include "exp.h"
32 #include "irc-write.h"
35 #define SEND_TO_USER 1
36 #define SEND_TO_SERVER 2
39 LOCAL CHAR *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
42 #ifdef PROTOTYPES
43 GLOBAL BOOLEAN
44 IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
45 #else
46 GLOBAL BOOLEAN
47 IRC_WriteStrClient( Client, Format, va_alist )
48 CLIENT *Client;
49 CHAR *Format;
50 va_dcl
51 #endif
52 {
53 CHAR buffer[1000];
54 BOOLEAN ok = CONNECTED;
55 va_list ap;
57 assert( Client != NULL );
58 assert( Format != NULL );
60 #ifdef PROTOTYPES
61 va_start( ap, Format );
62 #else
63 va_start( ap );
64 #endif
65 vsnprintf( buffer, 1000, Format, ap );
66 va_end( ap );
68 /* an den Client selber */
69 ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
71 return ok;
72 } /* IRC_WriteStrClient */
75 #ifdef PROTOTYPES
76 GLOBAL BOOLEAN
77 IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
78 #else
79 GLOBAL BOOLEAN
80 IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
81 CLIENT *Client;
82 CLIENT *Prefix;
83 CHAR *Format;
84 va_dcl
85 #endif
86 {
87 /* Text an Clients, lokal bzw. remote, senden. */
89 CHAR buffer[1000];
90 va_list ap;
92 assert( Client != NULL );
93 assert( Format != NULL );
94 assert( Prefix != NULL );
96 #ifdef PROTOTYPES
97 va_start( ap, Format );
98 #else
99 va_start( ap );
100 #endif
101 vsnprintf( buffer, 1000, Format, ap );
102 va_end( ap );
104 return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
105 } /* IRC_WriteStrClientPrefix */
108 #ifdef PROTOTYPES
109 GLOBAL BOOLEAN
110 IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
111 #else
112 GLOBAL BOOLEAN
113 IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
114 CLIENT *Client;
115 CHANNEL *Chan;
116 BOOLEAN Remote;
117 CHAR *Format;
118 va_dcl
119 #endif
121 CHAR buffer[1000];
122 va_list ap;
124 assert( Client != NULL );
125 assert( Format != NULL );
127 #ifdef PROTOTYPES
128 va_start( ap, Format );
129 #else
130 va_start( ap );
131 #endif
132 vsnprintf( buffer, 1000, Format, ap );
133 va_end( ap );
135 return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
136 } /* IRC_WriteStrChannel */
139 #ifdef PROTOTYPES
140 GLOBAL BOOLEAN
141 IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
142 #else
143 GLOBAL BOOLEAN
144 IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
145 CLIENT *Client;
146 CHANNEL *Chan;
147 CLIENT *Prefix;
148 BOOLEAN Remote;
149 CHAR *Format;
150 va_dcl
151 #endif
153 BOOLEAN ok = CONNECTED;
154 CHAR buffer[1000];
155 CL2CHAN *cl2chan;
156 CONN_ID conn;
157 CLIENT *c;
158 va_list ap;
160 assert( Client != NULL );
161 assert( Chan != NULL );
162 assert( Prefix != NULL );
163 assert( Format != NULL );
165 #ifdef PROTOTYPES
166 va_start( ap, Format );
167 #else
168 va_start( ap );
169 #endif
170 vsnprintf( buffer, 1000, Format, ap );
171 va_end( ap );
173 Conn_ClearFlags( );
175 /* An alle Clients, die in den selben Channels sind.
176 * Dabei aber nur einmal je Remote-Server */
177 cl2chan = Channel_FirstMember( Chan );
178 while( cl2chan )
180 c = Channel_GetClient( cl2chan );
181 if( ! Remote )
183 if( Client_Conn( c ) <= NONE ) c = NULL;
184 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
186 if( c ) c = Client_NextHop( c );
188 if( c && ( c != Client ))
190 /* Ok, anderer Client */
191 conn = Client_Conn( c );
192 if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
193 else Conn_SetFlag( conn, SEND_TO_USER );
195 cl2chan = Channel_NextMember( Chan, cl2chan );
198 /* Senden: alle Verbindungen durchgehen ... */
199 conn = Conn_First( );
200 while( conn != NONE )
202 /* muessen Daten ueber diese Verbindung verschickt werden? */
203 if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
204 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
205 if( ! ok ) break;
207 /* naechste Verbindung testen */
208 conn = Conn_Next( conn );
211 return ok;
212 } /* IRC_WriteStrChannelPrefix */
215 #ifdef PROTOTYPES
216 GLOBAL VOID
217 IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
218 #else
219 GLOBAL VOID
220 IRC_WriteStrServers( ExceptOf, Format, va_alist )
221 CLIENT *ExceptOf;
222 CHAR *Format;
223 va_dcl
224 #endif
226 CHAR buffer[1000];
227 va_list ap;
229 assert( Format != NULL );
231 #ifdef PROTOTYPES
232 va_start( ap, Format );
233 #else
234 va_start( ap );
235 #endif
236 vsnprintf( buffer, 1000, Format, ap );
237 va_end( ap );
239 /* an den Client selber */
240 IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
241 } /* IRC_WriteStrServers */
244 #ifdef PROTOTYPES
245 GLOBAL VOID
246 IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
247 #else
248 GLOBAL VOID
249 IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
250 CLIENT *ExceptOf;
251 CLIENT *Prefix;
252 CHAR *Format;
253 va_dcl
254 #endif
256 CHAR buffer[1000];
257 va_list ap;
259 assert( Format != NULL );
260 assert( Prefix != NULL );
262 #ifdef PROTOTYPES
263 va_start( ap, Format );
264 #else
265 va_start( ap );
266 #endif
267 vsnprintf( buffer, 1000, Format, ap );
268 va_end( ap );
270 IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
271 } /* IRC_WriteStrServersPrefix */
274 #ifdef PROTOTYPES
275 GLOBAL VOID
276 IRC_WriteStrServersPrefixFlag( CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... )
277 #else
278 GLOBAL VOID
279 IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, Flag, Format, va_alist )
280 CLIENT *ExceptOf;
281 CLIENT *Prefix;
282 CHAR Flag;
283 CHAR *Format;
284 va_dcl
285 #endif
287 CHAR buffer[1000];
288 CLIENT *c;
289 va_list ap;
291 assert( Format != NULL );
292 assert( Prefix != NULL );
294 #ifdef PROTOTYPES
295 va_start( ap, Format );
296 #else
297 va_start( ap );
298 #endif
299 vsnprintf( buffer, 1000, Format, ap );
300 va_end( ap );
302 c = Client_First( );
303 while( c )
305 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
307 /* Ziel-Server gefunden. Nun noch pruefen, ob Flags stimmen */
308 if(( Flag == '\0' ) || ( strchr( Client_Flags( c ), Flag ) != NULL )) IRC_WriteStrClientPrefix( c, Prefix, "%s", buffer );
310 c = Client_Next( c );
312 } /* IRC_WriteStrServersPrefixFlag */
315 #ifdef PROTOTYPES
316 GLOBAL BOOLEAN
317 IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
318 #else
319 GLOBAL BOOLEAN
320 IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
321 CLIENT *Client;
322 CLIENT *Prefix;
323 BOOLEAN Remote;
324 CHAR *Format;
325 va_dcl
326 #endif
328 BOOLEAN ok = CONNECTED;
329 CL2CHAN *chan_cl2chan, *cl2chan;
330 CHAR buffer[1000];
331 CHANNEL *chan;
332 CONN_ID conn;
333 va_list ap;
334 CLIENT *c;
336 assert( Client != NULL );
337 assert( Prefix != NULL );
338 assert( Format != NULL );
340 #ifdef PROTOTYPES
341 va_start( ap, Format );
342 #else
343 va_start( ap );
344 #endif
345 vsnprintf( buffer, 1000, Format, ap );
346 va_end( ap );
348 /* initialisieren */
349 Conn_ClearFlags( );
351 /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
352 * den Text schicken. An Remote-Server aber jeweils nur einmal. */
353 chan_cl2chan = Channel_FirstChannelOf( Client );
354 while( chan_cl2chan )
356 /* Channel des Users durchsuchen */
357 chan = Channel_GetChannel( chan_cl2chan );
358 cl2chan = Channel_FirstMember( chan );
359 while( cl2chan )
361 c = Channel_GetClient( cl2chan );
362 if( ! Remote )
364 if( Client_Conn( c ) <= NONE ) c = NULL;
365 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
367 if( c ) c = Client_NextHop( c );
369 if( c && ( c != Client ))
371 /* Ok, anderer Client */
372 conn = Client_Conn( c );
373 if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
374 else Conn_SetFlag( conn, SEND_TO_USER );
376 cl2chan = Channel_NextMember( chan, cl2chan );
379 /* naechsten Channel */
380 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
383 /* Senden: alle Verbindungen durchgehen ... */
384 conn = Conn_First( );
385 while( conn != NONE )
387 /* muessen ueber diese Verbindung Daten gesendet werden? */
388 if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
389 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
390 if( ! ok ) break;
392 /* naechste Verbindung testen */
393 conn = Conn_Next( conn );
395 return ok;
396 } /* IRC_WriteStrRelatedPrefix */
399 LOCAL CHAR *
400 Get_Prefix( CLIENT *Target, CLIENT *Client )
402 assert( Target != NULL );
403 assert( Client != NULL );
405 if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
406 else return Client_Mask( Client );
407 } /* Get_Prefix */
410 /* -eof- */