source: conf.c @ 5a61bf59

Last change on this file since 5a61bf59 was 21c87a7, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-14T09:27:50Z

Merging loads of stuff from mainline.

  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[c92e6801]4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
[b7d3cc34]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"
[54879ab]34#include "ipc.h"
[b7d3cc34]35
[df1694b]36#include "proxy.h"
[b7d3cc34]37
38static int conf_loadini( conf_t *conf, char *file );
39
40conf_t *conf_load( int argc, char *argv[] )
41{
42        conf_t *conf;
[eeb85a8]43        int opt, i, config_missing = 0;
[b7d3cc34]44       
45        conf = g_new0( conf_t, 1 );
46       
[aefaac3a]47        conf->iface_in = NULL;
48        conf->iface_out = NULL;
[d75597b]49        conf->port = g_strdup( "6667" );
[b7d3cc34]50        conf->nofork = 0;
51        conf->verbose = 0;
[d75597b]52        conf->primary_storage = g_strdup( "xml" );
[00ab350]53        conf->migrate_storage = g_strsplit( "text", ",", -1 );
[b7d3cc34]54        conf->runmode = RUNMODE_INETD;
55        conf->authmode = AUTHMODE_OPEN;
[d25f6fc]56        conf->auth_pass = NULL;
57        conf->oper_pass = NULL;
[b7d3cc34]58        conf->configdir = g_strdup( CONFIG );
[4bfca70]59        conf->plugindir = g_strdup( PLUGINDIR );
[7e0af53]60        conf->pidfile = g_strdup( PIDFILE );
[b7d3cc34]61        conf->motdfile = g_strdup( ETCDIR "/motd.txt" );
62        conf->ping_interval = 180;
63        conf->ping_timeout = 300;
[aaf92a9]64        conf->user = NULL;
[a02f34f]65        conf->ft_max_size = SIZE_MAX;
66        conf->ft_max_kbps = G_MAXUINT;
67        conf->ft_listen = NULL;
[90cd6c4]68        conf->protocols = NULL;
[f4a5940]69        proxytype = 0;
[b7d3cc34]70       
[eeb85a8]71        i = conf_loadini( conf, global.conf_file );
[b7d3cc34]72        if( i == 0 )
73        {
[eeb85a8]74                fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file );
75                return NULL;
[b7d3cc34]76        }
77        else if( i == -1 )
78        {
[eeb85a8]79                config_missing ++;
80                /* Whine after parsing the options if there was no -c pointing
81                   at a *valid* configuration file. */
[b7d3cc34]82        }
83       
[3d1481f]84        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:V" ) ) >= 0 )
[f4a5940]85        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
[b7d3cc34]86        {
87                if( opt == 'i' )
88                {
[aefaac3a]89                        conf->iface_in = g_strdup( optarg );
[b7d3cc34]90                }
91                else if( opt == 'p' )
92                {
[e9b755e]93                        g_free( conf->port );
94                        conf->port = g_strdup( optarg );
[b7d3cc34]95                }
[dd89a55]96                else if( opt == 'P' )
[34b17d9]97                {
98                        g_free( conf->pidfile );
99                        conf->pidfile = g_strdup( optarg );
100                }
[b7d3cc34]101                else if( opt == 'n' )
[74c119d]102                        conf->nofork = 1;
[b7d3cc34]103                else if( opt == 'v' )
[74c119d]104                        conf->verbose = 1;
[b7d3cc34]105                else if( opt == 'I' )
[74c119d]106                        conf->runmode = RUNMODE_INETD;
[b7d3cc34]107                else if( opt == 'D' )
[74c119d]108                        conf->runmode = RUNMODE_DAEMON;
[d25f6fc]109                else if( opt == 'F' )
[74c119d]110                        conf->runmode = RUNMODE_FORKDAEMON;
[b7d3cc34]111                else if( opt == 'c' )
112                {
[eeb85a8]113                        if( strcmp( global.conf_file, optarg ) != 0 )
[b7d3cc34]114                        {
[eeb85a8]115                                g_free( global.conf_file );
116                                global.conf_file = g_strdup( optarg );
[b7d3cc34]117                                g_free( conf );
[f4a5940]118                                /* Re-evaluate arguments. Don't use this option twice,
119                                   you'll end up in an infinite loop! Hope this trick
120                                   works with all libcs BTW.. */
[74c119d]121                                optind = 1;
[eeb85a8]122                                return conf_load( argc, argv );
[b7d3cc34]123                        }
124                }
125                else if( opt == 'd' )
126                {
127                        g_free( conf->configdir );
128                        conf->configdir = g_strdup( optarg );
129                }
130                else if( opt == 'h' )
131                {
[d4589cb]132                        printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
[7c9db24]133                                "               [-c <file>] [-d <dir>] [-x] [-h]\n"
[b7d3cc34]134                                "\n"
135                                "An IRC-to-other-chat-networks gateway\n"
136                                "\n"
137                                "  -I  Classic/InetD mode. (Default)\n"
[de8e584]138                                "  -D  Daemon mode. (one process serves all)\n"
[d25f6fc]139                                "  -F  Forking daemon. (one process per client)\n"
[aaf92a9]140                                "  -u  Run daemon as specified user.\n"
[7cf85e7]141                                "  -P  Specify PID-file (not for inetd mode)\n"
[b7d3cc34]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"
[7c9db24]149                                "  -x  Command-line interface to password encryption/hashing\n"
[3d1481f]150                                "  -h  Show this help page.\n"
151                                "  -V  Show version info.\n" );
152                        return NULL;
153                }
154                else if( opt == 'V' )
155                {
156                        printf( "BitlBee %s\nAPI version %06x\n",
157                                BITLBEE_VERSION, BITLBEE_VERSION_CODE );
[eeb85a8]158                        return NULL;
[b7d3cc34]159                }
[e0798cc]160                else if( opt == 'R' )
161                {
162                        /* Backward compatibility; older BitlBees passed this
163                           info using a command-line flag. Allow people to
164                           upgrade from such a version for now. */
165                        setenv( "_BITLBEE_RESTART_STATE", optarg, 0 );
166                }
[aaf92a9]167                else if( opt == 'u' )
168                {
169                        g_free( conf->user );
170                        conf->user = g_strdup( optarg );
171                }
[b7d3cc34]172        }
173       
174        if( conf->configdir[strlen(conf->configdir)-1] != '/' )
175        {
176                char *s = g_new( char, strlen( conf->configdir ) + 2 );
177               
178                sprintf( s, "%s/", conf->configdir );
179                g_free( conf->configdir );
180                conf->configdir = s;
181        }
182       
[eeb85a8]183        if( config_missing )
184                fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file );
185       
186        return conf;
[b7d3cc34]187}
188
189static int conf_loadini( conf_t *conf, char *file )
190{
191        ini_t *ini;
192        int i;
193       
194        ini = ini_open( file );
[eeb85a8]195        if( ini == NULL ) return -1;
[b7d3cc34]196        while( ini_read( ini ) )
197        {
198                if( g_strcasecmp( ini->section, "settings" ) == 0 )
199                {
200                        if( g_strcasecmp( ini->key, "runmode" ) == 0 )
201                        {
202                                if( g_strcasecmp( ini->value, "daemon" ) == 0 )
203                                        conf->runmode = RUNMODE_DAEMON;
[d25f6fc]204                                else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 )
205                                        conf->runmode = RUNMODE_FORKDAEMON;
[b7d3cc34]206                                else
207                                        conf->runmode = RUNMODE_INETD;
208                        }
[34b17d9]209                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
210                        {
211                                g_free( conf->pidfile );
212                                conf->pidfile = g_strdup( ini->value );
213                        }
[b7d3cc34]214                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
215                        {
[aefaac3a]216                                g_free( conf->iface_in );
217                                conf->iface_in = g_strdup( ini->value );
[b7d3cc34]218                        }
219                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
220                        {
[aaf92a9]221                                g_free( conf->port );
[e9b755e]222                                conf->port = g_strdup( ini->value );
[b7d3cc34]223                        }
[aefaac3a]224                        else if( g_strcasecmp( ini->key, "clientinterface" ) == 0 )
225                        {
226                                g_free( conf->iface_out );
227                                conf->iface_out = g_strdup( ini->value );
228                        }
[b7d3cc34]229                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
230                        {
231                                if( g_strcasecmp( ini->value, "registered" ) == 0 )
232                                        conf->authmode = AUTHMODE_REGISTERED;
233                                else if( g_strcasecmp( ini->value, "closed" ) == 0 )
234                                        conf->authmode = AUTHMODE_CLOSED;
235                                else
236                                        conf->authmode = AUTHMODE_OPEN;
237                        }
238                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
239                        {
[aaf92a9]240                                g_free( conf->auth_pass );
[d25f6fc]241                                conf->auth_pass = g_strdup( ini->value );
242                        }
243                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
244                        {
[aaf92a9]245                                g_free( conf->oper_pass );
[d25f6fc]246                                conf->oper_pass = g_strdup( ini->value );
[b7d3cc34]247                        }
248                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
249                        {
[aaf92a9]250                                g_free( conf->hostname );
[b7d3cc34]251                                conf->hostname = g_strdup( ini->value );
252                        }
253                        else if( g_strcasecmp( ini->key, "configdir" ) == 0 )
254                        {
255                                g_free( conf->configdir );
256                                conf->configdir = g_strdup( ini->value );
257                        }
258                        else if( g_strcasecmp( ini->key, "motdfile" ) == 0 )
259                        {
260                                g_free( conf->motdfile );
261                                conf->motdfile = g_strdup( ini->value );
[1ee6c18]262                        }
[b73ac9c]263                        else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
[1ee6c18]264                        {
[b73ac9c]265                                g_free( conf->primary_storage );
266                                conf->primary_storage = g_strdup( ini->value );
267                        }
268                        else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
269                        {
270                                g_strfreev( conf->migrate_storage );
[dd14ecc]271                                conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 );
[b7d3cc34]272                        }
273                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
274                        {
275                                if( sscanf( ini->value, "%d", &i ) != 1 )
276                                {
277                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
[eeb85a8]278                                        return 0;
[b7d3cc34]279                                }
280                                conf->ping_interval = i;
281                        }
282                        else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 )
283                        {
284                                if( sscanf( ini->value, "%d", &i ) != 1 )
285                                {
286                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
[eeb85a8]287                                        return 0;
[b7d3cc34]288                                }
289                                conf->ping_timeout = i;
290                        }
291                        else if( g_strcasecmp( ini->key, "proxy" ) == 0 )
292                        {
293                                url_t *url = g_new0( url_t, 1 );
294                               
295                                if( !url_set( url, ini->value ) )
296                                {
297                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
298                                        g_free( url );
[eeb85a8]299                                        return 0;
[b7d3cc34]300                                }
301                               
302                                strncpy( proxyhost, url->host, sizeof( proxyhost ) );
303                                strncpy( proxyuser, url->user, sizeof( proxyuser ) );
304                                strncpy( proxypass, url->pass, sizeof( proxypass ) );
305                                proxyport = url->port;
306                                if( url->proto == PROTO_HTTP )
307                                        proxytype = PROXY_HTTP;
308                                else if( url->proto == PROTO_SOCKS4 )
309                                        proxytype = PROXY_SOCKS4;
310                                else if( url->proto == PROTO_SOCKS5 )
311                                        proxytype = PROXY_SOCKS5;
312                               
313                                g_free( url );
314                        }
[aaf92a9]315                        else if( g_strcasecmp( ini->key, "user" ) == 0 )
316                        {
317                                g_free( conf->user );
318                                conf->user = g_strdup( ini->value );
319                        }
[a02f34f]320                        else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 )
321                        {
322                                size_t ft_max_size;
323                                if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 )
324                                {
325                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
326                                        return 0;
327                                }
328                                conf->ft_max_size = ft_max_size;
329                        }
330                        else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 )
331                        {
332                                if( sscanf( ini->value, "%d", &i ) != 1 )
333                                {
334                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
335                                        return 0;
336                                }
337                                conf->ft_max_kbps = i;
338                        }
339                        else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 )
340                        {
341                                g_free( conf->ft_listen );
342                                conf->ft_listen = g_strdup( ini->value );
343                        }
[90cd6c4]344                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
345                        {
346                                g_strfreev( conf->protocols );
347                                conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 );
348                        }
[b7d3cc34]349                        else
350                        {
[489f996]351                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line );
[eeb85a8]352                                return 0;
[b7d3cc34]353                                /* For now just ignore unknown keys... */
354                        }
355                }
356                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
357                {
[489f996]358                        fprintf( stderr, "Error: Unknown section [%s] in configuration file (line %d). "
359                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section, ini->line );
[eeb85a8]360                        return 0;
[b7d3cc34]361                }
362        }
363        ini_close( ini );
364       
[eeb85a8]365        return 1;
[b7d3cc34]366}
367
368void conf_loaddefaults( irc_t *irc )
369{
370        ini_t *ini;
371       
[eeb85a8]372        ini = ini_open( global.conf_file );
[b7d3cc34]373        if( ini == NULL ) return;
374        while( ini_read( ini ) )
375        {
376                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
377                {
[3ddb7477]378                        set_t *s = set_find( &irc->b->set, ini->key );
[b7d3cc34]379                       
380                        if( s )
381                        {
382                                if( s->def ) g_free( s->def );
383                                s->def = g_strdup( ini->value );
384                        }
385                }
386        }
387        ini_close( ini );
388}
Note: See TracBrowser for help on using the repository browser.