source: unix.c @ 7549d00

Last change on this file since 7549d00 was 6f10697, checked in by dequis <dx@…>, at 2015-01-16T19:50:23Z

Fix incorrect Free Software Foundation address

  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[0e788f5]4  * Copyright 2002-2012 Wilmer van der Gaast and others                *
[b7d3cc34]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;
[6f10697]22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
[b7d3cc34]24*/
25
26#include "bitlbee.h"
[7c9db24]27
28#include "arc.h"
29#include "base64.h"
[b7d3cc34]30#include "commands.h"
31#include "protocols/nogaim.h"
32#include "help.h"
[54879ab]33#include "ipc.h"
[7c9db24]34#include "md5.h"
35#include "misc.h"
[b7d3cc34]36#include <signal.h>
37#include <unistd.h>
38#include <sys/time.h>
[d25f6fc]39#include <sys/wait.h>
[aaf92a9]40#include <pwd.h>
[badd148]41#include <locale.h>
[ad46e4d]42#include <grp.h>
[b7d3cc34]43
[d150a9d]44#if defined(OTR_BI) || defined(OTR_PI)
45#include "otr.h"
46#endif
47
[b7d3cc34]48global_t global;        /* Against global namespace pollution */
49
[7233f68]50static int signal_shutdown_pipe[2] = { -1, -1 };
51static void sighandler_shutdown( int signal );
52static void sighandler_crash( int signal );
[b7d3cc34]53
[7c9db24]54static int crypt_main( int argc, char *argv[] );
55
[cd63d58]56int main( int argc, char *argv[] )
[b7d3cc34]57{
58        int i = 0;
[58bc4e6]59        char *old_cwd = NULL;
[b7d3cc34]60        struct sigaction sig, old;
61       
[badd148]62        /* Required to make iconv to ASCII//TRANSLIT work. This makes BitlBee
63           system-locale-sensitive. :-( */
64        setlocale( LC_CTYPE, "" );
65       
[7c9db24]66        if( argc > 1 && strcmp( argv[1], "-x" ) == 0 )
67                return crypt_main( argc, argv );
68       
[d25f6fc]69        log_init();
[5674207]70       
[eeb85a8]71        global.conf_file = g_strdup( CONF_FILE_DEF );
[b7d3cc34]72        global.conf = conf_load( argc, argv );
73        if( global.conf == NULL )
74                return( 1 );
[6e1fed7]75       
[60c1a4e]76        b_main_init();
77       
[3fc6c32]78        /* libpurple doesn't like fork()s after initializing itself, so if
79           we use it, do this init a little later (in case we're running in
80           ForkDaemon mode). */
81#ifndef WITH_PURPLE
82        nogaim_init();
83#endif
84       
[858ea01]85#ifdef OTR_BI
[823de9d]86        otr_init();
[858ea01]87#endif
[60c1a4e]88       
89        srand( time( NULL ) ^ getpid() );
[5674207]90       
[60c1a4e]91        global.helpfile = g_strdup( HELP_FILE );
[5674207]92        if( help_init( &global.help, global.helpfile ) == NULL )
93                log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE );
94
95        global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );
96        if( global.storage == NULL )
97        {
98                log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );
99                return( 1 );
100        }
[60c1a4e]101       
[b7d3cc34]102        if( global.conf->runmode == RUNMODE_INETD )
103        {
[99318ad]104                log_link( LOGLVL_ERROR, LOGOUTPUT_IRC );
105                log_link( LOGLVL_WARNING, LOGOUTPUT_IRC );
106       
[b7d3cc34]107                i = bitlbee_inetd_init();
[18e1f3b]108                log_message( LOGLVL_INFO, "%s %s starting in inetd mode.", PACKAGE, BITLBEE_VERSION );
[b7d3cc34]109
110        }
111        else if( global.conf->runmode == RUNMODE_DAEMON )
112        {
[156bbd7]113                log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE );
114                log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE );
[99318ad]115
[b7d3cc34]116                i = bitlbee_daemon_init();
[18e1f3b]117                log_message( LOGLVL_INFO, "%s %s starting in daemon mode.", PACKAGE, BITLBEE_VERSION );
[b7d3cc34]118        }
[d25f6fc]119        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
120        {
[156bbd7]121                log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE );
122                log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE );
123
[54879ab]124                /* In case the operator requests a restart, we need this. */
125                old_cwd = g_malloc( 256 );
126                if( getcwd( old_cwd, 255 ) == NULL )
127                {
128                        log_message( LOGLVL_WARNING, "Could not save current directory: %s", strerror( errno ) );
129                        g_free( old_cwd );
130                        old_cwd = NULL;
131                }
132               
[d25f6fc]133                i = bitlbee_daemon_init();
[18e1f3b]134                log_message( LOGLVL_INFO, "%s %s starting in forking daemon mode.", PACKAGE, BITLBEE_VERSION );
[d25f6fc]135        }
[b7d3cc34]136        if( i != 0 )
137                return( i );
[6e1fed7]138       
[aaf92a9]139        if( ( global.conf->user && *global.conf->user ) &&
140            ( global.conf->runmode == RUNMODE_DAEMON || 
141              global.conf->runmode == RUNMODE_FORKDAEMON ) &&
142            ( !getuid() || !geteuid() ) )
143        {
144                struct passwd *pw = NULL;
145                pw = getpwnam( global.conf->user );
146                if( pw )
147                {
[ad46e4d]148                        initgroups( global.conf->user, pw->pw_gid );
[aaf92a9]149                        setgid( pw->pw_gid );
150                        setuid( pw->pw_uid );
151                }
[ad46e4d]152                else
153                {
154                        log_message( LOGLVL_WARNING, "Failed to look up user %s.", global.conf->user );
155                }
[aaf92a9]156        }
[b7d3cc34]157       
158        /* Catch some signals to tell the user what's happening before quitting */
159        memset( &sig, 0, sizeof( sig ) );
[7233f68]160        sig.sa_handler = SIG_IGN;
[d25f6fc]161        sigaction( SIGCHLD, &sig, &old );
[b7d3cc34]162        sigaction( SIGPIPE, &sig, &old );
163        sig.sa_flags = SA_RESETHAND;
[7233f68]164        sig.sa_handler = sighandler_crash;
[b7d3cc34]165        sigaction( SIGSEGV, &sig, &old );
[7233f68]166
167        /* Use a pipe for SIGTERM/SIGINT so the actual signal handler doesn't do anything unsafe */
168        if ( pipe( signal_shutdown_pipe ) == 0 ) {
169                b_input_add( signal_shutdown_pipe[0], B_EV_IO_READ, bitlbee_shutdown, NULL );
170                sig.sa_handler = sighandler_shutdown;
171                sigaction( SIGINT, &sig, &old );
172                sigaction( SIGTERM, &sig, &old );
173        }
[b7d3cc34]174       
175        if( !getuid() || !geteuid() )
176                log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" );
177       
[ba9edaa]178        b_main_run();
[b7d3cc34]179       
[0fbda193]180        /* Mainly good for restarting, to make sure we close the help.txt fd. */
181        help_free( &global.help );
182       
[54879ab]183        if( global.restart )
184        {
185                char *fn = ipc_master_save_state();
[daae10f]186                char *env;
[54879ab]187               
[daae10f]188                env = g_strdup_printf( "_BITLBEE_RESTART_STATE=%s", fn );
189                putenv( env );
[cd63d58]190                g_free( fn );
[daae10f]191                /* Looks like env should *not* be freed here as putenv
192                   doesn't make a copy. Odd. */
[54879ab]193               
[fef7813]194                i = chdir( old_cwd );
[54879ab]195                close( global.listen_socket );
196               
[cd63d58]197                if( execv( argv[0], argv ) == -1 )
198                        /* Apparently the execve() failed, so let's just
199                           jump back into our own/current main(). */
200                        /* Need more cleanup code to make this work. */
201                        return 1; /* main( argc, argv ); */
[54879ab]202        }
203       
[b7d3cc34]204        return( 0 );
205}
206
[7c9db24]207static int crypt_main( int argc, char *argv[] )
208{
209        int pass_len;
210        unsigned char *pass_cr, *pass_cl;
211       
[8b6b740]212        if( argc < 4 || ( strcmp( argv[2], "hash" ) != 0 &&
213                          strcmp( argv[2], "unhash" ) != 0 && argc < 5 ) )
[7c9db24]214        {
215                printf( "Supported:\n"
216                        "  %s -x enc <key> <cleartext password>\n"
217                        "  %s -x dec <key> <encrypted password>\n"
218                        "  %s -x hash <cleartext password>\n"
219                        "  %s -x unhash <hashed password>\n"
220                        "  %s -x chkhash <hashed password> <cleartext password>\n",
221                        argv[0], argv[0], argv[0], argv[0], argv[0] );
222        }
223        else if( strcmp( argv[2], "enc" ) == 0 )
224        {
225                pass_len = arc_encode( argv[4], strlen( argv[4] ), (unsigned char**) &pass_cr, argv[3], 12 );
226                printf( "%s\n", base64_encode( pass_cr, pass_len ) );
227        }
228        else if( strcmp( argv[2], "dec" ) == 0 )
229        {
230                pass_len = base64_decode( argv[4], (unsigned char**) &pass_cr );
231                arc_decode( pass_cr, pass_len, (char**) &pass_cl, argv[3] );
232                printf( "%s\n", pass_cl );
233        }
234        else if( strcmp( argv[2], "hash" ) == 0 )
235        {
236                md5_byte_t pass_md5[21];
237                md5_state_t md5_state;
238               
239                random_bytes( pass_md5 + 16, 5 );
240                md5_init( &md5_state );
241                md5_append( &md5_state, (md5_byte_t*) argv[3], strlen( argv[3] ) );
242                md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */
243                md5_finish( &md5_state, pass_md5 );
244               
245                printf( "%s\n", base64_encode( pass_md5, 21 ) );
246        }
247        else if( strcmp( argv[2], "unhash" ) == 0 )
248        {
249                printf( "Hash %s submitted to a massive Beowulf cluster of\n"
250                        "overclocked 486s. Expect your answer next year somewhere around this time. :-)\n", argv[3] );
251        }
252        else if( strcmp( argv[2], "chkhash" ) == 0 )
253        {
[8b6b740]254                char *hash = strncmp( argv[3], "md5:", 4 ) == 0 ? argv[3] + 4 : argv[3];
255                int st = md5_verify_password( argv[4], hash );
[7c9db24]256               
257                printf( "Hash %s given password.\n", st == 0 ? "matches" : "does not match" );
258               
259                return st;
260        }
261       
262        return 0;
263}
264
[7233f68]265/* Signal handler for SIGTERM and SIGINT */
266static void sighandler_shutdown( int signal )
[b7d3cc34]267{
[7233f68]268        /* Write a single null byte to the pipe, just to send a message to the main loop.
269         * This gets handled by bitlbee_shutdown (the b_input_add callback for this pipe) */
270        write( signal_shutdown_pipe[1], "", 1 );
271}
272
273/* Signal handler for SIGSEGV
274 * A desperate attempt to tell the user that everything is wrong in the world.
275 * Avoids using irc_abort() because it has several unsafe calls to malloc */
276static void sighandler_crash( int signal )
277{
278        GSList *l;
279        const char *message = "ERROR :BitlBee crashed! (SIGSEGV received)\r\n";
280        int len = strlen(message);
281
282        for (l = irc_connection_list; l; l = l->next ) {
283                irc_t *irc = l->data;
284                write( irc->fd, message, len );
[b7d3cc34]285        }
[7233f68]286
287        raise( signal );
[b7d3cc34]288}
289
290double gettime()
291{
292        struct timeval time[1];
293
294        gettimeofday( time, 0 );
295        return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );
296}
Note: See TracBrowser for help on using the repository browser.