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