Updating dyld Shared Caches with Radmind: Best Practices

Similar to my last post about updating kernel extensions, you can run into problems with Radmind due to the dyld shared cache. You may see messages like this in your system log:

current cache invalid because /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit has changed

Running the update_dyld_shared_cache command will fix this, but there’s a better way. Sure, there’s almost no overhead to that command, but where’s the fun in that? Here’s a pre-apply script that will delete any shared caches that have changed, which will then be re-built at reboot.

#!/bin/sh

# update_dyld_caches: Inspects the applicable transcript for something that
#                     might cause a dyld cache to become outdated. If it exists,
#                     delete the cache so it's re-created at startup.

DYLD_CACHE_FOLDER="/private/var/db/dyld"
DYLD_PREFIX="dyld_shared_cache_"
ARCHITECTURES="i386 x86_64 rosetta ppc ppc64"

for arch in ${ARCHITECTURES}; do
	cache="${DYLD_CACHE_FOLDER}/${DYLD_PREFIX}${arch}"
	map="${DYLD_CACHE_FOLDER}/${DYLD_PREFIX}${arch}.map"

	if /bin/test -f "${cache}"; then
		if /bin/test -f "${map}"; then
			/bin/cat "${map}" | grep ^/ | sort --unique --ignore-case | while read line; do
				if /bin/test -n "$(grep ${line} ${1})"; then # found a match
					/bin/rm -f "${cache}"
					/bin/rm -f "${map}"
					break;
				fi
			done
		else
			# Cache exists, but there's no map.
			/bin/rm -f "${cache}"
		fi
	fi
done

Updating Kernel Extensions with Radmind: Best Practices

One of the problems that I’ve run into so far using Radmind to manage Mac OS X—specifically, the Leopard to Snow Leopard transition—is that kextd helpfully starts recreating your kernel extension cache as soon as you modify anything in /System/Library/Extensions. This can be problematic when you’re updating core system files; as you update the 10.5 kernel extensions to their 10.6 counterparts, you don’t want the 10.5 version of kextd creating a cache of 10.6 kernel extensions, especially as the kernel extension cache has moved (from /System/Library/Extensions.mkext to /System/Library/Caches/com.apple.kext.caches/). So, should you handle this? My solution is to stop kextd if I know that I’m updating kernel extensions; that way, they won’t be re-created until reboot. Here’s the script:

/private/var/radmind/preapply/update_kernel_extensions:

#!/bin/sh

# update_kernel_extensions: Manage the replacement of old kernel extensions.
#                           If there are updates, kill kextd and destroy the
#                           caches.

KEXT_CACHE="/System/Library/Caches/com.apple.kext.caches"
KEXT_FOLDER="/System/Library/Extensions"
KEXTD_LAUNCHD="com.apple.kextd"
SYSTEM_LAUNCHD_FOLDER="/System/Library/LaunchDaemons"

transcript="${1}"
result="${transcript}.$$"

/usr/bin/grep "${KEXT_FOLDER}" "${transcript}" > "${result}"

if test -n "${result}"; then #result is non-empty
    # Disable kextd to prevent it from recreating kernel extension caches, which
    # will be re-created at startup.
    if test -n "$(/bin/launchctl list | /usr/bin/grep ${KEXTD_LAUNCHD})"; then
        #kextd is running
        /bin/launchctl unload "${SYSTEM_LAUNCHD_FOLDER}/${KEXTD_LAUNCHD}.plist"
    fi

    # Remove kernel extension cache.
    /bin/rm -rf "${KEXT_CACHE}"
fi

rm -f "${result}"

In its present form, it only works on Snow Leopard, but I’ll be updating it to work on Leopard as well.

Using AppleScript to Automate an iChat Video Chat

I had to write a script to automatically start iChat at login and start a video chat with a specified screenname. I wanted to only start the chat if the user was online and available, and quit iChat on an error or if the chat ended. So here’s the script I have:

