Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
[ira/wip.git] / source4 / smbd / server.c
index 41d6329b024058e7822e98f8481d789d89b483a9..dd63ca1ecabd5901a514bed36aba67eb986624d0 100644 (file)
@@ -10,7 +10,7 @@
    
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -19,8 +19,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "lib/cmdline/popt_common.h"
 #include "system/dir.h"
 #include "system/filesys.h"
-#include "system/kerberos.h"
-
-/* For sepecifiying event context to GSSAPI below */
-#include "heimdal/lib/gssapi/gssapi_locl.h"
+#include "build.h"
+#include "ldb/include/ldb.h"
+#include "registry/registry.h"
+#include "ntvfs/ntvfs.h"
+#include "ntptr/ntptr.h"
+#include "auth/gensec/gensec.h"
+#include "smbd/process_model.h"
+#include "smbd/service.h"
+#include "param/secrets.h"
+#include "smbd/pidfile.h"
+#include "cluster/ctdb/ctdb_cluster.h"
+#include "param/param.h"
 
 /*
   recursively delete a directory tree
@@ -51,8 +58,7 @@ static void recursive_delete(const char *path)
                char *fname;
                struct stat st;
 
-               if (strcmp(de->d_name, ".") == 0 ||
-                   strcmp(de->d_name, "..") == 0) {
+               if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) {
                        continue;
                }
 
@@ -82,42 +88,64 @@ static void recursive_delete(const char *path)
   range locking system. So instead of putting the burden on tdb to
   cleanup tmp files, this function deletes them. 
 */
-static void cleanup_tmp_files(void)
+static void cleanup_tmp_files(struct loadparm_context *lp_ctx)
 {
        char *path;
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
-       path = smbd_tmp_path(mem_ctx, NULL);
+       path = smbd_tmp_path(mem_ctx, lp_ctx, NULL);
 
        recursive_delete(path);
        talloc_free(mem_ctx);
 }
 
+static void sig_hup(int sig)
+{
+       debug_schedule_reopen_logs();
+}
+
+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);
+}
+
 /*
   setup signal masks
 */
 static void setup_signals(void)
 {
        /* we are never interested in SIGPIPE */
-       BlockSignals(True,SIGPIPE);
+       BlockSignals(true,SIGPIPE);
 
 #if defined(SIGFPE)
        /* we are never interested in SIGFPE */
-       BlockSignals(True,SIGFPE);
+       BlockSignals(true,SIGFPE);
 #endif
 
+       /* We are no longer interested in USR1 */
+       BlockSignals(true, SIGUSR1);
+
 #if defined(SIGUSR2)
        /* We are no longer interested in USR2 */
-       BlockSignals(True,SIGUSR2);
+       BlockSignals(true,SIGUSR2);
 #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. */
-       BlockSignals(False, SIGHUP);
-       BlockSignals(False, SIGUSR1);
-       BlockSignals(False, SIGTERM);
-}
+       BlockSignals(false, SIGHUP);
+       BlockSignals(false, SIGTERM);
 
+       CatchSignal(SIGHUP, sig_hup);
+       CatchSignal(SIGTERM, sig_term);
+}
 
 /*
   handle io on stdin
@@ -125,123 +153,192 @@ static void setup_signals(void)
 static void server_stdin_handler(struct event_context *event_ctx, struct fd_event *fde, 
                                 uint16_t flags, void *private)
 {
+       const char *binary_name = (const char *)private;
        uint8_t c;
        if (read(0, &c, 1) == 0) {
-               DEBUG(0,("smbd: EOF on stdin - terminating\n"));
+               DEBUG(0,("%s: EOF on stdin - terminating\n", binary_name));
+#if HAVE_GETPGRP
+               if (getpgrp() == getpid()) {
+                       kill(-getpgrp(), SIGTERM);
+               }
+#endif
                exit(0);
        }
 }
 
-
 /*
   die if the user selected maximum runtime is exceeded
 */
-static void max_runtime_handler(struct event_context *ev, struct timed_event *te, 
-                               struct timeval t, void *private)
+_NORETURN_ static void max_runtime_handler(struct event_context *ev, 
+                                          struct timed_event *te, 
+                                          struct timeval t, void *private)
 {
-       DEBUG(0,("smbd maximum runtime exceeded - terminating\n"));
+       const char *binary_name = (const char *)private;
+       DEBUG(0,("%s: maximum runtime exceeded - terminating\n", binary_name));
        exit(0);
 }
 
-
 /*
  main server.
 */
