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