source: conf.c @ f9110b4

Last change on this file since f9110b4 was 3d1481f, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-13T22:25:40Z

Adding -V flag to show version info from a not-serving binary. (Bug #580)

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