r10656: BIG merge from trunk. Features not copied over
[sfrench/samba-autobuild/.git] / source / smbd / server.c
index 07723cc20e7e7284189c4d936b460cb058bacf9a..8310b408d07d74a5a466b4afca49a1968b136924 100644 (file)
 
 #include "includes.h"
 
-int am_parent = 1;
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
+static int am_parent = 1;
 
 /* the last message the was processed */
 int last_message = -1;
@@ -30,6 +34,7 @@ int last_message = -1;
 /* a useful macro to debug the last message processed */
 #define LAST_MESSAGE() smb_fn_name(last_message)
 
+extern struct auth_context *negprot_global_auth_context;
 extern pstring user_socket_options;
 extern SIG_ATOMIC_T got_sig_term;
 extern SIG_ATOMIC_T reload_after_sighup;
@@ -64,7 +69,7 @@ static void smbd_set_server_fd(int fd)
 static void sig_term(void)
 {
        got_sig_term = 1;
-       sys_select_signal();
+       sys_select_signal(SIGTERM);
 }
 
 /****************************************************************************
@@ -74,7 +79,7 @@ static void sig_term(void)
 static void sig_hup(int sig)
 {
        reload_after_sighup = 1;
-       sys_select_signal();
+       sys_select_signal(SIGHUP);
 }
 
 /****************************************************************************
@@ -91,7 +96,7 @@ static void  killkids(void)
  somewhere else.
 ****************************************************************************/
 
-static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid),
+static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
                         void *UNUSED(buf), size_t UNUSED(len))
 {
         DEBUG(10, ("** sam sync message received, ignoring\n"));
@@ -102,7 +107,8 @@ static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid),
  somewhere else.
 ****************************************************************************/
 
-static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len)
+static void msg_sam_repl(int msg_type, struct process_id pid,
+                        void *buf, size_t len)
 {
         uint32 low_serial;
 
@@ -135,7 +141,8 @@ static BOOL open_sockets_inetd(void)
        return True;
 }
 
-static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len)
+static void msg_exit_server(int msg_type, struct process_id src,
+                           void *buf, size_t len)
 {
        exit_server("Got a SHUTDOWN message");
 }
@@ -145,7 +152,7 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len)
  Have we reached the process limit ?
 ****************************************************************************/
 
-BOOL allowable_number_of_smbd_processes(void)
+static BOOL allowable_number_of_smbd_processes(void)
 {
        int max_processes = lp_max_smbd_processes();
 
@@ -186,6 +193,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
        int fd_listenset[FD_SETSIZE];
        fd_set listen_set;
        int s;
+       int maxfd = 0;
        int i;
        char *ports;
 
@@ -239,9 +247,11 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                                continue;
                        }
 
