]> git.saurik.com Git - apple/system_cmds.git/blobdiff - reboot.tproj/reboot.c
system_cmds-671.10.3.tar.gz
[apple/system_cmds.git] / reboot.tproj / reboot.c
index f970ca5252fec1e39aa6f074fee959cdb5f6ced2..e9aa380fddb8e5d577272921eec93e0b92be1ba5 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 1980, 1986, 1993
  *     The Regents of the University of California.  All rights reserved.
 /*
  * Copyright (c) 1980, 1986, 1993
  *     The Regents of the University of California.  All rights reserved.
+ * Portions copyright (c) 2007 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -61,16 +58,23 @@ static const char rcsid[] =
 #include <unistd.h>
 
 #ifdef __APPLE__
 #include <unistd.h>
 
 #ifdef __APPLE__
+#include <TargetConditionals.h>
+#if !TARGET_OS_EMBEDDED
 #include "kextmanager.h"
 #include <IOKit/kext/kextmanager_types.h>
 #include "kextmanager.h"
 #include <IOKit/kext/kextmanager_types.h>
+#endif
 #include <mach/mach_port.h>            // allocate
 #include <mach/mach.h>                 // task_self, etc
 #include <servers/bootstrap.h> // bootstrap
 #include <mach/mach_port.h>            // allocate
 #include <mach/mach.h>                 // task_self, etc
 #include <servers/bootstrap.h> // bootstrap
+#include <bootstrap_priv.h>
+#include <reboot2.h>
+#include <utmpx.h>
+#include <sys/time.h>
 #endif
 
 void usage(void);
 u_int get_pageins(void);
 #endif
 
 void usage(void);
 u_int get_pageins(void);
-#ifdef __APPLE__
+#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
 int reserve_reboot(void);
 #endif
 
 int reserve_reboot(void);
 #endif
 
@@ -80,10 +84,14 @@ int
 main(int argc, char *argv[])
 {
        struct passwd *pw;
 main(int argc, char *argv[])
 {
        struct passwd *pw;
-       int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag, uflag, sverrno;
-       u_int pageins;
-       char *kernel, *p;
+       int ch, howto, kflag, lflag, nflag, qflag, uflag;
+       char *p;
        const char *user;
        const char *user;
+#ifndef __APPLE__
+       int i, fd, pflag, sverrno;
+       u_int pageins;
+       char *kernel;
+#endif
 
        if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
                dohalt = 1;
 
        if (strstr((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
                dohalt = 1;
@@ -126,6 +134,7 @@ main(int argc, char *argv[])
                        break;
                case 'q':
                        qflag = 1;
                        break;
                case 'q':
                        qflag = 1;
+                       howto |= RB_QUICK;
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
@@ -143,9 +152,9 @@ main(int argc, char *argv[])
                err(1, NULL);
        }
 
                err(1, NULL);
        }
 
-#ifdef __APPLE__
-       if (!lflag) {   // shutdown(8) has already checked w/kextd
-               if ((errno = reserve_reboot()) && !qflag)
+#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
+       if (!qflag && !lflag) { // shutdown(8) has already checked w/kextd
+               if ((errno = reserve_reboot()))
                        err(1, "couldn't lock for reboot");
        }
 #endif
                        err(1, "couldn't lock for reboot");
        }
 #endif
@@ -182,7 +191,20 @@ main(int argc, char *argv[])
                        syslog(LOG_CRIT, "rebooted by %s", user);
                }
        }
                        syslog(LOG_CRIT, "rebooted by %s", user);
                }
        }
+#if defined(__APPLE__) 
+       {
+               struct utmpx utx;
+               bzero(&utx, sizeof(utx));
+               utx.ut_type = SHUTDOWN_TIME;
+               gettimeofday(&utx.ut_tv, NULL);
+               pututxline(&utx);
+
+               int newvalue = 1;
+               sysctlbyname("kern.willshutdown", NULL, NULL, &newvalue, sizeof(newvalue));
+       }
+#else
        logwtmp("~", "shutdown", "");
        logwtmp("~", "shutdown", "");
+#endif
 
        /*
         * Do a sync early on, so disks start transfers while we're off
 
        /*
         * Do a sync early on, so disks start transfers while we're off
@@ -192,9 +214,11 @@ main(int argc, char *argv[])
        if (!nflag)
                sync();
 
        if (!nflag)
                sync();
 
+#ifndef __APPLE__
        /* Just stop init -- if we fail, we'll restart it. */
        if (kill(1, SIGTSTP) == -1)
                err(1, "SIGTSTP init");
        /* Just stop init -- if we fail, we'll restart it. */
        if (kill(1, SIGTSTP) == -1)
                err(1, "SIGTSTP init");
+#endif
 
        /* Ignore the SIGHUP we get when our parent shell dies. */
        (void)signal(SIGHUP, SIG_IGN);
 
        /* Ignore the SIGHUP we get when our parent shell dies. */
        (void)signal(SIGHUP, SIG_IGN);
@@ -236,16 +260,19 @@ main(int argc, char *argv[])
        }
 #endif
 
        }
 #endif
 
