]> git.saurik.com Git - apple/launchd.git/blobdiff - launchd/src/SystemStarter.c
launchd-258.19.tar.gz
[apple/launchd.git] / launchd / src / SystemStarter.c
index ccefdb222649a71dde18370e07dca98330b85c18..5c445cc964726dbc9fa1ef085d4d2ee9470d24b1 100644 (file)
@@ -5,31 +5,33 @@
  **
  * 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 <IOKit/IOKitLib.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/stat.h>
+#include <paths.h>
 #include <unistd.h>
 #include <crt_externs.h>
 #include <fcntl.h>
 #include <syslog.h>
+#include <assert.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <NSSystemDirectories.h>
 #include "IPC.h"
@@ -43,14 +45,25 @@ bool gNoRunFlag = false;
 
 static void     usage(void) __attribute__((noreturn));
 static int      system_starter(Action anAction, const char *aService);
-static void    doCFnote(void);
+static void    displayErrorMessages(StartupContext aStartupContext);
+static pid_t   fwexec(const char *cmd, ...) __attribute__((sentinel));
+static void    dummy_sig(int signo __attribute__((unused)))
+{
+}
 
 int 
 main(int argc, char *argv[])
 {
+       struct kevent   kev;
        Action          anAction = kActionStart;
-       char           *aService = NULL;
-       int             ch;
+       int             ch, r, kq = kqueue();
+
+       assert(kq  != -1);
+
+       EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
+       r = kevent(kq, &kev, 1, NULL, 0, NULL);
+       assert(r != -1);
+       signal(SIGTERM, dummy_sig);
 
        while ((ch = getopt(argc, argv, "gvxirdDqn?")) != -1) {
                switch (ch) {
@@ -78,15 +91,18 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
-       if (argc > 2)
+       if (argc > 2) {
                usage();
+       }
 
        openlog(getprogname(), LOG_PID|LOG_CONS|(gDebugFlag ? LOG_PERROR : 0), LOG_DAEMON);
-       setlogmask(LOG_UPTO(LOG_NOTICE));
-       if (gVerboseFlag)
-               setlogmask(LOG_UPTO(LOG_INFO));
-       if (gDebugFlag)
+       if (gDebugFlag) {
                setlogmask(LOG_UPTO(LOG_DEBUG));
+       } else if (gVerboseFlag) {
+               setlogmask(LOG_UPTO(LOG_INFO));
+       } else {
+               setlogmask(LOG_UPTO(LOG_NOTICE));
+       }
 
        if (!gNoRunFlag && (getuid() != 0)) {
                syslog(LOG_ERR, "must be root to run");
@@ -105,53 +121,54 @@ main(int argc, char *argv[])
                }
        }
 
-       atexit(doCFnote);
+       if (argc == 2) {
+               exit(system_starter(anAction, argv[1]));
+       }
 
        unlink(kFixerPath);
 
-       if (argc == 2) {
-               aService = argv[1];
-       } else if (!gDebugFlag && anAction != kActionStop) {
-               pid_t ipwa;
-               int status;
-
-               setpriority(PRIO_PROCESS, 0, 20);
-               daemon(0, 0);
-
-               /* Too many old StartupItems had implicit dependancies on
-                * "Network" via other StartupItems that are now no-ops.
-                *
-                * SystemStarter is not on the critical path for boot up,
-                * so we'll stall here to deal with this legacy dependancy
-                * problem.
-                */
-               switch ((ipwa = fork())) {
-               case -1:
-                       syslog(LOG_WARNING, "fork(): %m");
-                       break;
-               case 0:
-                       execl("/usr/sbin/ipconfig", "ipconfig", "waitall", NULL);
-                       syslog(LOG_WARNING, "execl(): %m");
-                       exit(EXIT_FAILURE);
-               default:
-                       if (waitpid(ipwa, &status, 0) == -1) {
-                               syslog(LOG_WARNING, "waitpid(): %m");
-                               break;
-                       } else if (WIFEXITED(status)) {
-                               if (WEXITSTATUS(status) == 0) {
-                                       break;
-                               } else {
-                                       syslog(LOG_WARNING, "ipconfig waitall exit status: %d", WEXITSTATUS(status));
-                               }
-                       } else {
-                               /* must have died due to signal */
-                               syslog(LOG_WARNING, "ipconfig waitall: %s", strsignal(WTERMSIG(status)));
-                       }
-                       break;
-               }
+       mach_timespec_t w = { 600, 0 };
+       kern_return_t kr;
+       struct stat sb;
+
+       /*
+        * Too many old StartupItems had implicit dependancies on "Network" via
+        * other StartupItems that are now no-ops.
+        *
+        * SystemStarter is not on the critical path for boot up, so we'll
+        * stall here to deal with this legacy dependancy problem.
+        */
+
+       if ((kr = IOKitWaitQuiet(kIOMasterPortDefault, &w)) != kIOReturnSuccess) {
+               syslog(LOG_NOTICE, "IOKitWaitQuiet: %d\n", kr);
+       }
+
+       fwexec("/usr/sbin/ipconfig", "waitall", NULL);
+       fwexec("/sbin/autodiskmount", "-va", NULL);
+
+       system_starter(kActionStart, NULL);
+
+       if (stat("/etc/rc.local", &sb) != -1) {
+               fwexec(_PATH_BSHELL, "/etc/rc.local", NULL);
        }
 
-       exit(system_starter(anAction, aService));
+       CFNotificationCenterPostNotificationWithOptions(
+                       CFNotificationCenterGetDistributedCenter(),
+                       CFSTR("com.apple.startupitems.completed"),
+                       NULL, NULL,
+                       kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions);
+
+       r = kevent(kq, NULL, 0, &kev, 1, NULL);
+       assert(r != -1);
+       assert(kev.filter == EVFILT_SIGNAL && kev.ident == SIGTERM);
+
+       if (stat("/etc/rc.shutdown.local", &sb) != -1) {
+               fwexec(_PATH_BSHELL, "/etc/rc.shutdown.local", NULL);
+       }
+
+       system_starter(kActionStop, NULL);
+
+       exit(EXIT_SUCCESS);
 }
 
 
@@ -241,7 +258,6 @@ displayErrorMessages(StartupContext aStartupContext)
 static int 
 system_starter(Action anAction, const char *aService_cstr)
 {
-       CFRunLoopSourceRef anIPCSource = NULL;
        CFStringRef     aService = NULL;
        NSSearchPathDomainMask aMask;
 
@@ -256,18 +272,6 @@ system_starter(Action anAction, const char *aService_cstr)
        if (gDebugFlag && gNoRunFlag)
                sleep(1);
 
-       /**
-         * Create the IPC port
-         **/
-       anIPCSource = CreateIPCRunLoopSource(CFSTR(kSystemStarterMessagePort), aStartupContext);
-       if (anIPCSource) {
-               CFRunLoopAddSource(CFRunLoopGetCurrent(), anIPCSource, kCFRunLoopCommonModes);
-               CFRelease(anIPCSource);
-       } else {
-               syslog(LOG_ERR, "Could not create IPC bootstrap port: %s", kSystemStarterMessagePort);
-               return (1);
-       }
-
        /**
          * Get a list of Startup Items which are in /Local and /System.
          * We can't search /Network yet because the network isn't up.
@@ -392,11 +396,42 @@ usage(void)
        exit(EXIT_FAILURE);
 }
 
-static void doCFnote(void)
+pid_t
+fwexec(const char *cmd, ...)
 {
-       CFNotificationCenterPostNotificationWithOptions(
-                       CFNotificationCenterGetDistributedCenter(),
-                       CFSTR("com.apple.startupitems.completed"),
-                       NULL, NULL,
-                       kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions);
+       const char *argv[100] = { cmd };
+       va_list ap;
+       int wstatus, i = 1;
+       pid_t p;
+
+       va_start(ap, cmd);
+       do {
+               argv[i] = va_arg(ap, char *);
+       } while (argv[i++]);
+       va_end(ap);
+
+       switch ((p = fork())) {
+       case -1:
+               return -1;
+       case 0:
+               execvp(argv[0], (char *const *)argv);
+               _exit(EXIT_FAILURE);
+               break;
+       default:
+               if (waitpid(p, &wstatus, 0) == -1) {
+                       return -1;
+               } else if (WIFEXITED(wstatus)) {
+                       if (WEXITSTATUS(wstatus) == 0) {
+                               return 0;
+                       } else {
+                               syslog(LOG_WARNING, "%s exit status: %d", argv[0], WEXITSTATUS(wstatus));
+                       }
+               } else {
+                       /* must have died due to signal */
+                       syslog(LOG_WARNING, "%s died: %s", argv[0], strsignal(WTERMSIG(wstatus)));
+               }
+               break;
+       }
+
+       return -1;
 }