- Adjusted includes for new "conn-func.h" header.
[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  * 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 static char UNUSED id[] = "$Id: irc-write.c,v 1.14 2002/12/30 17:15:42 alex Exp $";
18
19 #include "imp.h"
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "conn-func.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 #define SEND_TO_USER 1
35 #define SEND_TO_SERVER 2
36
37
38 LOCAL CHAR *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
39
40
41 #ifdef PROTOTYPES
42 GLOBAL BOOLEAN
43 IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
44 #else
45 GLOBAL BOOLEAN
46 IRC_WriteStrClient( Client, Format, va_alist )
47 CLIENT *Client;
48 CHAR *Format;
49 va_dcl
50 #endif
51 {
52         CHAR buffer[1000];
53         BOOLEAN ok = CONNECTED;
54         va_list ap;
55
56         assert( Client != NULL );
57         assert( Format != NULL );
58
59 #ifdef PROTOTYPES
60         va_start( ap, Format );
61 #else
62         va_start( ap );
63 #endif
64         vsnprintf( buffer, 1000, Format, ap );
65         va_end( ap );
66
67         /* an den Client selber */
68         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
69
70         return ok;
71 } /* IRC_WriteStrClient */
72
73
74 #ifdef PROTOTYPES
75 GLOBAL BOOLEAN
76 IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
77 #else
78 GLOBAL BOOLEAN
79 IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
80 CLIENT *Client;
81 CLIENT *Prefix;
82 CHAR *Format;
83 va_dcl
84 #endif
85 {
86         /* Text an Clients, lokal bzw. remote, senden. */
87
88         CHAR buffer[1000];
89         va_list ap;
90
91         assert( Client != NULL );
92         assert( Format != NULL );
93         assert( Prefix != NULL );
94
95 #ifdef PROTOTYPES
96         va_start( ap, Format );
97 #else
98         va_start( ap );
99 #endif
100         vsnprintf( buffer, 1000, Format, ap );
101         va_end( ap );
102
103         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
104 } /* IRC_WriteStrClientPrefix */
105
106
107 #ifdef PROTOTYPES
108 GLOBAL BOOLEAN
109 IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
110 #else
111 GLOBAL BOOLEAN
112 IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
113 CLIENT *Client;
114 CHANNEL *Chan;
115 BOOLEAN Remote;
116 CHAR *Format;
117 va_dcl
118 #endif
119 {
120         CHAR buffer[1000];
121         va_list ap;
122
123         assert( Client != NULL );
124         assert( Format != NULL );
125
126 #ifdef PROTOTYPES
127         va_start( ap, Format );
128 #else
129         va_start( ap );
130 #endif
131         vsnprintf( buffer, 1000, Format, ap );
132         va_end( ap );
133
134         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
135 } /* IRC_WriteStrChannel */
136
137
138 #ifdef PROTOTYPES
139 GLOBAL BOOLEAN
140 IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
141 #else
142 GLOBAL BOOLEAN
143 IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
144 CLIENT *Client;
145 CHANNEL *Chan;
146 CLIENT *Prefix;
147 BOOLEAN Remote;
148 CHAR *Format;
149 va_dcl
150 #endif
151 {
152         BOOLEAN ok = CONNECTED;
153         CHAR buffer[1000];
154         CL2CHAN *cl2chan;
155         CONN_ID conn;
156         CLIENT *c;
157         va_list ap;
158
159         assert( Client != NULL );
160         assert( Chan != NULL );
161         assert( Prefix != NULL );
162         assert( Format != NULL );
163
164 #ifdef PROTOTYPES
165         va_start( ap, Format );
166 #else
167         va_start( ap  );
168 #endif
169         vsnprintf( buffer, 1000, Format, ap );
170         va_end( ap );
171
172         Conn_ClearFlags( );
173
174         /* An alle Clients, die in den selben Channels sind.
175          * Dabei aber nur einmal je Remote-Server */
176         cl2chan = Channel_FirstMember( Chan );
177         while( cl2chan )
178         {
179                 c = Channel_GetClient( cl2chan );
180                 if( ! Remote )
181                 {
182                         if( Client_Conn( c ) <= NONE ) c = NULL;
183                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
184                 }
185                 if( c ) c = Client_NextHop( c );
186                         
187                 if( c && ( c != Client ))
188                 {
189                         /* Ok, anderer Client */
190                         conn = Client_Conn( c );
191                         if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
192                         else Conn_SetFlag( conn, SEND_TO_USER );
193                 }
194                 cl2chan = Channel_NextMember( Chan, cl2chan );
195         }
196
197         /* Senden: alle Verbindungen durchgehen ... */
198         conn = Conn_First( );
199         while( conn != NONE )
200         {
201                 /* muessen Daten ueber diese Verbindung verschickt werden? */
202                 if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
203                 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
204                 if( ! ok ) break;
205
206                 /* naechste Verbindung testen */
207                 conn = Conn_Next( conn );
208         }
209
210         return ok;
211 } /* IRC_WriteStrChannelPrefix */
212
213
214 #ifdef PROTOTYPES
215 GLOBAL VOID
216 IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
217 #else
218 GLOBAL VOID
219 IRC_WriteStrServers( ExceptOf, Format, va_alist )
220 CLIENT *ExceptOf;
221 CHAR *Format;
222 va_dcl
223 #endif
224 {
225         CHAR buffer[1000];
226         va_list ap;
227
228         assert( Format != NULL );
229
230 #ifdef PROTOTYPES
231         va_start( ap, Format );
232 #else
233         va_start( ap );
234 #endif
235         vsnprintf( buffer, 1000, Format, ap );
236         va_end( ap );
237
238         /* an den Client selber */
239         IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
240 } /* IRC_WriteStrServers */
241
242
243 #ifdef PROTOTYPES
244 GLOBAL VOID
245 IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
246 #else
247 GLOBAL VOID
248 IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
249 CLIENT *ExceptOf;
250 CLIENT *Prefix;
251 CHAR *Format;
252 va_dcl
253 #endif
254 {
255         CHAR buffer[1000];
256         va_list ap;
257
258         assert( Format != NULL );
259         assert( Prefix != NULL );
260
261 #ifdef PROTOTYPES
262         va_start( ap, Format );
263 #else
264         va_start( ap );
265 #endif
266         vsnprintf( buffer, 1000, Format, ap );
267         va_end( ap );
268
269         IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
270 } /* IRC_WriteStrServersPrefix */
271         
272
273 #ifdef PROTOTYPES
274 GLOBAL VOID
275 IRC_WriteStrServersPrefixFlag( CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... )
276 #else
277 GLOBAL VOID
278 IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, Flag, Format, va_alist )
279 CLIENT *ExceptOf;
280 CLIENT *Prefix;
281 CHAR Flag;
282 CHAR *Format;
283 va_dcl
284 #endif
285 {
286         CHAR buffer[1000];
287         CLIENT *c;
288         va_list ap;
289         
290         assert( Format != NULL );
291         assert( Prefix != NULL );
292
293 #ifdef PROTOTYPES
294         va_start( ap, Format );
295 #else
296         va_start( ap );
297 #endif
298         vsnprintf( buffer, 1000, Format, ap );
299         va_end( ap );
300         
301         c = Client_First( );
302         while( c )
303         {
304                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
305                 {
306                         /* Ziel-Server gefunden. Nun noch pruefen, ob Flags stimmen */
307                         if(( Flag == '\0' ) || ( strchr( Client_Flags( c ), Flag ) != NULL )) IRC_WriteStrClientPrefix( c, Prefix, "%s", buffer );
308                 }
309                 c = Client_Next( c );
310         }
311 } /* IRC_WriteStrServersPrefixFlag */
312
313
314 #ifdef PROTOTYPES
315 GLOBAL BOOLEAN
316 IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
317 #else
318 GLOBAL BOOLEAN
319 IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
320 CLIENT *Client;
321 CLIENT *Prefix;
322 BOOLEAN Remote;
323 CHAR *Format;
324 va_dcl
325 #endif
326 {
327         BOOLEAN ok = CONNECTED;
328         CL2CHAN *chan_cl2chan, *cl2chan;
329         CHAR buffer[1000];
330         CHANNEL *chan;
331         CONN_ID conn;
332         va_list ap;
333         CLIENT *c;
334
335         assert( Client != NULL );
336         assert( Prefix != NULL );
337         assert( Format != NULL );
338
339 #ifdef PROTOTYPES
340         va_start( ap, Format );
341 #else
342         va_start( ap );
343 #endif
344         vsnprintf( buffer, 1000, Format, ap );
345         va_end( ap );
346
347         /* initialisieren */
348         Conn_ClearFlags( );
349
350         /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
351          * den Text schicken. An Remote-Server aber jeweils nur einmal. */
352         chan_cl2chan = Channel_FirstChannelOf( Client );
353         while( chan_cl2chan )
354         {
355                 /* Channel des Users durchsuchen */
356                 chan = Channel_GetChannel( chan_cl2chan );
357                 cl2chan = Channel_FirstMember( chan );
358                 while( cl2chan )
359                 {
360                         c = Channel_GetClient( cl2chan );
361                         if( ! Remote )
362                         {
363                                 if( Client_Conn( c ) <= NONE ) c = NULL;
364                                 else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
365                         }
366                         if( c ) c = Client_NextHop( c );
367
368                         if( c && ( c != Client ))
369                         {
370                                 /* Ok, anderer Client */
371                                 conn = Client_Conn( c );
372                                 if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
373                                 else Conn_SetFlag( conn, SEND_TO_USER );
374                         }
375                         cl2chan = Channel_NextMember( chan, cl2chan );
376                 }
377                 
378                 /* naechsten Channel */
379                 chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
380         }
381
382         /* Senden: alle Verbindungen durchgehen ... */
383         conn = Conn_First( );
384         while( conn != NONE )
385         {
386                 /* muessen ueber diese Verbindung Daten gesendet werden? */
387                 if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
388                 else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
389                 if( ! ok ) break;
390
391                 /* naechste Verbindung testen */
392                 conn = Conn_Next( conn );
393         }
394         return ok;
395 } /* IRC_WriteStrRelatedPrefix */
396
397
398 LOCAL CHAR *
399 Get_Prefix( CLIENT *Target, CLIENT *Client )
400 {
401         assert( Target != NULL );
402         assert( Client != NULL );
403
404         if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
405         else return Client_Mask( Client );
406 } /* Get_Prefix */
407
408
409 /* -eof- */