]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/client.c
- neue Funktion Client_CheckID(), diverse Aenderungen fuer Server-Links.
[ngircd-alex.git] / src / ngircd / client.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: client.c,v 1.18 2002/01/03 02:28:06 alex Exp $
13  *
14  * client.c: Management aller Clients
15  *
16  * Der Begriff "Client" ist in diesem Fall evtl. etwas verwirrend: Clients sind
17  * alle Verbindungen, die im gesamten(!) IRC-Netzwerk bekannt sind. Das sind IRC-
18  * Clients (User), andere Server und IRC-Services.
19  * Ueber welchen IRC-Server die Verbindung nun tatsaechlich in das Netzwerk her-
20  * gestellt wurde, muss der jeweiligen Struktur entnommen werden. Ist es dieser
21  * Server gewesen, so existiert eine entsprechende CONNECTION-Struktur.
22  *
23  * $Log: client.c,v $
24  * Revision 1.18  2002/01/03 02:28:06  alex
25  * - neue Funktion Client_CheckID(), diverse Aenderungen fuer Server-Links.
26  *
27  * Revision 1.17  2002/01/02 02:42:58  alex
28  * - Copyright-Texte aktualisiert.
29  *
30  * Revision 1.16  2002/01/01 18:25:44  alex
31  * - #include's fuer stdlib.h ergaenzt.
32  *
33  * Revision 1.15  2001/12/31 15:33:13  alex
34  * - neuer Befehl NAMES, kleinere Bugfixes.
35  * - Bug bei PING behoben: war zu restriktiv implementiert :-)
36  *
37  * Revision 1.14  2001/12/31 02:18:51  alex
38  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
39  * - neuen Header "defines.h" mit (fast) allen Konstanten.
40  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
41  *
42  * Revision 1.13  2001/12/30 19:26:11  alex
43  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
44  *
45  * Revision 1.12  2001/12/29 20:18:18  alex
46  * - neue Funktion Client_SetHostname().
47  *
48  * Revision 1.11  2001/12/29 03:10:47  alex
49  * - Client-Modes implementiert; Loglevel mal wieder angepasst.
50  *
51  * Revision 1.10  2001/12/27 19:13:47  alex
52  * - neue Funktion Client_Search(), besseres Logging.
53  *
54  * Revision 1.9  2001/12/27 17:15:29  alex
55  * - der eigene Hostname wird nun komplet (als FQDN) ermittelt.
56  *
57  * Revision 1.8  2001/12/27 16:54:51  alex
58  * - neue Funktion Client_GetID(), liefert die "Client ID".
59  *
60  * Revision 1.7  2001/12/26 14:45:37  alex
61  * - "Code Cleanups".
62  *
63  * Revision 1.6  2001/12/26 03:19:16  alex
64  * - neue Funktion Client_Nick().
65  *
66  * Revision 1.5  2001/12/25 22:04:26  alex
67  * - Aenderungen an den Debug- und Logging-Funktionen.
68  *
69  * Revision 1.4  2001/12/25 19:21:26  alex
70  * - Client-Typ ("Status") besser unterteilt, My_Clients ist zudem nun global.
71  *
72  * Revision 1.3  2001/12/24 01:31:14  alex
73  * - einige assert()'s eingestraeut.
74  *
75  * Revision 1.2  2001/12/23 22:04:37  alex
76  * - einige neue Funktionen,
77  * - CLIENT-Struktur erweitert.
78  *
79  * Revision 1.1  2001/12/14 08:13:43  alex
80  * - neues Modul begonnen :-)
81  */
82
83
84 #include <portab.h>
85 #include "global.h"
86
87 #include <imp.h>
88 #include <assert.h>
89 #include <unistd.h>
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <string.h>
93 #include <netdb.h>
94
95 #include <exp.h>
96 #include "client.h"
97
98 #include <imp.h>
99 #include "channel.h"
100 #include "conf.h"
101 #include "conn.h"
102 #include "irc.h"
103 #include "log.h"
104 #include "messages.h"
105
106 #include <exp.h>
107
108
109 LOCAL CLIENT *My_Clients;
110 LOCAL CHAR GetID_Buffer[CLIENT_ID_LEN];
111
112
113 LOCAL CLIENT *New_Client_Struct( VOID );
114
115
116 GLOBAL VOID Client_Init( VOID )
117 {
118         struct hostent *h;
119         
120         This_Server = New_Client_Struct( );
121         if( ! This_Server )
122         {
123                 Log( LOG_EMERG, "Can't allocate client structure for server! Going down." );
124                 Log( LOG_ALERT, PACKAGE" exiting due to fatal errors!" );
125                 exit( 1 );
126         }
127
128         /* Client-Struktur dieses Servers */
129         This_Server->next = NULL;
130         This_Server->type = CLIENT_SERVER;
131         This_Server->conn_id = NONE;
132         This_Server->introducer = This_Server;
133
134         gethostname( This_Server->host, CLIENT_HOST_LEN );
135         h = gethostbyname( This_Server->host );
136         if( h ) strcpy( This_Server->host, h->h_name );
137
138         strcpy( This_Server->nick, Conf_ServerName );
139         strcpy( This_Server->info, Conf_ServerInfo );
140
141         My_Clients = This_Server;
142 } /* Client_Init */
143
144
145 GLOBAL VOID Client_Exit( VOID )
146 {
147         CLIENT *c, *next;
148         INT cnt;
149
150         Client_Destroy( This_Server );
151         
152         cnt = 0;
153         c = My_Clients;
154         while( c )
155         {
156                 cnt++;
157                 next = c->next;
158                 free( c );
159                 c = next;
160         }
161         if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
162 } /* Client Exit */
163
164
165 GLOBAL CLIENT *Client_NewLocal( CONN_ID Idx, CHAR *Hostname )
166 {
167         /* Neuen lokalen Client erzeugen. */
168         
169         CLIENT *client;
170
171         assert( Idx >= 0 );
172         assert( Hostname != NULL );
173         
174         client = New_Client_Struct( );
175         if( ! client ) return NULL;
176
177         /* Initialisieren */
178         client->conn_id = Idx;
179         client->introducer = This_Server;
180         Client_SetHostname( client, Hostname );
181
182         /* Verketten */
183         client->next = My_Clients;
184         My_Clients = client;
185         
186         return client;
187 } /* Client_NewLocal */
188
189
190 GLOBAL VOID Client_Destroy( CLIENT *Client )
191 {
192         /* Client entfernen. */
193         
194         CLIENT *last, *c;
195
196         assert( Client != NULL );
197         
198         last = NULL;
199         c = My_Clients;
200         while( c )
201         {
202                 if( c == Client )
203                 {
204                         if( last ) last->next = c->next;
205                         else My_Clients = c->next;
206
207                         if( c->type == CLIENT_USER ) Log( LOG_NOTICE, "User \"%s!%s@%s\" (%s) exited (connection %d).", c->nick, c->user, c->host, c->name, c->conn_id );
208
209                         free( c );
210                         break;
211                 }
212                 last = c;
213                 c = c->next;
214         }
215 } /* Client_Destroy */
216
217
218 GLOBAL VOID Client_SetHostname( CLIENT *Client, CHAR *Hostname )
219 {
220         /* Hostname eines Clients setzen */
221         
222         assert( Client != NULL );
223         strncpy( Client->host, Hostname, CLIENT_HOST_LEN );
224         Client->host[CLIENT_HOST_LEN - 1] = '\0';
225 } /* Client_SetHostname */
226
227
228 GLOBAL CLIENT *Client_GetFromConn( CONN_ID Idx )
229 {
230         /* Client-Struktur, die zur lokalen Verbindung Idx gehoert,
231          * liefern. Wird keine gefunden, so wird NULL geliefert. */
232
233         CLIENT *c;
234
235         assert( Idx >= 0 );
236         
237         c = My_Clients;
238         while( c )
239         {
240                 if( c->conn_id == Idx ) return c;
241                 c = c->next;
242         }
243         return NULL;
244 } /* Client_GetFromConn */
245
246
247 GLOBAL CLIENT *Client_GetFromNick( CHAR *Nick )
248 {
249         /* Client-Struktur, die den entsprechenden Nick hat,
250         * liefern. Wird keine gefunden, so wird NULL geliefert. */
251
252         CLIENT *c;
253
254         assert( Nick != NULL );
255
256         c = My_Clients;
257         while( c )
258         {
259                 if( strcasecmp( c->nick, Nick ) == 0 ) return c;
260                 c = c->next;
261         }
262         return NULL;
263 } /* Client_GetFromNick */
264
265
266 GLOBAL CHAR *Client_Nick( CLIENT *Client )
267 {
268         assert( Client != NULL );
269
270         if( Client->nick[0] ) return Client->nick;
271         else return "*";
272 } /* Client_Name */
273
274
275 GLOBAL BOOLEAN Client_CheckNick( CLIENT *Client, CHAR *Nick )
276 {
277         /* Nick ueberpruefen */
278
279         CLIENT *c;
280         
281         assert( Client != NULL );
282         assert( Nick != NULL );
283         
284         /* Nick zu lang? */
285         if( strlen( Nick ) > CLIENT_NICK_LEN ) return IRC_WriteStrClient( Client, This_Server, ERR_ERRONEUSNICKNAME_MSG, Client_Nick( Client ), Nick );
286
287         /* Nick bereits vergeben? */
288         c = My_Clients;
289         while( c )
290         {
291                 if( strcasecmp( c->nick, Nick ) == 0 )
292                 {
293                         /* den Nick gibt es bereits */
294                         IRC_WriteStrClient( Client, This_Server, ERR_NICKNAMEINUSE_MSG, Client_Nick( Client ), Nick );
295                         return FALSE;
296                 }
297                 c = c->next;
298         }
299
300         return TRUE;
301 } /* Client_CheckNick */
302
303
304 GLOBAL BOOLEAN Client_CheckID( CLIENT *Client, CHAR *ID )
305 {
306         /* Nick ueberpruefen */
307
308         CHAR str[COMMAND_LEN];
309         CLIENT *c;
310
311         assert( Client != NULL );
312         assert( Client->conn_id > NONE );
313         assert( ID != NULL );
314
315         /* Nick zu lang? */
316         if( strlen( ID ) > CLIENT_ID_LEN ) return IRC_WriteStrClient( Client, This_Server, ERR_ERRONEUSNICKNAME_MSG, Client_Nick( Client ), ID );
317
318         /* ID bereits vergeben? */
319         c = My_Clients;
320         while( c )
321         {
322                 if( strcasecmp( c->nick, ID ) == 0 )
323                 {
324                         /* die Server-ID gibt es bereits */
325                         sprintf( str, "ID \"%s\" already registered!", ID );
326                         Log( LOG_ALERT, "%s (detected on connection %d)", str, Client->conn_id );
327                         Conn_Close( Client->conn_id, str );
328                         return FALSE;
329                 }
330                 c = c->next;
331         }
332
333         return TRUE;
334 } /* Client_CheckID */
335
336
337 GLOBAL CHAR *Client_GetID( CLIENT *Client )
338 {
339         /* Client-"ID" liefern, wie sie z.B. fuer
340          * Prefixe benoetigt wird. */
341
342         assert( Client != NULL );
343         
344         if( Client->type == CLIENT_SERVER ) return Client->nick;
345
346         sprintf( GetID_Buffer, "%s!%s@%s", Client->nick, Client->user, Client->host );
347         return GetID_Buffer;
348 } /* Client_GetID */
349
350
351 GLOBAL CLIENT *Client_Search( CHAR *ID )
352 {
353         /* Client suchen, auf den ID passt */
354
355         CLIENT *c;
356
357         assert( ID != NULL );
358
359         c = My_Clients;
360         while( c )
361         {
362                 if( strcasecmp( c->nick, ID ) == 0 ) return c;
363                 c = c->next;
364         }
365         
366         return NULL;
367 } /* Client_Search */
368
369
370 GLOBAL CLIENT *Client_First( VOID )
371 {
372         /* Ersten Client liefern. */
373
374         return My_Clients;
375 } /* Client_First */
376
377
378 GLOBAL CLIENT *Client_Next( CLIENT *c )
379 {
380         /* Naechsten Client liefern. Existiert keiner,
381          * so wird NULL geliefert. */
382
383         assert( c != NULL );
384         return c->next;
385 } /* Client_Next */
386
387
388 LOCAL CLIENT *New_Client_Struct( VOID )
389 {
390         /* Neue CLIENT-Struktur pre-initialisieren */
391         
392         CLIENT *c;
393         INT i;
394         
395         c = malloc( sizeof( CLIENT ));
396         if( ! c )
397         {
398                 Log( LOG_EMERG, "Can't allocate memory!" );
399                 return NULL;
400         }
401
402         c->next = NULL;
403         c->type = CLIENT_UNKNOWN;
404         c->conn_id = NONE;
405         c->introducer = NULL;
406         strcpy( c->nick, "" );
407         strcpy( c->pass, "" );
408         strcpy( c->host, "" );
409         strcpy( c->user, "" );
410         strcpy( c->name, "" );
411         strcpy( c->info, "" );
412         for( i = 0; i < MAX_CHANNELS; c->channels[i++] = NULL );
413         strcpy( c->modes, "" );
414         c->oper_by_me = FALSE;
415
416         return c;
417 } /* New_Client */
418
419
420 /* -eof- */