[REVIEW] launchd support for smbd and winbindd

James Peach jpeach at samba.org
Mon Oct 15 20:44:20 GMT 2007


Hi all,

The series of patches below are the changes for launchd support ported  
from the SAMBA_3_2 svn branch to the v3-2-test git branch. I believe  
that I have preserved Jeremy's IPv6 changes. Note that while the  
cherry-picked changes in the early patches are marked GPL2, this is  
corrected to GPL3 in subsequent patches.

These changes are available in the "feature/launchd" branch of git:// 
git.samba.org/jpeach/samba.git. You should be able to apply them to a  
local branch by sending this message into some form of git-am  
invocation.

If there are no dissenting voices, I'll merge this to v3-2-test before  
the end of this week.

thanks,

James

 From c8b3db77716b424a73be32b0d73227b006619b1b Mon Sep 17 00:00:00 2001
From: James Peach <jpeach at samba.org>
Date: Sat, 13 Oct 2007 18:12:34 -0700
Subject: [PATCH] Refactor the various daemon run-mode options.

This makes the semantics of the different daemon run modes explicit
and normalizes the commandline options of nmbd, smbd and winbindd
as much as possible.
---
  source/include/popt_common.h |   11 +++++
  source/nmbd/nmbd.c           |   60 ++++++++++++++--------------
  source/smbd/server.c         |   89 ++++++++++++++++++++++ 
+-------------------
  source/winbindd/winbindd.c   |   45 ++++++++++++---------
  4 files changed, 116 insertions(+), 89 deletions(-)

diff --git a/source/include/popt_common.h b/source/include/popt_common.h
index 24c0bbf..9944610 100644
--- a/source/include/popt_common.h
+++ b/source/include/popt_common.h
@@ -49,6 +49,17 @@ struct user_auth_info {
  	int signing_state;
  };

+enum smb_server_mode {
+	/* Daemonize and manage our own sockets */
+	SERVER_MODE_DAEMON,
+	/* Don't daemonize or manage sockets */
+	SERVER_MODE_INETD,
+	/* Don't daemonize, but do manage sockets */
+	SERVER_MODE_FOREGROUND,
+	/* Run in the foreground, log to stdout, don't fork children */
+	SERVER_MODE_INTERACTIVE
+};
+
  extern struct user_auth_info cmdline_auth_info;

  #endif /* _POPT_COMMON_H */
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index f0de0b8..28a6b25 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -31,15 +31,6 @@ extern BOOL global_in_nmbd;

  extern BOOL override_logfile;

-/* are we running as a daemon ? */
-static BOOL is_daemon;
-
-/* fork or run in foreground ? */
-static BOOL Fork = True;
-
-/* log to standard output ? */
-static BOOL log_stdout;
-
  /* have we found LanMan clients yet? */
  BOOL found_lm_clients = False;

@@ -649,7 +640,7 @@ static void process(void)
   Open the socket communication.
    
**************************************************************************** */