-                       for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) {
+                       for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
                                unsigned port = atoi(tok);
-                               if (port == 0) continue;
+                               if (port == 0) {
+                                       continue;
+                               }
                                s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
                                if(s == -1)
                                        return False;
@@ -249,13 +259,17 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                                /* ready to listen */
                                set_socket_options(s,"SO_KEEPALIVE"); 
                                set_socket_options(s,user_socket_options);
-      
-                               if (listen(s, 5) == -1) {
+     
+                               /* Set server socket to non-blocking for the accept. */
+                               set_blocking(s,False); 
+                               if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
                                        DEBUG(0,("listen: %s\n",strerror(errno)));
                                        close(s);
                                        return False;
                                }
                                FD_SET(s,&listen_set);
+                               maxfd = MAX( maxfd, s);
 
                                num_sockets++;
                                if (num_sockets >= FD_SETSIZE) {
@@ -273,7 +287,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
 
                num_interfaces = 1;
                
-               for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) {
+               for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
                        unsigned port = atoi(tok);
                        if (port == 0) continue;
                        /* open an incoming socket */
@@ -286,7 +300,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                        set_socket_options(s,"SO_KEEPALIVE"); 
                        set_socket_options(s,user_socket_options);
                        
-                       if (listen(s, 5) == -1) {
+                       /* Set server socket to non-blocking for the accept. */
+                       set_blocking(s,False); 
+                       if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
                                DEBUG(0,("open_sockets_smbd: listen: %s\n",
                                         strerror(errno)));
                                close(s);
@@ -295,6 +312,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
 
                        fd_listenset[num_sockets] = s;
                        FD_SET(s,&listen_set);
+                       maxfd = MAX( maxfd, s);
 
                        num_sockets++;
 
@@ -329,7 +347,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                memcpy((char *)&lfds, (char *)&listen_set, 
                       sizeof(listen_set));
                
-               num = sys_select(FD_SETSIZE,&lfds,NULL,NULL,NULL);
+               num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL);
                
                if (num == -1 && errno == EINTR) {
                        if (got_sig_term) {
@@ -378,6 +396,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                                continue;
                        }
 
+                       /* Ensure child is set to blocking mode */
+                       set_blocking(smbd_server_fd(),True);
+
                        if (smbd_server_fd() != -1 && interactive)
                                return True;
                        
@@ -398,17 +419,18 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
                                
                                /* this is needed so that we get decent entries
                                   in smbstatus for port 445 connects */
-                               set_remote_machine_name(get_socket_addr(smbd_server_fd()), False);
+                               set_remote_machine_name(get_peer_addr(smbd_server_fd()), False);
                                
-                               /* Reset global variables in util.c so
-                                  that client substitutions will be
-                                  done correctly in the process.  */
-                               reset_globals_after_fork();
+                               /* Reset the state of the random
+                                * number generation system, so
+                                * children do not get the same random
+                                * numbers as each other */
 
-                               /* tdb needs special fork handling */
+                               set_need_random_reseed();
+                               /* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
                                if (tdb_reopen_all() == -1) {
                                        DEBUG(0,("tdb_reopen_all failed.\n"));
-                                       return False;
+                                       smb_panic("tdb_reopen_all failed.");
                                }
 
                                return True; 
@@ -448,6 +470,39 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
 /* NOTREACHED  return True; */
 }
 
+/****************************************************************************
+ Reload printers
+**************************************************************************/
+void reload_printers(void)
+{
+       int snum;
+       int n_services = lp_numservices();
+       int pnum = lp_servicenumber(PRINTERS_NAME);
+       const char *pname;
+
+       pcap_cache_reload();
+
+       /* remove stale printers */
+       for (snum = 0; snum < n_services; snum++) {
+               /* avoid removing PRINTERS_NAME or non-autoloaded printers */
+               if (snum == pnum || !(lp_snum_ok(snum) && lp_print_ok(snum) &&
+                                     lp_autoloaded(snum)))
+                       continue;
+
+               pname = lp_printername(snum);
+               if (!pcap_printername_ok(pname)) {
+                       DEBUG(3, ("removing stale printer %s\n", pname));
+
+                       if (is_printer_published(NULL, snum, NULL))
+                               nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH);
+                       del_a_printer(pname);
+                       lp_killservice(snum);
+               }
+       }
+
+       load_printers();
+}
+
 /****************************************************************************
  Reload the services file.
 **************************************************************************/
@@ -472,10 +527,10 @@ BOOL reload_services(BOOL test)
                return(True);
 
        lp_killunused(conn_snum_used);
-       
+
        ret = lp_load(dyn_CONFIGFILE, False, False, True);
 
-       load_printers();
+       reload_printers();
 
        /* perhaps the config filename is now set */
        if (!test)
@@ -485,22 +540,21 @@ BOOL reload_services(BOOL test)
 
        load_interfaces();
 
-       {
-               if (smbd_server_fd() != -1) {      
-                       set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
-                       set_socket_options(smbd_server_fd(), user_socket_options);
-               }
+       if (smbd_server_fd() != -1) {      
+               set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
+               set_socket_options(smbd_server_fd(), user_socket_options);
        }
 
        mangle_reset_cache();
        reset_stat_cache();
 
        /* this forces service parameters to be flushed */
-       set_current_service(NULL,True);
+       set_current_service(NULL,0,True);
 
        return(ret);
 }
 
+
 #if DUMP_CORE
 /*******************************************************************
 prepare to dump a core file - carefully!
@@ -535,6 +589,10 @@ static BOOL dump_core(void)
 
 
        DEBUG(0,("Dumping core in %s\n", dname));
+       /* Ensure we don't have a signal handler for abort. */
+#ifdef SIGABRT
+       CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
+#endif
        abort();
        return(True);
 }
@@ -547,8 +605,6 @@ static BOOL dump_core(void)
 void exit_server(const char *reason)
 {
        static int firsttime=1;
-       extern char *last_inbuf;
-       extern struct auth_context *negprot_global_auth_context;
 
        if (!firsttime)
                exit(0);
@@ -567,9 +623,6 @@ void exit_server(const char *reason)
 
        print_notify_send_messages(3); /* 3 second timeout. */
 
-       /* run all registered exit events */
-       smb_run_exit_events();
-
        /* delete our entry in the connections database. */
        yield_connection(NULL,"");
 
@@ -584,6 +637,7 @@ void exit_server(const char *reason)
 
        if (!reason) {   
                int oldlevel = DEBUGLEVEL;
+               char *last_inbuf = get_InBuffer();
                DEBUGLEVEL = 10;
                DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
                if (last_inbuf)
@@ -696,6 +750,10 @@ void build_options(BOOL screen);
                log_stdout = True;
        }
 
+       if (interactive && (DEBUGLEVEL >= 9)) {
+               talloc_enable_leak_report();
+       }
+
        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);
