source: unix.c @ b14890d

Last change on this file since b14890d was ba5add7, checked in by Sven Moritz Hallberg <sm@…>, at 2008-02-17T01:39:39Z

explicitly initialize ssl in order to avoid gnutls and libotr fighting over the global state of libgcrypt

  • Property mode set to 100644
File size: 6.5 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Main file (Unix specific part)                                       */
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#include "commands.h"
28#include "crypting.h"
29#include "otr.h"
30#include "protocols/nogaim.h"
31#include "help.h"
32#include "ipc.h"
33#include "lib/ssl_client.h"
34#include <signal.h>
35#include <unistd.h>
36#include <sys/time.h>
37#include <sys/wait.h>
38#include <pwd.h>
39
40global_t global;        /* Against global namespace pollution */
41
42static void sighandler( int signal );
43
44int main( int argc, char *argv[], char **envp )
45{
46        int i = 0;
47        char *old_cwd = NULL;
48        struct sigaction sig, old;
49       
50        log_init();
51        global.conf_file = g_strdup( CONF_FILE_DEF );
52        global.conf = conf_load( argc, argv );
53        if( global.conf == NULL )
54                return( 1 );
55       
56        b_main_init();
57        nogaim_init();
58        /* Ugly Note: libotr and gnutls both use libgcrypt. libgcrypt
59           has a process-global config state whose initialization happpens
60           twice if libotr and gnutls are used together. libotr installs custom
61           memory management functions for libgcrypt while our gnutls module
62           uses the defaults. Therefore we initialize OTR after SSL. *sigh* */
63        ssl_init();
64        otr_init();
65       
66        srand( time( NULL ) ^ getpid() );
67        global.helpfile = g_strdup( HELP_FILE );
68       
69        if( global.conf->runmode == RUNMODE_INETD )
70        {
71                i = bitlbee_inetd_init();
72                log_message( LOGLVL_INFO, "Bitlbee %s starting in inetd mode.", BITLBEE_VERSION );
73
74        }
75        else if( global.conf->runmode == RUNMODE_DAEMON )
76        {
77                i = bitlbee_daemon_init();
78                log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );
79        }
80        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
81        {
82                /* In case the operator requests a restart, we need this. */
83                old_cwd = g_malloc( 256 );
84                if( getcwd( old_cwd, 255 ) == NULL )
85                {
86                        log_message( LOGLVL_WARNING, "Could not save current directory: %s", strerror( errno ) );
87                        g_free( old_cwd );
88                        old_cwd = NULL;
89                }
90               
91                i = bitlbee_daemon_init();
92                log_message( LOGLVL_INFO, "Bitlbee %s starting in forking daemon mode.", BITLBEE_VERSION );
93        }
94        if( i != 0 )
95                return( i );
96       
97        if( ( global.conf->user && *global.conf->user ) &&
98            ( global.conf->runmode == RUNMODE_DAEMON || 
99              global.conf->runmode == RUNMODE_FORKDAEMON ) &&
100            ( !getuid() || !geteuid() ) )
101        {
102                struct passwd *pw = NULL;
103                pw = getpwnam( global.conf->user );
104                if( pw )
105                {
106                        setgid( pw->pw_gid );
107                        setuid( pw->pw_uid );
108                }
109        }
110
111        global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );
112        if( global.storage == NULL )
113        {
114                log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );
115                return( 1 );
116        }
117       
118        /* Catch some signals to tell the user what's happening before quitting */
119        memset( &sig, 0, sizeof( sig ) );
120        sig.sa_handler = sighandler;
121        sigaction( SIGCHLD, &sig, &old );
122        sigaction( SIGPIPE, &sig, &old );
123        sig.sa_flags = SA_RESETHAND;
124        sigaction( SIGINT,  &sig, &old );
125        sigaction( SIGILL,  &sig, &old );
126        sigaction( SIGBUS,  &sig, &old );
127        sigaction( SIGFPE,  &sig, &old );
128        sigaction( SIGSEGV, &sig, &old );
129        sigaction( SIGTERM, &sig, &old );
130        sigaction( SIGQUIT, &sig, &old );
131        sigaction( SIGXCPU, &sig, &old );
132       
133        if( !getuid() || !geteuid() )
134                log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" );
135        if( help_init( &global.help, global.helpfile ) == NULL )
136                log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE );
137       
138        b_main_run();
139       
140        /* Mainly good for restarting, to make sure we close the help.txt fd. */
141        help_free( &global.help );
142       
143        if( global.restart )
144        {
145                char *fn = ipc_master_save_state();
146                char **args;
147                int n, i;
148               
149                chdir( old_cwd );
150               
151                n = 0;
152                args = g_new0( char *, argc + 3 );
153                args[n++] = argv[0];
154                if( fn )
155                {
156                        args[n++] = "-R";
157                        args[n++] = fn;
158                }
159                for( i = 1; argv[i] && i < argc; i ++ )
160                {
161                        if( strcmp( argv[i], "-R" ) == 0 )
162                                i += 2;
163                       
164                        args[n++] = argv[i];
165                }
166               
167                close( global.listen_socket );
168               
169                execve( args[0], args, envp );
170        }
171       
172        return( 0 );
173}
174
175static void sighandler( int signal )
176{
177        /* FIXME: Calling log_message() here is not a very good idea! */
178       
179        if( signal == SIGTERM )
180        {
181                static int first = 1;
182               
183                if( first )
184                {
185                        /* We don't know what we were doing when this signal came in. It's not safe to touch
186                           the user data now (not to mention writing them to disk), so add a timer. */
187                       
188                        log_message( LOGLVL_ERROR, "SIGTERM received, cleaning up process." );
189                        b_timeout_add( 1, (b_event_handler) bitlbee_shutdown, NULL );
190                       
191                        first = 0;
192                }
193                else
194                {
195                        /* Well, actually, for now we'll never need this part because this signal handler
196                           will never be called more than once in a session for a non-SIGPIPE signal...
197                           But just in case we decide to change that: */
198                       
199                        log_message( LOGLVL_ERROR, "SIGTERM received twice, so long for a clean shutdown." );
200                        raise( signal );
201                }
202        }
203        else if( signal == SIGCHLD )
204        {
205                pid_t pid;
206                int st;
207               
208                while( ( pid = waitpid( 0, &st, WNOHANG ) ) > 0 )
209                {
210                        if( WIFSIGNALED( st ) )
211                                log_message( LOGLVL_INFO, "Client %d terminated normally. (status = %d)", (int) pid, WEXITSTATUS( st ) );
212                        else if( WIFEXITED( st ) )
213                                log_message( LOGLVL_INFO, "Client %d killed by signal %d.", (int) pid, WTERMSIG( st ) );
214                }
215        }
216        else if( signal != SIGPIPE )
217        {
218                log_message( LOGLVL_ERROR, "Fatal signal received: %d. That's probably a bug.", signal );
219                raise( signal );
220        }
221}
222
223double gettime()
224{
225        struct timeval time[1];
226
227        gettimeofday( time, 0 );
228        return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );
229}
Note: See TracBrowser for help on using the repository browser.