source: conf.c @ edc767b

Last change on this file since edc767b was de8e584, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-05-24T19:57:47Z

Daemon mode is not an experiment anymore, it's running on testing.bitlbee.org
for two weeks already with >30 active connections and not a single crash.

  • Property mode set to 100644
File size: 9.8 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 "proxy.h"
37
38static int conf_loadini( conf_t *conf, char *file );
39
40conf_t *conf_load( int argc, char *argv[] )
41{
42        conf_t *conf;
43        int opt, i, config_missing = 0;
44       
45        conf = g_new0( conf_t, 1 );
46       
47        conf->iface_in = NULL;
48        conf->iface_out = NULL;
49        conf->port = g_strdup( "6667" );
50        conf->nofork = 0;
51        conf->verbose = 0;
52        conf->primary_storage = g_strdup( "xml" );
53        conf->migrate_storage = g_strsplit( "text", ",", -1 );
54        conf->runmode = RUNMODE_INETD;
55        conf->authmode = AUTHMODE_OPEN;
56        conf->auth_pass = NULL;
57        conf->oper_pass = NULL;
58        conf->configdir = g_strdup( CONFIG );
59        conf->plugindir = g_strdup( PLUGINDIR );
60        conf->pidfile = g_strdup( PIDFILE );
61        conf->motdfile = g_strdup( ETCDIR "/motd.txt" );
62        conf->ping_interval = 180;
63        conf->ping_timeout = 300;
64        conf->user = NULL;
65        proxytype = 0;
66       
67        i = conf_loadini( conf, global.conf_file );
68        if( i == 0 )
69        {
70                fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file );
71                return NULL;
72        }
73        else if( i == -1 )
74        {
75                config_missing ++;
76                /* Whine after parsing the options if there was no -c pointing
77                   at a *valid* configuration file. */
78        }
79       
80        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 )
81        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
82        {
83                if( opt == 'i' )
84                {
85                        conf->iface_in = g_strdup( optarg );
86                }
87                else if( opt == 'p' )
88                {
89                        g_free( conf->port );
90                        conf->port = g_strdup( optarg );
91                }
92                else if( opt == 'P' )
93                {
94                        g_free( conf->pidfile );
95                        conf->pidfile = g_strdup( optarg );
96                }
97                else if( opt == 'n' )
98                        conf->nofork = 1;
99                else if( opt == 'v' )
100                        conf->verbose = 1;
101                else if( opt == 'I' )
102                        conf->runmode = RUNMODE_INETD;
103                else if( opt == 'D' )
104                        conf->runmode = RUNMODE_DAEMON;
105                else if( opt == 'F' )
106                        conf->runmode = RUNMODE_FORKDAEMON;
107                else if( opt == 'c' )
108                {
109                        if( strcmp( global.conf_file, optarg ) != 0 )
110                        {
111                                g_free( global.conf_file );
112                                global.conf_file = g_strdup( optarg );
113                                g_free( conf );
114                                /* Re-evaluate arguments. Don't use this option twice,
115                                   you'll end up in an infinite loop! Hope this trick
116                                   works with all libcs BTW.. */
117                                optind = 1;
118                                return conf_load( argc, argv );
119                        }
120                }
121                else if( opt == 'd' )
122                {
123                        g_free( conf->configdir );
124                        conf->configdir = g_strdup( optarg );
125                }
126                else if( opt == 'h' )
127                {
128                        printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
129                                "               [-c <file>] [-d <dir>] [-h]\n"
130                                "\n"
131                                "An IRC-to-other-chat-networks gateway\n"
132                                "\n"
133                                "  -I  Classic/InetD mode. (Default)\n"
134                                "  -D  Daemon mode. (one process serves all)\n"
135                                "  -F  Forking daemon. (one process per client)\n"
136                                "  -u  Run daemon as specified user.\n"
137                                "  -P  Specify PID-file (not for inetd mode)\n"
138                                "  -i  Specify the interface (by IP address) to listen on.\n"
139                                "      (Default: 0.0.0.0 (any interface))\n"
140                                "  -p  Port number to listen on. (Default: 6667)\n"
141                                "  -n  Don't fork.\n"
142                                "  -v  Be verbose (only works in combination with -n)\n"
143                                "  -c  Load alternative configuration file\n"
144                                "  -d  Specify alternative user configuration directory\n"
145                                "  -h  Show this help page.\n" );
146                        return NULL;
147                }
148                else if( opt == 'R' )
149                {
150                        /* We can't load the statefile yet (and should make very sure we do this
151                           only once), so set the filename here and load the state information
152                           when initializing ForkDaemon. (This option only makes sense in that
153                           mode anyway!) */
154                        ipc_master_set_statefile( optarg );
155                }
156                else if( opt == 'u' )
157                {
158                        g_free( conf->user );
159                        conf->user = g_strdup( optarg );
160                }
161        }
162       
163        if( conf->configdir[strlen(conf->configdir)-1] != '/' )
164        {
165                char *s = g_new( char, strlen( conf->configdir ) + 2 );
166               
167                sprintf( s, "%s/", conf->configdir );
168                g_free( conf->configdir );
169                conf->configdir = s;
170        }
171       
172        if( config_missing )
173                fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file );
174       
175        return conf;
176}
177
178static int conf_loadini( conf_t *conf, char *file )
179{
180        ini_t *ini;
181        int i;
182       
183        ini = ini_open( file );
184        if( ini == NULL ) return -1;
185        while( ini_read( ini ) )
186        {
187                if( g_strcasecmp( ini->section, "settings" ) == 0 )
188                {
189                        if( g_strcasecmp( ini->key, "runmode" ) == 0 )
190                        {
191                                if( g_strcasecmp( ini->value, "daemon" ) == 0 )
192                                        conf->runmode = RUNMODE_DAEMON;
193                                else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 )
194                                        conf->runmode = RUNMODE_FORKDAEMON;
195                                else
196                                        conf->runmode = RUNMODE_INETD;
197                        }
198                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
199                        {
200                                g_free( conf->pidfile );
201                                conf->pidfile = g_strdup( ini->value );
202                        }
203                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
204                        {
205                                g_free( conf->iface_in );
206                                conf->iface_in = g_strdup( ini->value );
207                        }
208                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
209                        {
210                                g_free( conf->port );
211                                conf->port = g_strdup( ini->value );
212                        }
213                        else if( g_strcasecmp( ini->key, "clientinterface" ) == 0 )
214                        {
215                                g_free( conf->iface_out );
216                                conf->iface_out = g_strdup( ini->value );
217                        }
218                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
219                        {
220                                if( g_strcasecmp( ini->value, "registered" ) == 0 )
221                                        conf->authmode = AUTHMODE_REGISTERED;
222                                else if( g_strcasecmp( ini->value, "closed" ) == 0 )
223                                        conf->authmode = AUTHMODE_CLOSED;
224                                else
225                                        conf->authmode = AUTHMODE_OPEN;
226                        }
227                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
228                        {
229                                g_free( conf->auth_pass );
230                                conf->auth_pass = g_strdup( ini->value );
231                        }
232                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
233                        {
234                                g_free( conf->oper_pass );
235                                conf->oper_pass = g_strdup( ini->value );
236                        }
237                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
238                        {
239                                g_free( conf->hostname );
240                                conf->hostname = g_strdup( ini->value );
241                        }
242                        else if( g_strcasecmp( ini->key, "configdir" ) == 0 )
243                        {
244                                g_free( conf->configdir );
245                                conf->configdir = g_strdup( ini->value );
246                        }
247                        else if( g_strcasecmp( ini->key, "motdfile" ) == 0 )
248                        {
249                                g_free( conf->motdfile );
250                                conf->motdfile = g_strdup( ini->value );
251                        }
252                        else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
253                        {
254                                g_free( conf->primary_storage );
255                                conf->primary_storage = g_strdup( ini->value );
256                        }
257                        else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
258                        {
259                                g_strfreev( conf->migrate_storage );
260                                conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 );
261                        }
262                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 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_interval = i;
270                        }
271                        else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 )
272                        {
273                                if( sscanf( ini->value, "%d", &i ) != 1 )
274                                {
275                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
276                                        return 0;
277                                }
278                                conf->ping_timeout = i;
279                        }
280                        else if( g_strcasecmp( ini->key, "proxy" ) == 0 )
281                        {
282                                url_t *url = g_new0( url_t, 1 );
283                               
284                                if( !url_set( url, ini->value ) )
285                                {
286                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
287                                        g_free( url );
288                                        return 0;
289                                }
290                               
291                                strncpy( proxyhost, url->host, sizeof( proxyhost ) );
292                                strncpy( proxyuser, url->user, sizeof( proxyuser ) );
293                                strncpy( proxypass, url->pass, sizeof( proxypass ) );
294                                proxyport = url->port;
295                                if( url->proto == PROTO_HTTP )
296                                        proxytype = PROXY_HTTP;
297                                else if( url->proto == PROTO_SOCKS4 )
298                                        proxytype = PROXY_SOCKS4;
299                                else if( url->proto == PROTO_SOCKS5 )
300                                        proxytype = PROXY_SOCKS5;
301                               
302                                g_free( url );
303                        }
304                        else if( g_strcasecmp( ini->key, "user" ) == 0 )
305                        {
306                                g_free( conf->user );
307                                conf->user = g_strdup( ini->value );
308                        }
309                        else
310                        {
311                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key );
312                                return 0;
313                                /* For now just ignore unknown keys... */
314                        }
315                }
316                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
317                {
318                        fprintf( stderr, "Error: Unknown section [%s] in configuration file. "
319                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section );
320                        return 0;
321                }
322        }
323        ini_close( ini );
324       
325        return 1;
326}
327
328void conf_loaddefaults( irc_t *irc )
329{
330        ini_t *ini;
331       
332        ini = ini_open( global.conf_file );
333        if( ini == NULL ) return;
334        while( ini_read( ini ) )
335        {
336                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
337                {
338                        set_t *s = set_find( &irc->set, ini->key );
339                       
340                        if( s )
341                        {
342                                if( s->def ) g_free( s->def );
343                                s->def = g_strdup( ini->value );
344                        }
345                }
346        }
347        ini_close( ini );
348}
Note: See TracBrowser for help on using the repository browser.