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