source: unix.c @ c7d0f41

Last change on this file since c7d0f41 was 6e1fed7, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-06-25T17:07:25Z

Using salted MD5 checksums for the user's BitlBee password and salted RC4
encryption for the IM account passwords, plus some calls to srand() to keep
the salts secure and unique.

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