source: conf.c @ 1c8a7a2

Last change on this file since 1c8a7a2 was dd89a55, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-05-15T17:57:12Z

Fixed various memory leaks/other possible problems after code review.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Configuration reading code                                           */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#include "bitlbee.h"
27
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31#include "conf.h"
32#include "ini.h"
33#include "url.h"
34#include "ipc.h"
35
36#include "protocols/proxy.h"
37
38char *CONF_FILE;
39
40static int conf_loadini( conf_t *conf, char *file );
41
42conf_t *conf_load( int argc, char *argv[] )
43{
44        conf_t *conf;
45        int opt, i;
46       
47        conf = g_new0( conf_t, 1 );
48       
49#ifdef IPV6
50        conf->iface = "::";
51#else
52        conf->iface = "0.0.0.0";
53#endif
54        conf->port = 6667;
55        conf->nofork = 0;
56        conf->verbose = 0;
57        conf->primary_storage = "text";
58        conf->runmode = RUNMODE_INETD;
59        conf->authmode = AUTHMODE_OPEN;
60        conf->auth_pass = NULL;
61        conf->oper_pass = NULL;
62        conf->configdir = g_strdup( CONFIG );
63        conf->plugindir = g_strdup( PLUGINDIR );
64        conf->pidfile = g_strdup( "/var/run/bitlbee.pid" );
65        conf->motdfile = g_strdup( ETCDIR "/motd.txt" );
66        conf->ping_interval = 180;
67        conf->ping_timeout = 300;
68        proxytype = 0;
69       
70        i = conf_loadini( conf, CONF_FILE );
71        if( i == 0 )
72        {
73                fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", CONF_FILE );
74                return( NULL );
75        }
76        else if( i == -1 )
77        {
78                fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE );
79        }
80       
81        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:" ) ) >= 0 )
82        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
83        {
84                if( opt == 'i' )
85                {
86                        conf->iface = g_strdup( optarg );
87                }
88                else if( opt == 'p' )
89                {
90                        if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) )
91                        {
92                                fprintf( stderr, "Invalid port number: %s\n", optarg );
93                                return( NULL );
94                        }
95                        conf->port = i;
96                }
97                else if( opt == 'P' )
98                {
99                        g_free( conf->pidfile );
100                        conf->pidfile = g_strdup( optarg );
101                }
102                else if( opt == 'n' )
103                        conf->nofork = 1;
104                else if( opt == 'v' )
105                        conf->verbose = 1;
106                else if( opt == 'I' )
107                        conf->runmode = RUNMODE_INETD;
108                else if( opt == 'D' )
109                        conf->runmode = RUNMODE_DAEMON;
110                else if( opt == 'F' )
111                        conf->runmode = RUNMODE_FORKDAEMON;
112                else if( opt == 'c' )
113                {
114                        if( strcmp( CONF_FILE, optarg ) != 0 )
115                        {
116                                g_free( CONF_FILE );
117                                CONF_FILE = g_strdup( optarg );
118                                g_free( conf );
119                                /* Re-evaluate arguments. Don't use this option twice,
120                                   you'll end up in an infinite loop! Hope this trick
121                                   works with all libcs BTW.. */
122                                optind = 1;
123                                return( conf_load( argc, argv ) );
124                        }
125                }
126                else if( opt == 'd' )
127                {
128                        g_free( conf->configdir );
129                        conf->configdir = g_strdup( optarg );
130                }
131                else if( opt == 'h' )
132                {
133                        printf( "Usage: bitlbee [-D [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
134                                "               [-c <file>] [-d <dir>] [-h]\n"
135                                "\n"
136                                "An IRC-to-other-chat-networks gateway\n"
137                                "\n"
138                                "  -I  Classic/InetD mode. (Default)\n"
139                                "  -D  Daemon mode. (Still EXPERIMENTAL!)\n"
140                                "  -F  Forking daemon. (one process per client)\n"
141                                "  -P  Specify PID-file (not for inetd mode)\n"
142                                "  -i  Specify the interface (by IP address) to listen on.\n"
143                                "      (Default: 0.0.0.0 (any interface))\n"
144                                "  -p  Port number to listen on. (Default: 6667)\n"
145                                "  -n  Don't fork.\n"
146                                "  -v  Be verbose (only works in combination with -n)\n"
147                                "  -c  Load alternative configuration file\n"
148                                "  -d  Specify alternative user configuration directory\n"
149                                "  -h  Show this help page.\n" );
150                        return( NULL );
151                }
152                else if( opt == 'R' )
153                {
154                        /* We can't load the statefile yet (and should make very sure we do this
155                           only once), so set the filename here and load the state information
156                           when initializing ForkDaemon. (This option only makes sense in that
157                           mode anyway!) */
158                        ipc_master_set_statefile( optarg );
159                }
160        }
161       
162        if( conf->configdir[strlen(conf->configdir)-1] != '/' )
163        {
164                char *s = g_new( char, strlen( conf->configdir ) + 2 );
165               
166                sprintf( s, "%s/", conf->configdir );
167                g_free( conf->configdir );
168                conf->configdir = s;
169        }
170       
171        return( conf );
172}
173
174static int conf_loadini( conf_t *conf, char *file )
175{
176        ini_t *ini;
177        int i;
178       
179        ini = ini_open( file );
180        if( ini == NULL ) return( -1 );
181        while( ini_read( ini ) )
182        {
183                if( g_strcasecmp( ini->section, "settings" ) == 0 )
184                {
185                        if( g_strcasecmp( ini->key, "runmode" ) == 0 )
186                        {
187                                if( g_strcasecmp( ini->value, "daemon" ) == 0 )
188                                        conf->runmode = RUNMODE_DAEMON;
189                                else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 )
190                                        conf->runmode = RUNMODE_FORKDAEMON;
191                                else
192                                        conf->runmode = RUNMODE_INETD;
193                        }
194                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
195                        {
196                                g_free( conf->pidfile );
197                                conf->pidfile = g_strdup( ini->value );
198                        }
199                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
200                        {
201                                conf->iface = g_strdup( ini->value );
202                        }
203                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
204                        {
205                                if( ( sscanf( ini->value, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) )
206                                {
207                                        fprintf( stderr, "Invalid port number: %s\n", ini->value );
208                                        return( 0 );
209                                }
210                                conf->port = i;
211                        }
212                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
213                        {
214                                if( g_strcasecmp( ini->value, "registered" ) == 0 )
215                                        conf->authmode = AUTHMODE_REGISTERED;
216                                else if( g_strcasecmp( ini->value, "closed" ) == 0 )
217                                        conf->authmode = AUTHMODE_CLOSED;
218                                else
219                                        conf->authmode = AUTHMODE_OPEN;
220                        }
221                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
222                        {
223                                conf->auth_pass = g_strdup( ini->value );
224                        }
225                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
226                        {
227                                conf->oper_pass = g_strdup( ini->value );
228                        }
229                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
230                        {
231                                conf->hostname = g_strdup( ini->value );
232                        }
233                        else if( g_strcasecmp( ini->key, "configdir" ) == 0 )
234                        {
235                                g_free( conf->configdir );
236                                conf->configdir = g_strdup( ini->value );
237                        }
238                        else if( g_strcasecmp( ini->key, "motdfile" ) == 0 )
239                        {
240                                g_free( conf->motdfile );
241                                conf->motdfile = g_strdup( ini->value );
242                        }
243                        else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
244                        {
245                                g_free( conf->primary_storage );
246                                conf->primary_storage = g_strdup( ini->value );
247                        }
248                        else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
249                        {
250                                g_strfreev( conf->migrate_storage );
251                                conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 );
252                        }
253                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
254                        {
255                                if( sscanf( ini->value, "%d", &i ) != 1 )
256                                {
257                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
258                                        return( 0 );
259                                }
260                                conf->ping_interval = i;
261                        }
262                        else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 )
263                        {
264                                if( sscanf( ini->value, "%d", &i ) != 1 )
265                                {
266                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
267                                        return( 0 );
268                                }
269                                conf->ping_timeout = i;
270                        }
271                        else if( g_strcasecmp( ini->key, "proxy" ) == 0 )
272                        {
273                                url_t *url = g_new0( url_t, 1 );
274                               
275                                if( !url_set( url, ini->value ) )
276                                {
277                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
278                                        g_free( url );
279                                        return( 0 );
280                                }
281                               
282                                strncpy( proxyhost, url->host, sizeof( proxyhost ) );
283                                strncpy( proxyuser, url->user, sizeof( proxyuser ) );
284                                strncpy( proxypass, url->pass, sizeof( proxypass ) );
285                                proxyport = url->port;
286                                if( url->proto == PROTO_HTTP )
287                                        proxytype = PROXY_HTTP;
288                                else if( url->proto == PROTO_SOCKS4 )
289                                        proxytype = PROXY_SOCKS4;
290                                else if( url->proto == PROTO_SOCKS5 )
291                                        proxytype = PROXY_SOCKS5;
292                               
293                                g_free( url );
294                        }
295                        else
296                        {
297                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key );
298                                return( 0 );
299                                /* For now just ignore unknown keys... */
300                        }
301                }
302                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
303                {
304                        fprintf( stderr, "Error: Unknown section [%s] in configuration file. "
305                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section );
306                        return( 0 );
307                }
308        }
309        ini_close( ini );
310       
311        return( 1 );
312}
313
314void conf_loaddefaults( irc_t *irc )
315{
316        ini_t *ini;
317       
318        ini = ini_open( CONF_FILE );
319        if( ini == NULL ) return;
320        while( ini_read( ini ) )
321        {
322                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
323                {
324                        set_t *s = set_find( irc, ini->key );
325                       
326                        if( s )
327                        {
328                                if( s->def ) g_free( s->def );
329                                s->def = g_strdup( ini->value );
330                        }
331                }
332        }
333        ini_close( ini );
334}
Note: See TracBrowser for help on using the repository browser.