#!/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()