X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fngircd.c;h=89b2f7f8b0362406c0bbb2909bb77a52bc389f4a;hp=8bea98ae4429a55e7d4aca54b232787d48f9a83a;hb=112102b10ce991340ba56e272e32bc50a73e1b05;hpb=c40592d2cef21dd255af978644eb96c330913be7 diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index 8bea98ae..89b2f7f8 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: ngircd.c,v 1.78 2003/12/26 15:55:07 alex Exp $"; +static char UNUSED id[] = "$Id: ngircd.c,v 1.88 2005/02/04 14:24:21 alex Exp $"; #include "imp.h" #include @@ -24,20 +24,20 @@ static char UNUSED id[] = "$Id: ngircd.c,v 1.78 2003/12/26 15:55:07 alex Exp $"; #include #include #include +#include #include #include #include -#include #include #include +#include "defines.h" #include "resolve.h" #include "conn.h" #include "client.h" #include "channel.h" #include "conf.h" #include "cvs-version.h" -#include "defines.h" #include "lists.h" #include "log.h" #include "parse.h" @@ -57,6 +57,9 @@ LOCAL VOID Signal_Handler PARAMS(( INT Signal )); LOCAL VOID Show_Version PARAMS(( VOID )); LOCAL VOID Show_Help PARAMS(( VOID )); +LOCAL VOID Pidfile_Create PARAMS(( LONG )); +LOCAL VOID Pidfile_Delete PARAMS(( VOID )); + GLOBAL int main( int argc, const char *argv[] ) @@ -183,6 +186,11 @@ main( int argc, const char *argv[] ) ok = TRUE; } #endif + if( argv[i][n] == 't' ) + { + configtest = TRUE; + ok = TRUE; + } if( ! ok ) { @@ -223,6 +231,38 @@ main( int argc, const char *argv[] ) while( ! NGIRCd_SignalQuit ) { + /* Initialize global variables */ + NGIRCd_Start = time( NULL ); + (VOID)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start )); + + NGIRCd_SignalRehash = FALSE; + NGIRCd_SignalRestart = FALSE; + NGIRCd_SignalQuit = FALSE; + + /* Initialize modules, part I */ + Log_Init( ); + Conf_Init( ); + + if( Conf_Chroot[0] ) + { + /* Chroot */ + if( chdir( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno )); + + if( chroot( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't change root directory to \"%s\": %s", Conf_Chroot, strerror( errno )); + else Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot ); + } + + if( Conf_GID != 0 ) + { + /* Set new group ID */ + if( setgid( Conf_GID ) != 0 ) Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno )); + } + if( Conf_UID != 0 ) + { + /* Set new user ID */ + if( setuid( Conf_UID ) != 0 ) Log( LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror( errno )); + } + /* In der Regel wird ein Sub-Prozess ge-fork()'t, der * nicht mehr mit dem Terminal verbunden ist. Mit der * Option "--nodaemon" kann dies (z.B. zum Debuggen) @@ -247,18 +287,33 @@ main( int argc, const char *argv[] ) (VOID)setsid( ); chdir( "/" ); } - - /* Globale Variablen initialisieren */ - NGIRCd_Start = time( NULL ); - (VOID)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start )); - NGIRCd_SignalRehash = FALSE; - NGIRCd_SignalRestart = FALSE; - NGIRCd_SignalQuit = FALSE; - /* Module initialisieren */ - Log_Init( ); + /* Create PID file */ + pid = (LONG) getpid( ); + Pidfile_Create( pid ); + + /* Show user, group, and PID of the running daemon */ + pwd = getpwuid( getuid( )); grp = getgrgid( getgid( )); + Log( LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.", pwd ? pwd->pw_name : "unknown", (LONG)getuid( ), grp ? grp->gr_name : "unknown", (LONG)getgid( ), pid); + + /* Change working directory to home directory of the user + * we are running as (when not running chroot()'ed!) */ + if( Conf_UID != 0 && ! Conf_Chroot[0] ) + { + struct passwd *pwd; + + pwd = getpwuid( Conf_UID ); + if( pwd != NULL ) + { + if( chdir( pwd->pw_dir ) == 0 ) Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir ); + else Log( LOG_ERR, "Can't change working directory to \"%s\": %s", pwd->pw_dir, strerror( errno )); + } + else Log( LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID ); + } + + /* Initialize modules, part II: these functions are eventually + * called with already dropped privileges ... */ Resolve_Init( ); - Conf_Init( ); Lists_Init( ); Channel_Init( ); Client_Init( ); @@ -267,28 +322,11 @@ main( int argc, const char *argv[] ) #endif Conn_Init( ); - /* Wenn als root ausgefuehrt und eine andere UID - * konfiguriert ist, jetzt zu dieser wechseln */ - if( getuid( ) == 0 ) - { - if( Conf_GID != 0 ) - { - /* Neue Group-ID setzen */ - if( setgid( Conf_GID ) != 0 ) Log( LOG_ERR, "Can't change Group-ID to %u: %s", Conf_GID, strerror( errno )); - } - if( Conf_UID != 0 ) - { - /* Neue User-ID setzen */ - if( setuid( Conf_UID ) != 0 ) Log( LOG_ERR, "Can't change User-ID to %u: %s", Conf_UID, strerror( errno )); - } - } - - /* User, Gruppe und Prozess-ID des Daemon ausgeben */ - pwd = getpwuid( getuid( )); grp = getgrgid( getgid( )); - Log( LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.", pwd ? pwd->pw_name : "unknown", (LONG)getuid( ), grp ? grp->gr_name : "unknown", (LONG)getgid( ), (LONG)getpid( )); - - /* stderr in "Error-File" umlenken */ - Log_InitErrorfile( ); + /* Redirect stderr handle to "error file" for debugging. + * But don't try to write in the chroot jail, since it's more + * secure to have a chroot dir not writable by the daemon. + */ + if( ! Conf_Chroot[0] ) Log_InitErrorfile( ); /* Signal-Handler initialisieren */ Initialize_Signal_Handler( ); @@ -319,6 +357,7 @@ main( int argc, const char *argv[] ) { Log( LOG_ALERT, "Server isn't listening on a single port!" ); Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); + Pidfile_Delete( ); exit( 1 ); } @@ -334,6 +373,8 @@ main( int argc, const char *argv[] ) Channel_Exit( ); Lists_Exit( ); Log_Exit( ); + + Pidfile_Delete( ); } return 0; @@ -377,6 +418,10 @@ NGIRCd_VersionAddition( VOID ) if( txt[0] ) strcat( txt, "+" ); strcat( txt, "RENDEZVOUS" ); #endif +#ifdef IDENTAUTH + if( txt[0] ) strcat( txt, "+" ); + strcat( txt, "IDENT" ); +#endif #ifdef DEBUG if( txt[0] ) strcat( txt, "+" ); strcat( txt, "DEBUG" ); @@ -413,30 +458,26 @@ NGIRCd_Rehash( VOID ) Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); NGIRCd_SignalRehash = FALSE; - /* Alle Listen-Sockets schliessen */ + /* Close down all listening sockets */ Conn_ExitListeners( ); - /* Alten Server-Namen merken */ -#ifdef DEBUG - assert( sizeof( old_name ) == sizeof( Conf_ServerName )); -#endif + /* Remember old server name */ strcpy( old_name, Conf_ServerName ); - /* Konfiguration neu lesen ... */ + /* Re-read configuration ... */ Conf_Rehash( ); - /* Alten Server-Namen wiederherstellen: dieser - * kann nicht zur Laufzeit geaendert werden ... */ + /* Recover old server name: it can't be changed during run-time */ if( strcmp( old_name, Conf_ServerName ) != 0 ) { strcpy( Conf_ServerName, old_name ); Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." ); } - /* neue pre-defined Channel anlegen: */ + /* Create new pre-defined channels */ Channel_InitPredefined( ); - /* Listen-Sockets neu anlegen: */ + /* Start listening on sockets */ Conn_InitListeners( ); /* Sync configuration with established connections */ @@ -529,7 +570,7 @@ LOCAL VOID Show_Version( VOID ) { puts( NGIRCd_Version( )); - puts( "Copyright (c)2001-2003 by Alexander Barton ()." ); + puts( "Copyright (c)2001-2005 by Alexander Barton ()." ); puts( "Homepage: \n" ); puts( "This is free software; see the source for copying conditions. There is NO" ); puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." ); @@ -548,10 +589,53 @@ Show_Help( VOID ) #ifdef SNIFFER puts( " -s, --sniffer enable network sniffer and display all IRC traffic" ); #endif - puts( " --configtest read, validate and display configuration; then exit" ); + puts( " -t, --configtest read, validate and display configuration; then exit" ); puts( " --version output version information and exit" ); puts( " --help display this help and exit" ); } /* Show_Help */ +LOCAL VOID +Pidfile_Delete( VOID ) +{ + /* Pidfile configured? */ + if( ! Conf_PidFile[0] ) return; + +#ifdef DEBUG + Log( LOG_DEBUG, "Removing PID file (%s) ...", Conf_PidFile ); +#endif + + if( unlink( Conf_PidFile )) + Log( LOG_ERR, "Error unlinking PID file (%s): %s", Conf_PidFile, strerror( errno )); +} /* Pidfile_Delete */ + + +LOCAL VOID +Pidfile_Create( LONG pid ) +{ + FILE *pidf; + + /* Pidfile configured? */ + if( ! Conf_PidFile[0] ) return; + + pidf = fopen( Conf_PidFile, "w" ); + +#ifdef DEBUG + Log( LOG_DEBUG, "Creating PID file (%s) ...", Conf_PidFile ); +#endif + + if( ! pidf ) + { + Log( LOG_ERR, "Error writing PID file (%s): %s", Conf_PidFile, strerror( errno )); + return; + } + + if( fprintf( pidf, "%ld\n", pid ) < 0 ) + Log( LOG_ERR, "Can't write PID file (%s): %s", Conf_PidFile, strerror( errno )); + + if( fclose(pidf) != 0 ) + Log( LOG_ERR, "Error closing PID file (%s): %s", Conf_PidFile, strerror( errno )); +} /* Pidfile_Create */ + + /* -eof- */