@@ -705,7 +763,7 @@ void build_options(BOOL screen);
 
        /* we want to re-seed early to prevent time delays causing
            client problems at a later date. (tridge) */
-       generate_random_buffer(NULL, 0, False);
+       generate_random_buffer(NULL, 0);
 
        /* make absolutely sure we run as root - to handle cases where people
           are crazy enough to have it setuid */
@@ -744,8 +802,8 @@ void build_options(BOOL screen);
 
        reopen_logs();
 
-       DEBUG(0,( "smbd version %s started.\n", VERSION));
-       DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n"));
+       DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING));
+       DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2004\n"));
 
        DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
                 (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
@@ -767,6 +825,9 @@ void build_options(BOOL screen);
 
        init_structs();
 
+       if (!init_guest_info())
+               return -1;
+
 #ifdef WITH_PROFILE
        if (!profile_setup(False)) {
                DEBUG(0,("ERROR: failed to setup profiling\n"));
@@ -808,21 +869,47 @@ void build_options(BOOL screen);
        if (is_daemon)
                pidfile_create("smbd");
 
+       /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
        if (!message_init())
                exit(1);
 
+       if (!session_init())
+               exit(1);
+
+       if (conn_tdb_ctx() == NULL)
+               exit(1);
+
+       if (!locking_init(0))
+               exit(1);
+
+       if (!share_info_db_init())
+               exit(1);
+
+       namecache_enable();
+
+       if (!init_registry())
+               exit(1);
+
+#if 0
+       if (!init_svcctl_db())
+                exit(1);
+#endif
+
        if (!print_backend_init())
                exit(1);
 
        /* Setup the main smbd so that we can get messages. */
+       /* don't worry about general printing messages here */
+
        claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
 
-       /* 
-          DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD
-          THIS *killed* LOTS OF BUILD FARM MACHINES. IT CREATED HUNDREDS OF 
-          smbd PROCESSES THAT NEVER DIE
-          start_background_queue(); 
-       */
+       /* only start the background queue daemon if we are 
+          running as a daemon -- bad things will happen if
+          smbd is launched via inetd and we fork a copy of 
+          ourselves here */
+
+       if ( is_daemon && !interactive )
+               start_background_queue(); 
 
        if (!open_sockets_smbd(is_daemon, interactive, ports))
                exit(1);
@@ -831,40 +918,32 @@ void build_options(BOOL screen);
         * everything after this point is run after the fork()
         */ 
 
-       namecache_enable();
-
-       if (!locking_init(0))
-               exit(1);
-
-       if (!share_info_db_init())
-               exit(1);
+#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
+       /* On Linux we lose the ability to dump core when we change our user
+        * ID. We know how to dump core safely, so let's make sure we have our
+        * dumpable flag set.
+        */
+       prctl(PR_SET_DUMPABLE, 1);
+#endif
 
-       if (!init_registry())
-               exit(1);
+       /* Initialise the password backed before the global_sam_sid
+          to ensure that we fetch from ldap before we make a domain sid up */
 
        if(!initialize_password_db(False))
                exit(1);
 
-       if (!idmap_init())
-               exit(1);
-
-       if (!idmap_init_wellknown_sids())
+       if(!get_global_sam_sid()) {
+               DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
                exit(1);
+       }
 
        static_init_rpc;
 
        init_modules();
 
-       uni_group_cache_init(); /* Non-critical */
-       
        /* possibly reload the services file. */
        reload_services(True);
 
-       if(!get_global_sam_sid()) {
-               DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
-               exit(1);
-       }
-
        if (!init_account_policy()) {
                DEBUG(0,("Could not open account policy tdb.\n"));
                exit(1);
@@ -883,6 +962,9 @@ void build_options(BOOL screen);
        if (!init_change_notify())
                exit(1);
 
+       /* Setup aio signal handler. */
+       initialize_async_io_handler();
+
        /* re-initialise the timezone */
        TimeInit();
 
@@ -891,8 +973,8 @@ void build_options(BOOL screen);
 
        smbd_process();
        
-       uni_group_cache_shutdown();
        namecache_shutdown();
+
        exit_server("normal exit");
        return(0);
 }