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