using terms from application "iChat"
	tell application "iChat"
		activate
		log in
		delay 5
		set theBuddy to buddy "ScreennameGoesHere" of service "AIM"
		try
			set theStatus to status of theBuddy
		on error errmesg number errno
			set message to display dialog "The user is currently unavailable." buttons {"OK"}
			quit
			return
		end try
		if theStatus is available then
			set theCapabilities to get capabilities of theBuddy
			if (theCapabilities contains multiperson video) then
				send "A user is attempting to contact you." to theBuddy
				delay 2
				tell service "AIM" to make video chat with properties {participants:theBuddy}
				set theChat to result
				delay 30
				try
					set theStatus to the av connection status of theChat
				on error errmesg number errno
					quit
					return
				end try
				repeat while theStatus is not ended
					delay 5
					try
						set theStatus to the av connection status of theChat
					on error errmesg number errno
						quit
						return
					end try
				end repeat
				quit
				return
			else
				set message to display dialog "The user cannot video chat at this time. Please try again later." buttons {"OK"}
				quit
				return
			end if
		else
			set message to display dialog "The user is currently unavailable." buttons {"OK"}
			quit
			return
		end if
	end tell
end using terms from

A couple of gotchas:

  • I tried using video chat instead of multiperson video, but that always returned false. I don’t know why.
  • Once the video chat has ended, you can’t poll its status (hence the try block).

Google Delivers Mac Google Earth API Plugin, But at What Cost?

UPDATE: Google has released a version of Google Earth (including the plugin) without the self-updating feature.

The Mac blogs around the ‘net are all abuzz today about Google’s release of a Mac version of the Google Maps API, but I noticed something funny when I installed it.  The plug-in is a standard Mac Internet Plug-In, meaning you can install it at either /Library/Internet Plug-Ins or ~/Library/Internet Plug-Ins.  So why does the install package prompt you for administrator credentials when you choose to install it into your home folder?  The answer lives at /Library/Google.

It turns out that when you install the plugin, the installer also installs a software update component, code-named “keystone.”  It installs the following components:

  • An application bundle at /Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle
  • A “Ticket Store” at /Library/Google/GoogleSoftwareUpdate/TicketStore/ — does anyone know what this does?  I sure don’t.
  • A LaunchDaemon that runs as root on demand, at /Library/LaunchDaemons/com.google.keystone.daemon.plist
  • A LaunchAgent (/Library/LaunchAgents/com.google.keystone.agent.plist) that runs when you’re logged in, presumably to fire up the daemon so you can receive updates without administrative privileges.

Interestingly enough, this software component is never mentioned by Google.  It isn’t an option you can deselect in the installer.  Even worse, the plugin’s uninstall instructions don’t say a thing about it.  This means that after you follow the plugin uninstall instructions, your computer is still checking in with Google’s servers to make sure that it’s up-to-date.  I’m reluctant to call this malware, but it sure seems like spyware, doesn’t it?  At the very least the installer ought to mention something.

Be cautious when installing this plugin onto any computer where security is essential.  Any software component that runs as root, such as the updater this installer installs, is another attack vector for intruders trying to get at your data.

For what it’s worth, the API plugin does work if you only copy the stuff in /Library/Internet Plug-Ins to a computer or to your user account, so it appears that you can still use the plugin in a secure environment, you’ll just have to update it yourself and not have Google do it for you.

I’ve also mentioned this on the official Google Group.

New Safari 3.2 Feature: Secure Website Identification

Here’s a quick tip that slipped through the blogosphere (at least none of the Mac blogs I subscribe to featured it): in Safari 3.2, released last week, Apple’s added a feature from Firefox 3’s “awesome bar”: when you’re on a secure website, such as a bank’s, that has identification information, it’s displayed in green (though in Safari it’s at the top-right of the title bar).  A screenshot:

 

Safari 3.2 adds secure website information to the title bar.
Safari 3.2 adds secure website information to the title bar.

Along with a phishing filter, it looks like Safari is stepping up to the plate as a secure browser.