X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/b180c247da3427572377f1dda16026ceef181844..ac27e6b4e9f2f269ad11856171ae8e1f51fa26f0:/reboot.tproj/reboot.c diff --git a/reboot.tproj/reboot.c b/reboot.tproj/reboot.c index f970ca5..e9aa380 100644 --- a/reboot.tproj/reboot.c +++ b/reboot.tproj/reboot.c @@ -1,6 +1,7 @@ /* * 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 @@ -10,11 +11,7 @@ * 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. * @@ -61,16 +58,23 @@ static const char rcsid[] = #include #ifdef __APPLE__ +#include +#if !TARGET_OS_EMBEDDED #include "kextmanager.h" #include +#endif #include // allocate #include // task_self, etc #include // bootstrap +#include +#include +#include +#include #endif void usage(void); u_int get_pageins(void); -#ifdef __APPLE__ +#if defined(__APPLE__) && !TARGET_OS_EMBEDDED int reserve_reboot(void); #endif @@ -80,10 +84,14 @@ int 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; +#ifndef __APPLE__ + int i, fd, pflag, sverrno; + u_int pageins; + char *kernel; +#endif 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; + howto |= RB_QUICK; break; case '?': default: @@ -143,9 +152,9 @@ main(int argc, char *argv[]) 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 @@ -182,7 +191,20 @@ main(int argc, char *argv[]) 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", ""); +#endif /* * 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(); +#ifndef __APPLE__ /* 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); @@ -236,16 +260,19 @@ main(int argc, char *argv[]) } #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 */ -#ifndef __APPLE__ restart: -#endif sverrno = errno; errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "", strerror(sverrno)); /* NOTREACHED */ +#endif /* __APPLE__ */ } void @@ -275,65 +302,61 @@ get_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() { - int rval = ELAST+1; + int rval = ELAST + 1; 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 = ""; + 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) + 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; - // 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; - } 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); - } return rval; }