From 44f5211c170c0ddc2be23717f1ad08f5fc0b329a Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 20 Apr 2007 21:09:44 +0000 Subject: r22418: 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. (This used to be commit fc8589a3371d396197fae508e563f814899c2beb) --- source3/lib/launchd.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 source3/lib/launchd.c (limited to 'source3/lib/launchd.c') diff --git a/source3/lib/launchd.c b/source3/lib/launchd.c new file mode 100644 index 0000000000..1fd5a33db0 --- /dev/null +++ b/source3/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 +#include + +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) */ + -- cgit