2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
2005-01-30 03:54:57 +03:00
2003-08-13 05:53:07 +04:00
Main SMB server routines
2005-01-30 03:54:57 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 2005
2003-08-13 05:53:07 +04:00
Copyright ( C ) Martin Pool 2002
Copyright ( C ) Jelmer Vernooij 2002
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2005-01-18 13:10:35 +03:00
# include "version.h"
2004-11-02 05:57:18 +03:00
# include "lib/cmdline/popt_common.h"
2005-01-30 03:54:57 +03:00
# include "system/dir.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-03-09 20:39:24 +03:00
# include "ldb/include/ldb.h"
2005-12-28 00:11:09 +03:00
# include "registry/registry.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2005-12-28 18:38:36 +03:00
# include "ntptr/ntptr.h"
2005-12-31 01:46:16 +03:00
# include "auth/gensec/gensec.h"
2006-03-07 14:07:23 +03:00
# include "smbd/process_model.h"
2006-03-07 16:22:00 +03:00
# include "smbd/service.h"
2006-11-06 19:11:52 +03:00
# include "param/secrets.h"
2006-11-03 04:49:19 +03:00
# include "smbd/pidfile.h"
2007-01-19 07:09:32 +03:00
# include "cluster/ctdb/ctdb_cluster.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2003-08-13 05:53:07 +04:00
2005-01-30 03:54:57 +03:00
/*
2005-07-10 12:06:28 +04:00
recursively delete a directory tree
2005-01-30 03:54:57 +03:00
*/
2005-07-10 12:06:28 +04:00
static void recursive_delete ( const char * path )
2003-08-13 05:53:07 +04:00
{
2005-01-30 03:54:57 +03:00
DIR * dir ;
struct dirent * de ;
2003-08-13 05:53:07 +04:00
2005-01-30 03:54:57 +03:00
dir = opendir ( path ) ;
if ( ! dir ) {
return ;
2003-08-13 05:53:07 +04:00
}
2005-01-30 03:54:57 +03:00
for ( de = readdir ( dir ) ; de ; de = readdir ( dir ) ) {
2005-07-10 12:06:28 +04:00
char * fname ;
struct stat st ;
2006-04-24 04:16:51 +04:00
if ( ISDOT ( de - > d_name ) | | ISDOTDOT ( de - > d_name ) ) {
2005-07-10 12:06:28 +04:00
continue ;
}
fname = talloc_asprintf ( path , " %s/%s " , path , de - > d_name ) ;
if ( stat ( fname , & st ) ! = 0 ) {
continue ;
}
if ( S_ISDIR ( st . st_mode ) ) {
recursive_delete ( fname ) ;
talloc_free ( fname ) ;
continue ;
}
if ( unlink ( fname ) ! = 0 ) {
DEBUG ( 0 , ( " Unabled to delete '%s' - %s \n " ,
fname , strerror ( errno ) ) ) ;
smb_panic ( " unable to cleanup tmp files " ) ;
2005-01-30 03:54:57 +03:00
}
2005-07-10 12:06:28 +04:00
talloc_free ( fname ) ;
2003-08-13 05:53:07 +04:00
}
2005-01-30 03:54:57 +03:00
closedir ( dir ) ;
2005-07-10 12:06:28 +04:00
}
/*
cleanup temporary files . This is the new alternative to
TDB_CLEAR_IF_FIRST . Unfortunately TDB_CLEAR_IF_FIRST is not
efficient on unix systems due to the lack of scaling of the byte
range locking system . So instead of putting the burden on tdb to
cleanup tmp files , this function deletes them .
*/
2007-12-03 00:32:11 +03:00
static void cleanup_tmp_files ( struct loadparm_context * lp_ctx )
2005-07-10 12:06:28 +04:00
{
char * path ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
2007-12-03 00:32:11 +03:00
path = smbd_tmp_path ( mem_ctx , lp_ctx , NULL ) ;
2005-01-30 03:54:57 +03:00
2005-07-10 12:06:28 +04:00
recursive_delete ( path ) ;
2005-01-30 03:54:57 +03:00
talloc_free ( mem_ctx ) ;
}
2003-08-13 05:53:07 +04:00
2006-03-08 15:31:57 +03:00
static void sig_hup ( int sig )
{
debug_schedule_reopen_logs ( ) ;
}
2006-09-11 08:47:56 +04:00
static void sig_term ( int sig )
{
# if HAVE_GETPGRP
static int done_sigterm ;
if ( done_sigterm = = 0 & & getpgrp ( ) = = getpid ( ) ) {
DEBUG ( 0 , ( " SIGTERM: killing children \n " ) ) ;
done_sigterm = 1 ;
kill ( - getpgrp ( ) , SIGTERM ) ;
}
# endif
exit ( 0 ) ;
}
2005-01-30 03:54:57 +03:00
/*
setup signal masks
*/
static void setup_signals ( void )
{
2003-08-13 05:53:07 +04:00
/* we are never interested in SIGPIPE */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGPIPE ) ;
2003-08-13 05:53:07 +04:00
# if defined(SIGFPE)
/* we are never interested in SIGFPE */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGFPE ) ;
2003-08-13 05:53:07 +04:00
# endif
2005-12-15 19:53:20 +03:00
/* We are no longer interested in USR1 */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGUSR1 ) ;
2005-12-15 19:53:20 +03:00
2003-08-13 05:53:07 +04:00
# if defined(SIGUSR2)
/* We are no longer interested in USR2 */
2007-10-02 02:13:02 +04:00
BlockSignals ( true , SIGUSR2 ) ;
2003-08-13 05:53:07 +04:00
# endif
/* POSIX demands that signals are inherited. If the invoking process has
* these signals masked , we will have problems , as we won ' t recieve them . */
2007-10-02 02:13:02 +04:00
BlockSignals ( false , SIGHUP ) ;
BlockSignals ( false , SIGTERM ) ;
2005-01-30 03:54:57 +03:00
2006-03-08 15:31:57 +03:00
CatchSignal ( SIGHUP , sig_hup ) ;
2006-09-11 08:47:56 +04:00
CatchSignal ( SIGTERM , sig_term ) ;
2005-12-15 19:53:20 +03:00
}
2005-01-30 03:54:57 +03:00
2005-05-17 10:20:54 +04:00
/*
handle io on stdin
*/
static void server_stdin_handler ( struct event_context * event_ctx , struct fd_event * fde ,
uint16_t flags , void * private )
{
2007-09-08 17:34:42 +04:00
const char * binary_name = ( const char * ) private ;
2005-05-17 10:20:54 +04:00
uint8_t c ;
if ( read ( 0 , & c , 1 ) = = 0 ) {
2005-12-15 21:08:25 +03:00
DEBUG ( 0 , ( " %s: EOF on stdin - terminating \n " , binary_name ) ) ;
2006-09-11 08:47:56 +04:00
# if HAVE_GETPGRP
if ( getpgrp ( ) = = getpid ( ) ) {
kill ( - getpgrp ( ) , SIGTERM ) ;
}
# endif
2005-05-17 10:20:54 +04:00
exit ( 0 ) ;
}
}
2005-06-12 04:17:23 +04:00
/*
die if the user selected maximum runtime is exceeded
*/
2007-09-08 17:34:42 +04:00
_NORETURN_ static void max_runtime_handler ( struct event_context * ev ,
struct timed_event * te ,
struct timeval t , void * private )
2005-06-12 04:17:23 +04:00
{
2007-09-08 17:34:42 +04:00
const char * binary_name = ( const char * ) private ;
2005-12-15 21:08:25 +03:00
DEBUG ( 0 , ( " %s: maximum runtime exceeded - terminating \n " , binary_name ) ) ;
2005-06-12 04:17:23 +04:00
exit ( 0 ) ;
}
2005-01-30 03:54:57 +03:00
/*
main server .
*/
2005-12-15 21:08:25 +03:00
static int binary_smbd_main ( const char * binary_name , int argc , const char * argv [ ] )
2005-01-30 03:54:57 +03:00
{
2007-08-22 16:21:40 +04:00
bool opt_daemon = false ;
bool opt_interactive = false ;
2005-01-30 03:54:57 +03:00
int opt ;
poptContext pc ;
2007-12-24 10:28:22 +03:00
init_module_fn static_init [ ] = { STATIC_service_MODULES } ;
2005-12-26 19:46:55 +03:00
init_module_fn * shared_init ;
2005-01-30 03:54:57 +03:00
struct event_context * event_ctx ;
NTSTATUS status ;
const char * model = " standard " ;
2005-06-12 04:17:23 +04:00
int max_runtime = 0 ;
2006-04-03 18:02:53 +04:00
enum {
2007-08-22 16:21:40 +04:00
OPT_DAEMON = 1000 ,
OPT_INTERACTIVE ,
2006-04-03 18:02:53 +04:00
OPT_PROCESS_MODEL
} ;
2005-01-30 03:54:57 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2007-08-22 16:21:40 +04:00
{ " daemon " , ' D ' , POPT_ARG_NONE , NULL , OPT_DAEMON ,
" Become a daemon (default) " , NULL } ,
2006-04-03 18:02:53 +04:00
{ " interactive " , ' i ' , POPT_ARG_NONE , NULL , OPT_INTERACTIVE ,
2005-01-30 03:54:57 +03:00
" Run interactive (not a daemon) " , NULL } ,
2006-04-03 18:02:53 +04:00
{ " model " , ' M ' , POPT_ARG_STRING , NULL , OPT_PROCESS_MODEL ,
2005-01-30 03:54:57 +03:00
" Select process model " , " MODEL " } ,
2006-04-03 18:02:53 +04:00
{ " maximum-runtime " , 0 , POPT_ARG_INT , & max_runtime , 0 ,
2005-12-15 21:08:25 +03:00
" set maximum runtime of the server process, till autotermination " , " seconds " } ,
2005-06-13 12:12:39 +04:00
POPT_COMMON_SAMBA
2005-01-30 03:54:57 +03:00
POPT_COMMON_VERSION
2006-09-06 16:28:01 +04:00
{ NULL }
2005-01-30 03:54:57 +03:00
} ;
2005-12-15 21:08:25 +03:00
pc = poptGetContext ( binary_name , argc , argv , long_options , 0 ) ;
2006-04-03 18:02:53 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
2007-08-22 16:21:40 +04:00
case OPT_DAEMON :
opt_daemon = true ;
break ;
2006-04-03 18:02:53 +04:00
case OPT_INTERACTIVE :
2007-08-22 16:21:40 +04:00
opt_interactive = true ;
2006-04-03 18:02:53 +04:00
break ;
case OPT_PROCESS_MODEL :
model = poptGetOptArg ( pc ) ;
break ;
2007-08-22 16:21:40 +04:00
default :
2007-12-12 00:23:06 +03:00
fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
2007-08-22 16:21:40 +04:00
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
2006-04-03 18:02:53 +04:00
}
}
2007-08-22 16:21:40 +04:00
if ( opt_daemon & & opt_interactive ) {
2007-12-12 00:23:06 +03:00
fprintf ( stderr , " \n ERROR: "
2007-08-22 16:21:40 +04:00
" Option -i|--interactive is not allowed together with -D|--daemon \n \n " ) ;
poptPrintUsage ( pc , stderr , 0 ) ;
exit ( 1 ) ;
} else if ( ! opt_interactive ) {
/* default is --daemon */
opt_daemon = true ;
}
2005-01-30 03:54:57 +03:00
poptFreeContext ( pc ) ;
2007-08-22 16:21:40 +04:00
setup_logging ( binary_name , opt_interactive ? DEBUG_STDOUT : DEBUG_FILE ) ;
2005-01-30 03:54:57 +03:00
setup_signals ( ) ;
2003-08-13 05:53:07 +04:00
/* we want total control over the permissions on created files,
so set our umask to 0 */
umask ( 0 ) ;
2005-12-15 21:08:25 +03:00
DEBUG ( 0 , ( " %s version %s started. \n " , binary_name , SAMBA_VERSION_STRING ) ) ;
2008-02-22 16:08:13 +03:00
DEBUGADD ( 0 , ( " Copyright Andrew Tridgell and the Samba Team 1992-2008 \n " ) ) ;
2003-08-13 05:53:07 +04:00
2004-07-14 01:04:56 +04:00
if ( sizeof ( uint16_t ) < 2 | | sizeof ( uint32_t ) < 4 | | sizeof ( uint64_t ) < 8 ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " ERROR: Samba is not configured correctly for the word size on your machine \n " ) ) ;
2007-06-01 14:17:02 +04:00
DEBUGADD ( 0 , ( " sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u \n " ,
2007-08-23 06:10:17 +04:00
( unsigned int ) sizeof ( uint16_t ) , ( unsigned int ) sizeof ( uint32_t ) , ( unsigned int ) sizeof ( uint64_t ) ) ) ;
2003-08-13 05:53:07 +04:00
exit ( 1 ) ;
}
2004-07-14 01:04:56 +04:00
2007-08-22 16:21:40 +04:00
if ( opt_daemon ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " Becoming a daemon. \n " ) ) ;
2007-08-26 19:16:40 +04:00
become_daemon ( true ) ;
2003-08-13 05:53:07 +04:00
}
2007-12-10 06:33:16 +03:00
cleanup_tmp_files ( cmdline_lp_ctx ) ;
2005-01-30 03:54:57 +03:00
2007-12-10 06:33:16 +03:00
if ( ! directory_exist ( lp_lockdir ( cmdline_lp_ctx ) ) ) {
mkdir ( lp_lockdir ( cmdline_lp_ctx ) , 0755 ) ;
2003-08-13 05:53:07 +04:00
}
2007-12-10 06:33:16 +03:00
pidfile_create ( lp_piddir ( cmdline_lp_ctx ) , binary_name ) ;
2005-01-30 03:54:57 +03:00
/* Do *not* remove this, until you have removed
* passdb / secrets . c , and proved that Samba still builds . . . */
/* Setup the SECRETS subsystem */
2007-12-10 06:33:16 +03:00
if ( ! secrets_init ( cmdline_lp_ctx ) ) {
2005-01-30 03:54:57 +03:00
exit ( 1 ) ;
2003-08-13 05:53:07 +04:00
}
2007-12-10 06:33:16 +03:00
gensec_init ( cmdline_lp_ctx ) ; /* FIXME: */
2004-04-19 15:21:50 +04:00
2007-12-10 06:33:16 +03:00
ntptr_init ( cmdline_lp_ctx ) ; /* FIXME: maybe run this in the initialization function
2005-12-27 00:58:31 +03:00
of the spoolss RPC server instead ? */
2007-12-10 06:33:16 +03:00
ntvfs_init ( cmdline_lp_ctx ) ; /* FIXME: maybe run this in the initialization functions
2005-12-27 00:58:31 +03:00
of the SMB [ , 2 ] server instead ? */
2007-12-10 06:33:16 +03:00
process_model_init ( cmdline_lp_ctx ) ;
2005-12-27 00:58:31 +03:00
2007-12-10 06:33:16 +03:00
shared_init = load_samba_modules ( NULL , cmdline_lp_ctx , " service " ) ;
2005-12-26 19:46:55 +03:00
run_init_functions ( static_init ) ;
run_init_functions ( shared_init ) ;
talloc_free ( shared_init ) ;
2005-01-30 03:54:57 +03:00
/* the event context is the top level structure in smbd. Everything else
should hang off that */
2007-07-04 07:25:44 +04:00
event_ctx = event_context_init ( talloc_autofree_context ( ) ) ;
2005-01-14 04:32:56 +03:00
2007-10-06 01:51:47 +04:00
if ( event_ctx = = NULL ) {
DEBUG ( 0 , ( " Initializing event context failed \n " ) ) ;
return 1 ;
}
2007-01-19 07:09:32 +03:00
/* initialise clustering if needed */
2007-12-10 06:33:16 +03:00
cluster_ctdb_init ( cmdline_lp_ctx , event_ctx , model ) ;
2007-01-19 07:09:32 +03:00
2007-08-22 16:21:40 +04:00
if ( opt_interactive ) {
2005-06-07 12:33:17 +04:00
/* catch EOF on stdin */
2005-06-11 06:50:47 +04:00
# ifdef SIGTTIN
signal ( SIGTTIN , SIG_IGN ) ;
# endif
2005-06-07 12:33:17 +04:00
event_add_fd ( event_ctx , event_ctx , 0 , EVENT_FD_READ ,
2005-12-15 21:08:25 +03:00
server_stdin_handler ,
discard_const ( binary_name ) ) ;
2005-06-07 12:33:17 +04:00
}
2005-05-17 10:20:54 +04:00
2005-06-12 04:17:23 +04:00
if ( max_runtime ) {
event_add_timed ( event_ctx , event_ctx ,
timeval_current_ofs ( max_runtime , 0 ) ,
2005-12-15 21:08:25 +03:00
max_runtime_handler ,
discard_const ( binary_name ) ) ;
2005-06-12 04:17:23 +04:00
}
2005-12-15 21:08:25 +03:00
DEBUG ( 0 , ( " %s: using '%s' process model \n " , binary_name , model ) ) ;
2007-12-10 06:33:16 +03:00
status = server_service_startup ( event_ctx , cmdline_lp_ctx , model ,
lp_server_services ( cmdline_lp_ctx ) ) ;
2005-01-30 03:54:57 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Starting Services failed - %s \n " , nt_errstr ( status ) ) ) ;
2004-07-14 01:04:56 +04:00
return 1 ;
}
2003-08-13 05:53:07 +04:00
2005-01-30 03:54:57 +03:00
/* wait for events - this is where smbd sits for most of its
life */
event_loop_wait ( event_ctx ) ;
2005-01-14 04:32:56 +03:00
2005-01-30 03:54:57 +03:00
/* as everything hangs off this event context, freeing it
should initiate a clean shutdown of all services */
talloc_free ( event_ctx ) ;
2005-01-14 04:32:56 +03:00
return 0 ;
2004-07-14 01:04:56 +04:00
}
int main ( int argc , const char * argv [ ] )
{
2005-12-15 21:08:25 +03:00
return binary_smbd_main ( " smbd " , argc , argv ) ;
2003-08-13 05:53:07 +04:00
}