]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- PING/PONG-Befehle implementiert,
[ngircd-alex.git] / src / ngircd / irc.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001 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 comBase beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: irc.c,v 1.8 2001/12/26 03:21:46 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  *
16  * $Log: irc.c,v $
17  * Revision 1.8  2001/12/26 03:21:46  alex
18  * - PING/PONG-Befehle implementiert,
19  * - Meldungen ueberarbeitet: enthalten nun (fast) immer den Nick.
20  *
21  * Revision 1.7  2001/12/25 23:25:18  alex
22  * - und nochmal Aenderungen am Logging ;-)
23  *
24  * Revision 1.6  2001/12/25 23:13:33  alex
25  * - Debug-Meldungen angepasst.
26  *
27  * Revision 1.5  2001/12/25 22:02:42  alex
28  * - neuer IRC-Befehl "/QUIT". Verbessertes Logging & Debug-Ausgaben.
29  *
30  * Revision 1.4  2001/12/25 19:19:30  alex
31  * - bessere Fehler-Abfragen, diverse Bugfixes.
32  * - Nicks werden nur einmal vergeben :-)
33  * - /MOTD wird unterstuetzt.
34  *
35  * Revision 1.3  2001/12/24 01:34:06  alex
36  * - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert (wg. BitchX)
37  * - MOTD-Ausgabe begonnen zu implementieren.
38  *
39  * Revision 1.2  2001/12/23 21:57:16  alex
40  * - erste IRC-Befehle zu implementieren begonnen.
41  *
42  * Revision 1.1  2001/12/14 08:13:43  alex
43  * - neues Modul begonnen :-)
44  */
45
46
47 #include <portab.h>
48 #include "global.h"
49
50 #include <imp.h>
51 #include <assert.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <string.h>
55
56 #include "client.h"
57 #include "log.h"
58 #include "messages.h"
59 #include "parse.h"
60
61 #include <exp.h>
62 #include "irc.h"
63
64
65 #define CONNECTED TRUE
66 #define DISCONNECTED FALSE
67
68
69 LOCAL BOOLEAN Check_Valid_User( CLIENT *Client );
70
71 LOCAL BOOLEAN Hello_User( CLIENT *Client );
72 LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
73
74
75 GLOBAL VOID IRC_Init( VOID )
76 {
77 } /* IRC_Init */
78
79
80 GLOBAL VOID IRC_Exit( VOID )
81 {
82 } /* IRC_Exit */
83
84
85 GLOBAL BOOLEAN IRC_WriteStr_Client( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
86 {
87         /* Text an Clients, lokal bzw. remote, senden. */
88
89         CHAR buffer[1000];
90         BOOLEAN ok = CONNECTED;
91         va_list ap;
92
93         assert( Client != NULL );
94         assert( Format != NULL );
95
96         va_start( ap, Format );
97
98         if( Client->conn_id != NONE )
99         {
100                 /* Lokaler Client */
101                 vsnprintf( buffer, 1000, Format, ap );
102                 if( Prefix ) ok = Conn_WriteStr( Client->conn_id, ":%s %s", Prefix->host, buffer );
103                 else ok = Conn_WriteStr( Client->conn_id, buffer );
104         }
105         else
106         {
107                 /* Remote-Client */
108                 Log( LOG_EMERG, "not implemented: IRC_WriteStr_Client()" );
109         }
110
111         va_end( ap );
112         return ok;
113 } /* IRC_WriteStr_Client */
114
115
116 GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
117 {
118         assert( Client != NULL );
119         assert( Req != NULL );
120
121         if( Client->type == CLIENT_UNKNOWN )
122         {
123                 Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client->conn_id );
124                 return IRC_WriteStr_Client( Client, This_Server, ERR_UNKNOWNCOMMAND_MSG, Client_Name( Client ), Req->command );
125         }
126         else return IRC_WriteStr_Client( Client, This_Server, ERR_ALREADYREGISTRED_MSG, Client_Name( Client ));
127 } /* IRC_PASS */
128
129
130 GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
131 {
132         CLIENT *c;
133
134         assert( Client != NULL );
135         assert( Req != NULL );
136
137         if( Client->type != CLIENT_SERVER && Client->type != CLIENT_SERVICE )
138         {
139                 /* Falsche Anzahl Parameter? */
140                 if( Req->argc != 1 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Name( Client ), Req->command );
141
142                 /* Nick zu lang? */
143                 if( strlen( Req->argv[0] ) > CLIENT_NICK_LEN ) return IRC_WriteStr_Client( Client, This_Server, ERR_ERRONEUSNICKNAME_MSG, Client_Name( Client ), Req->argv[0] );
144
145                 /* pruefen, ob Nick bereits vergeben */
146                 c = My_Clients;
147                 while( c )
148                 {
149                         if( strcasecmp( c->nick, Req->argv[0] ) == 0 )
150                         {
151                                 /* den Nick gibt es bereits */
152                                 return IRC_WriteStr_Client( Client, This_Server, ERR_NICKNAMEINUSE_MSG, Client_Name( Client ), Req->argv[0] );
153                         }
154                         c = c->next;
155                 }
156
157                 /* Client-Nick registrieren */
158                 strcpy( Client->nick, Req->argv[0] );
159
160                 if( Client->type != CLIENT_USER )
161                 {
162                         /* Neuer Client */
163                         Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client->conn_id );
164                         if( Client->type == CLIENT_GOTUSER ) return Hello_User( Client );
165                         else Client->type = CLIENT_GOTNICK;
166                 }
167                 return CONNECTED;
168         }
169         else return IRC_WriteStr_Client( Client, This_Server, ERR_ALREADYREGISTRED_MSG, Client_Name( Client ));
170 } /* IRC_NICK */
171
172
173 GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req )
174 {
175         assert( Client != NULL );
176         assert( Req != NULL );
177
178         if( Client->type == CLIENT_UNKNOWN || Client->type == CLIENT_GOTNICK || Client->type == CLIENT_GOTPASS )
179         {
180                 /* Falsche Anzahl Parameter? */
181                 if( Req->argc != 4 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Name( Client ), Req->command );
182
183                 strncpy( Client->user, Req->argv[0], CLIENT_USER_LEN );
184                 Client->user[CLIENT_USER_LEN] = '\0';
185                 strncpy( Client->name, Req->argv[3], CLIENT_NAME_LEN );
186                 Client->name[CLIENT_NAME_LEN] = '\0';
187
188                 Log( LOG_DEBUG, "Connection %d: got USER command ...", Client->conn_id );
189                 if( Client->type == CLIENT_GOTNICK ) return Hello_User( Client );
190                 else Client->type = CLIENT_GOTUSER;
191                 return CONNECTED;
192         }
193         else if( Client->type == CLIENT_USER || Client->type == CLIENT_SERVER || Client->type == CLIENT_SERVICE )
194         {
195                 return IRC_WriteStr_Client( Client, This_Server, ERR_ALREADYREGISTRED_MSG, Client_Name( Client ));
196         }
197         else return IRC_WriteStr_Client( Client, This_Server, ERR_NOTREGISTERED_MSG, Client_Name( Client ));
198 } /* IRC_USER */
199
200
201 GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
202 {
203         assert( Client != NULL );
204         assert( Req != NULL );
205
206         if( Client->type != CLIENT_SERVER && Client->type != CLIENT_SERVICE )
207         {
208                 /* Falsche Anzahl Parameter? */
209                 if( Req->argc > 1 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Name( Client ), Req->command );
210
211                 Conn_Close( Client->conn_id, "Client wants to quit." );
212                 return DISCONNECTED;
213         }
214         else return IRC_WriteStr_Client( Client, This_Server, ERR_NOTREGISTERED_MSG, Client_Name( Client ));
215 } /* IRC_QUIT */
216
217
218 GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
219 {
220         assert( Client != NULL );
221         assert( Req != NULL );
222
223         return IRC_WriteStr_Client( Client, This_Server, ERR_UNKNOWNCOMMAND_MSG, Client_Name( Client ), Req->command );
224 } /* IRC_PING */
225
226
227 GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
228 {
229         assert( Client != NULL );
230         assert( Req != NULL );
231
232         if( ! Check_Valid_User( Client )) return CONNECTED;
233
234         /* Falsche Anzahl Parameter? */
235         if( Req->argc < 1 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NOORIGIN_MSG, Client_Name( Client ));
236         if( Req->argc > 1 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Name( Client ), Req->command );
237
238         /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
239          * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
240
241         Log( LOG_DEBUG, "Connection %d: received PONG.", Client->conn_id );
242         return CONNECTED;
243 } /* IRC_PONG */
244
245
246 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
247 {
248         assert( Client != NULL );
249         assert( Req != NULL );
250
251         if( ! Check_Valid_User( Client )) return CONNECTED;
252
253         /* Falsche Anzahl Parameter? */
254         if( Req->argc != 0 ) return IRC_WriteStr_Client( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Name( Client ), Req->command );
255
256         return Show_MOTD( Client );
257 } /* IRC_MOTD */
258
259
260 LOCAL BOOLEAN Check_Valid_User( CLIENT *Client )
261 {
262         assert( Client != NULL );
263
264         if( Client->type != CLIENT_USER )
265         {
266                 IRC_WriteStr_Client( Client, This_Server, ERR_NOTREGISTERED_MSG, Client_Name( Client ));
267                 return FALSE;
268         }
269         else return TRUE;
270 } /* Check_Valid_User */
271
272
273 LOCAL BOOLEAN Hello_User( CLIENT *Client )
274 {
275         assert( Client != NULL );
276         assert( Client->nick[0] );
277         
278         Log( LOG_NOTICE, "User \"%s!%s@%s\" (%s) registered.", Client->nick, Client->user, Client->host, Client->name );
279
280         IRC_WriteStr_Client( Client, This_Server, RPL_WELCOME_MSG, Client->nick, Client->nick, Client->user, Client->host );
281         IRC_WriteStr_Client( Client, This_Server, RPL_YOURHOST_MSG, Client->nick, This_Server->host );
282         IRC_WriteStr_Client( Client, This_Server, RPL_CREATED_MSG, Client->nick );
283         IRC_WriteStr_Client( Client, This_Server, RPL_MYINFO_MSG, Client->nick, This_Server->host );
284
285         Client->type = CLIENT_USER;
286
287         return Show_MOTD( Client );
288 } /* Hello_User */
289
290
291 LOCAL BOOLEAN Show_MOTD( CLIENT *Client )
292 {
293         assert( Client != NULL );
294         assert( Client->nick[0] );
295         
296         IRC_WriteStr_Client( Client, This_Server, RPL_MOTDSTART_MSG, Client->nick, This_Server->host );
297         IRC_WriteStr_Client( Client, This_Server, RPL_MOTD_MSG, Client->nick, "Some cool IRC server welcome message ;-)" );
298         return IRC_WriteStr_Client( Client, This_Server, RPL_ENDOFMOTD_MSG, Client->nick );
299 } /* Show_MOTD */
300
301
302 /* -eof- */