2 38b9cb88 2001-12-14 alex * ngIRCd -- The Next Generation IRC Daemon
3 1547f76c 2002-01-02 alex * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
5 38b9cb88 2001-12-14 alex * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6 38b9cb88 2001-12-14 alex * der GNU General Public License (GPL), wie von der Free Software Foundation
7 38b9cb88 2001-12-14 alex * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8 38b9cb88 2001-12-14 alex * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9 38b9cb88 2001-12-14 alex * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10 804b1ec4 2001-12-31 alex * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
12 0e38d10b 2002-03-25 alex * $Id: channel.c,v 1.20 2002/03/25 16:54:26 alex Exp $
14 38b9cb88 2001-12-14 alex * channel.c: Management der Channels
18 8a324b6d 2002-01-26 alex #define __channel_c__
21 ca33cbda 2002-03-12 alex #include "portab.h"
23 ca33cbda 2002-03-12 alex #include "imp.h"
24 38b9cb88 2001-12-14 alex #include <assert.h>
25 bb19cfda 2002-01-21 alex #include <stdlib.h>
26 bb19cfda 2002-01-21 alex #include <string.h>
28 bb19cfda 2002-01-21 alex #include "client.h"
29 0e38d10b 2002-03-25 alex #include "hash.h"
30 ff54198f 2002-02-27 alex #include "irc-write.h"
31 bb19cfda 2002-01-21 alex #include "log.h"
32 bb19cfda 2002-01-21 alex #include "messages.h"
34 ca33cbda 2002-03-12 alex #include "exp.h"
35 38b9cb88 2001-12-14 alex #include "channel.h"
38 38b9cb88 2001-12-14 alex LOCAL CHANNEL *My_Channels;
39 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *My_Cl2Chan;
42 bb19cfda 2002-01-21 alex LOCAL CHANNEL *New_Chan( CHAR *Name );
43 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client );
44 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client );
45 d569c924 2002-01-27 alex LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART );
46 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan );
47 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan );
48 bb19cfda 2002-01-21 alex LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan );
51 38b9cb88 2001-12-14 alex GLOBAL VOID Channel_Init( VOID )
53 38b9cb88 2001-12-14 alex My_Channels = NULL;
54 bb19cfda 2002-01-21 alex My_Cl2Chan = NULL;
55 38b9cb88 2001-12-14 alex } /* Channel_Init */
58 38b9cb88 2001-12-14 alex GLOBAL VOID Channel_Exit( VOID )
60 bb19cfda 2002-01-21 alex CHANNEL *c, *c_next;
61 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan, *cl2chan_next;
63 bb19cfda 2002-01-21 alex /* Channel-Strukturen freigeben */
64 bb19cfda 2002-01-21 alex c = My_Channels;
67 bb19cfda 2002-01-21 alex c_next = c->next;
72 bb19cfda 2002-01-21 alex /* Channel-Zuordnungstabelle freigeben */
73 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
76 bb19cfda 2002-01-21 alex cl2chan_next = cl2chan->next;
77 bb19cfda 2002-01-21 alex free( cl2chan );
78 bb19cfda 2002-01-21 alex cl2chan = cl2chan_next;
80 38b9cb88 2001-12-14 alex } /* Channel_Exit */
83 bb19cfda 2002-01-21 alex GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name )
85 bb19cfda 2002-01-21 alex CHANNEL *chan;
87 bb19cfda 2002-01-21 alex assert( Client != NULL );
88 bb19cfda 2002-01-21 alex assert( Name != NULL );
90 bb19cfda 2002-01-21 alex /* Valider Channel-Name? */
91 f53914b1 2002-02-06 alex if( ! Channel_IsValidName( Name ))
93 bb19cfda 2002-01-21 alex IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
94 bb19cfda 2002-01-21 alex return FALSE;
97 bb19cfda 2002-01-21 alex /* Channel suchen */
98 8a324b6d 2002-01-26 alex chan = Channel_Search( Name );
101 bb19cfda 2002-01-21 alex /* Ist der Client bereits Mitglied? */
102 bb19cfda 2002-01-21 alex if( Get_Cl2Chan( chan, Client )) return FALSE;
106 bb19cfda 2002-01-21 alex /* Gibt es noch nicht? Dann neu anlegen: */
107 bb19cfda 2002-01-21 alex chan = New_Chan( Name );
108 bb19cfda 2002-01-21 alex if( ! chan ) return FALSE;
110 bb19cfda 2002-01-21 alex /* Verketten */
111 bb19cfda 2002-01-21 alex chan->next = My_Channels;
112 bb19cfda 2002-01-21 alex My_Channels = chan;
115 bb19cfda 2002-01-21 alex /* User dem Channel hinzufuegen */
116 bb19cfda 2002-01-21 alex if( ! Add_Client( chan, Client )) return FALSE;
117 bb19cfda 2002-01-21 alex else return TRUE;
118 bb19cfda 2002-01-21 alex } /* Channel_Join */
121 bb19cfda 2002-01-21 alex GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason )
123 bb19cfda 2002-01-21 alex CHANNEL *chan;
125 bb19cfda 2002-01-21 alex assert( Client != NULL );
126 bb19cfda 2002-01-21 alex assert( Name != NULL );
128 bb19cfda 2002-01-21 alex /* Channel suchen */
129 8a324b6d 2002-01-26 alex chan = Channel_Search( Name );
130 bb19cfda 2002-01-21 alex if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
132 bb19cfda 2002-01-21 alex IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
133 bb19cfda 2002-01-21 alex return FALSE;
136 bb19cfda 2002-01-21 alex /* User aus Channel entfernen */
137 d569c924 2002-01-27 alex if( ! Remove_Client( chan, Client, Origin, Reason, TRUE )) return FALSE;
138 bb19cfda 2002-01-21 alex else return TRUE;
139 bb19cfda 2002-01-21 alex } /* Channel_Part */
142 bb19cfda 2002-01-21 alex GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason )
144 bb19cfda 2002-01-21 alex CHANNEL *c, *next_c;
146 bb19cfda 2002-01-21 alex assert( Client != NULL );
148 bb19cfda 2002-01-21 alex c = My_Channels;
151 bb19cfda 2002-01-21 alex next_c = c->next;
152 d569c924 2002-01-27 alex Remove_Client( c, Client, Client_ThisServer( ), Reason, FALSE );
153 bb19cfda 2002-01-21 alex c = next_c;
155 bb19cfda 2002-01-21 alex } /* Channel_RemoveClient */
158 56823924 2002-01-16 alex GLOBAL INT Channel_Count( VOID )
160 bb19cfda 2002-01-21 alex CHANNEL *c;
164 bb19cfda 2002-01-21 alex c = My_Channels;
168 bb19cfda 2002-01-21 alex c = c->next;
170 bb19cfda 2002-01-21 alex return count;
171 56823924 2002-01-16 alex } /* Channel_Count */
174 71c7a6fc 2002-01-28 alex GLOBAL CHAR *Channel_Name( CHANNEL *Chan )
176 71c7a6fc 2002-01-28 alex assert( Chan != NULL );
177 71c7a6fc 2002-01-28 alex return Chan->name;
178 71c7a6fc 2002-01-28 alex } /* Channel_Name */
181 f53914b1 2002-02-06 alex GLOBAL CHAR *Channel_Modes( CHANNEL *Chan )
183 f53914b1 2002-02-06 alex assert( Chan != NULL );
184 f53914b1 2002-02-06 alex return Chan->modes;
185 f53914b1 2002-02-06 alex } /* Channel_Modes */
188 71c7a6fc 2002-01-28 alex GLOBAL CHANNEL *Channel_First( VOID )
190 71c7a6fc 2002-01-28 alex return My_Channels;
191 71c7a6fc 2002-01-28 alex } /* Channel_First */
194 71c7a6fc 2002-01-28 alex GLOBAL CHANNEL *Channel_Next( CHANNEL *Chan )
196 71c7a6fc 2002-01-28 alex assert( Chan != NULL );
197 71c7a6fc 2002-01-28 alex return Chan->next;
198 71c7a6fc 2002-01-28 alex } /* Channel_Next */
201 8a324b6d 2002-01-26 alex GLOBAL CHANNEL *Channel_Search( CHAR *Name )
203 bb19cfda 2002-01-21 alex /* Channel-Struktur suchen */
205 bb19cfda 2002-01-21 alex CHANNEL *c;
206 0e38d10b 2002-03-25 alex UINT32 search_hash;
208 bb19cfda 2002-01-21 alex assert( Name != NULL );
210 0e38d10b 2002-03-25 alex search_hash = Hash( Name );
211 bb19cfda 2002-01-21 alex c = My_Channels;
214 0e38d10b 2002-03-25 alex if( search_hash == c->hash )
216 0e38d10b 2002-03-25 alex /* lt. Hash-Wert: Treffer! */
217 0e38d10b 2002-03-25 alex if( strcasecmp( Name, c->name ) == 0 ) return c;
219 bb19cfda 2002-01-21 alex c = c->next;
221 bb19cfda 2002-01-21 alex return NULL;
222 8a324b6d 2002-01-26 alex } /* Channel_Search */
225 8a324b6d 2002-01-26 alex GLOBAL CL2CHAN *Channel_FirstMember( CHANNEL *Chan )
227 8a324b6d 2002-01-26 alex assert( Chan != NULL );
228 8a324b6d 2002-01-26 alex return Get_First_Cl2Chan( NULL, Chan );
229 0bb9db1a 2002-01-29 alex } /* Channel_FirstMember */
232 8a324b6d 2002-01-26 alex GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
234 8a324b6d 2002-01-26 alex assert( Chan != NULL );
235 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
236 8a324b6d 2002-01-26 alex return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
237 8a324b6d 2002-01-26 alex } /* Channel_NextMember */
240 0bb9db1a 2002-01-29 alex GLOBAL CL2CHAN *Channel_FirstChannelOf( CLIENT *Client )
242 0bb9db1a 2002-01-29 alex assert( Client != NULL );
243 0bb9db1a 2002-01-29 alex return Get_First_Cl2Chan( Client, NULL );
244 0bb9db1a 2002-01-29 alex } /* Channel_FirstChannelOf */
247 0bb9db1a 2002-01-29 alex GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
249 0bb9db1a 2002-01-29 alex assert( Client != NULL );
250 0bb9db1a 2002-01-29 alex assert( Cl2Chan != NULL );
251 0bb9db1a 2002-01-29 alex return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
252 0bb9db1a 2002-01-29 alex } /* Channel_NextChannelOf */
255 8a324b6d 2002-01-26 alex GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan )
257 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
258 8a324b6d 2002-01-26 alex return Cl2Chan->client;
259 8a324b6d 2002-01-26 alex } /* Channel_GetClient */
262 8a324b6d 2002-01-26 alex GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan )
264 8a324b6d 2002-01-26 alex assert( Cl2Chan != NULL );
265 8a324b6d 2002-01-26 alex return Cl2Chan->channel;
266 8a324b6d 2002-01-26 alex } /* Channel_GetChannel */
269 f53914b1 2002-02-06 alex GLOBAL BOOLEAN Channel_IsValidName( CHAR *Name )
271 f53914b1 2002-02-06 alex /* PrŸfen, ob Name als Channelname gueltig */
273 7157d936 2002-03-02 alex CHAR *ptr, badchars[] = " ,:\x07";
275 f53914b1 2002-02-06 alex assert( Name != NULL );
277 f53914b1 2002-02-06 alex if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return FALSE;
279 7157d936 2002-03-02 alex ptr = Name;
280 7157d936 2002-03-02 alex while( *ptr )
282 7157d936 2002-03-02 alex if( strchr( badchars, *ptr )) return FALSE;
286 f53914b1 2002-02-06 alex return TRUE;
287 f53914b1 2002-02-06 alex } /* Channel_IsValidName */
290 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_ModeAdd( CHANNEL *Chan, CHAR Mode )
292 d72c55a0 2002-02-11 alex /* Mode soll gesetzt werden. TRUE wird geliefert, wenn der
293 d72c55a0 2002-02-11 alex * Mode neu gesetzt wurde, FALSE, wenn der Channel den Mode
294 d72c55a0 2002-02-11 alex * bereits hatte. */
298 d72c55a0 2002-02-11 alex assert( Chan != NULL );
300 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
301 d72c55a0 2002-02-11 alex if( ! strchr( Chan->modes, x[0] ))
303 d72c55a0 2002-02-11 alex /* Client hat den Mode noch nicht -> setzen */
304 d72c55a0 2002-02-11 alex strcat( Chan->modes, x );
305 d72c55a0 2002-02-11 alex return TRUE;
307 d72c55a0 2002-02-11 alex else return FALSE;
308 d72c55a0 2002-02-11 alex } /* Channel_ModeAdd */
311 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_ModeDel( CHANNEL *Chan, CHAR Mode )
313 d72c55a0 2002-02-11 alex /* Mode soll geloescht werden. TRUE wird geliefert, wenn der
314 d72c55a0 2002-02-11 alex * Mode entfernt wurde, FALSE, wenn der Channel den Mode
315 d72c55a0 2002-02-11 alex * ueberhaupt nicht hatte. */
317 d72c55a0 2002-02-11 alex CHAR x[2], *p;
319 d72c55a0 2002-02-11 alex assert( Chan != NULL );
321 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
323 d72c55a0 2002-02-11 alex p = strchr( Chan->modes, x[0] );
324 d72c55a0 2002-02-11 alex if( ! p ) return FALSE;
326 d72c55a0 2002-02-11 alex /* Client hat den Mode -> loeschen */
327 d72c55a0 2002-02-11 alex while( *p )
329 d72c55a0 2002-02-11 alex *p = *(p + 1);
332 d72c55a0 2002-02-11 alex return TRUE;
333 d72c55a0 2002-02-11 alex } /* Channel_ModeDel */
336 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
338 d72c55a0 2002-02-11 alex /* Channel-User-Mode soll gesetzt werden. TRUE wird geliefert,
339 d72c55a0 2002-02-11 alex * wenn der Mode neu gesetzt wurde, FALSE, wenn der User den
340 d72c55a0 2002-02-11 alex * Channel-Mode bereits hatte. */
342 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
345 d72c55a0 2002-02-11 alex assert( Chan != NULL );
346 d72c55a0 2002-02-11 alex assert( Client != NULL );
348 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
349 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
351 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
352 d72c55a0 2002-02-11 alex if( ! strchr( cl2chan->modes, x[0] ))
354 d72c55a0 2002-02-11 alex /* Client hat den Mode noch nicht -> setzen */
355 d72c55a0 2002-02-11 alex strcat( cl2chan->modes, x );
356 d72c55a0 2002-02-11 alex return TRUE;
358 d72c55a0 2002-02-11 alex else return FALSE;
359 d72c55a0 2002-02-11 alex } /* Channel_UserModeAdd */
362 d72c55a0 2002-02-11 alex GLOBAL BOOLEAN Channel_UserModeDel( CHANNEL *Chan, CLIENT *Client, CHAR Mode )
364 d72c55a0 2002-02-11 alex /* Channel-User-Mode soll geloescht werden. TRUE wird geliefert,
365 d72c55a0 2002-02-11 alex * wenn der Mode entfernt wurde, FALSE, wenn der User den Channel-Mode
366 d72c55a0 2002-02-11 alex * ueberhaupt nicht hatte. */
368 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
369 d72c55a0 2002-02-11 alex CHAR x[2], *p;
371 d72c55a0 2002-02-11 alex assert( Chan != NULL );
372 d72c55a0 2002-02-11 alex assert( Client != NULL );
374 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
375 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
377 d72c55a0 2002-02-11 alex x[0] = Mode; x[1] = '\0';
379 d72c55a0 2002-02-11 alex p = strchr( cl2chan->modes, x[0] );
380 d72c55a0 2002-02-11 alex if( ! p ) return FALSE;
382 d72c55a0 2002-02-11 alex /* Client hat den Mode -> loeschen */
383 d72c55a0 2002-02-11 alex while( *p )
385 d72c55a0 2002-02-11 alex *p = *(p + 1);
388 d72c55a0 2002-02-11 alex return TRUE;
389 d72c55a0 2002-02-11 alex } /* Channel_UserModeDel */
392 d72c55a0 2002-02-11 alex GLOBAL CHAR *Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
394 d72c55a0 2002-02-11 alex /* Channel-Modes eines Users liefern */
396 d72c55a0 2002-02-11 alex CL2CHAN *cl2chan;
398 d72c55a0 2002-02-11 alex assert( Chan != NULL );
399 d72c55a0 2002-02-11 alex assert( Client != NULL );
401 d72c55a0 2002-02-11 alex cl2chan = Get_Cl2Chan( Chan, Client );
402 d72c55a0 2002-02-11 alex assert( cl2chan != NULL );
404 d72c55a0 2002-02-11 alex return cl2chan->modes;
405 d72c55a0 2002-02-11 alex } /* Channel_UserModes */
408 153aa0aa 2002-02-27 alex GLOBAL BOOLEAN Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
410 153aa0aa 2002-02-27 alex /* Pruefen, ob Client Mitglied in Channel ist */
412 153aa0aa 2002-02-27 alex assert( Chan != NULL );
413 153aa0aa 2002-02-27 alex assert( Client != NULL );
415 153aa0aa 2002-02-27 alex if( Get_Cl2Chan( Chan, Client )) return TRUE;
416 153aa0aa 2002-02-27 alex else return FALSE;
417 153aa0aa 2002-02-27 alex } /* Channel_IsMemberOf */
420 52548bd3 2002-02-27 alex GLOBAL CHAR *Channel_Topic( CHANNEL *Chan )
422 52548bd3 2002-02-27 alex assert( Chan != NULL );
423 52548bd3 2002-02-27 alex return Chan->topic;
424 52548bd3 2002-02-27 alex } /* Channel_Topic */
427 52548bd3 2002-02-27 alex GLOBAL VOID Channel_SetTopic( CHANNEL *Chan, CHAR *Topic )
429 52548bd3 2002-02-27 alex assert( Chan != NULL );
430 52548bd3 2002-02-27 alex assert( Topic != NULL );
432 10363b39 2002-03-03 alex strncpy( Chan->topic, Topic, CHANNEL_TOPIC_LEN - 1 );
433 52548bd3 2002-02-27 alex Chan->topic[CHANNEL_TOPIC_LEN - 1] = '\0';
434 52548bd3 2002-02-27 alex } /* Channel_SetTopic */
437 0e38d10b 2002-03-25 alex GLOBAL BOOLEAN Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text )
439 0e38d10b 2002-03-25 alex BOOLEAN is_member, has_voice, is_op, ok;
441 0e38d10b 2002-03-25 alex /* Okay, Ziel ist ein Channel */
442 0e38d10b 2002-03-25 alex is_member = has_voice = is_op = FALSE;
443 0e38d10b 2002-03-25 alex if( Channel_IsMemberOf( Chan, From ))
445 0e38d10b 2002-03-25 alex is_member = TRUE;
446 0e38d10b 2002-03-25 alex if( strchr( Channel_UserModes( Chan, From ), 'v' )) has_voice = TRUE;
447 0e38d10b 2002-03-25 alex if( strchr( Channel_UserModes( Chan, From ), 'o' )) is_op = TRUE;
450 0e38d10b 2002-03-25 alex /* pruefen, ob Client in Channel schreiben darf */
452 0e38d10b 2002-03-25 alex if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = FALSE;
453 0e38d10b 2002-03-25 alex if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = FALSE;
455 0e38d10b 2002-03-25 alex if( ! ok ) return IRC_WriteStrClient( From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( From ), Channel_Name( Chan ));
457 0e38d10b 2002-03-25 alex /* Text senden */
458 0e38d10b 2002-03-25 alex if( Client_Conn( From ) > NONE ) Conn_UpdateIdle( Client_Conn( From ));
459 0e38d10b 2002-03-25 alex return IRC_WriteStrChannelPrefix( Client, Chan, From, TRUE, "PRIVMSG %s :%s", Channel_Name( Chan ), Text );
460 0e38d10b 2002-03-25 alex } /* Channel_Write */
464 bb19cfda 2002-01-21 alex LOCAL CHANNEL *New_Chan( CHAR *Name )
466 bb19cfda 2002-01-21 alex /* Neue Channel-Struktur anlegen */
468 bb19cfda 2002-01-21 alex CHANNEL *c;
470 bb19cfda 2002-01-21 alex assert( Name != NULL );
472 bb19cfda 2002-01-21 alex c = malloc( sizeof( CHANNEL ));
475 bb19cfda 2002-01-21 alex Log( LOG_EMERG, "Can't allocate memory!" );
476 bb19cfda 2002-01-21 alex return NULL;
478 bb19cfda 2002-01-21 alex c->next = NULL;
479 10363b39 2002-03-03 alex strncpy( c->name, Name, CHANNEL_NAME_LEN - 1 );
480 bb19cfda 2002-01-21 alex c->name[CHANNEL_NAME_LEN - 1] = '\0';
481 bb19cfda 2002-01-21 alex strcpy( c->modes, "" );
482 52548bd3 2002-02-27 alex strcpy( c->topic, "" );
483 0e38d10b 2002-03-25 alex c->hash = Hash( c->name );
485 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
488 bb19cfda 2002-01-21 alex } /* New_Chan */
491 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
493 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
495 bb19cfda 2002-01-21 alex assert( Chan != NULL );
496 bb19cfda 2002-01-21 alex assert( Client != NULL );
498 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
499 bb19cfda 2002-01-21 alex while( cl2chan )
501 bb19cfda 2002-01-21 alex if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
502 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
504 bb19cfda 2002-01-21 alex return NULL;
505 bb19cfda 2002-01-21 alex } /* Get_Cl2Chan */
508 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client )
510 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
512 bb19cfda 2002-01-21 alex assert( Chan != NULL );
513 bb19cfda 2002-01-21 alex assert( Client != NULL );
515 d72c55a0 2002-02-11 alex /* neue CL2CHAN-Struktur anlegen */
516 bb19cfda 2002-01-21 alex cl2chan = malloc( sizeof( CL2CHAN ));
517 bb19cfda 2002-01-21 alex if( ! cl2chan )
519 bb19cfda 2002-01-21 alex Log( LOG_EMERG, "Can't allocate memory!" );
520 bb19cfda 2002-01-21 alex return NULL;
522 bb19cfda 2002-01-21 alex cl2chan->channel = Chan;
523 bb19cfda 2002-01-21 alex cl2chan->client = Client;
524 d72c55a0 2002-02-11 alex strcpy( cl2chan->modes, "" );
526 bb19cfda 2002-01-21 alex /* Verketten */
527 bb19cfda 2002-01-21 alex cl2chan->next = My_Cl2Chan;
528 bb19cfda 2002-01-21 alex My_Cl2Chan = cl2chan;
530 d569c924 2002-01-27 alex Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( Client ), Chan->name );
532 bb19cfda 2002-01-21 alex return cl2chan;
533 bb19cfda 2002-01-21 alex } /* Add_Client */
536 d569c924 2002-01-27 alex LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART )
538 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan, *last_cl2chan;
539 bb19cfda 2002-01-21 alex CHANNEL *c;
541 bb19cfda 2002-01-21 alex assert( Chan != NULL );
542 bb19cfda 2002-01-21 alex assert( Client != NULL );
543 bb19cfda 2002-01-21 alex assert( Origin != NULL );
544 bb19cfda 2002-01-21 alex assert( Reason != NULL );
546 bb19cfda 2002-01-21 alex last_cl2chan = NULL;
547 bb19cfda 2002-01-21 alex cl2chan = My_Cl2Chan;
548 bb19cfda 2002-01-21 alex while( cl2chan )
550 bb19cfda 2002-01-21 alex if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
551 bb19cfda 2002-01-21 alex last_cl2chan = cl2chan;
552 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
554 bb19cfda 2002-01-21 alex if( ! cl2chan ) return FALSE;
556 bb19cfda 2002-01-21 alex c = cl2chan->channel;
557 bb19cfda 2002-01-21 alex assert( c != NULL );
559 bb19cfda 2002-01-21 alex /* Aus Verkettung loesen und freigeben */
560 bb19cfda 2002-01-21 alex if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
561 bb19cfda 2002-01-21 alex else My_Cl2Chan = cl2chan->next;
562 bb19cfda 2002-01-21 alex free( cl2chan );
564 b5ee4552 2002-01-27 alex if( ServerPART ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
565 d569c924 2002-01-27 alex IRC_WriteStrChannelPrefix( Origin, c, Client, FALSE, "PART %s :%s", c->name, Reason );
566 6491b984 2002-01-27 alex if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
568 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
570 bb19cfda 2002-01-21 alex /* Wenn Channel nun leer: loeschen */
571 bb19cfda 2002-01-21 alex if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
573 bb19cfda 2002-01-21 alex return TRUE;
574 bb19cfda 2002-01-21 alex } /* Remove_Client */
577 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
579 bb19cfda 2002-01-21 alex return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
580 bb19cfda 2002-01-21 alex } /* Get_First_Cl2Chan */
583 bb19cfda 2002-01-21 alex LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
585 bb19cfda 2002-01-21 alex CL2CHAN *cl2chan;
587 bb19cfda 2002-01-21 alex assert( Client != NULL || Channel != NULL );
589 bb19cfda 2002-01-21 alex cl2chan = Start;
590 bb19cfda 2002-01-21 alex while( cl2chan )
592 bb19cfda 2002-01-21 alex if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
593 bb19cfda 2002-01-21 alex if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
594 bb19cfda 2002-01-21 alex cl2chan = cl2chan->next;
596 bb19cfda 2002-01-21 alex return NULL;
597 bb19cfda 2002-01-21 alex } /* Get_Next_Cl2Chan */
600 bb19cfda 2002-01-21 alex LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan )
602 bb19cfda 2002-01-21 alex /* Channel-Struktur loeschen */
604 bb19cfda 2002-01-21 alex CHANNEL *chan, *last_chan;
606 bb19cfda 2002-01-21 alex last_chan = NULL;
607 bb19cfda 2002-01-21 alex chan = My_Channels;
608 bb19cfda 2002-01-21 alex while( chan )
610 bb19cfda 2002-01-21 alex if( chan == Chan ) break;
611 bb19cfda 2002-01-21 alex last_chan = chan;
612 bb19cfda 2002-01-21 alex chan = chan->next;
614 bb19cfda 2002-01-21 alex if( ! chan ) return FALSE;
616 bb19cfda 2002-01-21 alex Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
618 bb19cfda 2002-01-21 alex /* Neu verketten und freigeben */
619 bb19cfda 2002-01-21 alex if( last_chan ) last_chan->next = chan->next;
620 bb19cfda 2002-01-21 alex else My_Channels = chan->next;
621 bb19cfda 2002-01-21 alex free( chan );
623 bb19cfda 2002-01-21 alex return TRUE;
624 bb19cfda 2002-01-21 alex } /* Delete_Channel */
627 38b9cb88 2001-12-14 alex /* -eof- */