-static BOOL open_sockets(BOOL isdaemon, int port)
+static BOOL open_sockets(enum smb_server_mode server_mode, int port)
  {
  	/*
  	 * The sockets opened here will be used to receive broadcast
@@ -659,12 +650,13 @@ static BOOL open_sockets(BOOL isdaemon, int port)
  	 * now deprecated.
  	 */

-	if ( isdaemon )
+	if ( server_mode == SERVER_MODE_INETD ) {
+		ClientNMB = 0;
+	} else {
  		ClientNMB = open_socket_in(SOCK_DGRAM, port,
  					   0, interpret_addr(lp_socket_address()),
  					   True);
-	else
-		ClientNMB = 0;
+	}

  	ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
  					   3, interpret_addr(lp_socket_address()),
@@ -693,16 +685,20 @@ static BOOL open_sockets(BOOL isdaemon, int port)
   int main(int argc, const char *argv[])
  {
  	pstring logfile;
-	static BOOL opt_interactive;
  	poptContext pc;
-	static char *p_lmhosts = dyn_LMHOSTSFILE;
-	static BOOL no_process_group = False;
  	int opt;
+	const char *p_lmhosts = dyn_LMHOSTSFILE;
+	BOOL no_process_group = False;
+	BOOL log_stdout = False;
+	enum smb_server_mode server_mode = SERVER_MODE_DAEMON;
  	struct poptOption long_options[] = {
  	POPT_AUTOHELP
-	{"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a  
daemon(default)" },
-	{"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run  
interactive (not a daemon)" },
-	{"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in  
foreground (for daemontools & etc)" },
+	{"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON,
+		"Become a daemon(default)" },
+	{"interactive", 'i', POPT_ARG_VAL, &server_mode,
+		SERVER_MODE_INTERACTIVE, "Run interactive (not a daemon)" },
+	{"foreground", 'F', POPT_ARG_VAL, &server_mode,
+		SERVER_MODE_FOREGROUND, "Run daemon in foreground (for daemontools  
& etc)" },
  	{"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True,  
"Don't create a new process group" },
  	{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to  
stdout" },
  	{"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios  
hosts file"},
@@ -760,12 +756,11 @@ static BOOL open_sockets(BOOL isdaemon, int port)
  	BlockSignals(True, SIGUSR2);
  #endif

-	if ( opt_interactive ) {
-		Fork = False;
+	if (server_mode == SERVER_MODE_INTERACTIVE) {
  		log_stdout = True;
  	}

-	if ( log_stdout && Fork ) {
+	if (log_stdout && server_mode == SERVER_MODE_DAEMON) {
  		DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in  
foreground (-F) or interactive (-i)\n"));
  		exit(1);
  	}
@@ -792,14 +787,19 @@ static BOOL open_sockets(BOOL isdaemon, int port)

  	set_samba_nb_type();

-	if (!is_daemon && !is_a_socket(0)) {
-		DEBUG(0,("standard input is not a socket, assuming -D option\n"));
-		is_daemon = True;
+	if (is_a_socket(0)) {
+		if (server_mode == SERVER_MODE_DAEMON) {
+			DEBUG(0,("standard input is a socket, "
+				    "assuming -F option\n"));
+		}
+		server_mode = SERVER_MODE_INETD;
  	}
-
-	if (is_daemon && !opt_interactive) {
+
+	if (server_mode == SERVER_MODE_DAEMON) {
  		DEBUG( 2, ( "Becoming a daemon.\n" ) );
-		become_daemon(Fork, no_process_group);
+		become_daemon(True, no_process_group);
+	} else if (server_mode == SERVER_MODE_FOREGROUND) {
+		become_daemon(False, no_process_group);
  	}

  #if HAVE_SETPGID
@@ -807,7 +807,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)
  	 * If we're interactive we want to set our own process group for
  	 * signal management.
  	 */
-	if (opt_interactive && !no_process_group)
+	if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group)
  		setpgid( (pid_t)0, (pid_t)0 );
  #endif

@@ -846,7 +846,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)

  	DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );

-	if ( !open_sockets( is_daemon, global_nmb_port ) ) {
+	if ( !open_sockets( server_mode, global_nmb_port ) ) {
  		kill_async_dns_child();
  		return 1;
  	}
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 8c92c91..ccef37c 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -296,7 +296,7 @@ static BOOL allowable_number_of_smbd_processes(void)
   Open the socket communication.
   
****************************************************************************/

-static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const  
char *smb_ports)
+static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const  
char *smb_ports)
  {
  	int num_interfaces = iface_count();
  	int num_sockets = 0;
@@ -307,11 +307,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon,  
BOOL interactive, const char *smb_
  	int i;
  	char *ports;

-	if (!is_daemon) {
+	if (server_mode == SERVER_MODE_INETD) {
  		return open_sockets_inetd();
  	}

-		
  #ifdef HAVE_ATEXIT
  	{
  		static int atexit_set;
@@ -561,8 +560,13 @@ static BOOL open_sockets_smbd(BOOL is_daemon,  
BOOL interactive, const char *smb_
  			/* Ensure child is set to blocking mode */
  			set_blocking(smbd_server_fd(),True);

-			if (smbd_server_fd() != -1 && interactive)
+			/* In interactive mode, return with a connected socket.
+			 * Foreground and daemon modes should fork worker
+			 * processes.
+			 */
+			if (server_mode == SERVER_MODE_INTERACTIVE) {
  				return True;
+			}
  			
  			if (allowable_number_of_smbd_processes() &&
  			    smbd_server_fd() != -1 &&
@@ -882,23 +886,26 @@ extern void build_options(BOOL screen);
   int main(int argc,const char *argv[])
  {
  	/* shall I run as a daemon */
-	static BOOL is_daemon = False;
-	static BOOL interactive = False;
-	static BOOL Fork = True;
-	static BOOL no_process_group = False;
-	static BOOL log_stdout = False;
-	static char *ports = NULL;
-	static char *profile_level = NULL;
+	BOOL no_process_group = False;
+	BOOL log_stdout = False;
+	const char *ports = NULL;
+	const char *profile_level = NULL;
  	int opt;
  	poptContext pc;
  	BOOL print_build_options = False;

+	enum smb_server_mode server_mode = SERVER_MODE_DAEMON;
+
  	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.)" },
-	{"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True,  
"Don't create a new process group" },
+	{"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON,
+		"Become a daemon (default)" },
+	{"interactive", 'i', POPT_ARG_VAL, &server_mode,  
SERVER_MODE_INTERACTIVE,
+		"Run interactive (not a daemon)"},
+	{"foreground", 'F', POPT_ARG_VAL, &server_mode,  
SERVER_MODE_FOREGROUND,
+		"Run daemon in foreground (for daemontools, etc.)" },
+	{"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True,
+		"Don't create a new process group" },
  	{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to  
stdout" },
  	{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build  
options" },
  	{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified  
ports"},
@@ -945,16 +952,14 @@ extern void build_options(BOOL screen);

  	set_remote_machine_name("smbd", False);

-	if (interactive) {
-		Fork = False;
+	if (server_mode == SERVER_MODE_INTERACTIVE) {
  		log_stdout = True;
+		if (DEBUGLEVEL >= 9) {
+			talloc_enable_leak_report();
+		}
  	}

-	if (interactive && (DEBUGLEVEL >= 9)) {
-		talloc_enable_leak_report();
-	}
-
-	if (log_stdout && Fork) {
+	if (log_stdout && server_mode == SERVER_MODE_DAEMON) {
  		DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in  
foreground (-F) or interactive (-i)\n"));
  		exit(1);
  	}
@@ -1044,21 +1049,19 @@ extern void build_options(BOOL screen);

  	DEBUG(3,( "loaded services\n"));

-	if (!is_daemon && !is_a_socket(0)) {
-		if (!interactive)
-			DEBUG(0,("standard input is not a socket, assuming -D option\n"));
-
-		/*
-		 * Setting is_daemon here prevents us from eventually calling
-		 * the open_sockets_inetd()
-		 */
-
-		is_daemon = True;
+	if (is_a_socket(0)) {
+		if (server_mode == SERVER_MODE_DAEMON) {
+			DEBUG(0,("standard input is a socket, "
+				    "assuming -F option\n"));
+		}
+		server_mode = SERVER_MODE_INETD;
  	}

-	if (is_daemon && !interactive) {
+	if (server_mode == SERVER_MODE_DAEMON) {
  		DEBUG( 3, ( "Becoming a daemon.\n" ) );
-		become_daemon(Fork, no_process_group);
+		become_daemon(True, no_process_group);
+	} else if (server_mode == SERVER_MODE_FOREGROUND) {
+		become_daemon(False, no_process_group);
  	}

  #if HAVE_SETPGID
@@ -1066,15 +1069,18 @@ extern void build_options(BOOL screen);
  	 * If we're interactive we want to set our own process group for
  	 * signal management.
  	 */
-	if (interactive && !no_process_group)
+	if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) {
  		setpgid( (pid_t)0, (pid_t)0);
+	}
  #endif

  	if (!directory_exist(lp_lockdir(), NULL))
  		mkdir(lp_lockdir(), 0755);

-	if (is_daemon)
+	if (server_mode != SERVER_MODE_INETD &&
+	    server_mode != SERVER_MODE_INTERACTIVE) {
  		pidfile_create("smbd");
+	}

  	/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */

@@ -1128,9 +1134,10 @@ extern void build_options(BOOL screen);
  	   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 )
+	if (server_mode != SERVER_MODE_INETD &&
+	    server_mode != SERVER_MODE_INTERACTIVE) {
  		start_background_queue();
+	}

  	/* Always attempt to initialize DMAPI. We will only use it later if
  	 * lp_dmapi_support is set on the share, but we need a single global
@@ -1138,8 +1145,9 @@ extern void build_options(BOOL screen);
  	 */
  	dmapi_init_session();

-	if (!open_sockets_smbd(is_daemon, interactive, ports))
+	if (!open_sockets_smbd(server_mode, ports)) {
  		exit(1);
+	}

  	/*
  	 * everything after this point is run after the fork()
@@ -1152,7 +1160,8 @@ extern void build_options(BOOL screen);
  	/* Possibly reload the services file. Only worth doing in
  	 * daemon mode. In inetd mode, we know we only just loaded this.
  	 */
-	if (is_daemon) {
+	if (server_mode != SERVER_MODE_INETD &&
+	    server_mode != SERVER_MODE_INTERACTIVE) {
  		reload_services(True);
  	}

diff --git a/source/winbindd/winbindd.c b/source/winbindd/winbindd.c
index 81f07c4..fce422d 100644
--- a/source/winbindd/winbindd.c
+++ b/source/winbindd/winbindd.c
@@ -29,7 +29,6 @@
  #define DBGC_CLASS DBGC_WINBIND

  BOOL opt_nocache = False;
-static BOOL interactive = False;

  extern BOOL override_logfile;

@@ -984,17 +983,21 @@ static void process_loop(void)
  int main(int argc, char **argv, char **envp)
  {
  	pstring logfile;
-	static BOOL is_daemon = False;
-	static BOOL Fork = True;
-	static BOOL log_stdout = False;
-	static BOOL no_process_group = False;
+	BOOL log_stdout = False;
+	BOOL no_process_group = False;
+
+	enum smb_server_mode server_mode = SERVER_MODE_DAEMON;
+
+	/* XXX nmbd and smbd use --log-stdout, but winbindd uses --stdout.
+	 * Resolving this inconsistency would break compatibility :(
+	 */
+
  	struct poptOption long_options[] = {
  		POPT_AUTOHELP
  		{ "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
-		{ "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in  
foreground mode" },
+		{ "foreground", 'F', POPT_ARG_VAL, &server_mode,  
SERVER_MODE_FOREGROUND, "Daemon in foreground mode" },
  		{ "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True,  
"Don't create a new process group" },
-		{ "daemon", 'D', POPT_ARG_NONE, NULL, 'D', "Become a daemon  
(default)" },
-		{ "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
+		{ "interactive", 'i', POPT_ARG_VAL, &server_mode,  
SERVER_MODE_INTERACTIVE, "Interactive mode" },
  		{ "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable  
caching" },
  		POPT_COMMON_SAMBA
  		POPT_TABLEEND
@@ -1050,16 +1053,15 @@ int main(int argc, char **argv, char **envp)
  		}
  	}

-	if (is_daemon && interactive) {
-		d_fprintf(stderr,"\nERROR: "
-			  "Option -i|--interactive is not allowed together with -D|--daemon 
\n\n");
-		poptPrintUsage(pc, stderr, 0);
-		exit(1);
+	if (server_mode == SERVER_MODE_INTERACTIVE) {
+		log_stdout = True;
+		if (DEBUGLEVEL >= 9) {
+			talloc_enable_leak_report();
+		}
  	}

-	if (log_stdout && Fork) {
-		d_fprintf(stderr, "\nERROR: "
-			  "Can't log to stdout (-S) unless daemon is in foreground +(-F)  
or interactive (-i)\n\n");
+	if (log_stdout && server_mode == SERVER_MODE_DAEMON) {
+		printf("Can't log to stdout (-S) unless daemon is in foreground (- 
F) or interactive (-i)\n");
  		poptPrintUsage(pc, stderr, 0);
  		exit(1);
  	}
@@ -1132,8 +1134,12 @@ int main(int argc, char **argv, char **envp)
  	CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
  	CatchSignal(SIGHUP, sighup_handler);

-	if (!interactive)
-		become_daemon(Fork, no_process_group);
+	if (server_mode == SERVER_MODE_DAEMON) {
+		DEBUG( 3, ( "Becoming a daemon.\n" ) );
+		become_daemon(True, no_process_group);
+	} else if (server_mode == SERVER_MODE_FOREGROUND) {
+		become_daemon(False, no_process_group);
+	}

  	pidfile_create("winbindd");

@@ -1156,8 +1162,9 @@ int main(int argc, char **argv, char **envp)
  	 * If we're interactive we want to set our own process group for
  	 * signal management.
  	 */
-	if (interactive && !no_process_group)
+	if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) {
  		setpgid( (pid_t)0, (pid_t)0);
+	}
  #endif

  	TimeInit();
-- 
1.5.3.4


 From 764e7451e4bbe922431df892af2ee56a633d7048 Mon Sep 17 00:00:00 2001
From: James Peach <jpeach at samba.org>
Date: Sat, 13 Oct 2007 19:15:15 -0700
Subject: [PATCH] Support running under launchd.

We abstract the method of obtaining sockets to listen on a little,
because in the launchd case these are provided for us. We also add
an idle timeout so that a daemon can exit after a period of inactivity.
---
  source/Makefile.in           |    4 +-
  source/configure.in          |   29 +++++
  source/include/smb_launchd.h |   43 ++++++++
  source/lib/launchd.c         |  242 +++++++++++++++++++++++++++++++++ 
+++++++++
  source/smbd/connection.c     |   29 +++++-
  source/smbd/server.c         |  191 ++++++++++++++++++++++++---------
  source/winbindd/winbindd.c   |  122 ++++++++++++++++++----
  7 files changed, 584 insertions(+), 76 deletions(-)
  create mode 100644 source/include/smb_launchd.h
  create mode 100644 source/lib/launchd.c

diff --git a/source/Makefile.in b/source/Makefile.in
index 4d261d3..8558d81 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -529,7 +529,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/ 
connection.o \
  	       smbd/change_trust_pw.o smbd/fake_file.o \
  	       smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
  	       $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
-	       smbd/dmapi.o \
+	       smbd/dmapi.o lib/launchd.o \
  	       $(MANGLE_OBJ) @VFS_STATIC@

  SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $ 
(LIBSMB_OBJ) \
@@ -874,7 +874,7 @@ WINBINDD_OBJ = \
  		$(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \
  		$(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
  		$(DCUTIL_OBJ) $(IDMAP_OBJ) $(NSS_INFO_OBJ) \
-		$(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \
+		$(AFS_OBJ) $(AFS_SETTOKEN_OBJ) lib/launchd.o \
  		$(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ)

  WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $ 
(LIB_NONSMBD_OBJ) \
diff --git a/source/configure.in b/source/configure.in
index d1a05d1..14db3b6 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -394,6 +394,35 @@ AC_ARG_WITH(selftest-prefix,
    esac
  ])

+AC_ARG_ENABLE(launchd,
+[  --enable-launchd        Support running under launchd  
(default=auto)])
+
+if test x"$enable_launchd" != x"no" ; then
+    AC_CACHE_CHECK([whether to include launchd support],
+	samba_cv_launchd_support,
+	[
+	    AC_TRY_COMPILE(
+	    [
+#include <launch.h>
+	    ],
+	    [
+		launchd_msg(NULL);
+		launchd_data_get_fd(NULL);
+	    ],
+	    samba_cv_launchd_support=yes,
+	    samba_cv_launchd_support=no)
+	])
+
+    if test x"$samba_cv_launchd_support" = x"yes" ; then
+	AC_DEFINE(WITH_LAUNCHD_SUPPORT, 1,
+		    [Whether launchd support should be enabled])
+    else
+	if test x"$enable_launchd" = x"yes" ; then
+	    AC_ERROR(launchd support is not available)
+	fi
+    fi
+fi
+
  #################################################
  # set path of samba4's smbtorture
  smbtorture4_path=""
diff --git a/source/include/smb_launchd.h b/source/include/smb_launchd.h
new file mode 100644
index 0000000..2e758a4
--- /dev/null
+++ b/source/include/smb_launchd.h
@@ -0,0 +1,43 @@
+/*
+   Unix SMB/CIFS implementation.
+   Launchd integration wrapper API
+
+   Copyright (C) James Peach 2007
+
+   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
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+struct smb_launch_info
+{
+	int idle_timeout_secs;
+	int num_sockets;
+	int *socket_list;
+};
+
+/* Retrieve launchd configuration. Returns True if we are running under
+ * launchd, False otherwise. NOTE this does not guarantee to provide  
a list of
+ * sockets since this is a user configuration option.
+ */
+BOOL smb_launchd_checkin(struct smb_launch_info *linfo);
+
+/* Retrieve launchd configuration. The variadic arguments are a list of
+ * constant null-terminated strings. The strings are the names of the  
socket
+ * dictionaries to retrieve sockets from. The list of names is  
terminated by a
+ * NULL.
+ */
+BOOL smb_launchd_checkin_names(struct smb_launch_info *linfo, ...);
+
+/* Free any data or state associated with a successful launchd  
checkin. */
+void smb_launchd_checkout(struct smb_launch_info *linfo);
diff --git a/source/lib/launchd.c b/source/lib/launchd.c
new file mode 100644
index 0000000..1fd5a33
--- /dev/null
+++ b/source/lib/launchd.c
@@ -0,0 +1,242 @@
+/*
+   Unix SMB/CIFS implementation.
+   Launchd integration wrapper API
+
+   Copyright (C) 2007 James Peach
+
+   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
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+#include "smb_launchd.h"
+
+/* launchd source code and documentation is available here:
+ *	http://launchd.macosforge.org/
+ */
+
+#if defined(WITH_LAUNCHD_SUPPORT)
+
+#include <launch.h>
+#include <stdarg.h>
+
+typedef void (*launchd_iterator)(launch_data_t, const char*, void*);
+
+#define LAUNCHD_TRACE_LEVEL 10
+
+ void smb_launchd_checkout(struct smb_launch_info *linfo)
+{
+	talloc_free(linfo->socket_list);
+}
+
+static void pull_launch_sockets(launch_data_t key,
+				const char *name,
+				struct smb_launch_info *linfo)
+{
+	launch_data_type_t type;
+
+	type = launch_data_get_type(key);
+	DEBUG(LAUNCHD_TRACE_LEVEL,
+		("Searching item name='%s' type=%d for sockets\n",
+		 name ? name : "", (int)type));
+
+	switch (type) {
+	case LAUNCH_DATA_FD:
+		if (!linfo->socket_list) {
+			/* We are counting the number of sockets. */
+			linfo->num_sockets++;
+		} else {
+			/* We are collecting the socket fds. */
+			int fd = launch_data_get_fd(key);
+
+			linfo->socket_list[linfo->num_sockets] = fd;
+			linfo->num_sockets++;
+			DEBUG(LAUNCHD_TRACE_LEVEL,
+				("Added fd=%d to launchd set\n", fd));
+		}
+		return;
+	case LAUNCH_DATA_ARRAY:
+	{
+		int i;
+		launch_data_t item;
+
+		for (i = 0; i < launch_data_array_get_count(key); ++i) {
+			item = launch_data_array_get_index(key, i);
+			pull_launch_sockets(item, name, linfo);
+		}
+		return;
+	}
+	case LAUNCH_DATA_DICTIONARY:
+		launch_data_dict_iterate(key,
+			(launchd_iterator)pull_launch_sockets, linfo);
+		return;
+	default:
+		return;
+	}
+}
+
+ BOOL smb_launchd_checkin_names(struct smb_launch_info *linfo, ...)
+{
+	launch_data_t msg;
+	launch_data_t resp;
+	launch_data_t item;
+	BOOL is_launchd = False;
+
+	ZERO_STRUCTP(linfo);
+
+	msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
+	resp = launch_msg(msg);
+	if (resp == NULL) {
+		/* IPC to launchd failed. */
+		launch_data_free(msg);
+		return is_launchd;
+	}
+
+	if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) {
+		errno = launch_data_get_errno(resp);
+		goto done;
+	}
+
+	/* At this point, we know we are running under launchd. */
+	linfo->idle_timeout_secs = 600;
+	is_launchd = True;
+
+	if ((item = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_TIMEOUT))) {
+		linfo->idle_timeout_secs = launch_data_get_integer(item);
+	}
+
+	if ((item = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS))) {
+		int count = 0;
+		const char * sockname = NULL;
+		launch_data_t sockdata;
+		va_list args;
+
+		/* Figure out the maximum number of sockets. */
+		va_start(args, linfo);
+		while ((sockname = va_arg(args, const char *))) {
+		    ++count;
+		}
+		va_end(args);
+
+		DEBUG(LAUNCHD_TRACE_LEVEL, ("Found %d launchd sockets\n",
+					linfo->num_sockets));
+
+		if (launch_data_dict_get_count(item) < count) {
+			DEBUG(0, ("%d launchd sockets requested, "
+			    "but only %d are available\n",
+			    count, launch_data_dict_get_count(item)));
+		}
+
+		linfo->socket_list = talloc_array(NULL, int, count);
+		if (linfo->socket_list == NULL) {
+			goto done;
+		}
+
+		linfo->num_sockets = 0;
+		va_start(args, linfo);
+		while ((sockname = va_arg(args, const char *))) {
+		    sockdata = launch_data_dict_lookup(item, sockname);
+
+		    pull_launch_sockets(sockdata, sockname, linfo);
+		    DEBUG(LAUNCHD_TRACE_LEVEL,
+			    ("Added launchd socket \"%s\"\n", sockname));
+		}
+
+		SMB_ASSERT(count >= linfo->num_sockets);
+	}
+
+done:
+	launch_data_free(msg);
+	launch_data_free(resp);
+	return is_launchd;
+}
+
+ BOOL smb_launchd_checkin(struct smb_launch_info *linfo)
+{
+	launch_data_t msg;
+	launch_data_t resp;
+	launch_data_t item;
+	BOOL is_launchd = False;
+
+	ZERO_STRUCTP(linfo);
+
+	msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
+	resp = launch_msg(msg);
+	if (resp == NULL) {
+		/* IPC to launchd failed. */
+		launch_data_free(msg);
+		return is_launchd;
+	}
+
+	if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) {
+		errno = launch_data_get_errno(resp);
+		goto done;
+	}
+
+	/* At this point, we know we are running under launchd. */
+	linfo->idle_timeout_secs = 600;
+	is_launchd = True;
+
+	if ((item = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_TIMEOUT))) {
+		linfo->idle_timeout_secs = launch_data_get_integer(item);
+	}
+
+	if ((item = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS))) {
+		int count;
+
+		pull_launch_sockets(item, NULL, linfo);
+		DEBUG(LAUNCHD_TRACE_LEVEL, ("Found %d launchd sockets\n",
+					linfo->num_sockets));
+
+		count = linfo->num_sockets;
+		linfo->socket_list = talloc_array(NULL, int, count);
+		if (linfo->socket_list == NULL) {
+			goto done;
+		}
+
+		linfo->num_sockets = 0;
+		pull_launch_sockets(item, NULL, linfo);
+
+		DEBUG(LAUNCHD_TRACE_LEVEL, ("Added %d launchd sockets\n",
+					linfo->num_sockets));
+
+		SMB_ASSERT(count == linfo->num_sockets);
+	}
+
+done:
+	launch_data_free(msg);
+	launch_data_free(resp);
+	return is_launchd;
+}
+
+#else /* defined(WITH_LAUNCHD_SUPPORT) */
+
+ BOOL smb_launchd_checkin(struct smb_launch_info * UNUSED(linfo))
+{
+	ZERO_STRUCTP(linfo);
+	return False;
+}
+
+ BOOL smb_launchd_checkin_names(struct smb_launch_info *  
UNUSED(linfo), ...)
+{
+	ZERO_STRUCTP(linfo);
+	return False;
+}
+
+ void smb_launchd_checkout(struct smb_launch_info * UNUSED(linfo))
+{
+}
+
+#endif /* defined(WITH_LAUNCHD_SUPPORT) */
+
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 65b7c35..65e394c 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -83,9 +83,19 @@ static int count_fn(struct db_record *rec,
  		}
  		return 0;
  	}
-
-	if (strequal(crec->servicename, cs->name))
+
+	if (cs->name) {
+		/* We are counting all the connections to a given share. */
+		if (strequal(crec->servicename, cs->name)) {
+			cs->curr_connections++;
+		}
+	} else {
+		/* We are counting all the connections. Static registrations
+		 * like the lpq backgroud process and the smbd daemon process
+		 * have a cnum of -1, so won't be counted here.
+		 */
  		cs->curr_connections++;
+	}

  	return 0;
  }
@@ -111,13 +121,26 @@ int count_current_connections( const char  
*sharename, BOOL clear  )
  	if (connections_forall(count_fn, &cs) == -1) {
  		DEBUG(0,("count_current_connections: traverse of "
  			 "connections.tdb failed\n"));
-		return False;
  	}

+	/* If the traverse failed part-way through, we at least return
+	 * as many connections as we had already counted. If it failed
+	 * right at the start, we will return 0, which is about all we
+	 * can do anywway.
+	 */
  	return cs.curr_connections;
  }

  / 
****************************************************************************
+ Count the number of connections open across all shares.
+ 
****************************************************************************/
+
+int count_all_current_connections(void)
+{
+	return count_current_connections(NULL, True /* clear stale entries  
*/);
+}
+
+/ 
****************************************************************************
   Claim an entry in the connections database.
   
****************************************************************************/

diff --git a/source/smbd/server.c b/source/smbd/server.c
index ccef37c..fbf2a39 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -4,6 +4,7 @@
     Copyright (C) Andrew Tridgell		1992-1998
     Copyright (C) Martin Pool			2002
     Copyright (C) Jelmer Vernooij		2002-2003
+   Copyright (C) James Peach			2007

     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
@@ -20,6 +21,7 @@
  */

  #include "includes.h"
+#include "smb_launchd.h"

  static_decl_rpc;

@@ -292,39 +294,13 @@ static BOOL  
allowable_number_of_smbd_processes(void)
  	return num_children < max_processes;
  }

-/ 
****************************************************************************
- Open the socket communication.
- 
****************************************************************************/
-
-static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const  
char *smb_ports)
+static int init_sockets_smbd(const char *smb_ports,
+				int fd_listenset[FD_SETSIZE])
  {
  	int num_interfaces = iface_count();
+	char * ports;
  	int num_sockets = 0;
-	int fd_listenset[FD_SETSIZE];
-	fd_set listen_set;
-	int s;
-	int maxfd = 0;
-	int i;
-	char *ports;
-
-	if (server_mode == SERVER_MODE_INETD) {
-		return open_sockets_inetd();
-	}
-
-#ifdef HAVE_ATEXIT
-	{
-		static int atexit_set;
-		if(atexit_set == 0) {
-			atexit_set=1;
-			atexit(killkids);
-		}
-	}
-#endif
-
-	/* Stop zombies */
-	CatchSignal(SIGCLD, sig_cld);
-				
-	FD_ZERO(&listen_set);
+	int i, s;

  	/* use a reasonable default set of ports - listing on 445 and 139 */
  	if (!smb_ports) {
@@ -372,7 +348,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode  
server_mode, const char *smb_
  				}
  				s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM,  
port, 0, ifip->s_addr, True);
  				if(s == -1)
-					return False;
+					return 0;

  				/* ready to listen */
  				set_socket_options(s,"SO_KEEPALIVE");
@@ -384,15 +360,13 @@ static BOOL open_sockets_smbd(enum  
smb_server_mode server_mode, const char *smb_
  				if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
  					DEBUG(0,("listen: %s\n",strerror(errno)));
  					close(s);
-					return False;
+					return 0;
  				}
-				FD_SET(s,&listen_set);
-				maxfd = MAX( maxfd, s);

  				num_sockets++;
  				if (num_sockets >= FD_SETSIZE) {
-					DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
-					return False;
+					DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
+					return 0;
  				}
  			}
  		}
@@ -412,7 +386,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode  
server_mode, const char *smb_
  			s = open_socket_in(SOCK_STREAM, port, 0,
  					   interpret_addr(lp_socket_address()),True);
  			if (s == -1)
-				return(False);
+				return 0;
  		
  			/* ready to listen */
  			set_socket_options(s,"SO_KEEPALIVE");
@@ -422,26 +396,122 @@ static BOOL open_sockets_smbd(enum  
smb_server_mode server_mode, const char *smb_
  			set_blocking(s,False);

  			if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
-				DEBUG(0,("open_sockets_smbd: listen: %s\n",
+				DEBUG(0,("init_sockets_smbd: listen: %s\n",
  					 strerror(errno)));
  				close(s);
-				return False;
+				return 0;
  			}

  			fd_listenset[num_sockets] = s;
-			FD_SET(s,&listen_set);
-			maxfd = MAX( maxfd, s);
-
  			num_sockets++;

  			if (num_sockets >= FD_SETSIZE) {
-				DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
-				return False;
+				DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
+				return 0;
  			}
  		}
  	}

  	SAFE_FREE(ports);
+	return num_sockets;
+}
+
+static int init_sockets_launchd(const struct smb_launch_info *linfo,
+				const char * smb_ports,
+				int fd_listenset[FD_SETSIZE])
+{
+	int num_sockets;
+	int i;
+
+	/* The launchd service configuration does not have to provide sockets,
+	 * even though it's basically useless without it.
+	 */
+	if (!linfo->num_sockets) {
+		return init_sockets_smbd(smb_ports, fd_listenset);
+	}
+
+	/* Make sure we don't get more sockets than we can handle. */
+	num_sockets = MIN(FD_SETSIZE, linfo->num_sockets);
+	memcpy(fd_listenset, linfo->socket_list, num_sockets * sizeof(int));
+
+	/* Get the sockets ready. This could be hoisted into
+	 * open_sockets_smbd(), but the order of socket operations might
+	 * matter for some platforms, so this approach seems less risky.
+	 *	--jpeach
+	 */
+	for (i = 0; i < num_sockets; ++i) {
+		set_socket_options(fd_listenset[i], "SO_KEEPALIVE");
+		set_socket_options(fd_listenset[i], user_socket_options);
+
+		/* Set server socket to non-blocking for the accept. */
+		set_blocking(fd_listenset[i], False);
+	}
+
+	return num_sockets;
+}
+
+/ 
****************************************************************************
+ Open the socket communication.
+ 
****************************************************************************/
+
+static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const  
char *smb_ports)
+{
+	int num_sockets = 0;
+	int fd_listenset[FD_SETSIZE];
+	fd_set listen_set;
+	int s;
+	int maxfd = 0;
+	int i;
+	struct timeval idle_timeout = {0, 0};
+	struct smb_launch_info linfo;
+
+	if (server_mode == SERVER_MODE_INETD) {
+		return open_sockets_inetd();
+	}
+
+#ifdef HAVE_ATEXIT
+	{
+		static int atexit_set;
+		if(atexit_set == 0) {
+			atexit_set=1;
+			atexit(killkids);
+		}
+	}
+#endif
+
+	/* Stop zombies */
+	CatchSignal(SIGCLD, sig_cld);
+
+	FD_ZERO(&listen_set);
+
+	/* At this point, it doesn't matter what daemon mode we are in, we
+	 * need some sockets to listen on. If we are in FOREGROUND mode,
+	 * the launchd checkin might succeed. If we are in DAEMON or
+	 * INTERACTIVE modes, it will fail and we will open the sockets
+	 * ourselves.
+	 */
+	if (smb_launchd_checkin(&linfo)) {
+		/* We are running under launchd and launchd has
+		 * opened some sockets for us.
+		 */
+		num_sockets = init_sockets_launchd(&linfo,
+					    smb_ports,
+					    fd_listenset);
+		idle_timeout.tv_sec = linfo.idle_timeout_secs;
+		smb_launchd_checkout(&linfo);
+	} else {
+		num_sockets = init_sockets_smbd(smb_ports,
+					    fd_listenset);
+	}
+
+	if (num_sockets == 0) {
+		return False;
+	}
+
+	for (i = 0; i < num_sockets; ++i) {
+		FD_SET(fd_listenset[i], &listen_set);
+		maxfd = MAX(maxfd, fd_listenset[i]);
+	}


  	/* Setup the main smbd so that we can get messages. Note that
@@ -474,7 +544,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode  
server_mode, const char *smb_
  	   for each incoming connection */
  	DEBUG(2,("waiting for a connection\n"));
  	while (1) {
-		struct timeval now, idle_timeout;
+		struct timeval now, event_timeout;
  		fd_set r_fds, w_fds;
  		int num;
  		
@@ -490,7 +560,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode  
server_mode, const char *smb_
  			}
  		}

-		idle_timeout = timeval_zero();
+		event_timeout = timeval_zero();

  		memcpy((char *)&r_fds, (char *)&listen_set,
  		       sizeof(listen_set));
@@ -498,12 +568,19 @@ static BOOL open_sockets_smbd(enum  
smb_server_mode server_mode, const char *smb_
  		GetTimeOfDay(&now);

  		event_add_to_select_args(smbd_event_context(), &now,
-					 &r_fds, &w_fds, &idle_timeout,
+					 &r_fds, &w_fds, &event_timeout,
  					 &maxfd);

-		num = sys_select(maxfd+1,&r_fds,&w_fds,NULL,
-				 timeval_is_zero(&idle_timeout) ?
-				 NULL : &idle_timeout);
+		/* The event timeout has precedence over the idle timeout,
+		 * We expect that the event timeout will be shorter.
+		 */
+		if (timeval_is_zero(&event_timeout)) {
+		    event_timeout = idle_timeout;
+		}
+
+		num = sys_select(maxfd+ 1, &r_fds, &w_fds, NULL,
+				 timeval_is_zero(&event_timeout) ?
+				 NULL : &event_timeout);

  		if (num == -1 && errno == EINTR) {
  			if (got_sig_term) {
@@ -520,11 +597,23 @@ static BOOL open_sockets_smbd(enum  
smb_server_mode server_mode, const char *smb_

  			continue;
  		}
-		
+
+		/* At this point we don't know whether we woke up because of
+		 * the idle timeout or the event timeout. If we can run events,
+		 * then it was probably the latter.
+		 */
  		if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) {
  			continue;
  		}

+		/* If the idle timeout fired and we don't have any connected
+		 * users, exit gracefully. We should be running under a process
+		 * controller that will restart us if necessry.
+		 */
+		if (num == 0 && count_all_current_connections() == 0) {
+			exit_server_cleanly("idle timeout");
+		}
+
  		/* check if we need to reload services */
  		check_reload(time(NULL));

diff --git a/source/winbindd/winbindd.c b/source/winbindd/winbindd.c
index fce422d..4bea622 100644
--- a/source/winbindd/winbindd.c
+++ b/source/winbindd/winbindd.c
@@ -7,6 +7,7 @@
     Copyright (C) Andrew Tridgell 2002
     Copyright (C) Jelmer Vernooij 2003
     Copyright (C) Volker Lendecke 2004
+   Copyright (C) James Peach 2007

     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
@@ -24,6 +25,7 @@

  #include "includes.h"
  #include "winbindd.h"
+#include "smb_launchd.h"

  #undef DBGC_CLASS
  #define DBGC_CLASS DBGC_WINBIND
@@ -31,6 +33,7 @@
  BOOL opt_nocache = False;

  extern BOOL override_logfile;
+static BOOL unlink_winbindd_socket = True;

  struct event_context *winbind_event_context(void)
  {
@@ -131,9 +134,11 @@ static void terminate(void)
  	pstring path;

  	/* Remove socket file */
-	pstr_sprintf(path, "%s/%s",
-		 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME);
-	unlink(path);
+	if (unlink_winbindd_socket) {
+		pstr_sprintf(path, "%s/%s",
+			 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME);
+		unlink(path);
+	}

  	idmap_close();
  	
@@ -790,28 +795,56 @@ static BOOL remove_idle_client(void)
  	return False;
  }

+static BOOL winbindd_init_sockets(int *public_sock, int *priv_sock,
+				int *idle_timeout_sec)
+{
+	struct smb_launch_info linfo;
+
+	if (smb_launchd_checkin_names(&linfo, "WinbindPublicPipe",
+		    "WinbindPrivilegedPipe", NULL)) {
+		if (linfo.num_sockets != 2) {
+			DEBUG(0, ("invalid launchd configuration, "
+				"expected 2 sockets but got %d\n",
+				linfo.num_sockets));
+			return False;
+		}
+
+		*public_sock = linfo.socket_list[0];
+		*priv_sock = linfo.socket_list[1];
+		*idle_timeout_sec = linfo.idle_timeout_secs;
+
+		unlink_winbindd_socket = False;
+
+		smb_launchd_checkout(&linfo);
+		return True;
+	} else {
+		*public_sock = open_winbindd_socket();
+		*priv_sock = open_winbindd_priv_socket();
+		*idle_timeout_sec = -1;
+
+		if (*public_sock == -1 || *priv_sock == -1) {
+			DEBUG(0, ("failed to open winbindd pipes: %s\n",
+			    errno ? strerror(errno) : "unknown error"));
+			return False;
+		}
+
+		return True;
+	}
+}
+
  /* Process incoming clients on listen_sock.  We use a tricky non- 
blocking,
     non-forking, non-threaded model which allows us to handle many
     simultaneous connections while remaining impervious to many  
denial of
     service attacks. */

-static void process_loop(void)
+static int process_loop(int listen_sock, int listen_priv_sock)
  {
  	struct winbindd_cli_state *state;
  	struct fd_event *ev;
  	fd_set r_fds, w_fds;
-	int maxfd, listen_sock, listen_priv_sock, selret;
+	int maxfd, selret;
  	struct timeval timeout, ev_timeout;

-	/* Open Sockets here to get stuff going ASAP */
-	listen_sock = open_winbindd_socket();
-	listen_priv_sock = open_winbindd_priv_socket();
-
-	if (listen_sock == -1 || listen_priv_sock == -1) {
-		perror("open_winbind_socket");
-		exit(1);
-	}
-
  	/* We'll be doing this a lot */

  	/* Handle messages */
@@ -976,6 +1009,60 @@ static void process_loop(void)
  			winbind_child_died(pid);
  		}
  	}
+
+
+	return winbindd_num_clients();
+}
+
+static void winbindd_process_loop(enum smb_server_mode server_mode)
+{
+	int idle_timeout_sec;
+	struct timeval starttime;
+	int listen_public, listen_priv;
+
+	errno = 0;
+	if (!winbindd_init_sockets(&listen_public, &listen_priv,
+				    &idle_timeout_sec)) {
+		terminate();
+	}
+
+	starttime = timeval_current();
+
+	if (listen_public == -1 || listen_priv == -1) {
+		DEBUG(0, ("failed to open winbindd pipes: %s\n",
+			    errno ? strerror(errno) : "unknown error"));
+		terminate();
+	}
+
+	for (;;) {
+		int clients = 0;
+		TALLOC_CTX *frame = NULL;
+
+		frame = talloc_stackframe();
+		clients = process_loop(listen_public, listen_priv);
+		TALLOC_FREE(frame);
+
+		/* Don't bother figuring out the idle time if we won't be
+		 * timing out anyway.
+		 */
+		if (idle_timeout_sec < 0) {
+			continue;
+		}
+
+		if (clients == 0 && server_mode == SERVER_MODE_FOREGROUND) {
+			struct timeval now;
+
+			now = timeval_current();
+			if (timeval_elapsed2(&starttime, &now) >
+				(double)idle_timeout_sec) {
+				DEBUG(0, ("idle for %d secs, exitting\n",
+					    idle_timeout_sec));
+				terminate();
+			}
+		} else {
+			starttime = timeval_current();
+		}
+	}
  }

  /* Main function */
@@ -1221,12 +1308,7 @@ int main(int argc, char **argv, char **envp)
  	smb_nscd_flush_group_cache();

  	/* Loop waiting for requests */
-
-	while (1) {
-		TALLOC_CTX *frame = talloc_stackframe();
-		process_loop();
-		TALLOC_FREE(frame);
-	}
+	winbindd_process_loop(server_mode);

  	return 0;
  }
-- 
1.5.3.4


 From 714d5622aea999e35786334f848aebb59c1f9c6a Mon Sep 17 00:00:00 2001
From: James Peach <jpeach at samba.org>
Date: Sun, 14 Oct 2007 15:36:37 -0700
Subject: [PATCH] Update license headers.

---
  source/include/smb_launchd.h |   12 +++++++-----
  source/lib/launchd.c         |   11 +++++------
  2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/source/include/smb_launchd.h b/source/include/smb_launchd.h
index 2e758a4..6376f07 100644
--- a/source/include/smb_launchd.h
+++ b/source/include/smb_launchd.h
@@ -6,19 +6,21 @@

     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,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     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 "smb_launchd.h"
+
  struct smb_launch_info
  {
  	int idle_timeout_secs;
diff --git a/source/lib/launchd.c b/source/lib/launchd.c
index 1fd5a33..bfabaef 100644
--- a/source/lib/launchd.c
+++ b/source/lib/launchd.c
@@ -2,21 +2,20 @@
     Unix SMB/CIFS implementation.
     Launchd integration wrapper API

-   Copyright (C) 2007 James Peach
+   Copyright (C) James Peach 2007

     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,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     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"
-- 
1.5.3.4


 From 7b0a4f56f00923b37e669270fc3fa0042ebcfb43 Mon Sep 17 00:00:00 2001
From: James Peach <jpeach at samba.org>
Date: Sun, 14 Oct 2007 16:18:15 -0700
Subject: [PATCH] Wrap smbd socket initializaion.

Create small wrapper API to hide the details of obtaining a set of
sockets to listen on. We can currently either create these ourselves
or be given them by launchd.
---
  source/Makefile.in           |    2 +-
  source/include/smb_launchd.h |    3 -
  source/smbd/server.c         |  178  
+-----------------------------------
  source/smbd/sockinit.c       |  212 +++++++++++++++++++++++++++++++++ 
+++++++++
  4 files changed, 215 insertions(+), 180 deletions(-)
  create mode 100644 source/smbd/sockinit.c

diff --git a/source/Makefile.in b/source/Makefile.in
index 8558d81..dcb88fe 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -529,7 +529,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/ 
connection.o \
  	       smbd/change_trust_pw.o smbd/fake_file.o \
  	       smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
  	       $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
-	       smbd/dmapi.o lib/launchd.o \
+	       smbd/dmapi.o lib/launchd.o smbd/sockinit.o \
  	       $(MANGLE_OBJ) @VFS_STATIC@

  SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $ 
(LIBSMB_OBJ) \
diff --git a/source/include/smb_launchd.h b/source/include/smb_launchd.h
index 6376f07..6d6394f 100644
--- a/source/include/smb_launchd.h
+++ b/source/include/smb_launchd.h
@@ -18,9 +18,6 @@
     along with this program.  If not, see <http://www.gnu.org/ 
licenses/>.
  */

-#include "includes.h"
-#include "smb_launchd.h"
-
  struct smb_launch_info
  {
  	int idle_timeout_secs;
diff --git a/source/smbd/server.c b/source/smbd/server.c
index fbf2a39..6564267 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -21,7 +21,6 @@
  */

  #include "includes.h"
-#include "smb_launchd.h"

  static_decl_rpc;

@@ -294,162 +293,6 @@ static BOOL  
allowable_number_of_smbd_processes(void)
  	return num_children < max_processes;
  }

-static int init_sockets_smbd(const char *smb_ports,
-				int fd_listenset[FD_SETSIZE])
-{
-	int num_interfaces = iface_count();
-	char * ports;
-	int num_sockets = 0;
-	int i, s;
-
-	/* use a reasonable default set of ports - listing on 445 and 139 */
-	if (!smb_ports) {
-		ports = lp_smb_ports();
-		if (!ports || !*ports) {
-			ports = smb_xstrdup(SMB_PORTS);
-		} else {
-			ports = smb_xstrdup(ports);
-		}
-	} else {
-		ports = smb_xstrdup(smb_ports);
-	}
-
-	if (lp_interfaces() && lp_bind_interfaces_only()) {
-		/* We have been given an interfaces line, and been
-		   told to only bind to those interfaces. Create a
-		   socket per interface and bind to only these.
-		*/
-		
-		/* Now open a listen socket for each of the
-		   interfaces. */
-		for(i = 0; i < num_interfaces; i++) {
-			const struct sockaddr_storage *ifss =
-					iface_n_sockaddr_storage(i);
-			const struct in_addr *ifip;
-			fstring tok;
-			const char *ptr;
-
-			if (ifss == NULL) {
-				DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address ! 
\n", i));
-				continue;
-			}
-
-			/* For now only deal with IPv4. */
-			if (ifss->ss_family != AF_INET) {
-				continue;
-			}
-
-			ifip = &((const struct sockaddr_in *)ifss)->sin_addr;
-
-			for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
-				unsigned port = atoi(tok);
-				if (port == 0 || port > 0xffff) {
-					continue;
-				}
-				s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port,  
0, ifip->s_addr, True);
-				if(s == -1)
-					return 0;
-
-				/* ready to listen */
-				set_socket_options(s,"SO_KEEPALIVE");
-				set_socket_options(s,user_socket_options);
-
-				/* 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 0;
-				}
-
-				num_sockets++;
-				if (num_sockets >= FD_SETSIZE) {
-					DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
-					return 0;
-				}
-			}
-		}
-	} else {
-		/* Just bind to 0.0.0.0 - accept connections
-		   from anywhere. */
-
-		fstring tok;
-		const char *ptr;
-
-		num_interfaces = 1;
-		
-		for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
-			unsigned port = atoi(tok);
-			if (port == 0 || port > 0xffff) continue;
-			/* open an incoming socket */
-			s = open_socket_in(SOCK_STREAM, port, 0,
-					   interpret_addr(lp_socket_address()),True);
-			if (s == -1)
-				return 0;
-		
-			/* ready to listen */
-			set_socket_options(s,"SO_KEEPALIVE");
-			set_socket_options(s,user_socket_options);
-			
-			/* Set server socket to non-blocking for the accept. */
-			set_blocking(s,False);
-
-			if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
-				DEBUG(0,("init_sockets_smbd: listen: %s\n",
-					 strerror(errno)));
-				close(s);
-				return 0;
-			}
-
-			fd_listenset[num_sockets] = s;
-			num_sockets++;
-
-			if (num_sockets >= FD_SETSIZE) {
-				DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
-				return 0;
-			}
-		}
-	}
-
-	SAFE_FREE(ports);
-	return num_sockets;
-}
-
-static int init_sockets_launchd(const struct smb_launch_info *linfo,
-				const char * smb_ports,
-				int fd_listenset[FD_SETSIZE])
-{
-	int num_sockets;
-	int i;
-
-	/* The launchd service configuration does not have to provide sockets,
-	 * even though it's basically useless without it.
-	 */
-	if (!linfo->num_sockets) {
-		return init_sockets_smbd(smb_ports, fd_listenset);
-	}
-
-	/* Make sure we don't get more sockets than we can handle. */
-	num_sockets = MIN(FD_SETSIZE, linfo->num_sockets);
-	memcpy(fd_listenset, linfo->socket_list, num_sockets * sizeof(int));
-
-	/* Get the sockets ready. This could be hoisted into
-	 * open_sockets_smbd(), but the order of socket operations might
-	 * matter for some platforms, so this approach seems less risky.
-	 *	--jpeach
-	 */
-	for (i = 0; i < num_sockets; ++i) {
-		set_socket_options(fd_listenset[i], "SO_KEEPALIVE");
-		set_socket_options(fd_listenset[i], user_socket_options);
-
-		/* Set server socket to non-blocking for the accept. */
-		set_blocking(fd_listenset[i], False);
-	}
-
-	return num_sockets;
-}
-
  / 
****************************************************************************
   Open the socket communication.
   
****************************************************************************/
@@ -463,7 +306,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode  
server_mode, const char *smb_
  	int maxfd = 0;
  	int i;
  	struct timeval idle_timeout = {0, 0};
-	struct smb_launch_info linfo;

  	if (server_mode == SERVER_MODE_INETD) {
  		return open_sockets_inetd();
@@ -485,25 +327,9 @@ static BOOL open_sockets_smbd(enum  
smb_server_mode server_mode, const char *smb_
  	FD_ZERO(&listen_set);

  	/* At this point, it doesn't matter what daemon mode we are in, we
-	 * need some sockets to listen on. If we are in FOREGROUND mode,
-	 * the launchd checkin might succeed. If we are in DAEMON or
-	 * INTERACTIVE modes, it will fail and we will open the sockets
-	 * ourselves.
+	 * need some sockets to listen on.
  	 */
-	if (smb_launchd_checkin(&linfo)) {
-		/* We are running under launchd and launchd has
-		 * opened some sockets for us.
-		 */
-		num_sockets = init_sockets_launchd(&linfo,
-					    smb_ports,
-					    fd_listenset);
-		idle_timeout.tv_sec = linfo.idle_timeout_secs;
-		smb_launchd_checkout(&linfo);
-	} else {
-		num_sockets = init_sockets_smbd(smb_ports,
-					    fd_listenset);
-	}
-
+	num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout);
  	if (num_sockets == 0) {
  		return False;
  	}
diff --git a/source/smbd/sockinit.c b/source/smbd/sockinit.c
new file mode 100644
index 0000000..6473b5c
--- /dev/null
+++ b/source/smbd/sockinit.c
@@ -0,0 +1,212 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) Andrew Tridgell		1992-1998
+   Copyright (C) James Peach			2007
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/ 
 >.
+*/
+
+#include "includes.h"
+#include "smb_launchd.h"
+
+extern pstring user_socket_options;
+
+static int init_sockets_smbd(const char *smb_ports,
+				int fd_listenset[FD_SETSIZE])
+{
+	int num_interfaces = iface_count();
+	char * ports;
+	int num_sockets = 0;
+	int i, s;
+
+	/* use a reasonable default set of ports - listing on 445 and 139 */
+	if (!smb_ports) {
+		ports = lp_smb_ports();
+		if (!ports || !*ports) {
+			ports = smb_xstrdup(SMB_PORTS);
+		} else {
+			ports = smb_xstrdup(ports);
+		}
+	} else {
+		ports = smb_xstrdup(smb_ports);
+	}
+
+	if (lp_interfaces() && lp_bind_interfaces_only()) {
+		/* We have been given an interfaces line, and been
+		   told to only bind to those interfaces. Create a
+		   socket per interface and bind to only these.
+		*/
+
+		/* Now open a listen socket for each of the
+		   interfaces. */
+		for(i = 0; i < num_interfaces; i++) {
+			const struct sockaddr_storage *ifss =
+					iface_n_sockaddr_storage(i);
+			const struct in_addr *ifip;
+			fstring tok;
+			const char *ptr;
+
+			if (ifss == NULL) {
+				DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address ! 
\n", i));
+				continue;
+			}
+
+			/* For now only deal with IPv4. */
+			if (ifss->ss_family != AF_INET) {
+				continue;
+			}
+
+			ifip = &((const struct sockaddr_in *)ifss)->sin_addr;
+
+			for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
+				unsigned port = atoi(tok);
+				if (port == 0 || port > 0xffff) {
+					continue;
+				}
+				s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port,  
0, ifip->s_addr, True);
+				if(s == -1) {
+					return 0;
+				}
+
+				/* ready to listen */
+				set_socket_options(s,"SO_KEEPALIVE");
+				set_socket_options(s,user_socket_options);
+
+				/* 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 0;
+				}
+
+				num_sockets++;
+				if (num_sockets >= FD_SETSIZE) {
+					DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
+					return 0;
+				}
+			}
+		}
+	} else {
+		/* Just bind to 0.0.0.0 - accept connections
+		   from anywhere. */
+
+		fstring tok;
+		const char *ptr;
+
+		num_interfaces = 1;
+
+		for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
+			unsigned port = atoi(tok);
+			if (port == 0 || port > 0xffff) continue;
+			/* open an incoming socket */
+			s = open_socket_in(SOCK_STREAM, port, 0,
+					   interpret_addr(lp_socket_address()),True);
+			if (s == -1) {
+				return 0;
+			}
+
+			/* ready to listen */
+			set_socket_options(s,"SO_KEEPALIVE");
+			set_socket_options(s,user_socket_options);
+
+			/* Set server socket to non-blocking for the accept. */
+			set_blocking(s,False);
+
+			if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
+				DEBUG(0,("init_sockets_smbd: listen: %s\n",
+					 strerror(errno)));
+				close(s);
+				return 0;
+			}
+
+			fd_listenset[num_sockets] = s;
+			num_sockets++;
+
+			if (num_sockets >= FD_SETSIZE) {
+				DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
+				return 0;
+			}
+		}
+	}
+
+	SAFE_FREE(ports);
+	return num_sockets;
+}
+
+static int init_sockets_launchd(const struct smb_launch_info *linfo,
+				const char * smb_ports,
+				int listenset[FD_SETSIZE])
+{
+	int num_sockets;
+	int i;
+
+	/* The launchd service configuration does not have to provide sockets,
+	 * even though it's basically useless without it.
+	 */
+	if (!linfo->num_sockets) {
+		return init_sockets_smbd(smb_ports, listenset);
+	}
+
+	/* Make sure we don't get more sockets than we can handle. */
+	num_sockets = MIN(FD_SETSIZE, linfo->num_sockets);
+	memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int));
+
+	/* Get the sockets ready. This could be hoisted into
+	 * open_sockets_smbd(), but the order of socket operations might
+	 * matter for some platforms, so this approach seems less risky.
+	 *	--jpeach
+	 */
+	for (i = 0; i < num_sockets; ++i) {
+		set_socket_options(listenset[i], "SO_KEEPALIVE");
+		set_socket_options(listenset[i], user_socket_options);
+
+		/* Set server socket to non-blocking for the accept. */
+		set_blocking(listenset[i], False);
+	}
+
+	return num_sockets;
+}
+
+/* This function is responsible for opening (or retrieving) all the  
sockets we
+ * smbd will be listening on. It should apply all the configured  
socket options
+ * and return the number of valid sockets in listenset.
+ */
+int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE],
+			struct timeval *idle)
+{
+	int num_sockets;
+	struct smb_launch_info linfo;
+
+	ZERO_STRUCTP(idle);
+
+	if (smb_launchd_checkin(&linfo)) {
+		/* We are running under launchd and launchd has
+		 * opened some sockets for us.
+		 */
+		num_sockets = init_sockets_launchd(&linfo,
+					    cmdline_ports,
+					    listenset);
+		idle->tv_sec = linfo.idle_timeout_secs;
+		smb_launchd_checkout(&linfo);
+	} else {
+		num_sockets = init_sockets_smbd(cmdline_ports,
+					    listenset);
+	}
+
+	return num_sockets;
+}
+
-- 
1.5.3.4


 From e20a8c521d7860d9b7bd724ed5ea19c7306530ab Mon Sep 17 00:00:00 2001
From: James Peach <jpeach at samba.org>
Date: Sun, 14 Oct 2007 17:02:02 -0700
Subject: [PATCH] Wrap winbindd socket initialization.

Create small wrapper API to hide the details of obtaining a set
of sockets to listen on. We can currently either create these
ourselves or be given them by launchd.
---
  source/Makefile.in                  |    1 +
  source/winbindd/winbindd.c          |   48 +-------------
  source/winbindd/winbindd_sockinit.c |  126 ++++++++++++++++++++++++++ 
+++++++++
  source/winbindd/winbindd_util.c     |   47 -------------
  4 files changed, 128 insertions(+), 94 deletions(-)
  create mode 100644 source/winbindd/winbindd_sockinit.c

diff --git a/source/Makefile.in b/source/Makefile.in
index dcb88fe..f1d41e9 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -847,6 +847,7 @@ NSS_INFO_OBJ = winbindd/nss_info.o @NSS_INFO_STATIC@

  WINBINDD_OBJ1 = \
  		winbindd/winbindd.o       \
+		winbindd/winbindd_sockinit.o \
  		winbindd/winbindd_user.o  \
  		winbindd/winbindd_group.o \
  		winbindd/winbindd_util.o  \
diff --git a/source/winbindd/winbindd.c b/source/winbindd/winbindd.c
index 4bea622..61d3080 100644
--- a/source/winbindd/winbindd.c
+++ b/source/winbindd/winbindd.c
@@ -25,7 +25,6 @@

  #include "includes.h"
  #include "winbindd.h"
-#include "smb_launchd.h"

  #undef DBGC_CLASS
  #define DBGC_CLASS DBGC_WINBIND
@@ -33,7 +32,6 @@
  BOOL opt_nocache = False;

  extern BOOL override_logfile;
-static BOOL unlink_winbindd_socket = True;

  struct event_context *winbind_event_context(void)
  {
@@ -131,15 +129,8 @@ static void flush_caches(void)

  static void terminate(void)
  {
-	pstring path;
-
-	/* Remove socket file */
-	if (unlink_winbindd_socket) {
-		pstr_sprintf(path, "%s/%s",
-			 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME);
-		unlink(path);
-	}

+	winbindd_release_sockets();
  	idmap_close();
  	
  	trustdom_cache_shutdown();
@@ -795,43 +786,6 @@ static BOOL remove_idle_client(void)
  	return False;
  }

-static BOOL winbindd_init_sockets(int *public_sock, int *priv_sock,
-				int *idle_timeout_sec)
-{
-	struct smb_launch_info linfo;
-
-	if (smb_launchd_checkin_names(&linfo, "WinbindPublicPipe",
-		    "WinbindPrivilegedPipe", NULL)) {
-		if (linfo.num_sockets != 2) {
-			DEBUG(0, ("invalid launchd configuration, "
-				"expected 2 sockets but got %d\n",
-				linfo.num_sockets));
-			return False;
-		}
-
-		*public_sock = linfo.socket_list[0];
-		*priv_sock = linfo.socket_list[1];
-		*idle_timeout_sec = linfo.idle_timeout_secs;
-
-		unlink_winbindd_socket = False;
-
-		smb_launchd_checkout(&linfo);
-		return True;
-	} else {
-		*public_sock = open_winbindd_socket();
-		*priv_sock = open_winbindd_priv_socket();
-		*idle_timeout_sec = -1;
-
-		if (*public_sock == -1 || *priv_sock == -1) {
-			DEBUG(0, ("failed to open winbindd pipes: %s\n",
-			    errno ? strerror(errno) : "unknown error"));
-			return False;
-		}
-
-		return True;
-	}
-}
-
  /* Process incoming clients on listen_sock.  We use a tricky non- 
blocking,
     non-forking, non-threaded model which allows us to handle many
     simultaneous connections while remaining impervious to many  
denial of
diff --git a/source/winbindd/winbindd_sockinit.c b/source/winbindd/ 
winbindd_sockinit.c
new file mode 100644
index 0000000..27060fd
--- /dev/null
+++ b/source/winbindd/winbindd_sockinit.c
@@ -0,0 +1,126 @@
+/*
+   Unix SMB/CIFS implementation.
+   Copyright (C) Tim Potter 2000-2001
+   Copyright (C) 2001 by Martin Pool <mbp at samba.org>
+   Copyright (C) James Peach 2007
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/ 
 >.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "smb_launchd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+/* Open the winbindd socket */
+
+static int _winbindd_socket = -1;
+static int _winbindd_priv_socket = -1;
+static BOOL unlink_winbindd_socket = True;
+
+static int open_winbindd_socket(void)
+{
+	if (_winbindd_socket == -1) {
+		_winbindd_socket = create_pipe_sock(
+			WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755);
+		DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
+			   _winbindd_socket));
+	}
+
+	return _winbindd_socket;
+}
+
+static int open_winbindd_priv_socket(void)
+{
+	if (_winbindd_priv_socket == -1) {
+		_winbindd_priv_socket = create_pipe_sock(
+			get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
+		DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
+			   _winbindd_priv_socket));
+	}
+
+	return _winbindd_priv_socket;
+}
+
+/* Close the winbindd socket */
+
+static void close_winbindd_socket(void)
+{
+	if (_winbindd_socket != -1) {
+		DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
+			   _winbindd_socket));
+		close(_winbindd_socket);
+		_winbindd_socket = -1;
+	}
+	if (_winbindd_priv_socket != -1) {
+		DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
+			   _winbindd_priv_socket));
+		close(_winbindd_priv_socket);
+		_winbindd_priv_socket = -1;
+	}
+}
+
+BOOL winbindd_init_sockets(int *public_sock, int *priv_sock,
+				int *idle_timeout_sec)
+{
+	struct smb_launch_info linfo;
+
+	if (smb_launchd_checkin_names(&linfo, "WinbindPublicPipe",
+		    "WinbindPrivilegedPipe", NULL)) {
+		if (linfo.num_sockets != 2) {
+			DEBUG(0, ("invalid launchd configuration, "
+				"expected 2 sockets but got %d\n",
+				linfo.num_sockets));
+			return False;
+		}
+
+		*public_sock = _winbindd_socket = linfo.socket_list[0];
+		*priv_sock = _winbindd_priv_socket = linfo.socket_list[1];
+		*idle_timeout_sec = linfo.idle_timeout_secs;
+
+		unlink_winbindd_socket = False;
+
+		smb_launchd_checkout(&linfo);
+		return True;
+	} else {
+		*public_sock = open_winbindd_socket();
+		*priv_sock = open_winbindd_priv_socket();
+		*idle_timeout_sec = -1;
+
+		if (*public_sock == -1 || *priv_sock == -1) {
+			DEBUG(0, ("failed to open winbindd pipes: %s\n",
+			    errno ? strerror(errno) : "unknown error"));
+			return False;
+		}
+
+		return True;
+	}
+}
+
+void winbindd_release_sockets(void)
+{
+	pstring path;
+
+	close_winbindd_socket();
+
+	/* Remove socket file */
+	if (unlink_winbindd_socket) {
+		pstr_sprintf(path, "%s/%s",
+			 WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
+		unlink(path);
+	}
+}
+
diff --git a/source/winbindd/winbindd_util.c b/source/winbindd/ 
winbindd_util.c
index c2fe09e..e5fdb14 100644
--- a/source/winbindd/winbindd_util.c
+++ b/source/winbindd/winbindd_util.c
@@ -1165,53 +1165,6 @@ char *get_winbind_priv_pipe_dir(void)
  	return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
  }

-/* Open the winbindd socket */
-
-static int _winbindd_socket = -1;
-static int _winbindd_priv_socket = -1;
-
-int open_winbindd_socket(void)
-{
-	if (_winbindd_socket == -1) {
-		_winbindd_socket = create_pipe_sock(
-			get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
-		DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
-			   _winbindd_socket));
-	}
-
-	return _winbindd_socket;
-}
-
-int open_winbindd_priv_socket(void)
-{
-	if (_winbindd_priv_socket == -1) {
-		_winbindd_priv_socket = create_pipe_sock(
-			get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
-		DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
-			   _winbindd_priv_socket));
-	}
-
-	return _winbindd_priv_socket;
-}
-
-/* Close the winbindd socket */
-
-void close_winbindd_socket(void)
-{
-	if (_winbindd_socket != -1) {
-		DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
-			   _winbindd_socket));
-		close(_winbindd_socket);
-		_winbindd_socket = -1;
-	}
-	if (_winbindd_priv_socket != -1) {
-		DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
-			   _winbindd_priv_socket));
-		close(_winbindd_priv_socket);
-		_winbindd_priv_socket = -1;
-	}
-}
-
  /*
   * Client list accessor functions
   */
-- 
1.5.3.4




More information about the samba-technical mailing list