]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- externe portab-Header werden nicht mehr benoetigt/benutzt, dadurch
[ngircd-alex.git] / src / ngircd / irc.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.c,v 1.88 2002/03/12 14:37:52 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  */
16
17
18 #include "portab.h"
19
20 #include "imp.h"
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "ngircd.h"
28 #include "channel.h"
29 #include "client.h"
30 #include "conf.h"
31 #include "conn.h"
32 #include "irc-write.h"
33 #include "log.h"
34 #include "messages.h"
35 #include "tool.h"
36
37 #include "exp.h"
38 #include "irc.h"
39
40
41 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
42 {
43         assert( Client != NULL );
44         assert( Req != NULL );
45
46         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
47
48         /* Falsche Anzahl Parameter? */
49         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
50
51         return IRC_Show_MOTD( Client );
52 } /* IRC_MOTD */
53
54
55 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
56 {
57         BOOLEAN is_member, has_voice, is_op, ok;
58         CLIENT *cl, *from;
59         CHANNEL *chan;
60         
61         assert( Client != NULL );
62         assert( Req != NULL );
63
64         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
65
66         /* Falsche Anzahl Parameter? */
67         if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
68         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
69         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
70
71         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
72         else from = Client;
73         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
74
75         cl = Client_Search( Req->argv[0] );
76         if( cl )
77         {
78                 /* Okay, Ziel ist ein User */
79                 if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' )))
80                 {
81                         /* Ziel-User ist AWAY: Meldung verschicken */
82                         if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED;
83                 }
84
85                 /* Text senden */
86                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
87                 return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] );
88         }
89
90         chan = Channel_Search( Req->argv[0] );
91         if( chan )
92         {
93                 /* Okay, Ziel ist ein Channel */
94                 is_member = has_voice = is_op = FALSE;
95                 if( Channel_IsMemberOf( chan, from ))
96                 {
97                         is_member = TRUE;
98                         if( strchr( Channel_UserModes( chan, from ), 'v' )) has_voice = TRUE;
99                         if( strchr( Channel_UserModes( chan, from ), 'o' )) is_op = TRUE;
100                 }
101                 
102                 /* pruefen, ob Client in Channel schreiben darf */
103                 ok = TRUE;
104                 if( strchr( Channel_Modes( chan ), 'n' ) && ( ! is_member )) ok = FALSE;
105                 if( strchr( Channel_Modes( chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = FALSE;
106
107                 if( ! ok ) return IRC_WriteStrClient( from, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( from ), Req->argv[0] );
108
109                 /* Text senden */
110                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
111                 return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
112         }
113
114         return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
115 } /* IRC_PRIVMSG */
116
117
118 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
119 {
120         CLIENT *to, *from;
121
122         assert( Client != NULL );
123         assert( Req != NULL );
124
125         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
126
127         /* Falsche Anzahl Parameter? */
128         if( Req->argc != 2 ) return CONNECTED;
129
130         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
131         else from = Client;
132         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
133
134         to = Client_Search( Req->argv[0] );
135         if( to )
136         {
137                 /* Okay, Ziel ist ein User */
138                 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
139         }
140         else return CONNECTED;
141 } /* IRC_NOTICE */
142
143
144 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
145 {
146         CHAR rpl[COMMAND_LEN], *ptr;
147         CLIENT *target, *from, *c;
148         CHANNEL *chan;
149         
150         assert( Client != NULL );
151         assert( Req != NULL );
152
153         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
154
155         /* Falsche Anzahl Parameter? */
156         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
157
158         /* From aus Prefix ermitteln */
159         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
160         else from = Client;
161         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
162         
163         if( Req->argc == 2 )
164         {
165                 /* an anderen Server forwarden */
166                 target = Client_GetFromID( Req->argv[1] );
167                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
168
169                 if( target != Client_ThisServer( ))
170                 {
171                         /* Ok, anderer Server ist das Ziel: forwarden */
172                         return IRC_WriteStrClientPrefix( target, from, "NAMES %s :%s", Req->argv[0], Req->argv[1] );
173                 }
174         }
175
176         if( Req->argc > 0 )
177         {
178                 /* bestimmte Channels durchgehen */
179                 ptr = strtok( Req->argv[0], "," );
180                 while( ptr )
181                 {
182                         chan = Channel_Search( ptr );
183                         if( chan )
184                         {
185                                 /* Namen ausgeben */
186                                 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
187                         }
188                         if( ! IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), ptr )) return DISCONNECTED;
189                         
190                         /* naechsten Namen ermitteln */
191                         ptr = strtok( NULL, "," );
192                 }
193                 return CONNECTED;
194         }
195         
196         /* alle Channels durchgehen */
197         chan = Channel_First( );
198         while( chan )
199         {
200                 /* Namen ausgeben */
201                 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
202
203                 /* naechster Channel */
204                 chan = Channel_Next( chan );
205         }
206
207         /* Nun noch alle Clients ausgeben, die in keinem Channel sind */
208         c = Client_First( );
209         sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
210         while( c )
211         {
212                 if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ) && ( ! strchr( Client_Modes( c ), 'i' )))
213                 {
214                         /* Okay, das ist ein User: anhaengen */
215                         if( rpl[strlen( rpl ) - 1] != ':' ) strcat( rpl, " " );
216                         strcat( rpl, Client_ID( c ));
217
218                         if( strlen( rpl ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
219                         {
220                                 /* Zeile wird zu lang: senden! */
221                                 if( ! IRC_WriteStrClient( from, rpl )) return DISCONNECTED;
222                                 sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
223                         }
224                 }
225
226                 /* naechster Client */
227                 c = Client_Next( c );
228         }
229         if( rpl[strlen( rpl ) - 1] != ':')
230         {
231                 /* es wurden User gefunden */
232                 if( ! IRC_WriteStrClient( from, rpl )) return DISCONNECTED;
233         }
234         
235         return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" );
236 } /* IRC_NAMES */
237
238
239 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
240 {
241         CHAR rpl[COMMAND_LEN];
242         CLIENT *c;
243         CHAR *ptr;
244         INT i;
245         
246         assert( Client != NULL );
247         assert( Req != NULL );
248
249         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
250
251         /* Falsche Anzahl Parameter? */
252         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
253
254         strcpy( rpl, RPL_ISON_MSG );
255         for( i = 0; i < Req->argc; i++ )
256         {
257                 ptr = strtok( Req->argv[i], " " );
258                 while( ptr )
259                 {
260                         ngt_TrimStr( ptr );
261                         c = Client_GetFromID( ptr );
262                         if( c && ( Client_Type( c ) == CLIENT_USER ))
263                         {
264                                 /* Dieser Nick ist "online" */
265                                 strcat( rpl, ptr );
266                                 strcat( rpl, " " );
267                         }
268                         ptr = strtok( NULL, " " );
269                 }
270         }
271         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
272
273         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
274 } /* IRC_ISON */
275
276
277 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
278 {
279         CLIENT *from, *target, *c;
280         CHAR str[LINE_LEN + 1], *ptr = NULL;
281         CL2CHAN *cl2chan;
282         CHANNEL *chan;
283         
284         assert( Client != NULL );
285         assert( Req != NULL );
286
287         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
288
289         /* Falsche Anzahl Parameter? */
290         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
291
292         /* Client suchen */
293         c = Client_GetFromID( Req->argv[Req->argc - 1] );
294         if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
295
296         /* Empfaenger des WHOIS suchen */
297         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
298         else from = Client;
299         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
300         
301         /* Forwarden an anderen Server? */
302         if( Req->argc > 1 )
303         {
304                 /* angegebenen Ziel-Server suchen */
305                 target = Client_GetFromID( Req->argv[1] );
306                 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
307                 ptr = Req->argv[1];
308         }
309         else target = Client_ThisServer( );
310
311         assert( target != NULL );
312         
313         if(( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
314         
315         /* Nick, User und Name */
316         if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
317
318         /* Server */
319         if( ! IRC_WriteStrClient( from, RPL_WHOISSERVER_MSG, Client_ID( from ), Client_ID( c ), Client_ID( Client_Introducer( c )), Client_Info( Client_Introducer( c )))) return DISCONNECTED;
320
321         /* Channels */
322         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
323         cl2chan = Channel_FirstChannelOf( c );
324         while( cl2chan )
325         {
326                 chan = Channel_GetChannel( cl2chan );
327                 assert( chan != NULL );
328                 
329                 /* Channel-Name anhaengen */
330                 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
331                 if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
332                 else if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
333                 strcat( str, Channel_Name( chan ));
334
335                 if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
336                 {
337                         /* Zeile wird zu lang: senden! */
338                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
339                         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
340                 }
341
342                 /* naechstes Mitglied suchen */
343                 cl2chan = Channel_NextChannelOf( c, cl2chan );
344         }
345         if( str[strlen( str ) - 1] != ':')
346         {
347                 /* Es sind noch Daten da, die gesendet werden muessen */
348                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
349         }
350         
351         /* IRC-Operator? */
352         if( Client_HasMode( c, 'o' ))
353         {
354                 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
355         }
356
357         /* Idle (nur lokale Clients) */
358         if( Client_Conn( c ) > NONE )
359         {
360                 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
361         }
362
363         /* Away? */
364         if( Client_HasMode( c, 'a' ))
365         {
366                 if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED;
367         }
368
369         /* End of Whois */
370         return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
371 } /* IRC_WHOIS */
372
373
374 GLOBAL BOOLEAN IRC_WHO( CLIENT *Client, REQUEST *Req )
375 {
376         BOOLEAN ok, only_ops;
377         CHAR flags[8], *ptr;
378         CL2CHAN *cl2chan;
379         CHANNEL *chan;
380         CLIENT *c;
381         
382         assert( Client != NULL );
383         assert( Req != NULL );
384
385         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
386
387         /* Falsche Anzahl Parameter? */
388         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
389
390         only_ops = FALSE;
391         chan = NULL;
392
393         if( Req->argc == 2 )
394         {
395                 /* Nur OPs anzeigen? */
396                 if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = TRUE;
397 #ifdef STRICT_RFC
398                 else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
399 #endif
400         }
401         
402         if( Req->argc >= 1 )
403         {
404                 /* wurde ein Channel oder Nick-Mask angegeben? */
405                 chan = Channel_Search( Req->argv[0] );
406         }
407
408         if( chan )
409         {
410                 /* User eines Channels ausgeben */
411                 if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED;
412         }
413
414         c = Client_First( );
415         while( c )
416         {
417                 if(( Client_Type( c ) == CLIENT_USER ) && ( ! strchr( Client_Modes( c ), 'i' )))
418                 {
419                         ok = FALSE;
420                         if( Req->argc == 0 ) ok = TRUE;
421                         else
422                         {
423                                 if( strcasecmp( Req->argv[0], Client_ID( c )) == 0 ) ok = TRUE;
424                                 else if( strcmp( Req->argv[0], "0" ) == 0 ) ok = TRUE;
425                         }
426                                 
427                         if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' ))))
428                         {
429                                 /* Flags zusammenbasteln */
430                                 strcpy( flags, "H" );
431                                 if( strchr( Client_Modes( c ), 'o' )) strcat( flags, "*" );
432
433                                 /* ausgeben */
434                                 cl2chan = Channel_FirstChannelOf( c );
435                                 if( cl2chan ) ptr = Channel_Name( Channel_GetChannel( cl2chan ));
436                                 else ptr = "*";
437                                 if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
438                         }
439                 }
440
441                 /* naechster Client */
442                 c = Client_Next( c );
443         }
444
445         if( chan ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Channel_Name( chan ));
446         else if( Req->argc == 0 ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), "*" );
447         else return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Req->argv[0] );
448 } /* IRC_WHO */
449
450
451 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
452 {
453         CHAR rpl[COMMAND_LEN];
454         CLIENT *c;
455         INT max, i;
456
457         assert( Client != NULL );
458         assert( Req != NULL );
459
460         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
461
462         /* Falsche Anzahl Parameter? */
463         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
464
465         if( Req->argc > 5 ) max = 5;
466         else max = Req->argc;
467         
468         strcpy( rpl, RPL_USERHOST_MSG );
469         for( i = 0; i < max; i++ )
470         {
471                 c = Client_GetFromID( Req->argv[i] );
472                 if( c && ( Client_Type( c ) == CLIENT_USER ))
473                 {
474                         /* Dieser Nick ist "online" */
475                         strcat( rpl, Client_ID( c ));
476                         if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
477                         strcat( rpl, "=" );
478                         if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
479                         else strcat( rpl, "+" );
480                         strcat( rpl, Client_User( c ));
481                         strcat( rpl, "@" );
482                         strcat( rpl, Client_Hostname( c ));
483                         strcat( rpl, " " );
484                 }
485         }
486         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
487
488         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
489 } /* IRC_USERHOST */
490
491
492 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
493 {
494         assert( Client != NULL );
495         assert( Req != NULL );
496
497         if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
498         else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
499
500         return CONNECTED;
501 } /* IRC_ERROR */
502
503
504 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
505 {
506         CLIENT *target, *from;
507         
508         assert( Client != NULL );
509         assert( Req != NULL );
510
511         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
512
513         /* Falsche Anzahl Parameter? */
514         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
515
516         /* Absender ermitteln */
517         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
518         else from = Client;
519         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
520
521         /* An anderen Server forwarden? */
522         if( Req->argc == 2 )
523         {
524                 target = Client_GetFromID( Req->argv[1] );
525                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
526                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
527         }
528
529         /* Wer ist der Absender? */
530         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
531         else target = Client;
532         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
533         
534         IRC_Send_LUSERS( target );
535
536         return CONNECTED;
537 } /* IRC_LUSERS */
538
539
540 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
541 {
542         CLIENT *target, *from, *c;
543         CHAR *mask;
544         
545         assert( Client != NULL );
546         assert( Req != NULL );
547
548         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
549
550         /* Falsche Anzahl Parameter? */
551         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
552
553         /* Server-Mask ermitteln */
554         if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
555         else mask = "*";
556
557         /* Absender ermitteln */
558         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
559         else from = Client;
560         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
561         
562         /* An anderen Server forwarden? */
563         if( Req->argc == 2 )
564         {
565                 target = Client_GetFromID( Req->argv[0] );
566                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
567                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
568         }
569
570         /* Wer ist der Absender? */
571         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
572         else target = Client;
573         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
574         
575         c = Client_First( );
576         while( c )
577         {
578                 if( Client_Type( c ) == CLIENT_SERVER )
579                 {
580                         if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
581                 }
582                 c = Client_Next( c );
583         }
584         
585         return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
586 } /* IRC_LINKS */
587
588
589 GLOBAL BOOLEAN IRC_VERSION( CLIENT *Client, REQUEST *Req )
590 {
591         CLIENT *target, *prefix;
592         
593         assert( Client != NULL );
594         assert( Req != NULL );
595
596         /* Falsche Anzahl Parameter? */
597         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
598
599         /* Ziel suchen */
600         if( Req->argc == 1 ) target = Client_GetFromID( Req->argv[0] );
601         else target = Client_ThisServer( );
602
603         /* Prefix ermitteln */
604         if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_GetFromID( Req->prefix );
605         else prefix = Client;
606         if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
607         
608         /* An anderen Server weiterleiten? */
609         if( target != Client_ThisServer( ))
610         {
611                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
612
613                 /* forwarden */
614                 IRC_WriteStrClientPrefix( target, prefix, "VERSION %s", Req->argv[0] );
615                 return CONNECTED;
616         }
617
618         /* mit Versionsinfo antworten */
619         return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition( ));
620 } /* IRC_VERSION */
621
622
623 GLOBAL BOOLEAN IRC_KILL( CLIENT *Client, REQUEST *Req )
624 {
625         CLIENT *prefix, *c;
626         
627         assert( Client != NULL );
628         assert( Req != NULL );
629
630         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
631
632         /* Falsche Anzahl Parameter? */
633         if(( Req->argc != 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
634
635         prefix = Client_GetFromID( Req->prefix );
636         if( ! prefix )
637         {
638                 Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Req->prefix );
639                 prefix = Client_ThisServer( );
640         }
641         
642         Log( LOG_NOTICE, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
643         
644         /* andere Server benachrichtigen */
645         IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s", Req->argv[0], Req->argv[1] );
646
647         /* haben wir selber einen solchen Client? */
648         c = Client_GetFromID( Req->argv[0] );
649         if( c && ( Client_Conn( c ) != NONE )) Conn_Close( Client_Conn( c ), NULL, Req->argv[1], TRUE );
650         
651         return CONNECTED;
652 } /* IRC_KILL */
653
654
655 GLOBAL BOOLEAN IRC_Show_MOTD( CLIENT *Client )
656 {
657         BOOLEAN ok;
658         CHAR line[127];
659         FILE *fd;
660         
661         assert( Client != NULL );
662
663         fd = fopen( Conf_MotdFile, "r" );
664         if( ! fd )
665         {
666                 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
667                 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
668         }
669         
670         IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
671         while( TRUE )
672         {
673                 if( ! fgets( line, 126, fd )) break;
674                 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
675                 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
676                 {
677                         fclose( fd );
678                         return FALSE;
679                 }
680         }
681         ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
682
683         fclose( fd );
684         
685         return ok;
686 } /* IRC_Show_MOTD */
687
688
689 GLOBAL BOOLEAN IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
690 {
691         BOOLEAN is_visible, is_member;
692         CHAR str[LINE_LEN + 1];
693         CL2CHAN *cl2chan;
694         CLIENT *cl;
695         
696         assert( Client != NULL );
697         assert( Chan != NULL );
698
699         if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE;
700         else is_member = FALSE;
701                          
702         /* Alle Mitglieder suchen */
703         sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
704         cl2chan = Channel_FirstMember( Chan );
705         while( cl2chan )
706         {
707                 cl = Channel_GetClient( cl2chan );
708
709                 if( strchr( Client_Modes( cl ), 'i' )) is_visible = FALSE;
710                 else is_visible = TRUE;
711
712                 if( is_member || is_visible )
713                 {
714                         /* Nick anhaengen */
715                         if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
716                         if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
717                         else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
718                         strcat( str, Client_ID( cl ));
719         
720                         if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
721                         {
722                                 /* Zeile wird zu lang: senden! */
723                                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
724                                 sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
725                         }
726                 }
727
728                 /* naechstes Mitglied suchen */
729                 cl2chan = Channel_NextMember( Chan, cl2chan );
730         }
731         if( str[strlen( str ) - 1] != ':')
732         {
733                 /* Es sind noch Daten da, die gesendet werden muessen */
734                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
735         }
736
737         return CONNECTED;
738 } /* IRC_Send_NAMES */
739
740
741 GLOBAL BOOLEAN IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, BOOLEAN OnlyOps )
742 {
743         BOOLEAN is_visible, is_member;
744         CL2CHAN *cl2chan;
745         CHAR flags[8];
746         CLIENT *c;
747
748         assert( Client != NULL );
749         assert( Chan != NULL );
750
751         if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE;
752         else is_member = FALSE;
753
754         /* Alle Mitglieder suchen */
755         cl2chan = Channel_FirstMember( Chan );
756         while( cl2chan )
757         {
758                 c = Channel_GetClient( cl2chan );
759
760                 if( strchr( Client_Modes( c ), 'i' )) is_visible = FALSE;
761                 else is_visible = TRUE;
762
763                 if( is_member || is_visible )
764                 {
765                         /* Flags zusammenbasteln */
766                         strcpy( flags, "H" );
767                         if( strchr( Client_Modes( c ), 'o' )) strcat( flags, "*" );
768                         if( strchr( Channel_UserModes( Chan, c ), 'o' )) strcat( flags, "@" );
769                         else if( strchr( Channel_UserModes( Chan, c ), 'v' )) strcat( flags, "+" );
770                         
771                         /* ausgeben */
772                         if(( ! OnlyOps ) || ( strchr( Client_Modes( c ), 'o' )))
773                         {
774                                 if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), Channel_Name( Chan ), Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
775                         }
776                 }
777
778                 /* naechstes Mitglied suchen */
779                 cl2chan = Channel_NextMember( Chan, cl2chan );
780         }
781         return CONNECTED;
782 } /* IRC_Send_WHO */
783
784
785 GLOBAL BOOLEAN IRC_Send_LUSERS( CLIENT *Client )
786 {
787         INT cnt;
788
789         assert( Client != NULL );
790
791         /* Users, Services und Serevr im Netz */
792         if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
793
794         /* IRC-Operatoren im Netz */
795         cnt = Client_OperCount( );
796         if( cnt > 0 )
797         {
798                 if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
799         }
800
801         /* Unbekannt Verbindungen */
802         cnt = Client_UnknownCount( );
803         if( cnt > 0 )
804         {
805                 if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
806         }
807
808         /* Channels im Netz */
809         if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
810
811         /* Channels im Netz */
812         if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
813         
814         return CONNECTED;
815 } /* IRC_Send_LUSERS */
816
817
818 /* -eof- */