コード例 #1
0
ファイル: atconfig.c プロジェクト: aosm/configd_plugins
static void
stopAppleTalk(CFRunLoopTimerRef timer, void *info)
{
	char	*argv[]	= { "appletalk",
			    "-d",
			    NULL };

	SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown"));

	execCommand = _SCDPluginExecCommand(stopComplete,		// callback
					    info,			// context
					    0,				// uid
					    0,				// gid
					    "/usr/sbin/appletalk",	// path
					    argv);			// argv

	if (!timer) {
		execRetry = 5;	// initialize retry count
	}

	return;
}
コード例 #2
0
ファイル: kicker.c プロジェクト: aosm/configd_plugins
static void
booter(kickeeRef target)
{
	char			**argv		= NULL;
	char			*cmd		= NULL;
	CFStringRef		execCommand	= CFDictionaryGetValue(target->dict, CFSTR("execCommand"));
	int			i;
	CFArrayRef		keys		= NULL;
	CFStringRef		name		= CFDictionaryGetValue(target->dict, CFSTR("name"));
	int			nKeys		= 0;
	Boolean			ok		= FALSE;
	CFStringRef		postName	= CFDictionaryGetValue(target->dict, CFSTR("postName"));

	SCLog(_verbose, LOG_DEBUG, CFSTR("Kicker callback, target=%@"), name);

	if (!isA_CFString(postName) && !isA_CFString(execCommand)) {
		goto error;	/* if no notifications to post nor commands to execute */
	}

	if (isA_CFString(postName)) {
		uint32_t	status;

		/*
		 * post a notification
		 */
		cmd = _SC_cfstring_to_cstring(postName, NULL, 0, kCFStringEncodingASCII);
		if (!cmd) {
			SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert post name to C string"));
			goto error;
		}

		SCLog(TRUE, LOG_NOTICE, CFSTR("posting notification %s"), cmd);
		status = notify_post(cmd);
		if (status != NOTIFY_STATUS_OK) {
			SCLog(TRUE, LOG_DEBUG, CFSTR("  notify_post() failed: error=%ld"), status);
			goto error;
		}

		CFAllocatorDeallocate(NULL, cmd);	/* clean up */
		cmd = NULL;
	}

	/*
	 * get the arguments for the kickee
	 */
	keys = target->changedKeys;
	target->changedKeys = NULL;

	if (isA_CFString(execCommand)) {
		CFRange			bpr;
		CFNumberRef		execGID		= CFDictionaryGetValue(target->dict, CFSTR("execGID"));
		CFNumberRef		execUID		= CFDictionaryGetValue(target->dict, CFSTR("execUID"));
		CFBooleanRef		passKeys	= CFDictionaryGetValue(target->dict, CFSTR("changedKeysAsArguments"));
		gid_t			reqGID		= 0;
		uid_t			reqUID		= 0;
		CFMutableStringRef	str;

		/*
		 * build the kickee command
		 */
		str = CFStringCreateMutableCopy(NULL, 0, execCommand);
		bpr = CFStringFind(str, CFSTR("$BUNDLE"), 0);
		if (bpr.location != kCFNotFound) {
			CFStringRef	bundlePath;

			bundlePath = CFURLCopyFileSystemPath(myBundleURL, kCFURLPOSIXPathStyle);
			CFStringReplace(str, bpr, bundlePath);
			CFRelease(bundlePath);
		}

		cmd = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingASCII);
		CFRelease(str);
		if (!cmd) {
			SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert command to C string"));
			goto error;
		}

		/*
		 * get the UID/GID for the kickee
		 */
		if (isA_CFNumber(execUID)) {
			CFNumberGetValue(execUID, kCFNumberIntType, &reqUID);
		}

		if (isA_CFNumber(execGID)) {
			CFNumberGetValue(execGID, kCFNumberIntType, &reqGID);
		}

		nKeys = CFArrayGetCount(keys);
		argv  = CFAllocatorAllocate(NULL, (nKeys + 2) * sizeof(char *), 0);
		for (i = 0; i < (nKeys + 2); i++) {
			argv[i] = NULL;
		}

		/* create command name argument */
		if ((argv[0] = rindex(cmd, '/')) != NULL) {
			argv[0]++;
		} else {
			argv[0] = cmd;
		}

		/* create changed key arguments */
		if (isA_CFBoolean(passKeys) && CFBooleanGetValue(passKeys)) {
			for (i = 0; i < nKeys; i++) {
				CFStringRef	key = CFArrayGetValueAtIndex(keys, i);

				argv[i+1] = _SC_cfstring_to_cstring(key, NULL, 0, kCFStringEncodingASCII);
				if (!argv[i+1]) {
					SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert argument to C string"));
					goto error;
				}
			}
		}

		SCLog(TRUE,     LOG_NOTICE, CFSTR("executing %s"), cmd);
		SCLog(_verbose, LOG_DEBUG,  CFSTR("  current uid = %d, requested = %d"), geteuid(), reqUID);

		/* this kicker is now "running" */
		target->active = TRUE;

		(void)_SCDPluginExecCommand(booterExit,
			      target,
			      reqUID,
			      reqGID,
			      cmd,
			      argv);

//		CFAllocatorDeallocate(NULL, cmd);	/* clean up */
//		cmd = NULL;
	} else {
		target->active = FALSE;
	}

	target->needsKick = FALSE;	/* allow additional requests to be queued */
	ok = TRUE;

    error :

	if (keys)	CFRelease(keys);
	if (cmd)	CFAllocatorDeallocate(NULL, cmd);
	if (argv) {
		for (i = 0; i < nKeys; i++) {
			if (argv[i+1]) {
				CFAllocatorDeallocate(NULL, argv[i+1]);
			}
		}
		CFAllocatorDeallocate(NULL, argv);
	}

	if (!ok) {
		/*
		 * If the target action can't be performed this time then
		 * there's not much point in trying again. As such, I close
		 * the session and the kickee target released.
		 */
		cleanupKicker(target);
	}

	return;
}
コード例 #3
0
/* _doPowerEmergencyShutdown()
 *
 Performs a semi-complicated proecdure to get machines experiencing power failure
 to automatically power up when external power is restored. We do this to trigger
 the onboard "Restart Automatically after a power failure" feature; pulling the power
 from a mostly-shutdown machine simulates a "power failure."
 
 At the time we do the shutdown...
 The UPS has lost external power (presumably due to a power outage) and our backup
 power thresholds have been exceeded and we've decided to do a system shutdown.
 
 1. Request that the UPS remove power from the system in kDelayedRemovePowerMinutes
 2. Set the StallSystemAtHalt root domain property that will cause the machine to hang 
    at shutdown (after the OS has been shutdown).
 3. We run the emergency shutdown script (/usr/libexec/upsshutdown) and shutdown to
    the point of stalling.
 4. OS hangs there at the endpoint, waiting for UPS to remove power to its AC plugs.
 
 Later...
 1. External power is restored to the UPS
 2. The UPS restores power to its outlets, the CPU's "Restart Automatically after a
    power failure" switch is triggered. System boots up and resumes operation.
 *
 */
