#!/usr/bin/env python
# Based on the PyObjC SystemConfiguration callback demos:
#
from Cocoa import *
from SystemConfiguration import *
import signal
import os
from syslog import *
import sys
# SystemConfiguration state change events obtained from a 10.5 system
# Use scutil list to list all possible events:
# subKey [44] = State:/Network/Global/DNS
# subKey [45] = State:/Network/Global/IPv4
# subKey [46] = State:/Network/Global/Proxies
# subKey [47] = State:/Network/Global/SMB
# subKey [48] = State:/Network/Interface
# subKey [49] = State:/Network/Interface/en0/IPv4
# subKey [50] = State:/Network/Interface/en0/IPv6
# subKey [51] = State:/Network/Interface/en0/Link
# subKey [52] = State:/Network/Interface/en1/AirPort
# subKey [53] = State:/Network/Interface/en1/Link
# subKey [54] = State:/Network/Interface/fw0/Link
# subKey [55] = State:/Network/Interface/lo0/IPv4
# subKey [56] = State:/Network/Interface/lo0/IPv6
# subKey [57] = State:/Network/MulticastDNS
# subKey [58] = State:/Network/PrivateDNS
# subKey [63] = State:/Users/ConsoleUser
# This contains the list of states we want to monitor and the command to run when a given event occurs:
handlerDict = {
'State:/Network/Interface/Global/IPv4': "/bin/echo Global IPv4 config changed",
'State:/Network/Interface/en0/IPv4': "/bin/echo en0 IPv4 config changed",
'State:/Network/Interface/*/IPv4': "/bin/echo Some interface\'s IPv4 config changed",
'State:/Network/Global/DNS': "/bin/echo Global DNS configuration changed"
}
def handleConfigChange(store, changedKeys, info):
for key in changedKeys:
syslog(LOG_NOTICE, "%s changed: running %s" % (key, handlerDict[key]))
os.system(handlerDict[key])
def clean_shutdown():
CFRunLoopStop(CFRunLoopGetCurrent())
sys.exit(0)
openlog("kicker-replacement")
# This uses the SystemConfiguration framework to get a SCDynamicStore session
# and register for certain events. See the Appl SystemConfiguration
# documentation for details:
#
#
#
# TN1145 may also be of interest:
#
store = SCDynamicStoreCreate(None, "kicker-replacement", handleConfigChange, None)
SCDynamicStoreSetNotificationKeys(store, None, handlerDict.keys())
# Get a CFRunLoopSource for our store session and add it to the application's runloop:
CFRunLoopAddSource(CFRunLoopGetCurrent(), SCDynamicStoreCreateRunLoopSource(None, store, 0), kCFRunLoopCommonModes)
# Add a signal handler so we can shutdown cleanly if we get a ^C:
# BUG: This does not work - it's necessary to ^Z or kill from another window
signal.signal(signal.SIGINT, clean_shutdown)
syslog(LOG_NOTICE, "Listening for SystemConfiguration changes to these keys: %s" % ', '.join(handlerDict.keys()))
CFRunLoopRun()