r6187: 1. Make sure that we don't try to delete . and .. in a more portable way.
[tprouty/samba.git] / source4 / smbd / server.c
index d25339bfc1b9c6013b2595342833522b69496b3c..1357541ceadfcbc67a30c6bf96650fe810cc247f 100644 (file)
@@ -1,7 +1,9 @@
 /* 
    Unix SMB/CIFS implementation.
+
    Main SMB server routines
-   Copyright (C) Andrew Tridgell               1992-1998
+
+   Copyright (C) Andrew Tridgell               1992-2005
    Copyright (C) Martin Pool                   2002
    Copyright (C) Jelmer Vernooij               2002
    Copyright (C) James J Myers                         2003 <myersjj@samba.org>
 */
 
 #include "includes.h"
-
-static void exit_server(const char *reason)
+#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"
+
+
+/*
+  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)
 {
-       DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
-       exit(0);
-}
+       char *path;
+       DIR *dir;
+       struct dirent *de;
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
-/****************************************************************************
- main server.
-****************************************************************************/
-static int binary_smbd_main(int argc,const char *argv[])
-{
-       BOOL is_daemon = False;
-       BOOL interactive = False;
-       BOOL Fork = True;
-       BOOL log_stdout = False;
-       int opt;
-       poptContext pc;
-       struct server_context *srv_ctx;
-       const char *model = "standard";
-       struct poptOption long_options[] = {
-               POPT_AUTOHELP
-       {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" },
-       {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"},
-       {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
-       {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
-       {"port", 'p', POPT_ARG_STRING, NULL, 0, "Listen on the specified ports"},
-       {"model", 'M', POPT_ARG_STRING, &model, 0, "select process model"},
-       POPT_COMMON_SAMBA
-       { NULL }
-       };
-       
-       pc = poptGetContext("smbd", argc, argv, long_options, 0);
-       
-       while((opt = poptGetNextOpt(pc)) != -1) {
-               switch (opt)  {
-               case 'p':
-                       lp_set_cmdline("smb ports", poptGetOptArg(pc));
-                       break;
-               }
-       }
-       poptFreeContext(pc);
+       path = smbd_tmp_path(mem_ctx, NULL);
 
-       if (interactive) {
-               Fork = False;
-               log_stdout = True;
+       dir = opendir(path);
+       if (!dir) {
+               talloc_free(mem_ctx);
+               return;
        }
 
-       if (log_stdout && Fork) {
-               DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
-               exit(1);
+       for (de=readdir(dir);de;de=readdir(dir)) {
+               /*
+                * Don't try to delete . and ..
+                */
+               if (strcmp(de->d_name, ".") != 0 &&
+                   strcmp(de->d_name, "..")) {
+                   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);
+               }
        }
-       setup_logging(argv[0], log_stdout?DEBUG_STDOUT:DEBUG_FILE);
+       closedir(dir);
+
+       talloc_free(mem_ctx);
+}
 
-       fault_setup((void (*)(void *))exit_server);
+/*
+  setup signal masks
+*/
+static void setup_signals(void)
+{
+       fault_setup(NULL);
        
        /* we are never interested in SIGPIPE */
        BlockSignals(True,SIGPIPE);
@@ -96,6 +121,39 @@ static int binary_smbd_main(int argc,const char *argv[])
        BlockSignals(False, SIGHUP);
        BlockSignals(False, SIGUSR1);
        BlockSignals(False, SIGTERM);
+}
+
+
+/*
+ main server.
+*/
+static int binary_smbd_main(int argc, const char *argv[])
+{
+       BOOL interactive = False;
+       int opt;
+       poptContext pc;
+       struct event_context *event_ctx;
+       NTSTATUS status;
+       const char *model = "standard";
+       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"},
+               POPT_COMMON_VERSION
+               POPT_TABLEEND
+       };
+       
+       pc = poptGetContext("smbd", argc, argv, long_options, 0);
+       
+       while((opt = poptGetNextOpt(pc)) != -1) /* noop */ ;
+
+       poptFreeContext(pc);
+
+       setup_logging(argv[0], interactive?DEBUG_STDOUT:DEBUG_FILE);
+       setup_signals();
 
        /* we want total control over the permissions on created files,
           so set our umask to 0 */
@@ -104,52 +162,60 @@ static int binary_smbd_main(int argc,const char *argv[])
        reopen_logs();
 
        DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING));
-       DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2004\n"));
+       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) {
                DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
                exit(1);
        }
 
-       if (!reload_services(NULL, False))
-               return(-1);     
-
-       if (!is_daemon && !is_a_socket(0)) {
-               if (!interactive)
-                       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+       lp_load(dyn_CONFIGFILE, False, False, True);
 
-               /*
-                * Setting is_daemon here prevents us from eventually calling
-                * the open_sockets_inetd()
-                */
-
-               is_daemon = True;
-       }
+       reopen_logs();
+       load_interfaces();
 
-       if (is_daemon && !interactive) {
+       if (!interactive) {
                DEBUG(3,("Becoming a daemon.\n"));
-               become_daemon(Fork);
+               become_daemon(True);
        }
 
-       if (!directory_exist(lp_lockdir(), NULL)) {
+       cleanup_tmp_files();
+
+       if (!directory_exist(lp_lockdir())) {
                mkdir(lp_lockdir(), 0755);
        }
 
-       if (is_daemon) {
-               pidfile_create("smbd");
+       pidfile_create("smbd");
+
+       /* Do *not* remove this, until you have removed
+        * passdb/secrets.c, and proved that Samba still builds... */
+       /* Setup the SECRETS subsystem */
+       if (!secrets_init()) {
+               exit(1);
        }
 
-       init_subsystems();
+       smbd_init_subsystems;
+
+       /* 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));
-       srv_ctx = server_service_startup(model);
-       if (!srv_ctx) {
-               DEBUG(0,("Starting Services failed.\n"));
+       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)));
                return 1;
        }
 
-       /* wait for events */
-       return event_loop_wait(srv_ctx->events);
+       /* wait for events - this is where smbd sits for most of its
+          life */
+       event_loop_wait(event_ctx);
+
+       /* as everything hangs off this event context, freeing it
+          should initiate a clean shutdown of all services */
+       talloc_free(event_ctx);
+
+       return 0;
 }
 
  int main(int argc, const char *argv[])