source: conf.c @ f665dab

Last change on this file since f665dab was 1d2e3c2, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-02-02T13:59:14Z

Added RESTART command for easier upgrades without losing IPC connections.
(Obviously only works well for forking daemon mode.)

  • Property mode set to 100644
File size: 9.2 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                                "  -i  Specify the interface (by IP address) to listen on.\n"
142                                "      (Default: 0.0.0.0 (any interface))\n"
143                                "  -p  Port number to listen on. (Default: 6667)\n"
144                                "  -n  Don't fork.\n"
145                                "  -v  Be verbose (only works in combination with -n)\n"
146                                "  -c  Load alternative configuration file\n"
147                                "  -d  Specify alternative user configuration directory\n"
148                                "  -h  Show this help page.\n" );
149                        return( NULL );
150                }
151                else if( opt == 'R' )
152                {
153                        /* We can't load the statefile yet (and should make very sure we do this
154                           only once), so set the filename here and load the state information
155                           when initializing ForkDaemon. (This option only makes sense in that
156                           mode anyway!) */
157                        ipc_master_set_statefile( optarg );
158                }
159        }
160       
161        if( conf->configdir[strlen(conf->configdir)-1] != '/' )
162        {
163                char *s = g_new( char, strlen( conf->configdir ) + 2 );
164               
165                sprintf( s, "%s/", conf->configdir );
166                g_free( conf->configdir );
167                conf->configdir = s;
168        }
169       
170        return( conf );
171}
172
173static int conf_loadini( conf_t *conf, char *file )
174{
175        ini_t *ini;
176        int i;
177       
178        ini = ini_open( file );
179        if( ini == NULL ) return( -1 );
180        while( ini_read( ini ) )
181        {
182                if( g_strcasecmp( ini->section, "settings" ) == 0 )
183                {
184                        if( g_strcasecmp( ini->key, "runmode" ) == 0 )
185                        {
186                                if( g_strcasecmp( ini->value, "daemon" ) == 0 )
187                                        conf->runmode = RUNMODE_DAEMON;
188                                else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 )
189                                        conf->runmode = RUNMODE_FORKDAEMON;
190                                else
191                                        conf->runmode = RUNMODE_INETD;
192                        }
193                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
194                        {
195                                g_free( conf->pidfile );
196                                conf->pidfile = g_strdup( ini->value );
197                        }
198                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
199                        {
200                                conf->iface = g_strdup( ini->value );
201                        }
202                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
203                        {
204                                if( ( sscanf( ini->value, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) )
205                                {
206                                        fprintf( stderr, "Invalid port number: %s\n", ini->value );
207                                        return( 0 );
208                                }
209                                conf->port = i;
210                        }
211                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
212                        {
213                                if( g_strcasecmp( ini->value, "registered" ) == 0 )
214                                        conf->authmode = AUTHMODE_REGISTERED;
215                                else if( g_strcasecmp( ini->value, "closed" ) == 0 )
216                                        conf->authmode = AUTHMODE_CLOSED;
217                                else
218                                        conf->authmode = AUTHMODE_OPEN;
219                        }
220                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
221                        {
222                                conf->auth_pass = g_strdup( ini->value );
223                        }
224                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
225                        {
226                                conf->oper_pass = g_strdup( ini->value );
227                        }
228                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
229                        {
230                                conf->hostname = g_strdup( ini->value );
231                        }
232                        else if( g_strcasecmp( ini->key, "configdir" ) == 0 )
233                        {
234                                g_free( conf->configdir );
235                                conf->configdir = g_strdup( ini->value );
236                        }
237                        else if( g_strcasecmp( ini->key, "motdfile" ) == 0 )
238                        {
239                                g_free( conf->motdfile );
240                                conf->motdfile = g_strdup( ini->value );
241                        }
242                        else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
243                        {
244                                g_free( conf->primary_storage );
245                                conf->primary_storage = g_strdup( ini->value );
246                        }
247                        else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
248                        {
249                                g_strfreev( conf->migrate_storage );
250                                conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 );
251                        }
252                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
253                        {
254                                if( sscanf( ini->value, "%d", &i ) != 1 )
255                                {
256                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
257                                        return( 0 );
258                                }
259                                conf->ping_interval = i;
260                        }
261                        else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 )
262                        {
263                                if( sscanf( ini->value, "%d", &i ) != 1 )
264                                {
265                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
266                                        return( 0 );
267                                }
268                                conf->ping_timeout = i;
269                        }
270                        else if( g_strcasecmp( ini->key, "proxy" ) == 0 )
271                        {
272                                url_t *url = g_new0( url_t, 1 );
273                               
274                                if( !url_set( url, ini->value ) )
275                                {
276                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
277                                        g_free( url );
278                                        return( 0 );
279                                }
280                               
281                                strncpy( proxyhost, url->host, sizeof( proxyhost ) );
282                                strncpy( proxyuser, url->user, sizeof( proxyuser ) );
283                                strncpy( proxypass, url->pass, sizeof( proxypass ) );
284                                proxyport = url->port;
285                                if( url->proto == PROTO_HTTP )
286                                        proxytype = PROXY_HTTP;
287                                else if( url->proto == PROTO_SOCKS4 )
288                                        proxytype = PROXY_SOCKS4;
289                                else if( url->proto == PROTO_SOCKS5 )
290                                        proxytype = PROXY_SOCKS5;
291                               
292                                g_free( url );
293                        }
294                        else
295                        {
296                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key );
297                                return( 0 );
298                                /* For now just ignore unknown keys... */
299                        }
300                }
301                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
302                {
303                        fprintf( stderr, "Error: Unknown section [%s] in configuration file. "
304                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section );
305                        return( 0 );
306                }
307        }
308        ini_close( ini );
309       
310        return( 1 );
311}
312
313void conf_loaddefaults( irc_t *irc )
314{
315        ini_t *ini;
316       
317        ini = ini_open( CONF_FILE );
318        if( ini == NULL ) return;
319        while( ini_read( ini ) )
320        {
321                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
322                {
323                        set_t *s = set_find( irc, ini->key );
324                       
325                        if( s )
326                        {
327                                if( s->def ) g_free( s->def );
328                                s->def = g_strdup( ini->value );
329                        }
330                }
331        }
332        ini_close( ini );
333}
Note: See TracBrowser for help on using the repository browser.