param: Change from _lp to lp__ as the prefix for internal parameter wrappers
[kai/samba.git] / source3 / smbd / server.c
index 369b7ab450d69a3889a9a21ab0ca93204a72c9d9..16c2d28a26678a11b8505da1422ae8c5f862dd69 100644 (file)
@@ -184,7 +184,7 @@ static void msg_inject_fault(struct messaging_context *msg,
                  procid_str_static(&src), sig));
 #endif
 
-       kill(sys_getpid(), sig);
+       kill(getpid(), sig);
 }
 #endif /* DEVELOPER */
 
@@ -269,6 +269,15 @@ static void smbd_parent_id_cache_delete(struct messaging_context *ctx,
        messaging_send_to_children(ctx, msg_type, msg_data);
 }
 
+static void smb_parent_force_tdis(struct messaging_context *ctx,
+                                 void* data,
+                                 uint32_t msg_type,
+                                 struct server_id srv_id,
+                                 DATA_BLOB* msg_data)
+{
+       messaging_send_to_children(ctx, msg_type, msg_data);
+}
+
 static void add_child_pid(struct smbd_parent_context *parent,
                          pid_t pid)
 {
@@ -457,6 +466,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
        }
 
        if (s->parent->interactive) {
+               reinit_after_fork(msg_ctx, sconn->ev_ctx, true);
                smbd_process(ev, sconn);
                exit_server_cleanly("end of interactive mode");
                return;
@@ -472,9 +482,9 @@ static void smbd_accept_connection(struct tevent_context *ev,
         * Generate a unique id in the parent process so that we use
         * the global random state in the parent.
         */
-       generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
+       unique_id = serverid_get_random_unique_id();
 
-       pid = sys_fork();
+       pid = fork();
        if (pid == 0) {
                NTSTATUS status = NT_STATUS_OK;
 
@@ -494,12 +504,6 @@ static void smbd_accept_connection(struct tevent_context *ev,
                 * them, counting worker smbds. */
                CatchChild();
 
-               /* close our standard file
-                  descriptors */
-               if (!debug_get_output_is_stdout()) {
-                       close_low_fds(False); /* Don't close stderr */
-               }
-
                status = reinit_after_fork(msg_ctx,
                                           ev,
                                           true);
@@ -541,7 +545,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
        }
 
        if (pid < 0) {
-               DEBUG(0,("smbd_accept_connection: sys_fork() failed: %s\n",
+               DEBUG(0,("smbd_accept_connection: fork() failed: %s\n",
                         strerror(errno)));
        }
 
@@ -806,6 +810,8 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
                           smb_pcap_updated);
        messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE,
                           brl_revalidate);
+       messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS,
+                          smb_parent_force_tdis);
 
        messaging_register(msg_ctx, NULL,
                           ID_CACHE_FLUSH, smbd_parent_id_cache_flush);
@@ -845,6 +851,23 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
        return true;
 }
 
+
+/*
+  handle stdin becoming readable when we are in --foreground mode
+ */
+static void smbd_stdin_handler(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags,
+                              void *private_data)
+{
+       char c;
+       if (read(0, &c, 1) != 1) {
+               /* we have reached EOF on stdin, which means the
+                  parent has exited. Shutdown the server */
+               exit_server_cleanly("EOF on stdin");
+       }
+}
+
 static void smbd_parent_loop(struct tevent_context *ev_ctx,
                             struct smbd_parent_context *parent)
 {
@@ -962,10 +985,10 @@ extern void build_options(bool screen);
        struct smbd_parent_context *parent = NULL;
        TALLOC_CTX *frame;
        NTSTATUS status;
-       uint64_t unique_id;
        struct tevent_context *ev_ctx;
        struct messaging_context *msg_ctx;
        struct tevent_signal *se;
+       char *np_dir = NULL;
 
        /*
         * Do this before any other talloc operation
@@ -1180,8 +1203,7 @@ extern void build_options(bool screen);
                become_daemon(Fork, no_process_group, log_stdout);
        }
 
-        generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
-        set_my_unique_id(unique_id);
+        set_my_unique_id(serverid_get_random_unique_id());
 
 #if HAVE_SETPGID
        /*
@@ -1195,6 +1217,9 @@ extern void build_options(bool screen);
        if (!directory_exist(lp_lockdir()))
                mkdir(lp_lockdir(), 0755);
 
+       if (!directory_exist(lp_piddir()))
+               mkdir(lp_piddir(), 0755);
+
        if (is_daemon)
                pidfile_create("smbd");
 
@@ -1206,6 +1231,19 @@ extern void build_options(bool screen);
                exit(1);
        }
 
+       if (!interactive) {
+               /*
+                * Do not initialize the parent-child-pipe before becoming a
+                * daemon: this is used to detect a died parent in the child
+                * process.
+                */
+               status = init_before_fork();
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
+                       exit(1);
+               }
+       }
+
        smbd_server_conn->msg_ctx = msg_ctx;
 
        parent = talloc_zero(ev_ctx, struct smbd_parent_context);
@@ -1327,16 +1365,24 @@ extern void build_options(bool screen);
                return -1;
        }
 
+       np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
+       if (!np_dir) {
+               DEBUG(0, ("%s: Out of memory\n", __location__));
+               return -1;
+       }
+
+       if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
+               DEBUG(0, ("Failed to create pipe directory %s - %s\n",
+                         np_dir, strerror(errno)));
+               return -1;
+       }
+
        if (is_daemon && !interactive) {
                if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
                        start_epmd(ev_ctx, msg_ctx);
                }
        }
 
-       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
-               exit(1);
-       }
-
        /* only start other daemons 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 */
@@ -1346,7 +1392,7 @@ extern void build_options(bool screen);
                        start_lsasd(ev_ctx, msg_ctx);
                }
 
-               if (!_lp_disable_spoolss() &&
+               if (!lp__disable_spoolss() &&
                    (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
                        bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);
 
@@ -1354,13 +1400,17 @@ extern void build_options(bool screen);
                                exit(1);
                        }
                }
-       } else if (!_lp_disable_spoolss() &&
+       } else if (!lp__disable_spoolss() &&
                   (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
                if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) {
                        exit(1);
                }
        }
 
+       if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
+               exit(1);
+       }
+
        if (!is_daemon) {
                /* inetd mode */
                TALLOC_FREE(frame);
@@ -1370,10 +1420,8 @@ extern void build_options(bool screen);
                   goes away */
                smbd_server_conn->sock = dup(0);
 
-               /* close our standard file descriptors */
-               if (!debug_get_output_is_stdout()) {
-                       close_low_fds(False); /* Don't close stderr */
-               }
+               /* close stdin, stdout (if not logging to it), but not stderr */
+               close_low_fds(true, !debug_get_output_is_stdout(), false);
 
 #ifdef HAVE_ATEXIT
                atexit(killkids);
@@ -1399,6 +1447,14 @@ extern void build_options(bool screen);
        /* make sure we always have a valid stackframe */
        frame = talloc_stackframe();
 
+       if (!Fork) {
+               /* if we are running in the foreground then look for
+                  EOF on stdin, and exit if it happens. This allows
+                  us to die if the parent process dies
+               */
+               tevent_add_fd(ev_ctx, parent, 0, TEVENT_FD_READ, smbd_stdin_handler, NULL);
+       }
+
        smbd_parent_loop(ev_ctx, parent);
 
        exit_server_cleanly(NULL);