Installing things to /usr/bin – Trampolines
Thursday, January 10th, 2008
Some Mac OS X applications can install useful tools to use with Terminal. PDFKey Pro is one of those applications. Currently I simply installed a binary called “pdfkeypro” in /usr/bin via a .pkg file. This had the obvious draw back of needing the user upgrade it manually on every release.
Some applications, like the excellent TextMate place a symlink to an executable inside the application bundle, solving said problem. But introducing another one: as soon as the application bundle is moved, the symlink breaks.
As I am about to update the command line tools for PDFKey Pro, I started thinking about a better way to install said binaries. One which would update automatically when the main bundle is updated, but wouldn’t break if said bundle is moved in another location.
Trampolines to the rescue! Instead of installing the real tools I install 2 trampoline applications in /usr/bin called respectively pdflock and pdfunlock. The trampoline then uses NSWorkspace to locate the bundle, and starts the real executable found in the application’s bundle. The code of a trampoline looks like this:
int main(int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSWorkspace *env = [NSWorkspace sharedWorkspace]; NSString *app = [env absolutePathForAppBundleWithIdentifier:@"com.pdfkey.pdfkeypro"]; NSString *targetPath = [[app stringByAppendingPathComponent:@"Contents/Resources/pdflock"] retain]; const char *CStringPath = [targetPath UTF8String]; [pool release]; execv(CStringPath, argv); // You reach this code only if execv returns, which means that something wrong happened. [targetPath release]; printf("PDFKey Pro is not installed. Please download it from http://pdfkey.com\n"); return 0; }
I can already read the comment that I could use argv[0] instead of hardcoding the application name. That’s true, but this trampoline once written should not be ever modified again and I want it to perform the minimum number of instructions required to work.
You can use this code liberally to make your very own trampoline, consider this to be of public domain. You can also find it at codebeach.
As a side note, I wonder why most application installing things in /usr/bin usually have their very own installer. Why wouldn’t a .pkg do? This is a sincere question, not an attempt to flame. In PDFKey Pro all I do is bundle a .pkg file and provide a menu item which launches it. It couldn’t be easier!