+#ifdef __APPLE__
+       // launchd(8) handles reboot.  This call returns NULL on success.
+       exit(reboot2(howto) == NULL ? EXIT_SUCCESS : EXIT_FAILURE);
+#else /* __APPLE__ */
        reboot(howto);
        /* FALLTHROUGH */
 
        reboot(howto);
        /* FALLTHROUGH */
 
-#ifndef __APPLE__
 restart:
 restart:
-#endif
        sverrno = errno;
        errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
            strerror(sverrno));
        /* NOTREACHED */
        sverrno = errno;
        errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
            strerror(sverrno));
        /* NOTREACHED */
+#endif /* __APPLE__ */
 }
 
 void
 }
 
 void
@@ -275,65 +302,61 @@ get_pageins()
        return pageins;
 }
 
        return pageins;
 }
 
-#ifdef __APPLE__
-// XX another copy of this routine is in shutdown.c; it would be nice to share
+#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
+// XX this routine is also in shutdown.tproj; it would be nice to share
 
 
-#define LCK_MAXTRIES 10
-#define LCK_DELAY       30
+#define WAITFORLOCK 1
 /*
  * contact kextd to lock for reboot
  */
 int
 reserve_reboot()
 {
 /*
  * contact kextd to lock for reboot
  */
 int
 reserve_reboot()
 {
-       int rval = ELAST+1;
+       int rval = ELAST + 1;
        kern_return_t macherr = KERN_FAILURE;
        kern_return_t macherr = KERN_FAILURE;
-       mach_port_t tport, bsport, kxport, myport = MACH_PORT_NULL;
-       int busyStatus, nretries = LCK_MAXTRIES;
-       dev_path_t busyDev = "<unknown>";
+       mach_port_t kxport, tport = MACH_PORT_NULL, myport = MACH_PORT_NULL;
+       int busyStatus = ELAST + 1;
+       mountpoint_t busyVol;
 
 
-       // find kextd
-       tport = mach_task_self();
-       if (tport == MACH_PORT_NULL)  goto finish;
-       macherr = task_get_bootstrap_port(tport, &bsport);
-       if (macherr)  goto finish;
-       macherr = bootstrap_look_up(bsport, KEXTD_SERVER_NAME, &kxport);
+       macherr = bootstrap_look_up2(bootstrap_port, KEXTD_SERVER_NAME, &kxport, 0, BOOTSTRAP_PRIVILEGED_SERVER);
        if (macherr)  goto finish;
 
        // allocate a port to pass to kextd (in case we die)
        if (macherr)  goto finish;
 
        // allocate a port to pass to kextd (in case we die)
+       tport = mach_task_self();
+       if (tport == MACH_PORT_NULL)  goto finish;
        macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
        if (macherr)  goto finish;
 
        macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
        if (macherr)  goto finish;
 
-       // loop trying to lock for reboot (i.e. no volumes are busy)
-       do {
-               nretries--;
-               macherr = kextmanager_lock_reboot(kxport, myport, busyDev, &busyStatus);
-               if (macherr)  goto finish;
-
-               if (busyStatus == EBUSY) {
-                       if (*busyDev) {
-                               warnx("%s is busy updating; delaying reboot (%d retries left)",
-                                               busyDev, nretries);
-                       } else
-                               warnx("kextd still starting up");
-                       if (nretries)           sleep(LCK_DELAY);       // don't sleep the last time
-               }
-       } while (busyStatus == EBUSY && nretries > 0);
+       // try to lock for reboot
+       macherr = kextmanager_lock_reboot(kxport, myport, !WAITFORLOCK, busyVol,
+                                      &busyStatus);
+       if (macherr)  goto finish;
 
 
-       rval = busyStatus;
+       if (busyStatus == EBUSY) {
+               warnx("%s is busy updating; waiting for lock", busyVol);
+               macherr = kextmanager_lock_reboot(kxport, myport, WAITFORLOCK,
+                                                                                 busyVol, &busyStatus);
+               if (macherr)    goto finish;
+       }
 
 
-finish:
-       if (macherr == BOOTSTRAP_UNKNOWN_SERVICE) {
-               mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
+       if (busyStatus == EALREADY) {
+               // reboot already in progress
                rval = 0;
                rval = 0;
-       } else if (macherr) {
-               warnx("couldn't lock kext manager for reboot: %s",
-                               mach_error_string(macherr));
-               rval = ELAST + 1;
+       } else {
+               rval = busyStatus;
        }
        }
-       if (rval && myport != MACH_PORT_NULL) {
+
+finish:
+       // in general, we want to err on the side of allowing the reboot
+       if (macherr) {
+               if (macherr != BOOTSTRAP_UNKNOWN_SERVICE)
+                       warnx("WARNING: couldn't lock kext manager for reboot: %s",
+                                       mach_error_string(macherr));
+               rval = 0;
+       } 
+       // unless we got the lock, clean up our port
+       if (busyStatus != 0 && myport != MACH_PORT_NULL)
                mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
                mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
-       }
 
        return rval;
 }
 
        return rval;
 }