static void 
_doPowerEmergencyShutdown(CFNumberRef ups_id)
{
    static int      _alreadyShuttingDown = 0;
    CFDictionaryRef _ESSettings = NULL;
    char            *shutdown_argv[3];
    CFNumberRef     auto_restart;
    IOReturn        error;
    bool            upsRestart = false;
    int             restart_setting;
    
    if(_alreadyShuttingDown) 
        return;
    _alreadyShuttingDown = 1;
    
    syslog(LOG_INFO, "Performing emergency UPS low power shutdown now");

    _ESSettings = PMSettings_CopyActivePMSettings();
    if(!_ESSettings) 
        goto shutdown;
    
    auto_restart = isA_CFNumber(CFDictionaryGetValue(_ESSettings, CFSTR(kIOPMRestartOnPowerLossKey)));
    if(auto_restart) {
        CFNumberGetValue(auto_restart, kCFNumberIntType, &restart_setting);
    } else { 
        restart_setting = 0;
    }
    upsRestart = restart_setting ? true:false;
        
    if(!upsRestart)
    {
        // Automatic Restart On Power Loss checkbox is disabled - 
        // just do a plain old shutdown
        // and don't attempt to auto-restart.
        goto shutdown;
    }

    // Does the attached UPS support RemovePowerDelayed?
    if(_upsSupports(ups_id, CFSTR(kIOPSCommandDelayedRemovePowerKey)))
    {
        syslog(LOG_INFO, "System will restart when external power is restored to UPS.");

        error = _upsCommand(ups_id, 
                    CFSTR(kIOPSCommandStartupDelayKey), 
                    _delayBeforeStartupMinutes);

        if(kIOReturnSuccess != error)
        {
            // Attempt to set "startup when power restored" delay failed
            syslog(LOG_INFO, "UPS Emergency shutdown: error 0x%08x requesting UPS startup delay of %d minutes\n", 
                                error, _delayBeforeStartupMinutes);
            goto shutdown;
        }

        error = _upsCommand(ups_id, CFSTR(kIOPSCommandDelayedRemovePowerKey), _delayedRemovePowerMinutes);
        if(kIOReturnSuccess != error)
        {
            // We tried telling the UPS to auto-restart us, but since that's 
            // failing we're just going to do an old school shutdown that 
            // requires human intervention to power on.
            syslog(LOG_INFO, "UPS Emergency shutdown: error 0x%08x communicating shutdown time to UPS\n", error);
            goto shutdown;
        }
    }
    
shutdown:

    if (_ESSettings) {
        CFRelease(_ESSettings);
    }
    
    shutdown_argv[0] = (char *)"/usr/libexec/upsshutdown";

    if(upsRestart) {
        shutdown_argv[1] = (char *)"WaitForUPS";
        shutdown_argv[2] = NULL;
    } else {
        shutdown_argv[1] = NULL; 
    }
    _SCDPluginExecCommand(0, 0, 0, 0, 
                        "/usr/libexec/upsshutdown", shutdown_argv);
}
コード例 #4
0
ファイル: atconfig.c プロジェクト: aosm/configd_plugins
static void
startAppleTalk(CFRunLoopTimerRef timer, void *info)
{
	int		argc		= 0;
	char		*argv[8];
	char		*computerName	= NULL;
	char		*interface	= NULL;
	CFStringRef	mode		= CFDictionaryGetValue(curStartup, CFSTR("APPLETALK"));
	CFStringRef	name		= CFDictionaryGetValue(curStartup, CFSTR("APPLETALK_HOSTNAME"));

	SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup"));

	if (!mode) {
		// Huh?
		return;
	}

	// set command name
	argv[argc++] = "appletalk";

	// set hostname
	if (name) {
		computerName = cfstring_to_cstring(name, NULL, 0);
		if (computerName) {
			argv[argc++] = "-C";
			argv[argc++] = computerName;
		} else {
			// could not convert name
			goto done;
		}
	}

	// set mode
	if (CFEqual(mode, CFSTR("-ROUTER-"))) {
		argv[argc++] = "-r";
	} else if (CFEqual(mode, CFSTR("-MULTIHOME-"))) {
		argv[argc++] = "-x";
	} else {
		interface = cfstring_to_cstring(mode, NULL, 0);
		if (interface) {
			argv[argc++] = "-u";
			argv[argc++] = interface;
		} else {
			// could not convert interface
			goto done;
		}
	}

	// set non-interactive
	argv[argc++] = "-q";

	// close argument list
	argv[argc++] = NULL;

	execCommand = _SCDPluginExecCommand(startComplete,		// callback
					    info,			// context
					    0,				// uid
					    0,				// gid
					    "/usr/sbin/appletalk",	// path
					    argv);			// argv

	if (!timer) {
		execRetry = 5;	// initialize retry count
	}

    done :

	if (computerName)	CFAllocatorDeallocate(NULL, computerName);
	if (interface)		CFAllocatorDeallocate(NULL, interface);

	return;
}