]> git.saurik.com Git - apple/launchd.git/blobdiff - launchd/src/IPC.c
launchd-392.39.tar.gz
[apple/launchd.git] / launchd / src / IPC.c
index ac3a6ce336f2e3114c96ccb64672baa8d2117879..2b9350ad6993b9164d0bab09570f57e01d34daea 100644 (file)
@@ -6,34 +6,32 @@
  **
  * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License").  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
  **/
 
 #include <sys/wait.h>
 #include <mach/mach.h>
 #include <mach/message.h>
 #include <mach/mach_error.h>
-#include <servers/bootstrap.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <syslog.h>
+
+#include "bootstrap.h"
+
 #include "IPC.h"
 #include "StartupItems.h"
 #include "SystemStarter.h"
@@ -145,255 +143,3 @@ out_bad:
                startupItemTerminated(NULL, aTerminationContext);
        }
 }
-
-/**
- * Returns a reference to an item based on tokens passed in an IPC message.
- * This is useful for figuring out which item the message came from.
- *
- * Currently two tokens are supported:
- * kIPCProcessIDKey - the pid of the running startup script
- * kIPCServiceNameKey - a name of a service that the item provides.  This
- *     takes precedence over the pid key when both are present.
- **/
-static CFMutableDictionaryRef 
-itemFromIPCMessage(StartupContext aStartupContext, CFDictionaryRef anIPCMessage)
-{
-       CFMutableDictionaryRef anItem = NULL;
-
-       if (aStartupContext && anIPCMessage) {
-               CFStringRef     aServiceName = CFDictionaryGetValue(anIPCMessage, kIPCServiceNameKey);
-               CFIndex         aPID = 0;
-               CFNumberRef     aPIDNumber = CFDictionaryGetValue(anIPCMessage, kIPCProcessIDKey);
-
-               if (aServiceName && CFGetTypeID(aServiceName) == CFStringGetTypeID()) {
-                       anItem = StartupItemListGetProvider(aStartupContext->aWaitingList, aServiceName);
-               } else if (aPIDNumber &&
-                          CFGetTypeID(aPIDNumber) == CFNumberGetTypeID() &&
-               CFNumberGetValue(aPIDNumber, kCFNumberCFIndexType, &aPID)) {
-                       anItem = StartupItemWithPID(aStartupContext->aWaitingList, aPID);
-               }
-       }
-       return anItem;
-}
-
-/**
- * Displays a message on the console.
- * aConsoleMessage will be localized according to the dictionary in the specified item.
- * Running tems may be specified by their current process id.  Items may also be specified
- * by one of the service names they provide.
- **/
-static void 
-consoleMessage(StartupContext aStartupContext, CFDictionaryRef anIPCMessage)
-{
-       if (aStartupContext && anIPCMessage) {
-               CFStringRef     aConsoleMessage = CFDictionaryGetValue(anIPCMessage, kIPCConsoleMessageKey);
-
-               if (aConsoleMessage && CFGetTypeID(aConsoleMessage) == CFStringGetTypeID()) {
-                       CF_syslog(LOG_INFO, CFSTR("%@"), aConsoleMessage);
-               }
-       }
-}
-
-/**
- * Records the success or failure or a particular service.
- * If no service name is specified, but a pid is, then all services provided
- * by the item are flagged.
- **/
-static void 
-statusMessage(StartupContext aStartupContext, CFDictionaryRef anIPCMessage)
-{
-       if (anIPCMessage && aStartupContext && aStartupContext->aStatusDict) {
-               CFMutableDictionaryRef anItem = itemFromIPCMessage(aStartupContext, anIPCMessage);
-               CFStringRef     aServiceName = CFDictionaryGetValue(anIPCMessage, kIPCServiceNameKey);
-               CFBooleanRef    aStatus = CFDictionaryGetValue(anIPCMessage, kIPCStatusKey);
-
-               if (anItem && aStatus &&
-                   CFGetTypeID(aStatus) == CFBooleanGetTypeID() &&
-                   (!aServiceName || CFGetTypeID(aServiceName) == CFStringGetTypeID())) {
-                       StartupItemSetStatus(aStartupContext->aStatusDict, anItem, aServiceName, CFBooleanGetValue(aStatus), TRUE);
-               }
-       }
-}
-
-/**
- * Queries one of several configuration settings.
- */
-static CFDataRef 
-queryConfigSetting(StartupContext aStartupContext, CFDictionaryRef anIPCMessage)
-{
-       char           *aValue = "";
-
-       if (anIPCMessage) {
-               CFStringRef     aSetting = CFDictionaryGetValue(anIPCMessage, kIPCConfigSettingKey);
-
-               if (aSetting && CFGetTypeID(aSetting) == CFStringGetTypeID()) {
-                       if (CFEqual(aSetting, kIPCConfigSettingVerboseFlag)) {
-                               aValue = gVerboseFlag ? "-YES-" : "-NO-";
-                       } else if (CFEqual(aSetting, kIPCConfigSettingNetworkUp)) {
-                               Boolean         aNetworkUpFlag = FALSE;
-                               if (aStartupContext && aStartupContext->aStatusDict) {
-                                       aNetworkUpFlag = CFDictionaryContainsKey(aStartupContext->aStatusDict, CFSTR("Network"));
-                               }
-                               aValue = aNetworkUpFlag ? "-YES-" : "-NO-";
-                       }
-               }
-       }
-       return CFDataCreate(NULL, (const UInt8 *)aValue, strlen(aValue) + 1);   /* aValue + null */
-}
-
-static void    *handleIPCMessage(void *aMsgParam, CFIndex aMessageSize __attribute__((unused)), CFAllocatorRef anAllocator __attribute__((unused)), void *aMachPort) {
-       SystemStarterIPCMessage *aMessage = (SystemStarterIPCMessage *) aMsgParam;
-       SystemStarterIPCMessage *aReplyMessage = NULL;
-
-       CFDataRef       aResult = NULL;
-       CFDataRef       aData = NULL;
-
-       if (aMessage->aHeader.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
-               syslog(LOG_WARNING, "Ignoring out-of-line IPC message");
-               return NULL;
-       } else {
-               mach_msg_security_trailer_t *aSecurityTrailer = (mach_msg_security_trailer_t *)
-               ((uint8_t *) aMessage + round_msg(sizeof(SystemStarterIPCMessage) + aMessage->aByteLength));
-
-               /*
-                * CFRunLoop includes the format 0 message trailer with the
-                * passed message.
-                */
-               if (aSecurityTrailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0 &&
-                   aSecurityTrailer->msgh_sender.val[0] != 0) {
-                       syslog(LOG_WARNING, "Ignoring IPC message sent from uid %d", aSecurityTrailer->msgh_sender.val[0]);
-                       return NULL;
-               }
-       }
-
-       if (aMessage->aProtocol != kIPCProtocolVersion) {
-               syslog(LOG_WARNING, "Unsupported IPC protocol version number: %d.  Message ignored", aMessage->aProtocol);
-               return NULL;
-       }
-       aData = CFDataCreateWithBytesNoCopy(NULL,
-                    (uint8_t *) aMessage + sizeof(SystemStarterIPCMessage),
-                                           aMessage->aByteLength,
-                                           kCFAllocatorNull);
-       /*
-         * Dispatch the IPC message.
-         */
-       if (aData) {
-               StartupContext  aStartupContext = NULL;
-               CFStringRef     anErrorString = NULL;
-               CFDictionaryRef anIPCMessage = (CFDictionaryRef) CFPropertyListCreateFromXMLData(NULL, aData, kCFPropertyListImmutable, &anErrorString);
-
-               CF_syslog(LOG_DEBUG, CFSTR("IPC message = %@"), anIPCMessage);
-
-               if (aMachPort) {
-                       CFMachPortContext aMachPortContext;
-                       CFMachPortGetContext((CFMachPortRef) aMachPort, &aMachPortContext);
-                       aStartupContext = (StartupContext) aMachPortContext.info;
-               }
-               if (anIPCMessage && CFGetTypeID(anIPCMessage) == CFDictionaryGetTypeID()) {
-                       /* switch on the type of the IPC message */
-                       CFStringRef     anIPCMessageType = CFDictionaryGetValue(anIPCMessage, kIPCMessageKey);
-                       if (anIPCMessageType && CFGetTypeID(anIPCMessageType) == CFStringGetTypeID()) {
-                               if (CFEqual(anIPCMessageType, kIPCConsoleMessage)) {
-                                       consoleMessage(aStartupContext, anIPCMessage);
-                               } else if (CFEqual(anIPCMessageType, kIPCStatusMessage)) {
-                                       statusMessage(aStartupContext, anIPCMessage);
-                               } else if (CFEqual(anIPCMessageType, kIPCQueryMessage)) {
-                                       aResult = queryConfigSetting(aStartupContext, anIPCMessage);
-                               }
-                       }
-               } else {
-                       CF_syslog(LOG_ERR, CFSTR("Unable to parse IPC message: %@"), anErrorString);
-               }
-               CFRelease(aData);
-       } else {
-               syslog(LOG_ERR, "Out of memory.  Could not allocate space for IPC message");
-       }
-
-       /*
-         * Generate a Mach message for the result data.
-         */
-       if (!aResult)
-               aResult = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)"", 1, kCFAllocatorNull);
-       if (aResult) {
-               CFIndex         aDataSize = CFDataGetLength(aResult);
-               CFIndex         aReplyMessageSize = round_msg(sizeof(SystemStarterIPCMessage) + aDataSize + 3);
-               aReplyMessage = CFAllocatorAllocate(kCFAllocatorSystemDefault, aReplyMessageSize, 0);
-               if (aReplyMessage) {
-                       aReplyMessage->aHeader.msgh_id = -1 * (SInt32) aMessage->aHeader.msgh_id;
-                       aReplyMessage->aHeader.msgh_size = aReplyMessageSize;
-                       aReplyMessage->aHeader.msgh_remote_port = aMessage->aHeader.msgh_remote_port;
-                       aReplyMessage->aHeader.msgh_local_port = MACH_PORT_NULL;
-                       aReplyMessage->aHeader.msgh_reserved = 0;
-                       aReplyMessage->aHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
-                       aReplyMessage->aBody.msgh_descriptor_count = 0;
-                       aReplyMessage->aProtocol = kIPCProtocolVersion;
-                       aReplyMessage->aByteLength = CFDataGetLength(aResult);
-                       memmove((uint8_t *) aReplyMessage + sizeof(SystemStarterIPCMessage),
-                               CFDataGetBytePtr(aResult),
-                               CFDataGetLength(aResult));
-               }
-               CFRelease(aResult);
-       }
-       if (!aReplyMessage) {
-               syslog(LOG_ERR, "Out of memory.  Could not allocate IPC result");
-       }
-       return aReplyMessage;
-}
-
-
-static mach_port_t 
-getIPCPort(void *anInfo)
-{
-       return anInfo ? CFMachPortGetPort((CFMachPortRef) anInfo) : MACH_PORT_NULL;
-}
-
-CFRunLoopSourceRef 
-CreateIPCRunLoopSource(CFStringRef aPortName, StartupContext aStartupContext)
-{
-       CFRunLoopSourceRef aSource = NULL;
-       CFMachPortRef   aMachPort = NULL;
-       CFMachPortContext aContext;
-       kern_return_t   aKernReturn = KERN_FAILURE;
-
-       aContext.version = 0;
-       aContext.info = (void *) aStartupContext;
-       aContext.retain = 0;
-       aContext.release = 0;
-       aContext.copyDescription = 0;
-       aMachPort = CFMachPortCreate(NULL, NULL, &aContext, NULL);
-
-       if (aMachPort && aPortName) {
-               CFIndex         aPortNameLength = CFStringGetLength(aPortName);
-               CFIndex         aPortNameSize = CFStringGetMaximumSizeForEncoding(aPortNameLength, kCFStringEncodingUTF8) + 1;
-               char            *aBuffer = CFAllocatorAllocate(NULL, aPortNameSize, 0);
-               if (aBuffer && CFStringGetCString(aPortName,
-                                                 aBuffer,
-                                                 aPortNameSize,
-                                                 kCFStringEncodingUTF8)) {
-                       mach_port_t     aBootstrapPort;
-                       task_get_bootstrap_port(mach_task_self(), &aBootstrapPort);
-                       aKernReturn = bootstrap_register(aBootstrapPort, aBuffer, CFMachPortGetPort(aMachPort));
-               }
-               if (aBuffer)
-                       CFAllocatorDeallocate(NULL, aBuffer);
-       }
-       if (aMachPort && aKernReturn == KERN_SUCCESS) {
-               CFRunLoopSourceContext1 aSourceContext;
-               aSourceContext.version = 1;
-               aSourceContext.info = aMachPort;
-               aSourceContext.retain = CFRetain;
-               aSourceContext.release = CFRelease;
-               aSourceContext.copyDescription = CFCopyDescription;
-               aSourceContext.equal = CFEqual;
-               aSourceContext.hash = CFHash;
-               aSourceContext.getPort = getIPCPort;
-               aSourceContext.perform = (void *) handleIPCMessage;
-               aSource = CFRunLoopSourceCreate(NULL, 0, (CFRunLoopSourceContext *) & aSourceContext);
-       }
-       if (aMachPort && (!aSource || aKernReturn != KERN_SUCCESS)) {
-               CFMachPortInvalidate(aMachPort);
-               CFRelease(aMachPort);
-               aMachPort = NULL;
-       }
-       return aSource;
-}