r12620: Get rid of automatically generated lists of init functions of subsystems.
[kai/samba.git] / source4 / smbd / server.c
index d6f2afdaea4f54524401542d33055569ae67e364..513fa19c428150d9240473f3a1ef3b2eed4f4c29 100644 (file)
 #include "includes.h"
 #include "lib/events/events.h"
 #include "version.h"
-#include "dynconfig.h"
 #include "lib/cmdline/popt_common.h"
 #include "system/dir.h"
 #include "system/filesys.h"
-
+#include "smb_build.h"
+#include "registry/registry.h"
+#include "ntvfs/ntvfs.h"
+#include "ntptr/ntptr.h"
+#include "auth/gensec/gensec.h"
 
 /*
-  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. 
+  recursively delete a directory tree
 */
-static void cleanup_tmp_files(void)
+static void recursive_delete(const char *path)
 {
-       char *path;
        DIR *dir;
        struct dirent *de;
-       TALLOC_CTX *mem_ctx = talloc_new(NULL);
-
-       path = smbd_tmp_path(mem_ctx, NULL);
 
        dir = opendir(path);
        if (!dir) {
-               talloc_free(mem_ctx);
                return;
        }
 
        for (de=readdir(dir);de;de=readdir(dir)) {
-               /*
-                * Don't try to delete . and ..
-                */
-               if (strcmp(de->d_name, ".") != 0 &&
-                   strcmp(de->d_name, "..") != 0) {
-                   char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
-                   int ret = unlink(fname);
-                   if (ret == -1 &&
-                       errno != ENOENT &&
-                       errno != EPERM &&
-                       errno != EISDIR) {
-                           DEBUG(0,("Unabled to delete '%s' - %s\n", 
-                                     fname, strerror(errno)));
-                           smb_panic("unable to cleanup tmp files");
-                   }
-                   if (ret == -1 &&
-                       errno == EPERM) {
-                       /*
-                        * If it is a dir, don't complain
-                        * NOTE! The test will only happen if we have
-                        * sys/stat.h, otherwise we will always error out
-                        */
-#ifdef HAVE_SYS_STAT_H
-                       struct stat sb;
-                       if (stat(fname, &sb) != -1 &&
-                           !S_ISDIR(sb.st_mode))
-#endif
-                       {
-                            DEBUG(0,("Unable to delete '%s' - %s\n",
-                                     fname, strerror(errno)));
-                            smb_panic("unable to cleanup tmp files");
-                       }
-                   }
-                   talloc_free(fname);
+               char *fname;
+               struct stat st;
+
+               if (strcmp(de->d_name, ".") == 0 ||
+                   strcmp(de->d_name, "..") == 0) {
+                       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");
                }
+               talloc_free(fname);
        }
        closedir(dir);
+}
+
+/*
+  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. 
+*/
+static void cleanup_tmp_files(void)
+{
+       char *path;
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+
+       path = smbd_tmp_path(mem_ctx, NULL);
 
+       recursive_delete(path);
        talloc_free(mem_ctx);
 }
 
@@ -101,8 +99,6 @@ static void cleanup_tmp_files(void)
 */
 static void setup_signals(void)
 {
-       fault_setup(NULL);
-       
        /* we are never interested in SIGPIPE */
        BlockSignals(True,SIGPIPE);
 
@@ -111,6 +107,9 @@ static void setup_signals(void)
        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);
@@ -119,49 +118,79 @@ static void setup_signals(void)
        /* 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);
+
+       /* as we don't handle on this signals yet, we need to ignore them,
+        * instead of terminating */
+       CatchSignal(SIGHUP, SIG_IGN);
+}
+
+/*
+  handle io on stdin
+*/
+static void server_stdin_handler(struct event_context *event_ctx, struct fd_event *fde, 
+                                uint16_t flags, void *private)
+{
+       const char *binary_name = private;
+       uint8_t c;
+       if (read(0, &c, 1) == 0) {
+               DEBUG(0,("%s: EOF on stdin - terminating\n", binary_name));
+               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)
+{
+       const char *binary_name = 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;
        int opt;
        poptContext pc;
+       init_module_fn static_init[] = STATIC_SERVER_SERVICE_MODULES;
+       init_module_fn *shared_init;
        struct event_context *event_ctx;
        NTSTATUS status;
        const char *model = "standard";
+       int max_runtime = 0;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               POPT_COMMON_SAMBA
                {"interactive", 'i', POPT_ARG_VAL, &interactive, True, 
                 "Run interactive (not a daemon)", NULL},
                {"model", 'M', POPT_ARG_STRING, &model, True, 
                 "Select process model", "MODEL"},
+               {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, True, 
+                "set maximum runtime of the server process, till autotermination", "seconds"},
+               POPT_COMMON_SAMBA
                POPT_COMMON_VERSION
                POPT_TABLEEND
        };
-       
-       pc = poptGetContext("smbd", argc, argv, long_options, 0);
+
+       pc = poptGetContext(binary_name, argc, argv, long_options, 0);
        
        while((opt = poptGetNextOpt(pc)) != -1) /* noop */ ;
 
        poptFreeContext(pc);
 
-       setup_logging(argv[0], interactive?DEBUG_STDOUT:DEBUG_FILE);
+       setup_logging(binary_name, 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);
 
-       reopen_logs();
-
-       DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING));
+       DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
        DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2005\n"));
 
        if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
@@ -169,11 +198,6 @@ static int binary_smbd_main(int argc, const char *argv[])
                exit(1);
        }
 
-       lp_load(dyn_CONFIGFILE, False, False, True);
-
-       reopen_logs();
-       load_interfaces();
-
        if (!interactive) {
                DEBUG(3,("Becoming a daemon.\n"));
                become_daemon(True);
@@ -185,7 +209,7 @@ static int binary_smbd_main(int argc, const char *argv[])
                mkdir(lp_lockdir(), 0755);
        }
 
-       pidfile_create("smbd");
+       pidfile_create(binary_name);
 
        /* Do *not* remove this, until you have removed
         * passdb/secrets.c, and proved that Samba still builds... */
@@ -194,13 +218,49 @@ static int binary_smbd_main(int argc, const char *argv[])
                exit(1);
        }
 
-       smbd_init_subsystems;
+       gensec_init();
+
+       registry_init(); /* FIXME: maybe run this in the initialization function 
+                                               of the winreg RPC server instead? */
+
+       ntptr_init();   /* FIXME: maybe run this in the initialization function 
+                                               of the spoolss RPC server instead? */
+
+       ntvfs_init();   /* FIXME: maybe run this in the initialization functions 
+                                               of the SMB[,2] server instead? */
+
+       process_model_init(); 
+
+       shared_init = load_samba_modules(NULL, "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);
 
-       DEBUG(0,("Using %s process model\n", model));
+       if (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,
+                            discard_const(binary_name));
+       }
+
+
+       if (max_runtime) {
+               event_add_timed(event_ctx, event_ctx, 
+                               timeval_current_ofs(max_runtime, 0), 
+                               max_runtime_handler,
+                               discard_const(binary_name));
+       }
+
+       DEBUG(0,("%s: using '%s' process model\n", binary_name, model));
        status = server_service_startup(event_ctx, model, lp_server_services());
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
@@ -220,5 +280,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);
 }