source: conf.c @ b919363

Last change on this file since b919363 was 3ddb7477, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-26T12:14:37Z

One total mess that doesn't do much yet, but reorganised some stuff and
untying the IRC and the core parts a little bit. Lots of work left to do.

  • Property mode set to 100644
File size: 10.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        conf->ft_max_size = SIZE_MAX;
66        conf->ft_max_kbps = G_MAXUINT;
67        conf->ft_listen = NULL;
68        conf->protocols = NULL;
69        proxytype = 0;
70       
71        i = conf_loadini( conf, global.conf_file );
72        if( i == 0 )
73        {
74                fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file );
75                return NULL;
76        }
77        else if( i == -1 )
78        {
79                config_missing ++;
80                /* Whine after parsing the options if there was no -c pointing
81                   at a *valid* configuration file. */
82        }
83       
84        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 )
85        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
86        {
87                if( opt == 'i' )
88                {
89                        conf->iface_in = g_strdup( optarg );
90                }
91                else if( opt == 'p' )
92                {
93                        g_free( conf->port );
94                        conf->port = g_strdup( optarg );
95                }
96                else if( opt == 'P' )
97                {
98                        g_free( conf->pidfile );
99                        conf->pidfile = g_strdup( optarg );
100                }
101                else if( opt == 'n' )
102                        conf->nofork = 1;
103                else if( opt == 'v' )
104                        conf->verbose = 1;
105                else if( opt == 'I' )
106                        conf->runmode = RUNMODE_INETD;
107                else if( opt == 'D' )
108                        conf->runmode = RUNMODE_DAEMON;
109                else if( opt == 'F' )
110                        conf->runmode = RUNMODE_FORKDAEMON;
111                else if( opt == 'c' )
112                {
113                        if( strcmp( global.conf_file, optarg ) != 0 )
114                        {
115                                g_free( global.conf_file );
116                                global.conf_file = g_strdup( optarg );
117                                g_free( conf );
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.. */
121                                optind = 1;
122                                return conf_load( argc, argv );
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                {
132                        printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
133                                "               [-c <file>] [-d <dir>] [-x] [-h]\n"
134                                "\n"
135                                "An IRC-to-other-chat-networks gateway\n"
136                                "\n"
137                                "  -I  Classic/InetD mode. (Default)\n"
138                                "  -D  Daemon mode. (one process serves all)\n"
139                                "  -F  Forking daemon. (one process per client)\n"
140                                "  -u  Run daemon as specified user.\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                                "  -x  Command-line interface to password encryption/hashing\n"
150                                "  -h  Show this help page.\n" );
151                        return NULL;
152                }
153                else if( opt == 'R' )
154                {
155                        /* Backward compatibility; older BitlBees passed this
156                           info using a command-line flag. Allow people to
157                           upgrade from such a version for now. */
158                        setenv( "_BITLBEE_RESTART_STATE", optarg, 0 );
159                }
160                else if( opt == 'u' )
161                {
162                        g_free( conf->user );
163                        conf->user = g_strdup( optarg );
164                }
165        }
166       
167        if( conf->configdir[strlen(conf->configdir)-1] != '/' )
168        {
169                char *s = g_new( char, strlen( conf->configdir ) + 2 );
170               
171                sprintf( s, "%s/", conf->configdir );
172                g_free( conf->configdir );
173                conf->configdir = s;
174        }
175       
176        if( config_missing )
177                fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file );
178       
179        return conf;
180}
181
182static int conf_loadini( conf_t *conf, char *file )
183{
184        ini_t *ini;
185        int i;
186       
187        ini = ini_open( file );
188        if( ini == NULL ) return -1;
189        while( ini_read( ini ) )
190        {
191                if( g_strcasecmp( ini->section, "settings" ) == 0 )
192                {
193                        if( g_strcasecmp( ini->key, "runmode" ) == 0 )
194                        {
195                                if( g_strcasecmp( ini->value, "daemon" ) == 0 )
196                                        conf->runmode = RUNMODE_DAEMON;
197                                else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 )
198                                        conf->runmode = RUNMODE_FORKDAEMON;
199                                else
200                                        conf->runmode = RUNMODE_INETD;
201                        }
202                        else if( g_strcasecmp( ini->key, "pidfile" ) == 0 )
203                        {
204                                g_free( conf->pidfile );
205                                conf->pidfile = g_strdup( ini->value );
206                        }
207                        else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 )
208                        {
209                                g_free( conf->iface_in );
210                                conf->iface_in = g_strdup( ini->value );
211                        }
212                        else if( g_strcasecmp( ini->key, "daemonport" ) == 0 )
213                        {
214                                g_free( conf->port );
215                                conf->port = g_strdup( ini->value );
216                        }
217                        else if( g_strcasecmp( ini->key, "clientinterface" ) == 0 )
218                        {
219                                g_free( conf->iface_out );
220                                conf->iface_out = g_strdup( ini->value );
221                        }
222                        else if( g_strcasecmp( ini->key, "authmode" ) == 0 )
223                        {
224                                if( g_strcasecmp( ini->value, "registered" ) == 0 )
225                                        conf->authmode = AUTHMODE_REGISTERED;
226                                else if( g_strcasecmp( ini->value, "closed" ) == 0 )
227                                        conf->authmode = AUTHMODE_CLOSED;
228                                else
229                                        conf->authmode = AUTHMODE_OPEN;
230                        }
231                        else if( g_strcasecmp( ini->key, "authpassword" ) == 0 )
232                        {
233                                g_free( conf->auth_pass );
234                                conf->auth_pass = g_strdup( ini->value );
235                        }
236                        else if( g_strcasecmp( ini->key, "operpassword" ) == 0 )
237                        {
238                                g_free( conf->oper_pass );
239                                conf->oper_pass = g_strdup( ini->value );
240                        }
241                        else if( g_strcasecmp( ini->key, "hostname" ) == 0 )
242                        {
243                                g_free( conf->hostname );
244                                conf->hostname = g_strdup( ini->value );
245                        }
246                        else if( g_strcasecmp( ini->key, "configdir" ) == 0 )
247                        {
248                                g_free( conf->configdir );
249                                conf->configdir = g_strdup( ini->value );
250                        }
251                        else if( g_strcasecmp( ini->key, "motdfile" ) == 0 )
252                        {
253                                g_free( conf->motdfile );
254                                conf->motdfile = g_strdup( ini->value );
255                        }
256                        else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
257                        {
258                                g_free( conf->primary_storage );
259                                conf->primary_storage = g_strdup( ini->value );
260                        }
261                        else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 )
262                        {
263                                g_strfreev( conf->migrate_storage );
264                                conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 );
265                        }
266                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
267                        {
268                                if( sscanf( ini->value, "%d", &i ) != 1 )
269                                {
270                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
271                                        return 0;
272                                }
273                                conf->ping_interval = i;
274                        }
275                        else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 )
276                        {
277                                if( sscanf( ini->value, "%d", &i ) != 1 )
278                                {
279                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
280                                        return 0;
281                                }
282                                conf->ping_timeout = i;
283                        }
284                        else if( g_strcasecmp( ini->key, "proxy" ) == 0 )
285                        {
286                                url_t *url = g_new0( url_t, 1 );
287                               
288                                if( !url_set( url, ini->value ) )
289                                {
290                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
291                                        g_free( url );
292                                        return 0;
293                                }
294                               
295                                strncpy( proxyhost, url->host, sizeof( proxyhost ) );
296                                strncpy( proxyuser, url->user, sizeof( proxyuser ) );
297                                strncpy( proxypass, url->pass, sizeof( proxypass ) );
298                                proxyport = url->port;
299                                if( url->proto == PROTO_HTTP )
300                                        proxytype = PROXY_HTTP;
301                                else if( url->proto == PROTO_SOCKS4 )
302                                        proxytype = PROXY_SOCKS4;
303                                else if( url->proto == PROTO_SOCKS5 )
304                                        proxytype = PROXY_SOCKS5;
305                               
306                                g_free( url );
307                        }
308                        else if( g_strcasecmp( ini->key, "user" ) == 0 )
309                        {
310                                g_free( conf->user );
311                                conf->user = g_strdup( ini->value );
312                        }
313                        else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 )
314                        {
315                                size_t ft_max_size;
316                                if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 )
317                                {
318                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
319                                        return 0;
320                                }
321                                conf->ft_max_size = ft_max_size;
322                        }
323                        else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 )
324                        {
325                                if( sscanf( ini->value, "%d", &i ) != 1 )
326                                {
327                                        fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
328                                        return 0;
329                                }
330                                conf->ft_max_kbps = i;
331                        }
332                        else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 )
333                        {
334                                g_free( conf->ft_listen );
335                                conf->ft_listen = g_strdup( ini->value );
336                        }
337                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
338                        {
339                                g_strfreev( conf->protocols );
340                                conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 );
341                        }
342                        else
343                        {
344                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line );
345                                return 0;
346                                /* For now just ignore unknown keys... */
347                        }
348                }
349                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
350                {
351                        fprintf( stderr, "Error: Unknown section [%s] in configuration file (line %d). "
352                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section, ini->line );
353                        return 0;
354                }
355        }
356        ini_close( ini );
357       
358        return 1;
359}
360
361void conf_loaddefaults( irc_t *irc )
362{
363        ini_t *ini;
364       
365        ini = ini_open( global.conf_file );
366        if( ini == NULL ) return;
367        while( ini_read( ini ) )
368        {
369                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
370                {
371                        set_t *s = set_find( &irc->b->set, ini->key );
372                       
373                        if( s )
374                        {
375                                if( s->def ) g_free( s->def );
376                                s->def = g_strdup( ini->value );
377                        }
378                }
379        }
380        ini_close( ini );
381}
Note: See TracBrowser for help on using the repository browser.