-static int binary_smbd_main(int argc, const char *argv[])
+static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
 {
-       BOOL interactive = False;
+       bool opt_daemon = false;
+       bool opt_interactive = false;
        int opt;
        poptContext pc;
+       init_module_fn static_init[] = { STATIC_service_MODULES };
+       init_module_fn *shared_init;
        struct event_context *event_ctx;
        NTSTATUS status;
        const char *model = "standard";
        int max_runtime = 0;
+       enum {
+               OPT_DAEMON = 1000,
+               OPT_INTERACTIVE,
+               OPT_PROCESS_MODEL
+       };
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               {"interactive", 'i', POPT_ARG_VAL, &interactive, True, 
+               {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
+                "Become a daemon (default)", NULL },
+               {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
                 "Run interactive (not a daemon)", NULL},
-               {"model", 'M', POPT_ARG_STRING, &model, True
+               {"model", 'M', POPT_ARG_STRING, NULL, OPT_PROCESS_MODEL
                 "Select process model", "MODEL"},
-               {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, True
-                "set maximum time for smbd to live", "seconds"},
+               {"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0
+                "set maximum runtime of the server process, till autotermination", "seconds"},
                POPT_COMMON_SAMBA
                POPT_COMMON_VERSION
-               POPT_TABLEEND
+               { NULL }
        };
-       
-       pc = poptGetContext("smbd", argc, argv, long_options, 0);
-       
-       while((opt = poptGetNextOpt(pc)) != -1) /* noop */ ;
+
+       pc = poptGetContext(binary_name, argc, argv, long_options, 0);
+       while((opt = poptGetNextOpt(pc)) != -1) {
+               switch(opt) {
+               case OPT_DAEMON:
+                       opt_daemon = true;
+                       break;
+               case OPT_INTERACTIVE:
+                       opt_interactive = true;
+                       break;
+               case OPT_PROCESS_MODEL:
+                       model = poptGetOptArg(pc);
+                       break;
+               default:
+                       fprintf(stderr, "\nInvalid option %s: %s\n\n",
+                                 poptBadOption(pc, 0), poptStrerror(opt));
+                       poptPrintUsage(pc, stderr, 0);
+                       exit(1);
+               }
+       }
+
+       if (opt_daemon && opt_interactive) {
+               fprintf(stderr,"\nERROR: "
+                         "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;
+       }
 
        poptFreeContext(pc);
 
-       setup_logging(argv[0], interactive?DEBUG_STDOUT:DEBUG_FILE);
+       setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
        setup_signals();
 
        /* we want total control over the permissions on created files,
           so set our umask to 0 */
        umask(0);
 
-       DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING));
-       DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2005\n"));
+       DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
+       DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2007\n"));
 
        if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
                DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
+               DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
+                           (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
                exit(1);
        }
 
-       if (!interactive) {
+       if (opt_daemon) {
                DEBUG(3,("Becoming a daemon.\n"));
-               become_daemon(True);
+               become_daemon(true);
        }
 
-       cleanup_tmp_files();
+       cleanup_tmp_files(cmdline_lp_ctx);
 
-       if (!directory_exist(lp_lockdir())) {
-               mkdir(lp_lockdir(), 0755);
+       if (!directory_exist(lp_lockdir(cmdline_lp_ctx))) {
+               mkdir(lp_lockdir(cmdline_lp_ctx), 0755);
        }
 
-       pidfile_create("smbd");
+       pidfile_create(lp_piddir(cmdline_lp_ctx), binary_name);
 
        /* Do *not* remove this, until you have removed
         * passdb/secrets.c, and proved that Samba still builds... */
        /* Setup the SECRETS subsystem */
-       if (!secrets_init()) {
+       if (!secrets_init(cmdline_lp_ctx)) {
                exit(1);
        }
 
-       smbd_init_subsystems;
+       share_init();
+
+       gensec_init(cmdline_lp_ctx); /* FIXME: */
+
+       ntptr_init(cmdline_lp_ctx);     /* FIXME: maybe run this in the initialization function 
+                                               of the spoolss RPC server instead? */
+
+       ntvfs_init(cmdline_lp_ctx);     /* FIXME: maybe run this in the initialization functions 
+                                               of the SMB[,2] server instead? */
 
+       process_model_init(cmdline_lp_ctx); 
+
+       shared_init = load_samba_modules(NULL, cmdline_lp_ctx, "service");
+
+       run_init_functions(static_init);
+       run_init_functions(shared_init);
+
+       talloc_free(shared_init);
+       
        /* the event context is the top level structure in smbd. Everything else
           should hang off that */
-       event_ctx = event_context_init(NULL);
+       event_ctx = event_context_init(talloc_autofree_context());
 
-       if (interactive) {
+       if (event_ctx == NULL) {
+               DEBUG(0,("Initializing event context failed\n"));
+               return 1;
+       }
+
+       /* initialise clustering if needed */
+       cluster_ctdb_init(cmdline_lp_ctx, event_ctx, model);
+
+       if (opt_interactive) {
                /* catch EOF on stdin */
 #ifdef SIGTTIN
                signal(SIGTTIN, SIG_IGN);
 #endif
                event_add_fd(event_ctx, event_ctx, 0, EVENT_FD_READ, 
-                            server_stdin_handler, NULL);
+                            server_stdin_handler,
+                            discard_const(binary_name));
        }
 
 
        if (max_runtime) {
                event_add_timed(event_ctx, event_ctx, 
                                timeval_current_ofs(max_runtime, 0), 
-                               max_runtime_handler, NULL);
+                               max_runtime_handler,
+                               discard_const(binary_name));
        }
 
-       DEBUG(0,("Using %s process model\n", model));
-       status = server_service_startup(event_ctx, model, lp_server_services());
+       DEBUG(0,("%s: using '%s' process model\n", binary_name, model));
+       status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
+                                       lp_server_services(cmdline_lp_ctx));
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
                return 1;
        }
 
-       /* Hack to ensure that GSSAPI uses the right event context */
-       gssapi_krb5_init_ev(event_ctx);
-
        /* wait for events - this is where smbd sits for most of its
           life */
        event_loop_wait(event_ctx);
@@ -255,5 +352,5 @@ static int binary_smbd_main(int argc, const char *argv[])
 
  int main(int argc, const char *argv[])
 {
-       return binary_smbd_main(argc, argv);
+       return binary_smbd_main("smbd", argc, argv);
 }