9d98ede357e4a900852d879e2b8c81f136a11381
[ngircd-alex.git] / src / ngircd / conf.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: conf.c,v 1.8 2002/01/02 02:44:36 alex Exp $
13  *
14  * conf.h: Konfiguration des ngircd
15  *
16  * $Log: conf.c,v $
17  * Revision 1.8  2002/01/02 02:44:36  alex
18  * - neue Defines fuer max. Anzahl Server und Operatoren.
19  *
20  * Revision 1.7  2002/01/01 18:25:44  alex
21  * - #include's fuer stdlib.h ergaenzt.
22  *
23  * Revision 1.6  2001/12/31 02:18:51  alex
24  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
25  * - neuen Header "defines.h" mit (fast) allen Konstanten.
26  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
27  *
28  * Revision 1.5  2001/12/30 19:26:11  alex
29  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
30  *
31  * Revision 1.4  2001/12/26 22:48:53  alex
32  * - MOTD-Datei ist nun konfigurierbar und wird gelesen.
33  *
34  * Revision 1.3  2001/12/26 14:45:37  alex
35  * - "Code Cleanups".
36  *
37  * Revision 1.2  2001/12/26 03:19:57  alex
38  * - erste Konfigurations-Variablen definiert: PING/PONG-Timeout.
39  *
40  * Revision 1.1  2001/12/12 17:18:20  alex
41  * - Modul fuer Server-Konfiguration begonnen.
42  */
43
44
45 #include <portab.h>
46 #include "global.h"
47
48 #include <imp.h>
49 #include <assert.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #include "client.h"
56 #include "log.h"
57 #include "tool.h"
58
59 #include <exp.h>
60 #include "conf.h"
61
62
63 LOCAL VOID Read_Config( VOID );
64
65 GLOBAL VOID Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg );
66 GLOBAL VOID Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg );
67 GLOBAL VOID Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg );
68
69 LOCAL VOID Validate_Config( VOID );
70
71
72 GLOBAL VOID Conf_Init( VOID )
73 {
74         /* Konfigurationsvariablen initialisieren: zunaechst Default-
75          * Werte setzen, dann Konfigurationsdtaei einlesen. */
76
77         strcpy( Conf_File, "/usr/local/etc/ngircd.conf" );
78
79         strcpy( Conf_ServerName, "" );
80         strcpy( Conf_ServerInfo, PACKAGE" "VERSION );
81
82         strcpy( Conf_MotdFile, "/usr/local/etc/ngircd.motd" );
83
84         Conf_ListenPorts_Count = 0;
85         
86         Conf_PingTimeout = 120;
87         Conf_PongTimeout = 10;
88
89         Conf_ConnectRetry = 60;
90
91         Conf_Oper_Count = 0;
92
93         Conf_Server_Count = 0;
94
95         /* Konfigurationsdatei einlesen und validieren */
96         Read_Config( );
97         Validate_Config( );
98 } /* Config_Init */
99
100
101 GLOBAL VOID Conf_Exit( VOID )
102 {
103         /* ... */
104 } /* Config_Exit */
105
106
107 LOCAL VOID Read_Config( VOID )
108 {
109         /* Konfigurationsdatei einlesen. */
110
111         CHAR section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
112         INT line;
113         FILE *fd;
114
115         fd = fopen( Conf_File, "r" );
116         if( ! fd )
117         {
118                 /* Keine Konfigurationsdatei gefunden */
119                 Log( LOG_ALERT, "Can't read configuration \"%s\": %s", Conf_File, strerror( errno ));
120                 Log( LOG_ALERT, PACKAGE" exiting due to fatal errors!" );
121                 exit( 1 );
122         }
123
124         line = 0;
125         strcpy( section, "" );
126         while( TRUE )
127         {
128                 if( ! fgets( str, LINE_LEN, fd )) break;
129                 ngt_TrimStr( str );
130                 line++;
131
132                 /* Kommentarzeilen und leere Zeilen ueberspringen */
133                 if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue;
134
135                 /* Anfang eines Abschnittes? */
136                 if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' ))
137                 {
138                         strcpy( section, str );
139                         if( strcasecmp( section, "[GLOBAL]" ) == 0 ) continue;
140                         if( strcasecmp( section, "[OPERATOR]" ) == 0 )
141                         {
142                                 if( Conf_Oper_Count + 1 > MAX_OPERATORS ) Log( LOG_ERR, "Too many operators configured." );
143                                 else
144                                 {
145                                         /* neuen Operator initialisieren */
146                                         strcpy( Conf_Oper[Conf_Oper_Count].name, "" );
147                                         strcpy( Conf_Oper[Conf_Oper_Count].pwd, "" );
148                                         Conf_Oper_Count++;
149                                 }
150                                 continue;
151                         }
152                         if( strcasecmp( section, "[SERVER]" ) == 0 )
153                         {
154                                 if( Conf_Server_Count + 1 > MAX_SERVERS ) Log( LOG_ERR, "Too many servers configured." );
155                                 else
156                                 {
157                                         /* neuen Server ("Peer") initialisieren */
158                                         strcpy( Conf_Server[Conf_Server_Count].host, "" );
159                                         strcpy( Conf_Server[Conf_Server_Count].ip, "" );
160                                         strcpy( Conf_Server[Conf_Server_Count].name, "" );
161                                         strcpy( Conf_Server[Conf_Server_Count].pwd, "" );
162                                         Conf_Server[Conf_Server_Count].port = 0;
163                                         Conf_Server[Conf_Server_Count].lasttry = 0;
164                                         Conf_Server[Conf_Server_Count].res_stat = NULL;
165                                         Conf_Server_Count++;
166                                 }
167                                 continue;
168                         }
169                         Log( LOG_ERR, "%s, line %d: Unknown section \"%s\"!", Conf_File, line, section );
170                         section[0] = 0x1;
171                 }
172                 if( section[0] == 0x1 ) continue;
173
174                 /* In Variable und Argument zerlegen */
175                 ptr = strchr( str, '=' );
176                 if( ! ptr )
177                 {
178                         Log( LOG_ERR, "%s, line %d: Syntax error!", Conf_File, line );
179                         continue;
180                 }
181                 *ptr = '\0';
182                 var = str; ngt_TrimStr( var );
183                 arg = ptr + 1; ngt_TrimStr( arg );
184
185                 if( strcasecmp( section, "[GLOBAL]" ) == 0 ) Handle_GLOBAL( line, var, arg );
186                 else if( strcasecmp( section, "[OPERATOR]" ) == 0 ) Handle_OPERATOR( line, var, arg );
187                 else if( strcasecmp( section, "[SERVER]" ) == 0 ) Handle_SERVER( line, var, arg );
188                 else Log( LOG_ERR, "%s, line %d: Variable \"%s\" outside section!", Conf_File, line, var );
189         }
190         
191         fclose( fd );
192 } /* Read_Config */
193
194
195 GLOBAL VOID Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
196 {
197         CHAR *ptr;
198         INT port;
199         
200         assert( Line > 0 );
201         assert( Var != NULL );
202         assert( Arg != NULL );
203         
204         if( strcasecmp( Var, "Name" ) == 0 )
205         {
206                 /* Der Server-Name */
207                 strncpy( Conf_ServerName, Arg, CLIENT_ID_LEN );
208                 Conf_ServerName[CLIENT_ID_LEN - 1] = '\0';
209                 return;
210         }
211         if( strcasecmp( Var, "Info" ) == 0 )
212         {
213                 /* Server-Info-Text */
214                 strncpy( Conf_ServerInfo, Arg, CLIENT_INFO_LEN );
215                 Conf_ServerInfo[CLIENT_INFO_LEN - 1] = '\0';
216                 return;
217         }
218         if( strcasecmp( Var, "Ports" ) == 0 )
219         {
220                 /* Ports, durch "," getrennt, auf denen der Server
221                 * Verbindungen annehmen soll */
222                 ptr = strtok( Arg, "," );
223                 while( ptr )
224                 {
225                         ngt_TrimStr( ptr );
226                         port = atol( ptr );
227                         if( Conf_ListenPorts_Count + 1 > MAX_LISTEN_PORTS ) Log( LOG_ERR, "Too many listen ports configured. Port %ld ignored.", port );
228                         else
229                         {
230                                 if( port > 0 && port < 0xFFFF ) Conf_ListenPorts[Conf_ListenPorts_Count++] = port;
231                                 else Log( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!", Conf_File, Line, port );
232                         }
233                         ptr = strtok( NULL, "," );
234                 }
235                 return;
236         }
237         if( strcasecmp( Var, "MotdFile" ) == 0 )
238         {
239                 /* Datei mit der "message of the day" (MOTD) */
240                 strncpy( Conf_MotdFile, Arg, FNAME_LEN );
241                 Conf_MotdFile[FNAME_LEN - 1] = '\0';
242                 return;
243         }
244         if( strcasecmp( Var, "PingTimeout" ) == 0 )
245         {
246                 /* PING-Timeout */
247                 Conf_PingTimeout = atoi( Arg );
248                 if(( Conf_PingTimeout ) < 5 ) Conf_PingTimeout = 5;
249                 return;
250         }
251         if( strcasecmp( Var, "PongTimeout" ) == 0 )
252         {
253                 /* PONG-Timeout */
254                 Conf_PongTimeout = atoi( Arg );
255                 if(( Conf_PongTimeout ) < 5 ) Conf_PongTimeout = 5;
256                 return;
257         }
258         if( strcasecmp( Var, "ConnectRetry" ) == 0 )
259         {
260                 /* Sekunden zwischen Verbindungsversuchen zu anderen Servern */
261                 Conf_ConnectRetry = atoi( Arg );
262                 if(( Conf_ConnectRetry ) < 5 ) Conf_ConnectRetry = 5;
263                 return;
264         }
265                 
266         Log( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", Conf_File, Line, Var );
267 } /* Handle_GLOBAL */
268
269
270 GLOBAL VOID Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg )
271 {
272         assert( Line > 0 );
273         assert( Var != NULL );
274         assert( Arg != NULL );
275         assert( Conf_Oper_Count > 0 );
276
277         if( strcasecmp( Var, "Name" ) == 0 )
278         {
279                 /* Name des IRC Operator */
280                 strncpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, CLIENT_ID_LEN );
281                 Conf_Oper[Conf_Oper_Count - 1].name[CLIENT_ID_LEN - 1] = '\0';
282                 return;
283         }
284         if( strcasecmp( Var, "Password" ) == 0 )
285         {
286                 /* Passwort des IRC Operator */
287                 strncpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, CLIENT_PASS_LEN );
288                 Conf_Oper[Conf_Oper_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0';
289                 return;
290         }
291         
292         Log( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!", Conf_File, Line, Var );
293 } /* Handle_OPERATOR */
294
295
296 GLOBAL VOID Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg )
297 {
298         INT port;
299         
300         assert( Line > 0 );
301         assert( Var != NULL );
302         assert( Arg != NULL );
303
304         if( strcasecmp( Var, "Host" ) == 0 )
305         {
306                 /* Hostname des Servers */
307                 strncpy( Conf_Server[Conf_Server_Count - 1].host, Arg, HOST_LEN );
308                 Conf_Server[Conf_Server_Count - 1].host[HOST_LEN - 1] = '\0';
309                 return;
310         }
311         if( strcasecmp( Var, "Name" ) == 0 )
312         {
313                 /* Name des Servers ("Nick") */
314                 strncpy( Conf_Server[Conf_Server_Count - 1].name, Arg, CLIENT_PASS_LEN );
315                 Conf_Server[Conf_Server_Count - 1].name[CLIENT_PASS_LEN - 1] = '\0';
316                 return;
317         }
318         if( strcasecmp( Var, "Password" ) == 0 )
319         {
320                 /* Passwort des Servers */
321                 strncpy( Conf_Server[Conf_Server_Count - 1].pwd, Arg, CLIENT_PASS_LEN );
322                 Conf_Server[Conf_Server_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0';
323                 return;
324         }
325         if( strcasecmp( Var, "Port" ) == 0 )
326         {
327                 /* Port, zu dem Verbunden werden soll */
328                 port = atol( Arg );
329                 if( port > 0 && port < 0xFFFF ) Conf_Server[Conf_Server_Count - 1].port = port;
330                 else Log( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!", Conf_File, Line, port );
331                 return;
332         }
333         
334         Log( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!", Conf_File, Line, Var );
335 } /* Handle_SERVER */
336
337
338 LOCAL VOID Validate_Config( VOID )
339 {
340         /* Konfiguration ueberpruefen */
341         
342         if( ! Conf_ServerName[0] )
343         {
344                 /* Kein Servername konfiguriert */
345                 Log( LOG_ALERT, "No server name configured (use \"ServerName\")!", Conf_File, strerror( errno ));
346                 Log( LOG_ALERT, PACKAGE" exiting due to fatal errors!" );
347                 exit( 1 );
348         }
349 } /* Validate_Config */
350
351 /* -eof- */